OpenGL rotating an object around it's own axis - c++

I am trying to rotate an object around its own x-axis. It works exactly as expected when it is on the right side of the y-axis but showcases strange behavior when it on the left.
void Animation::rotate_x(float degree) {
// get the position of the object wrt to origin
glm::vec3 position = glm::vec3(m_model_mat[3]);
glm::vec3 position_rev = -position;
// get the angle of the obj wrt y-axis
float angleY = atan2(m_model_mat[0][2], sqrt((m_model_mat[0][0] * m_model_mat[0][0]) + (m_model_mat[0][1] * m_model_mat[0][1])));
angleY = angleY * 180 / M_PI;
std::cout << angleY << "\n";
if(position[0] < 0){
if(angleY > 0){
angleY = 90 + angleY;
} else if (angleY < 0)
{
angleY = -90 + angleY;
} else{
angleY = 180;
}
}
std::cout << angleY << "\n";
// rotate so angle with y is 0
glm::mat4 rot_y_mat = glm::mat4(1.0f);
rot_y_mat = glm::rotate(rot_y_mat, glm::radians(-angleY), glm::vec3(0.0f, 1.0f, 0.0f));
// rotate to bring back to the correct position wrt y
glm::mat4 rev_rot_y_mat = glm::mat4(1.0f);
rev_rot_y_mat = glm::rotate(rev_rot_y_mat, glm::radians(angleY), glm::vec3(0.0f, 1.0f, 0.0f));
// rotate on x
glm::mat4 rotation_mat = glm::mat4(1.0f);
rotation_mat = glm::rotate(rotation_mat, glm::radians(degree), glm::vec3(1.0f, 0.0f, 0.0f));
// translate back to the original position
glm::mat4 trans_to_position = glm::mat4(1.0f);
trans_to_position = glm::translate(trans_to_position, position);
// move obj to origin
glm::mat4 trans_to_origin = glm::mat4(1.0f);
trans_to_origin = glm::translate(trans_to_origin, position_rev);
m_model_mat = trans_to_origin * m_model_mat;
m_model_mat = rev_rot_y_mat * m_model_mat;
m_model_mat = rotation_mat * m_model_mat;
m_model_mat = rot_y_mat * m_model_mat;
m_model_mat = trans_to_position * m_model_mat;
}
Here the m_model_mat is my object matrix which I am transforming.

Related

What is the right way to update "front" vector with custom "world up" vector?

I am trying to implement "planet" world. So in any point on it's surface with my old camera class I got result like this :
Camera class update code is:
void cCamera::ProcessMouseMovement(GLdouble dt, glm::vec2 curOffset)
{
curOffset.x *= static_cast<GLfloat>(dt * m_MouseSensitivity);
curOffset.y *= static_cast<GLfloat>(dt * m_MouseSensitivity);
m_fPitch += curOffset.x;
m_fYaw += curOffset.y;
if (m_fYaw > 89.0f)
m_fYaw = 89.0f;
if (m_fYaw < -89.0f)
m_fYaw = -89.0f;
UpdateCameraVectors();
}
void cCamera::UpdateCameraVectors(void)
{
float fYawRad = glm::radians(m_fYaw);
float fPitchRad = glm::radians(m_fPitch);
float fYawCos = cos(fYawRad);
glm::vec3 front { cos(fPitchRad) * fYawCos,
sin(fYawRad),
sin(fPitchRad) * fYawCos };
*m_pCameraFront = glm::normalize(front);
m_Right = glm::normalize(glm::cross(*m_pCameraFront, m_WorldUp));
m_Up = glm::normalize(glm::cross(m_Right, front));
*m_pViewMatrix = glm::lookAt(glm::vec3(0.f), glm::vec3(0.f) + *m_pCameraFront, m_Up);
}
As (0,0,0) is planet center, I suppose I should udate m_WorldUp vector this way:
m_WorldUp = glm::normalize(*m_pPos);
And indeed, the results are good: camera turned the right way, but it's rotation is broken. Yaw and pitch are still dependent on old world up. I think, I should update front vector with new m_WorldUp, but don't really know how.
Solution was found here: https://gamedev.stackexchange.com/questions/73588/how-do-i-fix-my-planet-facing-camera
In my case code is
void cCamera::UpdateCameraVectors(void)
{
m_WorldUp = glm::normalize(*m_pPos);
glm::quat world_axes_rotation = glm::angleAxis(glm::radians(m_fPitch), glm::vec3(0.0f, -1.0f, 0.0f));
world_axes_rotation = glm::normalize(world_axes_rotation);
world_axes_rotation = glm::rotate(world_axes_rotation, glm::radians(m_fYaw), glm::vec3(1.0f, 0.0f, 0.0f));
m_Pole = glm::normalize(m_Pole - glm::dot(m_WorldUp, m_Pole) * m_WorldUp);
glm::mat4 local_transform;
local_transform[0] = glm::vec4(m_Pole, 0.0f);
local_transform[1] = glm::vec4(m_WorldUp, 0.0f);
local_transform[2] = glm::vec4(glm::cross(m_Pole, m_WorldUp), 0.0f);
local_transform[3] = glm::vec4(0.f, 0.f, 0.f, 1.0f);
world_axes_rotation = glm::normalize(world_axes_rotation);
*m_pViewMatrix = local_transform * glm::mat4_cast(world_axes_rotation);
*m_pCameraFront = -1.0f * glm::vec3((*m_pViewMatrix)[2]);
m_Up = glm::vec3((*m_pViewMatrix)[1]);
m_Right = glm::vec3((*m_pViewMatrix)[0]);
*m_pViewMatrix = glm::inverse(*m_pViewMatrix);
}

