3
\$\begingroup\$

I'm trying to implement a Camera class in order to walk and look on the world as follow:

#ifndef _CAMERA_H_
#define _CAMERA_H_

#include <glm\glm.hpp>

class Camera
{
public:
    Camera();
    ~Camera();

    void Update(const glm::vec2& newXY);
    //if by = 0.0 it means, it will use the const Class speed to scale it
    void MoveForward(const float by = 0.0f);
    void MoveBackword(const float by = 0.0f);
    void MoveLef(const float by = 0.0f);
    void MoveRight(const float by = 0.0f);
    void MoveUp(const float by = 0.0f);
    void MoveDown(const float by = 0.0f);
    void Speed(const float speed = 0.0f);

    glm::vec3& GetCurrentPosition();
    glm::vec3& GetCurrentDirection();
    glm::mat4 GetWorldToView() const;
private:
    glm::vec3 position, viewDirection, strafeDir;
    glm::vec2 oldYX;

    float speed;
    const glm::vec3 up;
};

#endif

#include "Camera.h"
#include <glm\gtx\transform.hpp>

Camera::Camera()
    :up(0.0f, 1.0f, 0.0), viewDirection(0.0f, 0.0f, -1.0f),
    speed(0.1f)
{
}


Camera::~Camera()
{
}


void Camera::Update(const glm::vec2& newXY)
{
    glm::vec2 delta = newXY - oldYX;
    auto length = glm::length(delta);
    if (glm::length(delta) < 50.f)
    {
        strafeDir = glm::cross(viewDirection, up);
        glm::mat4 rotation = glm::rotate(-delta.x * speed, up) *
            glm::rotate(-delta.y * speed, strafeDir);

        viewDirection = glm::mat3(rotation) * viewDirection;
    }

    oldYX = newXY;
}

void Camera::Speed(const float speed)
{
    this->speed = speed;
}

void Camera::MoveForward(const float by)
{
    float s = by == 0.0f ? speed : by;

    position += s * viewDirection;
}
void Camera::MoveBackword(const float by)
{
    float s = by == 0.0f ? speed : by;

    position += -s * viewDirection;
}
void Camera::MoveLef(const float by )
{
    float s = by == 0.0f ? speed : by;
    position += -s * strafeDir;
}
void Camera::MoveRight(const float by )
{
    float s = by == 0.0f ? speed : by;
    position += -s * strafeDir;
}
void Camera::MoveUp(const float by )
{
    float s = by == 0.0f ? speed : by;
    position += s * up;
}
void Camera::MoveDown(const float by )
{
    float s = by == 0.0f ? speed : by;
    position += -s * up;
}

glm::vec3& Camera::GetCurrentPosition()
{
    return position;
}
glm::vec3& Camera::GetCurrentDirection()
{
    return viewDirection;
}

glm::mat4 Camera::GetWorldToView() const
{
    return glm::lookAt(position, position + viewDirection, up);
}

and I update and render as follow :

void Game::OnUpdate()
{
    glLoadIdentity();
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


    glUniformMatrix4fv(program->GetUniformLocation("modelToViewWorld"), 1, GL_FALSE, &cam.GetWorldToView()[0][0]);

}

void Game::OnRender()
{

    model->Draw();

}

Which the Vertix shader is:

#version 410

layout (location = 0) in vec3 inVertex;
layout (location = 1) in vec2 inTexture;
layout (location = 2) in vec3 inNormal;

uniform mat4 modelToViewWorld;


void main()
{
        gl_Position    = vec4(mat3(modelToViewWorld) * inVertex, 1);

}

But in result the model itslef is moving/rotating instead of moving the camera around the model. What am I doing wrong here?

\$\endgroup\$
  • 1
    \$\begingroup\$ "but what is happening is am moving/rotating the Model it's self not the camera around it . what am doing wrong here?" Do you mean that everything moves the reverse of what you intend? If so, you could reverse all your CamereMoveXxx() actions. Or invert the matrix (either before applying the uniform, or in the vertex shader). \$\endgroup\$ – david van brink Dec 28 '14 at 1:11
  • 1
    \$\begingroup\$ Unrelated suggestion: you can combine things like MoveForward and MoveBackward by using the convention of a positive amount being forward and a negative amount being backward. You can then combine all six axis functions into a single one that takes a vec3 of some kind, which is more generic and easier to compose with movement controller logic. \$\endgroup\$ – Sean Middleditch Jan 28 '15 at 23:59
2
\$\begingroup\$

Depending on the way your matrix type stores its values you may have to transpose the matrix to get the transformation right. You can use the boolean parameter of glUniformMatrix4fv(); to do that.

And the way you're applying the transformation in the vertex shader is omitting the translation part. Use it this way:

gl_Position = modelToViewWorld * vec4(inVertex, 1);
| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.