Camera not rotation

Hello!

I’m following the tutorial at learnopengl.com but I can’t get my camera to rotate. I did it slightly differenly to the tutorial so I’ll drop the code here.
The pitch goes up like crazy here’s the yaw and pitch values outputted from the console -90, 6.94683e+06. The meshes also dissapper whenever moving my mouse more then 10cm and then they come back when I move it back. I also can’t translate the camera because it dissapers there as well. I have to be very close to the exact middle. Why?

Main

#define GLEW_STATIC
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <memory>

#include <SOIL/SOIL.h>

#define GLM_FORCE_RADIANS
#include <GL/glew.h>
#include <SDL2/SDL.h>

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

bool keys[1024];
GLfloat deltaTime = 0.0f;
GLfloat lastFrame = 0.0f;
GLfloat lastX = 400;
GLfloat lastY = 300;
GLfloat pitch = 0, yaw = -90.0f;
bool firstMouse = true;
#include "../include/OGRenderer.h"
#include "../include/mesh.h"
#include "../include/Camera.h"

//Add the include var
#define PROGRAMNAME "OPENGL!!!!"

std::string readFile(std::string path){
    std::string content;
    std::ifstream fileStream(path, std::ios::in);
    if(!fileStream.is_open()){
        std::cout << "Shader failed to open
";
        return "";
    }
    std::string line;
    while(!fileStream.eof()){
        std::getline(fileStream, line);
        content.append(line + "
");
    }
    fileStream.close();
    return content;
}


void loadImage(const char* path, GLint curTex, GLuint textureArray[]){
    int width, height;
    glBindTexture(GL_TEXTURE_2D, textureArray[curTex]);
    unsigned char* image = SOIL_load_image(path, &width, &height, 0, SOIL_LOAD_RGB);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
    glGenerateMipmap(GL_TEXTURE_2D);
    SOIL_free_image_data(image);
}

void doMovement(Camera &camera);
bool handleInput(SDL_Event &windowEvent, Camera &camera);
GLuint createShaders(std::string vertexShaderPath, std::string fragmentShaderPath);
void setupShaderVariables(GLint shaderProgram);

int main() {

    int screenHeight = 512, screenWidht = 512;
    OGRenderer render(3,0,1,24);
    glewExperimental = GL_TRUE;
    glewInit();

    /*std::vector<GLfloat> vertices = {
    //  Position      Color             Texcoords
    -0.5f,  0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // Top-left
     0.5f,  0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // Top-right
     0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // Bottom-right
    -0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f  // Bottom-left
    };*/

    //SDL_SetRelativeMouseMode(SDL_TRUE);
    glEnable(GL_DEPTH_TEST);

    std::vector<GLfloat> vertices = {
    //  Position        Texcoords
    -1.0f,  1.0f, 0.5f, 0.0f, 0.0f, // Top-left
     0.0f,  1.0f, 0.5f, 1.0f, 0.0f, // Top-right
     0.0f, -0.0f, 0.5f, 1.0f, 1.0f, // Bottom-right
    -1.0f, -0.0f, 0.5f, 0.0f, 1.0f,  // Bottom-left

    -1.0f,  1.0f, -0.5f, 1.0f, 0.0f, // Top-left
     0.0f,  1.0f, -0.5f, 0.0f, 0.0f, // Top-right
     0.0f, -0.0f, -0.5f, 0.0f, 1.0f, // Bottom-right
    -1.0f, -0.0f, -0.5f, 1.0f, 1.0f  // Bottom-left

    };

    std::vector<GLuint> elements = {
        0, 1, 2, //Front
        2, 3, 0, //Front
        2, 3, 7, //Bottom
        2, 7, 6, //Bottom
        0, 3, 4, //Left
        3, 4, 7, //Left
        4, 7, 5, //Back
        5, 7, 6, //Back
        1, 5, 6, //Right
        1, 2, 6, //Right
        0, 1, 4, //Top
        1, 4, 5//Top
    };

    std::vector<glm::vec3> cubePositions = {
        glm::vec3( 0.0f,  0.0f,  0.0f),
        glm::vec3( 2.0f,  5.0f, -15.0f),
        glm::vec3(-1.5f, -2.2f, -2.5f),
        glm::vec3(-3.8f, -2.0f, -12.3f),
        glm::vec3( 2.4f, -0.4f, -3.5f),
        glm::vec3(-1.7f,  3.0f, -7.5f),
        glm::vec3( 1.3f, -2.0f, -2.5f),
        glm::vec3( 1.5f,  2.0f, -2.5f),
        glm::vec3( 1.5f,  0.2f, -1.5f),
        glm::vec3(-1.3f,  1.0f, -1.5f)
    };


    //Load shaders
    GLuint shaderProgram = createShaders("vertexShader.glsl", "fragmentShader.glsl");
    //Shaders have been loaded


    std::vector<std::shared_ptr<mesh>> cubes;

    for(GLuint i = 0; i < 10; i++){
        std::shared_ptr<mesh> newMesh = std::make_shared<mesh>();
        newMesh->initMesh(vertices, elements, shaderProgram);
        newMesh->Translate(cubePositions[i]);
        newMesh->Rotate(glm::vec3(1.0f, 0.3f, 0.5f), 300.0f * i);
        cubes.push_back(newMesh);
    }
    //For stroing textures
    GLuint textures[2];
    glGenTextures(2, textures);
    glActiveTexture(GL_TEXTURE0);
    loadImage("CAT.jpg", 0, textures);
    glUniform1i(glGetUniformLocation(shaderProgram, "tex"), 0);
    glActiveTexture(GL_TEXTURE1);
    loadImage("TW.png", 1, textures);
    glUniform1i(glGetUniformLocation(shaderProgram, "tex2"), 1);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    std::cout << glGetString(GL_VERSION) << std::endl;

    Camera camera(glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, -1.0f));


    GLint time = glGetUniformLocation(shaderProgram, "time");
    SDL_Event windowEvent;
    bool quit = false;
    while(!quit){
        GLfloat currentFrame = SDL_GetTicks();
        deltaTime = currentFrame - lastFrame;
        lastFrame = currentFrame;

        quit = handleInput(windowEvent, camera);
        doMovement(camera);

        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glUniform1f(time, (float)clock() / (float)CLOCKS_PER_SEC);

        glm::mat4 trans;
        glm::mat4 view;
        glm::mat4 projection;
        float radius = 10.0f;
        //camera.Translate(glm::vec3(glm::sin(((float)clock() / (float)CLOCKS_PER_SEC) * 9.0f) * radius, 0.0f, glm::cos(((float)clock() / (float)CLOCKS_PER_SEC) * 9.0f) * radius));
        view  = camera.getViewVector();
        projection = glm::perspective(45.0f, (GLfloat)screenWidht / (GLfloat)screenHeight, 0.1f, 100.0f);


        glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "view"), 1, GL_FALSE, glm::value_ptr(view));
        glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "projection"), 1, GL_FALSE, glm::value_ptr(projection));

        for(GLuint i = 0; i < 10; i++){
            cubes[i]->render();
        }

        render.update();
    }
    glDeleteTextures(2, textures);

    glDeleteProgram(shaderProgram);
    return 0;
}