rotate camera LookAt point

Using a glm::lookAt function to create the camera view matrix is good but does not help in storing the camera Euler angles. although the calculations seem correct, the view seems to bring the wrong pitch value.
in the following code, if the Y values of the current camera position and destination is the same then, there is no problem. however, the view seems to tilt further down or up if the Y values of the camera position and destination are not equal.
The question is: why does the camera not correctly points an object if the Y values of the camera and object positions are not equal.
float wrapAngle(float angle)
{
int break_after = 100;
constexpr float full_rotation = 2.0 * glm::pi<float>();
while (angle < 0.0f || angle >= full_rotation)
{
if (angle < 0.0f) angle = angle + full_rotation;
if (angle >= full_rotation) angle = angle - full_rotation;
if (--break_after == 0) break;
}
if (break_after == 0) angle = 0.0f;
return angle;
}
void getLookAtAngle(const glm::vec3& position, const glm::vec3& destination, glm::vec3 &angle)
{
//! Find vector of sight toward destination.
glm::vec3 sight = destination - position;
//! Find X, Y rotation against the axis (global).
double yAngle = wrapAngle(std::atan2(sight.x, sight.z));
glm::mat4 yModel(1);
yModel = glm::rotate(yModel, static_cast<float>(-yAngle), glm::vec3(0.0f, 1, 0));
sight = yModel * glm::vec4(sight, 1.0f);
double xAngle = wrapAngle(-std::atan2(sight.y, sight.z));
//! assign xAngle, yAngle to the parameter 'angle'
angle.x = glm::degrees(static_cast<float>(xAngle));
angle.y = glm::degrees(static_cast<float>(yAngle));
angle.z = 0.0f;
}
void updateCamera(const glm::vec3& position, const glm::vec3& destination)
{
glm::vec3 m_rotation(1);
getLookAtAngle(position, destination, m_rotation)
m_model = glm::mat4(1);
m_model = glm::rotate(m_model, glm::radians(m_rotation[0]), glm::vec3(1.0f, 0, 0));
m_model = glm::rotate(m_model, glm::radians(m_rotation[1]), glm::vec3(0.0f, 1, 0));
m_model = glm::rotate(m_model, glm::radians(m_rotation[2]), glm::vec3(0.0f, 0, 1));
m_front = glm::normalize(glm::vec3(m_model * glm::vec4(0, 0, 1.0f, 1.0f)));
m_right = glm::normalize(glm::cross(m_front, glm::vec3(0, 1.0f, 0)));
m_up = glm::normalize(glm::cross(m_right, m_front));
m_view = glm::lookAt(position, position+ m_front, m_up);
}

How to move camera around and stick it to the player?

