146 lines
3.7 KiB
C++
146 lines
3.7 KiB
C++
#include "camera.h"
|
|
|
|
QMatrix4x4 Camera::m_reflection = QMatrix4x4(1, 0, 0, 0,
|
|
0,-1, 0, 0,
|
|
0, 0, 1, 0,
|
|
0, 0, 0, 1);
|
|
|
|
Camera::Camera(QVector3D position, QVector3D rotation): m_position(position)
|
|
{
|
|
setXAngleDegrees(double(rotation.x()));
|
|
setYAngleDegrees(double(rotation.y()));
|
|
|
|
m_ratio = 1.0;
|
|
|
|
connect(this, SIGNAL(positionChanged(QVector3D)), this, SLOT(computeViewMatrix()));
|
|
connect(this, SIGNAL(rotationXChanged(double)), this, SLOT(computeViewMatrix()));
|
|
connect(this, SIGNAL(rotationYChanged(double)), this, SLOT(computeViewMatrix()));
|
|
|
|
computeViewMatrix();
|
|
computeProjectionMatrix();
|
|
}
|
|
|
|
QMatrix4x4 Camera::view() const
|
|
{
|
|
return m_view;
|
|
}
|
|
|
|
QMatrix4x4 Camera::projection() const
|
|
{
|
|
return m_projection;
|
|
}
|
|
|
|
void Camera::rotateAroundX(float deltaAngleRad)
|
|
{
|
|
m_xAngle += deltaAngleRad;
|
|
emit rotationXChanged(double(m_xAngle) / M_PI * 180);
|
|
}
|
|
|
|
void Camera::rotateAroundY(float deltaAngleRad)
|
|
{
|
|
m_yAngle += deltaAngleRad;
|
|
emit rotationYChanged(double(m_yAngle) / M_PI * 180);
|
|
}
|
|
|
|
void Camera::moveX(float deltaX)
|
|
{
|
|
m_position += m_right * deltaX;
|
|
emit positionChanged(m_position);
|
|
}
|
|
|
|
void Camera::moveY(float deltaY)
|
|
{
|
|
m_position += m_up * deltaY;
|
|
emit positionChanged(m_position);
|
|
}
|
|
|
|
void Camera::moveZ(float deltaZ)
|
|
{
|
|
m_position -= m_front * deltaZ;
|
|
emit positionChanged(m_position);
|
|
}
|
|
|
|
void Camera::setRatio(float ratio)
|
|
{
|
|
m_ratio = ratio;
|
|
computeProjectionMatrix();
|
|
}
|
|
|
|
void Camera::computeViewMatrix()
|
|
{
|
|
m_front = QVector3D(std::cos(m_xAngle) * std::sin(m_yAngle), std::sin(m_xAngle), std::cos(m_xAngle) * std::cos(m_yAngle));
|
|
m_right = QVector3D(std::sin(m_yAngle - float(M_PI) / 2.f), 0, std::cos(m_yAngle - float(M_PI) / 2.f));
|
|
m_up = QVector3D::crossProduct(m_right, m_front);
|
|
|
|
m_view.setToIdentity();
|
|
m_view.lookAt(m_position, m_position + m_front, m_up);
|
|
|
|
m_reflectedView = m_view * m_reflection;
|
|
emit updated();
|
|
}
|
|
|
|
void Camera::computeProjectionMatrix()
|
|
{
|
|
m_projection.setToIdentity();
|
|
m_projection.perspective(90, m_ratio, 0.1f, 100);
|
|
emit updated();
|
|
}
|
|
|
|
void Camera::setX(double x)
|
|
{
|
|
if (!qFuzzyCompare(m_position.x(), float(x))) {
|
|
m_position.setX(float(x));
|
|
emit positionChanged(m_position);
|
|
}
|
|
}
|
|
|
|
void Camera::setY(double y)
|
|
{
|
|
if (!qFuzzyCompare(m_position.y(), float(y))) {
|
|
m_position.setY(float(y));
|
|
emit positionChanged(m_position);
|
|
}
|
|
}
|
|
|
|
void Camera::setZ(double z)
|
|
{
|
|
if (!qFuzzyCompare(m_position.z(), float(z))) {
|
|
m_position.setZ(float(z));
|
|
emit positionChanged(m_position);
|
|
}
|
|
}
|
|
|
|
void Camera::setXAngleDegrees(double xAngleDeg)
|
|
{
|
|
float xAngleRad = float(xAngleDeg / 180 * M_PI);
|
|
if (!qFuzzyCompare(m_xAngle, xAngleRad)) {
|
|
m_xAngle = xAngleRad;
|
|
emit rotationXChanged(xAngleDeg);
|
|
}
|
|
}
|
|
|
|
void Camera::setYAngleDegrees(double yAngleDeg)
|
|
{
|
|
float yAngleRad = float(yAngleDeg / 180 * M_PI);
|
|
if (!qFuzzyCompare(m_yAngle, yAngleRad)) {
|
|
m_yAngle = yAngleRad;
|
|
emit rotationYChanged(yAngleDeg);
|
|
}
|
|
}
|
|
|
|
void Camera::setUniforms(Shader* program, RenderPassType renderPass)
|
|
{
|
|
if (renderPass == RenderPassType::REFLECTION) {
|
|
glUniformMatrix4fv(program->uniformLocation("u_view"), 1, GL_FALSE, m_reflectedView.data());
|
|
} else {
|
|
glUniformMatrix4fv(program->uniformLocation("u_view"), 1, GL_FALSE, m_view.data());
|
|
}
|
|
glUniformMatrix4fv(program->uniformLocation("u_projection"), 1, GL_FALSE, m_projection.data());
|
|
glUniform3f(program->uniformLocation("u_cameraPosition"), m_position.x(), m_position.y(), m_position.z());
|
|
}
|
|
|
|
void Camera::initGl()
|
|
{
|
|
initializeOpenGLFunctions();
|
|
}
|