GLuint createShaders(std::string vertexShaderPath, std::string fragmentShaderPath){
    //Load the shader sources
    std::string vertexSource = readFile(vertexShaderPath);
    std::string fragmentSource = readFile(fragmentShaderPath);
    //Convert them to a c-style string
    const char *vertShaderSrc = vertexSource.c_str();
    const char *fragShaderSrc = fragmentSource.c_str();

    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertShaderSrc, NULL);
    glCompileShader(vertexShader);

    //Check so the shader was compiled succesfully
    GLint status;
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &status);
    char buffer[512];
    glGetShaderInfoLog(vertexShader, 512, NULL, buffer);
    std::cout << buffer << std::endl;
    if(status != true){
        std::cout << "The vertexShader was not compiled succesfully
";
        exit(-1);
    }
    //Check so the shader was compiled succesfully

    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragShaderSrc, NULL);
    glCompileShader(fragmentShader);


    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &status);
    glGetShaderInfoLog(fragmentShader, 512, NULL, buffer);
    std::cout << buffer << std::endl;
    if(status != true){
        std::cout << "The fragmentShader was not compiled succesfully
";
        exit(-1);
    }

    GLuint shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);
    glUseProgram(shaderProgram);

    glDeleteShader(fragmentShader);
    glDeleteShader(vertexShader);

    return shaderProgram;
}