I'm trying to move camera around the player.
Right now I'm using camera class like this:
Camera::Camera(glm::vec3 position, glm::vec3 up, GLfloat yaw, GLfloat pitch)
{
this->position = position;
this->m_WorldUp = up;
this->up = up;
this->m_Yaw = yaw;
this->m_Pitch = pitch;
this->UpdateCameraVectors();
}
glm::mat4 Camera::getViewMatrix()
{
return glm::lookAt(position, position + m_Front, up);
}
void Camera::ProcessKeyboard(Camera_Movement direction, GLfloat deltaTime)
{
float velocity = moveSpeed * deltaTime;
switch (direction) {
case FORWARD: position += m_Front * velocity; break;
case BACKWARD: position -= m_Front * velocity; break;
case LEFT: position -= m_Right * velocity; break;
case RIGHT: position += m_Right * velocity; break;
case UPWARDS: position += m_WorldUp * velocity; break;
case DOWNWARDS: position -= m_WorldUp * velocity; break;
}
}
void Camera::ProcessMouseMovement(GLfloat xOffset, GLfloat yOffset, GLboolean constrainPitch)
{
xOffset *= sensitivity;
yOffset *= sensitivity;
m_Yaw += xOffset;
m_Pitch += yOffset;
if (constrainPitch) {
if (m_Pitch > 89.0f) {
m_Pitch = 89.0f;
} else if (m_Pitch < -89.0f) {
m_Pitch = -89.0f;
}
}
UpdateCameraVectors();
}
void Camera::UpdateCameraVectors()
{
glm::vec3 front;
front.x = cos(glm::radians(m_Yaw)) * cos(glm::radians(m_Pitch));
front.y = -sin(glm::radians(m_Pitch));
front.z = sin(glm::radians(m_Yaw)) * cos(glm::radians(m_Pitch));
m_Front = glm::normalize(front);
m_Right = glm::normalize(glm::cross(m_Front, m_WorldUp));
up = glm::normalize(glm::cross(m_Right, m_Front));
}
It allows me to free look and move around the world.
Player's update method at the moment:
glm::mat4 projection = glm::mat4(1.0f);
projection = glm::perspective(glm::radians(45.0f), 16.0f / 9.0f, 0.1f, 1000.0f);
glm::mat4 view = glm::mat4(1.0f);
view = camera->getViewMatrix();
glm::mat4 model = glm::mat4(1.0f); {
glm::mat4 translate = glm::translate(model, position);
glm::mat4 rotate = glm::rotate(model, glm::radians(180.0f), glm::vec3(0.0f, 1.0f, 0.0f));
glm::mat4 scale = glm::scale(model, glm::vec3(0.1f, 0.1f, 0.1f));
model = translate * rotate * scale;
}
glm::mat4 mvp = projection * view * model;
GLint u_mvp = shader.GetUniformLocation("u_mvp");
glUniformMatrix4fv(u_mvp, 1, GL_FALSE, glm::value_ptr(mvp));
I know that I have to change something with view matrix, but I have not got enough knowledge.
How can I upgrade my camera class that it can look, rotate, around a player, like in a circle, an MMO RPG style?
The camera class itself should not be receiving keyboard updates at all - that should be done in the player class. Every time the player moves, update the camera class with its new position. See comments in below code for more details.
Camera::Camera(glm::vec3 position, glm::vec3 up, GLfloat yaw, GLfloat pitch, GLfloat dist)
{
m_WorldUp = up;
// this->up = up; <- delete this variable; lookAt computes it for us
m_Pos = position; // this is the *player* position
m_Yaw = yaw;
m_Pitch = pitch;
m_Dist = dist; // distance from the player
UpdateViewMatrix(true);
}
// private method
void Camera::UpdateViewMatrix(bool computeDir = false)
{
// compute the new direction
if (computeDir)
{
glm::vec3 radial;
radial.x = cos(glm::radians(m_Yaw)) * cos(glm::radians(m_Pitch));
radial.y = sin(glm::radians(m_Pitch)); // there was a sign error here
radial.z = sin(glm::radians(m_Yaw)) * cos(glm::radians(m_Pitch));
m_Dir = -radial;
}
glm::vec3 pos = m_Pos - m_Dist * m_Dir; // *camera* position
// additional view matrix member variable
// you were using lookAt in the wrong way
m_View = glm::lookAt(m_Pos, pos, m_WorldUp);
}
// public method - call this everytime the player moves
void Camera::UpdateTargetPosition(glm::vec3 const & pos)
{
m_Pos = pos;
UpdateViewMatrix();
}
void Camera::UpdateAngles(GLfloat yaw, GLfloat pitch, GLboolean constrainPitch)
{
if (constrainPitch) {
if (pitch > 89.0f) {
pitch = 89.0f;
} else if (pitch < -89.0f) {
pitch = -89.0f;
}
}
// if yaw is outside the conventional range (-180.0, 180.0], shift it
if (yaw < -180.0f || yaw > 180.0f) {
yaw -= floor((yaw + 180.0f) / 360.0f) * 360.0f;
}
m_Yaw = yaw;
m_Pitch = pitch;
UpdateViewMatrix(true);
}
void Camera::ProcessMouseMovement(GLfloat xOffset, GLfloat yOffset, GLboolean constrainPitch)
{
UpdateAngles(m_Yaw + xOffset * sensitivity,
m_Pitch + yOffset * sensitivity,
constrainPitch);
}
for mouse follow you need:
camera = inverse(player * camera_view_and_offset)
where player is your player direct matrix, camera_view_and_offset is the view offset and turn around matrix relative to your player coordinate system and camera is your camera inverse matrix you should use as part of modelview ....
for more info see:
Understanding 4x4 homogenous transform matrices

