You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

142 lines
6.0 KiB

#include "Camera.h"
#include "ShaderProgram.h"
#include "ExternalLib/glm/gtc/matrix_transform.hpp"
#include "ExternalLib/glm/gtc/type_ptr.hpp"
#include "ExternalLib/glm/gtc/matrix_access.hpp"
/******************
* Constructors *
******************/
Camera::Camera(int* width_, int* height_, float minDistance_, float maxDistance_)
: width(width_), height(height_), minDistance(minDistance_), maxDistance(maxDistance_)
{
/**
* \brief Create a default camera at position(0;0;0) with its View and Projection Matrices
* \param width, height : resolution
* minDistance : defines frustrum's nearplan
* maxDistance : defines frustrum's farplan
*/
/***************************************************************
* DEFINING COMMON MATRICES : Projection and View *
****************************************************************/
/* View Matrix */
/* Allow conversion from world space to view space/camera view */
cameraPos = glm::vec3(0.0f, 0.0f, -2.0f); // initial position of the camera
cameraForward = glm::vec3(0.0f, 0.0f, -1.0f); // Z axis of the camera
cameraUp = glm::vec3(0.0f, 1.0f, 0.0f); // Y axis of the camera
// Default FOV
FOV = 80.0f; // Field Of View
FOVScrollStep = 5.0f; // For each mouseScroll input, modify FOV by FOVScrollStep
// Default look direction
cameraPitch = 2*glm::pi<float>(); // camera's pitch
cameraYaw = glm::pi<float>()/2; // camera's yaw
cameraRoll = 0; // camera's roll
cameraRollStep = glm::radians(45.0f); // Step used for roll
cameraStep = 5.0f; // Step used for planar movements
// Player's configuration // TODO : deserialize below informations from an option file
xAxisSensitivity = 0.1f; // x axis mouse sensitivity
yAxisSensitivity = 0.2f; // y axis mouse sensitivity
invertYAxis = false; // inverted x axis ?
invertXAxis = false; // inverted y axis ?
// Set Matrices
actualizeProjectionMatrix();
actualizeViewMatrix();
}
/*************
* Setters *
*************/
void Camera::setPosition(const glm::vec3& cameraPos_)
{ cameraPos = cameraPos_; actualizeViewMatrix();}
/*************
* Methods *
*************/
void Camera::actualizeViewMatrix()
{
/**
* \brief Actualize Camera's View Matrix
*/
// modulo those values to two pi in order to avoid overflow over time
float pi2 = 2.0f*glm::pi<float>();
cameraPitch = fmodf(cameraPitch, pi2);
cameraYaw = fmodf(cameraYaw, pi2);
cameraRoll = fmodf(cameraRoll, pi2);
// Apply pitch and Yaw
glm::vec3 newCameraForward = cameraPos;
newCameraForward.z += cosf(cameraPitch)*sinf(cameraYaw);
newCameraForward.y += cosf(cameraYaw);
newCameraForward.x += sinf(cameraPitch)*sinf(cameraYaw);
cameraForward = glm::vec3(0, 0, -1) * glm::mat3(view);
// Apply roll (will probably be easier to implement with quaternions)
// TODO : here are a few tries, probably not that far off...
// cameraUp = glm::rotate(cameraUp, cameraRoll, newCameraForward);
// float foo[16] = { cos(cameraRoll), -sin(cameraRoll), 0, 0,
// sin(cameraRoll), cos(cameraRoll), 0, 0,
// 0, 0, 1, 0,
// 0, 0, 0, 1
// };
// glm::mat4 rotationMatrix = glm::make_mat4(foo);
/* Setting View matrix, it allows conversion from world space to view space/camera view */
view = glm::lookAt(cameraPos, newCameraForward, cameraUp); // define view Matrix to suit our camera system
// view *= rotationMatrix;
// view = glm::rotate(view, cameraRoll, cameraForward);
// viewLoc = glGetUniformLocation(sp->getId(), "view");
// glProgramUniformMatrix4fv(sp->getId(), viewLoc, 1, GL_FALSE, glm::value_ptr(view));
}
void Camera::actualizeProjectionMatrix()
{
/**
* \brief Actualize Camera's Projection Matrix (for FOV changes)
*/
/* Convert current coordinates to Normalized Device Coordinates (-1.0;1.0) */
/* And defines frustrum and perspective of the camera */
projection = glm::perspective(static_cast<GLfloat>(glm::radians(FOV))
, static_cast<GLfloat>(*width) / static_cast<GLfloat>(*height)
, static_cast<GLfloat>(minDistance)
, static_cast<GLfloat>(maxDistance) );
}
void Camera::bindToShaderProgram(const ShaderProgram& sp)
{
/**
* \brief Bind Camera to a ShaderProgram
*/
viewLoc = glGetUniformLocation(sp.getId(), "view");
glProgramUniformMatrix4fv(sp.getId(), viewLoc, 1, GL_FALSE, glm::value_ptr(view));
projectionLoc = glGetUniformLocation(sp.getId(), "projection");
glProgramUniformMatrix4fv(sp.getId(), projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));
}
Camera Camera::mirrorCamera(const glm::mat4& mirrorModelMatrix, const glm::vec4& /*mirror*/, const glm::vec4& /*pointOnMirror*/) const
{
/**
* \brief Create a Camera with mirrored view matrix behind the mirror given in parameter
* \param mirrorModelMatrix <=> mirror's matrix model
* mirror <=> mirror's forward vector
* pointOnMirror <=> point on mirror to locate it in worldspace
*/
Camera mirroredCamera = *this;
// Put camera behind the mirror
mirroredCamera.view = view * mirrorModelMatrix * glm::scale(glm::mat4() , glm::vec3(1, 1, -1)) * glm::inverse(mirrorModelMatrix);
// Overlap nearplan's view on mirror plan in order to cull objects behind the mirror (cf "Oblique View Frustum Depth Projection and Clipping" paper)
// BUGGY, doing things, not sure what probably moving camera somewhere else
// mirroredCamera.view[2] = ((-2*pointOnMirror.z)/(glm::dot(mirror, pointOnMirror)))*mirror + glm::vec4(0,0,-1,0);
// mirroredCamera.view[3] = glm::vec4(0,0,-1,0);
return mirroredCamera;
}