bool handleInput(SDL_Event &windowEvent, Camera &camera){
    while(SDL_PollEvent(&windowEvent)){
        if(windowEvent.type == SDL_QUIT || (windowEvent.type == SDL_KEYUP && windowEvent.key.keysym.sym == SDLK_ESCAPE)){
            return true;
            break;
        }
        switch(windowEvent.type){
            case SDL_KEYDOWN:
                //std::cout << windowEvent.key.keysym.sym <<std::endl;
                keys[windowEvent.key.keysym.sym] = true;
                break;
            case SDL_KEYUP:
                keys[windowEvent.key.keysym.sym] = false;
                break;
            default:
                break;
        }
        if(firstMouse){
            lastX = windowEvent.motion.x;
            lastY = windowEvent.motion.y;
            firstMouse = false;
        }
        //std::cout << lastX << ", " << lastY << std::endl;
        camera.processMouseMovement(windowEvent.motion.xrel, windowEvent.motion.yrel);
    }
    return false;
}

void doMovement(Camera &camera){
    GLfloat cameraSpeed = 0.005f * deltaTime;
    if(keys[SDLK_w]){
        camera.Translate(glm::vec3(0.0f, 0.0f, -1.0f) * cameraSpeed);
    }
    if(keys[SDLK_s]){
        camera.Translate(glm::vec3(0.0f, 0.0f, 1.0f) * cameraSpeed);
    }
    if(keys[SDLK_a]){
        camera.Translate(glm::vec3(-1.0f, 0.0f, 0.0f) * cameraSpeed);
    }
    if(keys[SDLK_d]){
        camera.Translate(glm::vec3(1.0f, 0.0f, 0.0f) * cameraSpeed);
    }
   /* if(keys[SDLK_LSHIFT]){
        camera.Translate(glm::vec3(0.0f, 1.0f, 0.0f) * cameraSpeed);
    }
    if(keys[SDLK_SPACE]){
        camera.Translate(glm::vec3(0.0f, -1.0f, 0.0f) * cameraSpeed);
    }*/
}

Camera:

.cpp

#include "Camera.h"

Camera::Camera(glm::vec3 cameraPos, glm::vec3 cameraFront, glm::vec3 worldUp, GLfloat sensitivity, GLfloat yaw, GLfloat pitch)
{
    this->sensitivity = sensitivity;
    this->yaw = yaw;
    this->pitch = pitch;
    this->cameraPos = cameraPos;
    //this-> cameraFront = cameraFront;
    this->worldUp = worldUp;

    updateCameraViewVector();
    //ctor
}

Camera::~Camera()
{
    //dtor
}

glm::mat4x4 Camera::getViewVector(){
    return view;
}

void Camera::Translate(glm::vec3 addVector){
    cameraPos += addVector;
    updateCameraViewVector();
}

void Camera::Rotate(glm::vec3 rotVector){
    cameraFront = glm::normalize(rotVector);
    //std::cout << cameraFront.x << ", " << cameraFront.y << ", " << cameraFront.z << std::endl;
    updateCameraViewVector();
}