Pool Game physics velocity calculation issue

Hi I am making a 3d pool game and I am currently at the state of applying collisions, I am using openGL and C++. I already have the collision written and it is working properly. The issue I have is related only to the velocity of the ball class and passing forces to other balls on collision.
I have a ball class that is used for all the balls including the cue ball. I have a drawBall() function:
void drawBall(Shader ourShader) {
extern GLfloat deltaTime;
a = F / radius;
v = v + (a * deltaTime);
ballPos = ballPos + (v*deltaTime) + (0.5f*a*deltaTime*deltaTime);
collision();
//F = glm::vec3(0.0f, 0.0f, 0.0f);
//ACTUAL DRAWING
glBindVertexArray(VAO);
glm::mat4 model;
model = glm::translate(model, ballPos);
model = glm::rotate(model, glm::radians(40.0f), glm::vec3(1.0f, 0.0f, 0.0f));
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
And a collision function:
void collision() {
extern vector <Ball> ballCollection;
for (int i = 0; i < ballCollection.size(); i++) {
if (glm::distance(ballCollection.at(i).ballPos, ballPos) <= (2 * radius)) {
if (!glm::distance(ballCollection.at(i).ballPos, ballPos) == 0) {
extern GLfloat forceAmount;
if (isColliding == 0) {
glm::vec3 collPoint = glm::vec3((ballPos.x + ballCollection.at(i).ballPos.x) / 2, 0.0f, (ballPos.z + ballCollection.at(i).ballPos.z) / 2);
glm::vec3 collPointPerp = collPoint - ballPos;
glm::vec3 otherNew = collPointPerp;
glm::vec3 thisNew = glm::cross(collPointPerp, glm::vec3(0.0, 1.0, 0.0));
F = thisNew;
ballCollection.at(i).F = otherNew;
glm::vec3 newV;
glm::vec3 otherNewV;
newV.x = (v.x * (2 * ballCollection.at(i).radius * ballCollection.at(i).v.x)) / (radius + ballCollection.at(i).radius);
newV.z = (v.z * (2 * ballCollection.at(i).radius * ballCollection.at(i).v.z)) / (radius + ballCollection.at(i).radius);
newV.y = 0.0f;
otherNewV.x = (ballCollection.at(i).v.x * (2 * radius * v.x)) / (radius + ballCollection.at(i).radius);
otherNewV.z = (ballCollection.at(i).v.z * (2 * radius * v.z)) / (radius + ballCollection.at(i).radius);
otherNewV.y = 0.0f;
v.x = newV.x;
v.z = newV.z;
ballCollection.at(i).v.x = otherNewV.x;
ballCollection.at(i).v.z = otherNewV.z;
}
isColliding = 1;
ballCollection.at(i).isColliding = 1;
}
}
}
isColliding = 0;
This calss is in a separate file, in my main cpp. This has a key_kallback function:
void do_movement()
{
glm::vec3 cameraRight = glm::normalize(glm::cross(cameraFront, cameraUp));
GLfloat cameraSpeed = 50.0f;
glm::vec3 aboveBall = glm::vec3(ballCollection.at(15).ballPos.x, ballCollection.at(15).ballPos.y + 20.0f, ballCollection.at(15).ballPos.z);
glm::vec3 cameraFwd = aboveBall - cameraPos;
//cout << cameraFwd.x << "," << cameraFwd.y << "," << cameraFwd.z << endl;
if (keys[GLFW_KEY_W])
ballCollection.at(15).ballPos = ballCollection.at(15).ballPos + glm::vec3(0.0f, 0.0f, -0.1f);
if (keys[GLFW_KEY_S])
ballCollection.at(15).ballPos = ballCollection.at(15).ballPos + glm::vec3(0.0f, 0.0f, 0.1f);
if (keys[GLFW_KEY_A])
ballCollection.at(15).ballPos = ballCollection.at(15).ballPos + glm::vec3(-0.1f, 0.0f, 0.0f);
if (keys[GLFW_KEY_D])
ballCollection.at(15).ballPos = ballCollection.at(15).ballPos + glm::vec3(0.1f, 0.0f, 0.0f);
if (keys[GLFW_KEY_SPACE]) {
ballCollection.at(15).F = 10.0f*glm::normalize(cameraFwd);
}
if (keys[GLFW_KEY_E]) {
ballCollection.at(15).F = -10.0f * glm::normalize(cameraFwd);
}
}
And then within the game loop:
for (int i = 0; i < 16; i++) {
ballCollection.at(i).drawBall(ourShader);
}
cameraPos = ballCollection.at(15).ballPos + glm::vec3(0.0f, 20.0f, 20.0f);
do_movement();
My problem is that when I apply the force to the cue ball with space, since the F value keeps adding to v, my cue ball speed increases every frame. If I put F back to 0 after applying the force, I can't pass force to other balls, therefore their v is 0 and they don't move after collision.
Any help would be very appreciated, please comment if I there is extra information needed.
EDIT
I realized that I had an error in the collision calculation, it should be:
newV.x = (v.x + (2 * ballCollection.at(i).radius * ballCollection.at(i).v.x)) / (radius + ballCollection.at(i).radius);
newV.z = (v.z + (2 * ballCollection.at(i).radius * ballCollection.at(i).v.z)) / (radius + ballCollection.at(i).radius);
newV.y = 0.0f;
otherNewV.x = (ballCollection.at(i).v.x + (2 * radius * v.x)) / (radius + ballCollection.at(i).radius);
otherNewV.z = (ballCollection.at(i).v.z + (2 * radius * v.z)) / (radius + ballCollection.at(i).radius);
otherNewV.y = 0.0f;
Now, if I make F back to zero in the class after calculations, the ball moves with constant velocity which is fine for now. My issue now is that sometimes the collision works, sometimes the balls fly away, sometimes hitting the first ball is fine but if the second ball hits another one then its wrong again. I think this happens because they keep colliding and calculating their speed wrong, but I can't figure out how to set up a boolean to collide only once, anyone have any idea?
EDIT
I managed to set up the boolean correctly now.
On collision, the force that should be applied to the other ball is the magnitude of the velocity vector. So if you pass in sqrt(v.x*v.x+v.y*v.y+v.z*v.z) as the initial force of the collision and set F to zero after applying the force like you stated, you should get the results you desire.

Rotating a Open GL camera correctly using GLM

I have a camera class, which is initialized like so:
CameraFP::CameraFP() {
this->aspect_ratio = 800.0f / 600.0f;
this->fov = 45.0f;
this->near_plane = 0.1f;
this->far_plane = 1000.0f;
this->position = glm::vec3(0, 0, 0);
this->target = position + glm::vec3(0, 0, -1);
this->up = glm::vec3(0, 1, 0);
this->m_rotation = glm::mat4(1.0);
m_view = glm::lookAt(position, target, up);
m_projection = glm::perspective(fov, aspect_ratio, near_plane, far_plane);
}
And here are other functions of import:
void CameraFP::update(sf::Window *app) {
process_keyboard(app);
process_mouse(app);
calculate_view();
}
void CameraFP::process_keyboard(sf::Window *app) {
const sf::Input *input = &app->GetInput();
up = m_rotation * glm::vec3(0, 1, 0);
glm::vec3 forward = glm::vec3(0, 0, -1);
glm::vec3 forward_rotated = m_rotation * forward;
glm::vec3 right = glm::vec3(1, 0, 0);
glm::vec3 right_rotated = m_rotation * right;
if (input->IsKeyDown(sf::Key::W)) {
position += forward_rotated;
}
if (input->IsKeyDown(sf::Key::S)) {
position -= forward_rotated;
}
if (input->IsKeyDown(sf::Key::A)) {
position -= right_rotated;
}
if (input->IsKeyDown(sf::Key::D)) {
position += right_rotated;
}
}
void CameraFP::process_mouse(sf::Window *app) {
// TODO: Make the below constants, and take framerate into account
GLfloat SPEED_X = 0.000001f;
GLfloat SPEED_Y = 0.000001f;
GLfloat mouse_x = app->GetInput().GetMouseX();
GLfloat mouse_y = app->GetInput().GetMouseY();
GLfloat mouse_x_delta = old_mouse_x - mouse_x;
GLfloat mouse_y_delta = old_mouse_y - mouse_y;
if (mouse_x_delta != 0 ||
mouse_y_delta != 0) {
if (mouse_x_delta != 0) {
y_rot += mouse_x_delta * SPEED_X;
m_rotation = glm::rotate(m_rotation, y_rot, glm::vec3(0, 1, 0));
}
if (mouse_y_delta != 0) {
x_rot += mouse_y_delta * SPEED_Y;
m_rotation = glm::rotate(m_rotation, x_rot, glm::vec3(1, 0, 0));;
}
}
this->old_mouse_x = mouse_x;
this->old_mouse_y = mouse_y;
app->SetCursorPosition(app->GetWidth() / 2, app->GetHeight() / 2);
}
void CameraFP::calculate_view() {
glm::vec3 forward = glm::vec3(0, 0, -1);
glm::vec3 forward_rotated = m_rotation * forward;
target = position += glm::normalize(forward_rotated);
m_view = glm::lookAt(position, target, up);
}
My problem is that when I compile the project, the compiler outputs an error saying:
\CameraFP.cpp|59|error: no match for 'operator*' in '((CameraFP*)this)->CameraFP::m_rotation * glm::detail::tvec3<float>(((const int&)((const int*)(&0))), ((const int&)((const int*)(&1))), ((const int&)((const int*)(&0))))'|
From what I understand vec = mat4 * vec should yield a rotated vector? Since I haven't been able to test this code, I don't know if the function work correctly.
Edit
Updated code according to the comments and awnsers. My problem is now that I get a BSOD, somewhere in the render function...
void CameraFP::process_keyboard(sf::Window *app) {
const sf::Input *input = &app->GetInput();
up = m_rotation * glm::vec4(0.0f, 1.0f, 0.0f, 0.0f);
glm::vec4 forward = glm::vec4(0.0f, 0.0f, -1.0f, 0.0f);
glm::vec4 forward_rotated = m_rotation * forward;
glm::vec4 right = glm::vec4(1.0f, 0.0f, 0.0f, 0.0f);
glm::vec4 right_rotated = m_rotation * right;
if (input->IsKeyDown(sf::Key::W)) {
position += forward_rotated;
}
if (input->IsKeyDown(sf::Key::S)) {
position -= forward_rotated;
}
if (input->IsKeyDown(sf::Key::A)) {
position -= right_rotated;
}
if (input->IsKeyDown(sf::Key::D)) {
position += right_rotated;
}
}
void CameraFP::process_mouse(sf::Window *app) {
// TODO: Make the below constants, and take framerate into account
GLfloat SPEED_X = 0.000001f;
GLfloat SPEED_Y = 0.000001f;
GLfloat mouse_x = app->GetInput().GetMouseX();
GLfloat mouse_y = app->GetInput().GetMouseY();
GLfloat mouse_x_delta = old_mouse_x - mouse_x;
GLfloat mouse_y_delta = old_mouse_y - mouse_y;
if (mouse_x_delta != 0 ||
mouse_y_delta != 0) {
if (mouse_x_delta != 0) {
y_rot += mouse_x_delta * SPEED_X;
m_rotation = glm::rotate(m_rotation, y_rot, glm::vec3(0.0f, 1.0f, 0.0f));
}
if (mouse_y_delta != 0) {
x_rot += mouse_y_delta * SPEED_Y;
m_rotation = glm::rotate(m_rotation, x_rot, glm::vec3(1.0f, 0.0f, 0.0f));;
}
}
this->old_mouse_x = mouse_x;
this->old_mouse_y = mouse_y;
app->SetCursorPosition(app->GetWidth() / 2, app->GetHeight() / 2);
}
void CameraFP::calculate_view() {
glm::vec4 forward = glm::vec4(0.0f, 0.0f, -1.0f, 0.0f);
glm::vec4 forward_rotated = m_rotation * forward;
target = position += forward_rotated;
m_view = glm::lookAt(v4tov3(position), v4tov3(target), v4tov3(up));
}
glm::vec3 v4tov3(glm::vec4 v1) {
return glm::vec3(v1.x, v1.y, v1.z);
}
Edit 2
Problem now is with the camera rotation with the mouse, it just doesn't work, for some reason changes on the x axis oft times effect change on the y and vice versa. In addition, if I move the mouse right or left on the x axis (y rotation) the camera rotates left...
void CameraFP::process_mouse(sf::Clock *clock, sf::Window *app) {
// TODO: Make the below constants, and take framerate into account
GLfloat SPEED_X = 0.25f;
GLfloat SPEED_Y = 0.25f;
GLfloat screen_x = app->GetWidth();
GLfloat screen_y = app->GetHeight();
GLfloat mouse_x = float(screen_x / 2 - app->GetInput().GetMouseX());
GLfloat mouse_y = float(screen_y / 2 - app->GetInput().GetMouseY());
GLfloat mouse_x_delta = old_mouse_x - mouse_x;
GLfloat mouse_y_delta = old_mouse_y - mouse_y;
GLfloat current_time = clock->GetElapsedTime();
GLfloat delta_time = current_time - last_time;
this->last_time = current_time;
if (mouse_x_delta != 0 ||
mouse_y_delta != 0) {
if (mouse_x_delta != 0) {
y_rot += glm::radians(delta_time * SPEED_X * mouse_x);
m_rotation = glm::rotate(m_rotation, y_rot, glm::vec3(0.0f, 1.0f, 0.0f));
std::cout << "Y Rotation: " << y_rot << "\n";
}
if (mouse_y_delta != 0) {
x_rot += glm::radians(delta_time * SPEED_Y * mouse_y);
m_rotation = glm::rotate(m_rotation, x_rot, glm::vec3(1.0f, 0.0f, 0.0f));
std::cout << "X rotation: " << x_rot << "\n";
}
}
app->SetCursorPosition(screen_x / 2, screen_y / 2);
this->old_mouse_x = float(screen_x / 2 - app->GetInput().GetMouseX());
this->old_mouse_y = float(screen_y / 2 - app->GetInput().GetMouseY());
}
Replace all glm::vec3(0, 1, 0); by glm::vec3(0.0f, 1.0f, 0.0f);
As for the vec-mac multiplication, AquilaRapax is right in that you can only multiply a mat4 with a vec4. But since you're multiplying directions, the 4rth coordinate should be 0.0f, not 1.0f. This will have the effect to ignore the translations (1.0 will teke them into account, which you don't want)
See http://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/ for details on matrices.
However, it's often a good idea to keep vec3 instead of vec4's, mostly for clarity purposes (i.e., glm::vec3 mPosition instead of glm::vec4 mPosition). It is thus handy to have 2 functions like these (untested) :
glm::vec3 TransformDirection(glm::vec3 pDirection, glm::mat4 pMatrix){
return pMatrix * glm::vec4(pDirection, 0.0f);
}
glm::vec3 TransformPosition(glm::vec3 pDirection, glm::mat4 pMatrix){
return pMatrix * glm::vec4(pDirection, 1.0f);
}
At the end of process::mouse you save the coordinates in old_mouse_x and old_mouse_y but then you move the cursor to the middle of the screen. If you do this old_mouse_x and old_mouse_y becomes invalid. What you need to do is set these variables after repositioning the cursor:
app->SetCursorPosition(app->GetWidth() / 2, app->GetHeight() / 2);
this->old_mouse_x = app->GetWidth() / 2;
this->old_mouse_y = app->GetHeight() / 2;