void Camera::processMouseMovement(GLfloat xoffset, GLfloat yoffset, GLboolean constrainPitch){
    xoffset *= sensitivity;
    yoffset *= sensitivity;

    yaw += xoffset;
    pitch += yoffset;
    std::cout << yaw << ", " << pitch << std::endl;
    updateCameraViewVector();
}
void Camera::updateCameraViewVector(){
    glm::vec3 front;

    front.x = glm::cos(glm::radians(yaw)) * glm::cos(glm::radians(pitch));
    front.y = glm::sin(glm::radians(pitch));
    front.z = glm::sin(glm::radians(yaw)) * glm::radians(glm::radians(pitch));

    cameraFront = glm::normalize(front);
    cameraRight = glm::normalize(glm::cross(cameraFront, worldUp));
    cameraUp = glm::normalize(glm::cross(cameraRight, cameraFront));
    //std::cout << cameraFront.x << ", " << cameraFront.y << ", " << cameraFront.z << std::endl;
    view = glm::lookAt(cameraPos, cameraPos + cameraFront, cameraUp);

}

.h

#ifndef CAMERA_H
#define CAMERA_H

#include <iostream>

#include <SDL2/SDL.h>
#include <GL/glew.h>

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

class Camera
{
    public:
        Camera(glm::vec3 cameraPos = glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3 cameraFront = glm::vec3(0.0f, 0.0f, -1.0f), glm::vec3 worldUp = glm::vec3(0.0f, 1.0f, 0.0f), GLfloat sensitivity = 0.5f, GLfloat yaw = -90.0f, GLfloat pitch = 0.0f);
        ~Camera();
        glm::mat4x4 getViewVector();
        void Translate(glm::vec3 addVector);
        void Rotate(glm::vec3 rotVector);
        void processMouseMovement(GLfloat xoffset, GLfloat yoffset, GLboolean constrainPitch = true);
    protected:
    private:
        GLfloat pitch;
        GLfloat yaw;
        GLfloat sensitivity;

        glm::vec3 cameraPos;
        glm::vec3 cameraFront;
        glm::vec3 cameraUp;
        glm::vec3 cameraRight;
        glm::vec3 worldUp;

        glm::vec3 up;
        glm::mat4x4 view;
        glm::mat4x4 transform;

        void updateCameraViewVector();

};

#endif // CAMERA_H

I have no idea what could be causing this, so thank you for your help! :slight_smile:

EDIT: just saw my title is all wrong xD.
Sorry about that :confused:

Hi,

in my projects, I don’t use glm::lookAt anymore, instead I rotate the view matrix around the x- and y-axis:


void Camera::processMouseMovement(GLfloat xoffset, GLfloat yoffset, GLboolean constrainPitch)
{
	yaw   -= sensitivity * xoffset;
	pitch -= sensitivity * yoffset;
	if(yaw < 0.0f)
		yaw += 360.0f;
	else if(yaw > 360.0f)
		yaw -= 360.0f;
	if(pitch > 90.0f)
		pitch = 90.0f;
	else if(pitch < -90.0f)
		pitch = -90.0f;
	updateCameraViewVector();
}

void Camera::updateCameraViewVector()		//shouldn't it be called "updateCameraViewMatrix()"? (it updates the glm::mat4 view)
{
	view = glm::mat4(1.0f);
	view = glm::rotate(view, (float)-(pitch*(M_PI/180.0)), glm::vec3(1, 0, 0));
	view = glm::rotate(view, (float)-(yaw*(M_PI/180.0)),   glm::vec3(0, 1, 0));
	view = glm::translate(view, -cameraPos);
}

I hope, this helps :slight_smile:

I have a question which is why you convert the pitch and yaw into radian because i thought glm uses degrees as argument? and does this method remain smooth transition when the user rotates mouse very quickly?

I am quite used to radians, so I defined GLM_FORCE_RADIANS at the beginning of my code, but of course you don’t have to use it (just delete the (M_PI/180.0)'s). And it should remain smooth when you have enough frames per second in your main program (in my programs, where I use this code, the camera works quite well).