2017-07-31 23 views
2

我正在尝试将2个程序集成在一起。如何让我的OpenGL相机向下指向?

  • 一种具有行星系统(具有移动立方体)
  • 另一个具有用于移动摄像机的代码。它也可以摇动

我已经设法将它们放在一起。行星系统的视图可以被切换为显示

  • 透视图(“1”时被按下)
  • 顶视图(“2”时被按下)

我有我的顶视图出现问题(按2时)。它不是指向地球系统。它位于行星的正上方,但不向下看。我想将摄像机向下指向,使其看起来像这样 Top-view of planet system 我没有成功玩这部分代码(下面)让摄像机看不起来。更具体地说,在g_camera.setViewMatrix函数中的坐标。

// render from top view 
    else if (key == GLFW_KEY_2 && action == GLFW_PRESS) { 
     cout << "Top-View" << endl << endl; 
     // set camera's view matrix 
     g_camera.setViewMatrix(glm::vec3(0, 15, 0), glm::vec3(0, 0, 0), glm::vec3(1, 0, 0)); 
     //g_viewMatrix = glm::lookAt(glm::vec3(0, 15, 0), glm::vec3(0, 0, 0), glm::vec3(1, 0, 0)); 
     render_scene(); 
    } 

在集成摄像头代码之前,我使用了这个功能。

g_viewMatrix = glm::lookAt(glm::vec3(0, 15, 0), glm::vec3(0, 0, 0), glm::vec3(1, 0, 0)); 

然而,当我插上这些相同的载体为g_camera.setViewMatrix功能,它没有指向同一方向。

另一个问题,我有:

红色椭圆形实际上是一个圆。我如何让它看起来像一个圆圈而不是椭圆形?我整合了另一个程序的圈子的代码。在那个节目中,这是一个完美的圆圈。

这里是我的代码

#include <cstdio>  // for C++ i/o 
#include <iostream> 
#include <string> 
#include <cstddef> 
using namespace std; // to avoid having to use std:: 

#define GLEW_STATIC  // include GLEW as a static library 
#include <GLEW/glew.h> // include GLEW 
#include <GLFW/glfw3.h> // include GLFW (which includes the OpenGL header) 
#include <glm/glm.hpp> // include GLM (ideally should only use the GLM headers that are actually used) 
#include <glm/gtx/transform.hpp> 
using namespace glm; // to avoid having to use glm:: 

#include "shader.h" 
#include "camera.h" 

#define PI 3.14159265 
#define MAX_SLICES 50 
#define MIN_SLICES 8 
#define MAX_VERTICES (MAX_SLICES+2)*3 // a triangle fan should have a minimum of 3 vertices 
#define CIRCLE_RADIUS 3.0 
#define WINDOW_WIDTH 1500 
#define WINDOW_HEIGHT 800 

// struct for vertex attributes 
struct Vertex 
{ 
    GLfloat position[3]; 
    GLfloat color[3]; 
}; 

// global variables 

GLfloat g_vertices_circle[MAX_VERTICES] = { 
    0.0f, 0.0f, 0.0f,  // try adjusting this value to get rid of red line 
    0.0f, 0.0f, 0.0f 
}; 

GLfloat g_colors_circle[MAX_VERTICES] = { 
    1.0f, 0.0f, 0.0f, 
    1.0f, 0.0f, 0.0f 
}; 

GLuint g_slices = MAX_SLICES; // number of circle slices 

Vertex g_vertices[] = { 
    // vertex 1 
    -0.5f, 0.5f, 0.5f, // position 
    1.0f, 0.0f, 1.0f, // colour 
    // vertex 2 
    -0.5f, -0.5f, 0.5f, // position 
    1.0f, 0.0f, 0.0f, // colour 
    // vertex 3 
    0.5f, 0.5f, 0.5f, // position 
    1.0f, 1.0f, 1.0f, // colour 
    // vertex 4 
    0.5f, -0.5f, 0.5f, // position 
    1.0f, 1.0f, 0.0f, // colour 
    // vertex 5 
    -0.5f, 0.5f, -0.5f, // position 
    0.0f, 0.0f, 1.0f, // colour 
    // vertex 6 
    -0.5f, -0.5f, -0.5f,// position 
    0.0f, 0.0f, 0.0f, // colour 
    // vertex 7 
    0.5f, 0.5f, -0.5f, // position 
    0.0f, 1.0f, 1.0f, // colour 
    // vertex 8 
    0.5f, -0.5f, -0.5f, // position 
    0.0f, 1.0f, 0.0f, // colour 
}; 

GLuint g_indices[] = { 
    0, 1, 2, // triangle 1 
    2, 1, 3, // triangle 2 
    4, 5, 0, // triangle 3 
    0, 5, 1, // ... 
    2, 3, 6, 
    6, 3, 7, 
    4, 0, 6, 
    6, 0, 2, 
    1, 5, 3, 
    3, 5, 7, 
    5, 4, 7, 
    7, 4, 6, // triangle 12 
}; 

GLuint g_IBO = 0;    // index buffer object identifier 
GLuint g_VBO[3];    // vertex buffer object identifier 
GLuint g_VAO[2];    // vertex array object identifier 
GLuint g_shaderProgramID = 0; // shader program identifier 
GLuint g_MVP_Index = 0;   // location in shader 
glm::mat4 g_modelMatrix[5];  // planets object model matrices 
glm::mat4 g_modelMatrixCircle[5];// circle model matrices 
glm::mat4 g_modelMatrixSubPlanets[5];// object matrices for sub-planets (moon, disc etc) 
glm::mat4 g_viewMatrix;   // view matrix 
glm::mat4 g_projectionMatrix; // projection matrix 

Camera g_camera;   // camera 

float g_orbitSpeed[5] = { 0.3f, 1.0f, 0.7f, 0.9f, 1.2f };  // for speed of rotation around sun 
float g_rotationSpeed[5] = { 0.07f, 0.7f, 3.0f, 5.0f, 1.0f }; // for speed of rotation on own axis 
float g_scaleSize[5] = { 0.5f, 0.5f, 0.5f, 0.5f, 0.5f };  // for scaling the orbiting planets 
float g_axisOfRotation[5] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, }; // for offsetting the axis of rotation 

void generate_circle() 
{ 
    float angle = PI * 2/static_cast<float>(g_slices); // used to generate x and y coordinates 
    float scale_factor = static_cast<float>(WINDOW_HEIGHT)/WINDOW_WIDTH; // scale to make it a circle instead of an elipse 
    int index = 0; // vertex index 

    g_vertices_circle[3] = CIRCLE_RADIUS * scale_factor; // set x coordinate of vertex 1 

                  // generate vertex coordinates for triangle fan 
    for (int i = 2; i < g_slices + 2; i++) 
    { 
     // multiply by 3 because a vertex has x, y, z coordinates 
     index = i * 3; 

     g_vertices_circle[index] = CIRCLE_RADIUS * cos(angle) * scale_factor; 
     g_vertices_circle[index + 1] = CIRCLE_RADIUS * sin(angle); 
     g_vertices_circle[index + 2] = 0.0f; 

     //Color for edges. See stackoverflow 
     g_colors_circle[index] = 1.0f; 
     g_colors_circle[index + 1] = 0.0f; 
     g_colors_circle[index + 2] = 0.0f; 

     // update to next angle 
     angle += PI * 2/static_cast<float>(g_slices); 
    } 

    // Gets rid of line from middle of circle 
    g_vertices_circle[0] = g_vertices_circle[3]; 
    g_vertices_circle[1] = g_vertices_circle[4]; 
    g_vertices_circle[2] = g_vertices_circle[5]; 
} 

static void init(GLFWwindow* window) 
{ 
    glClearColor(0.0, 0.0, 0.0, 1.0); // set clear background colour 

    glEnable(GL_DEPTH_TEST); // enable depth buffer test 

    // create and compile our GLSL program from the shader files 
    g_shaderProgramID = loadShaders("MVP_VS.vert", "ColorFS.frag"); 

    // find the location of shader variables 
    GLuint positionIndex = glGetAttribLocation(g_shaderProgramID, "aPosition"); 
    GLuint colorIndex = glGetAttribLocation(g_shaderProgramID, "aColor"); 
    g_MVP_Index = glGetUniformLocation(g_shaderProgramID, "uModelViewProjectionMatrix"); 

    // initialise model matrix to the identity matrix 
    g_modelMatrix[0] = g_modelMatrix[1] = g_modelMatrix[2] = g_modelMatrix[3] = g_modelMatrix[4] = glm::mat4(1.0f); 
    g_modelMatrixCircle[0] = g_modelMatrixCircle[1] = glm::mat4(1.0f); 
    g_modelMatrixSubPlanets[3] = glm::mat4(1.0f);; 

    // initialise view matrix 
    //g_viewMatrix = glm::lookAt(glm::vec3(10, 3, 8), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0)); //perspective 

    // set camera's view matrix 
    //g_camera.setViewMatrix(glm::vec3(10, 3, 8), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0)); 
    g_camera.setViewMatrix(glm::vec3(0, 3, 14), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0)); 

    int width, height; 
    glfwGetFramebufferSize(window, &width, &height); 
    float aspectRatio = static_cast<float>(width)/height; 

    // set camera's projection matrix 
    g_camera.setProjectionMatrix(glm::perspective(45.0f, aspectRatio, 0.1f, 100.0f)); 

    // initialise projection matrix 
    g_projectionMatrix = glm::perspective(45.0f, aspectRatio, 0.1f, 100.0f); 

    // generate identifier for VBO and copy data to GPU 
    glGenBuffers(1, &g_VBO[0]); 
    glBindBuffer(GL_ARRAY_BUFFER, g_VBO[0]); 
    glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertices), g_vertices, GL_STATIC_DRAW); 

    // generate identifier for IBO and copy data to GPU 
    glGenBuffers(1, &g_IBO); 
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_IBO); 
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(g_indices), g_indices, GL_STATIC_DRAW); 

    // generate identifiers for VAO 
    glGenVertexArrays(1, &g_VAO[0]); 

    // create VAO and specify VBO data 
    glBindVertexArray(g_VAO[0]); 
    glBindBuffer(GL_ARRAY_BUFFER, g_VBO[0]); 
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_IBO); 
    // interleaved attributes 
    glVertexAttribPointer(positionIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, position))); 
    glVertexAttribPointer(colorIndex, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<void*>(offsetof(Vertex, color))); 

    glEnableVertexAttribArray(positionIndex); // enable vertex attributes 
    glEnableVertexAttribArray(colorIndex); 

    /*------------------------Circle----------------------*/ 

    // generate vertices of triangle fan 
    generate_circle(); 

    // create VBO and buffer the data 
    glGenBuffers(1, &g_VBO[1]); 
    glBindBuffer(GL_ARRAY_BUFFER, g_VBO[1]); 
    glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * (g_slices + 2), g_vertices_circle, GL_STATIC_DRAW); 

    glGenBuffers(1, &g_VBO[2]); 
    glBindBuffer(GL_ARRAY_BUFFER, g_VBO[2]); 
    glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * (g_slices + 2), g_colors_circle, GL_STATIC_DRAW); 

    // create VAO and specify VBO data 
    glGenVertexArrays(1, &g_VAO[1]); 
    glBindVertexArray(g_VAO[1]); 
    glBindBuffer(GL_ARRAY_BUFFER, g_VBO[1]); 
    glVertexAttribPointer(positionIndex, 3, GL_FLOAT, GL_FALSE, 0, 0); // specify the form of the data 
    glBindBuffer(GL_ARRAY_BUFFER, g_VBO[2]); 
    glVertexAttribPointer(colorIndex, 3, GL_FLOAT, GL_FALSE, 0, 0); // specify the form of the data 

    /*----------------------------------------------------*/ 

    glEnableVertexAttribArray(positionIndex); // enable vertex attributes 
    glEnableVertexAttribArray(colorIndex); 
} 

//Generates a random value between 0.1 and 0.9 
double generateRandomFloat(float min, float max) 
{ 
    return min + static_cast <float> (rand())/(static_cast <float> (RAND_MAX/(max - min))); 
} 

// function used to update the scene 
static void update_scene() 
{ 
    // static variables for rotation angles 
    static float orbitAngle[5] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, }; 
    static float rotationAngle[5] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; 
    float scaleFactor = 0.05; 

    orbitAngle[0] += g_orbitSpeed[0] * scaleFactor; 
    orbitAngle[1] += g_orbitSpeed[1] * scaleFactor; 
    orbitAngle[2] += g_orbitSpeed[2] * scaleFactor; 
    orbitAngle[3] += g_orbitSpeed[3] * scaleFactor; 
    orbitAngle[4] += g_orbitSpeed[4] * scaleFactor; 

    // update rotation angles 
    rotationAngle[0] += g_rotationSpeed[0] * scaleFactor; 
    rotationAngle[1] += g_rotationSpeed[1] * scaleFactor; 
    rotationAngle[2] += g_rotationSpeed[2] * scaleFactor; 
    rotationAngle[3] += g_rotationSpeed[3] * scaleFactor; 
    rotationAngle[4] += g_rotationSpeed[4] * scaleFactor; 

    // update model matrix (planets) 
    g_modelMatrix[0] = glm::rotate(rotationAngle[0], glm::vec3(0.0f, 1.0f, 0.0f)); 

    g_modelMatrix[1] = glm::translate(glm::vec3(g_axisOfRotation[1], 0.0f, 0.0f)) //moves the axis of rotation along x-axis 
     * glm::rotate(orbitAngle[1], glm::vec3(0.0f, 1.0f, 0.0f)) 
     * glm::translate(glm::vec3(2.0f, 0.0f, 0.0f)) 
     * glm::rotate(rotationAngle[1], glm::vec3(0.0f, -1.0f, 0.0f))  //enables rotation on own axis. try comment 
     * glm::rotate(glm::radians(45.0f), glm::vec3(1.0f, 0.0f, 0.0f))  //rotates into a diamond shape 
     * glm::rotate(glm::radians(45.0f), glm::vec3(0.0f, 0.0f, 1.0f))  //rotates into a diamond shape 
     * glm::scale(glm::vec3(g_scaleSize[1], g_scaleSize[1], g_scaleSize[1])); 

    g_modelMatrix[2] = glm::translate(glm::vec3(g_axisOfRotation[2], 0.0f, 0.0f)) 
     * glm::rotate(orbitAngle[2], glm::vec3(0.0f, -1.0f, 0.0f)) 
     * glm::translate(glm::vec3(4.0f, 0.0f, 0.0f)) 
     * glm::rotate(rotationAngle[2], glm::vec3(0.0f, 1.0f, 0.0f)) 
     * glm::scale(glm::vec3(g_scaleSize[2], g_scaleSize[2], g_scaleSize[2])); 

    g_modelMatrix[3] = glm::translate(glm::vec3(g_axisOfRotation[3], 0.0f, 0.0f)) 
     * glm::rotate(orbitAngle[3], glm::vec3(0.0f, 1.0f, 0.0f)) 
     * glm::translate(glm::vec3(6.0f, 0.0f, 0.0f)) 
     * glm::rotate(rotationAngle[3], glm::vec3(0.0f, 1.0f, 0.0f)) 
     * glm::scale(glm::vec3(g_scaleSize[3], g_scaleSize[3], g_scaleSize[3])); 

    g_modelMatrix[4] = glm::translate(glm::vec3(g_axisOfRotation[4], 0.0f, 0.0f)) 
     * glm::rotate(orbitAngle[4], glm::vec3(0.0f, -1.0f, 0.0f)) // -y changes orbit to clock-wise 
     * glm::translate(glm::vec3(8.0f, 0.0f, 0.0f)) 
     * glm::rotate(rotationAngle[4], glm::vec3(0.0f, -1.0f, 0.0f)) 
     * glm::scale(glm::vec3(g_scaleSize[4], g_scaleSize[4], g_scaleSize[4])); 

    // update model matrix (orbit paths ie.circles) 
    g_modelMatrixCircle[1] = glm::rotate(glm::radians(90.0f), glm::vec3(1.0f, 0.0f, 0.0f)); 

    // update model matrix (mini planets eg. moon) 
    g_modelMatrixSubPlanets[3] = glm::translate(glm::vec3(g_axisOfRotation[3], 0.0f, 0.0f)) 
     * glm::rotate(orbitAngle[3], glm::vec3(0.0f, 1.0f, 0.0f)) 
     * glm::translate(glm::vec3(6.0f, 0.0f, 0.0f)) 
     * glm::rotate(rotationAngle[3], glm::vec3(0.0f, 1.0f, 0.0f)) 
     * glm::scale(glm::vec3(g_scaleSize[3], g_scaleSize[3], g_scaleSize[3])); 
} 

// function used to render the scene 
static void render_scene() 
{ 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear colour buffer and depth buffer 

    glUseProgram(g_shaderProgramID); // use the shaders associated with the shader program 

    glm::mat4 MVP = glm::mat4(1.0f); //ModelViewProjection matrix to be shared. Initialized to identity 

//Circle 1 
    //MVP = g_projectionMatrix * g_viewMatrix * g_modelMatrixCircle[1]; 
    MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrixCircle[1]; 
    //MVP = g_camera.getViewMatrix() * g_modelMatrixCircle[1]; 
    glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]); 
    glBindVertexArray(g_VAO[1]);   // make VAO active 
    glDrawArrays(GL_LINE_LOOP, 0, g_slices + 2); // display the vertices based on the primitive type 

    glBindVertexArray(g_VAO[0]);  // make VAO active 

// Object 1 
    //MVP = g_projectionMatrix * g_viewMatrix * g_modelMatrix[0]; 
    MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix[0]; 
    // set uniform model transformation matrix 
    glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]); 

    glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type 

// Object 2 
    //MVP = g_projectionMatrix * g_viewMatrix * g_modelMatrix[1]; 
    MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix[1]; 
    glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]); 
    glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type 

// Object 3 
    //MVP = g_projectionMatrix * g_viewMatrix * g_modelMatrix[2]; 
    MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix[2]; 
    glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]); 
    glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type 

// Object 4 
    //MVP = g_projectionMatrix * g_viewMatrix * g_modelMatrix[3]; 
    MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix[3]; 
    glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]); 
    glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type 

// Object 5 
    //MVP = g_projectionMatrix * g_viewMatrix * g_modelMatrix[4]; 
    MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix[4]; 
    glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]); 
    glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type 

// Moon for Object 3 
    //MVP = g_projectionMatrix * g_viewMatrix * g_modelMatrixSubPlanets[3] * g_modelMatrix[4]; 
    MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrixSubPlanets[3] * g_modelMatrix[4]; 
    glUniformMatrix4fv(g_MVP_Index, 1, GL_FALSE, &MVP[0][0]); 
    glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); // display the vertices based on their indices and primitive type 

    glFlush(); // flush the pipeline 
} 

static void cursor_position_callback(GLFWwindow* window, double xpos, double ypos) 
{ 
    // variables to store mouse cursor coordinates 
    static double previous_xpos = xpos; 
    static double previous_ypos = ypos; 
    double delta_x = xpos - previous_xpos; 
    double delta_y = ypos - previous_ypos; 

    // pass mouse movement to camera class 
    g_camera.updateYaw(delta_x); 
    g_camera.updatePitch(delta_y); 

    // update previous mouse coordinates 
    previous_xpos = xpos; 
    previous_ypos = ypos; 
} 

// key press or release callback function 
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) 
{ 
    // quit if the ESCAPE key was press 
    if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) 
    { 
     // set flag to close the window 
     glfwSetWindowShouldClose(window, GL_TRUE); 
     return; 
    } 
    // render in perspective view 
    else if (key == GLFW_KEY_1 && action == GLFW_PRESS) { 
     cout << "Perspective-View" << endl << endl; 
     // set camera's view matrix 
     g_camera.setViewMatrix(glm::vec3(0, 3, 14), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0)); 
     //g_viewMatrix = glm::lookAt(glm::vec3(10, 3, 8), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0)); 
     render_scene(); 
    } 
    // render from top view 
    else if (key == GLFW_KEY_2 && action == GLFW_PRESS) { 
     cout << "Top-View" << endl << endl; 
     // set camera's view matrix 
     g_camera.setViewMatrix(glm::vec3(0, 15, 0), glm::vec3(0, 0, 0), glm::vec3(1, 0, 0)); 
     //g_viewMatrix = glm::lookAt(glm::vec3(0, 15, 0), glm::vec3(0, 0, 0), glm::vec3(1, 0, 0)); 
     render_scene(); 
    } 
    // render from eye-level view 
    else if (key == GLFW_KEY_3 && action == GLFW_PRESS) { 
     cout << "Eye-level View" << endl << endl; 
     // set camera's view matrix 
     g_camera.setViewMatrix(glm::vec3(0, 0, 10), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0)); 
     //g_viewMatrix = glm::lookAt(glm::vec3(0, 0, 10), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0)); 
     render_scene(); 
    } 
    // Randomize size, orbit speed, axis rotation speed of planets 
    else if (key == GLFW_KEY_R && action == GLFW_PRESS) { 

     // Randomize planet size 
     g_scaleSize[1] = generateRandomFloat(0.1, 0.75); 
     g_scaleSize[2] = generateRandomFloat(0.1, 0.75); 
     g_scaleSize[3] = generateRandomFloat(0.1, 0.75); 
     g_scaleSize[4] = generateRandomFloat(0.1, 0.75); 

     // Randomize speed of rotation (on planets own axis) 
     g_rotationSpeed[1] = generateRandomFloat(0.1, 10.0); 
     g_rotationSpeed[2] = generateRandomFloat(0.1, 10.0); 
     g_rotationSpeed[3] = generateRandomFloat(0.1, 10.0); 
     g_rotationSpeed[4] = generateRandomFloat(0.1, 10.0); 

     // Randomize speed of rotation around sun 
     g_orbitSpeed[1] = generateRandomFloat(0.1, 1.2); 
     g_orbitSpeed[2] = generateRandomFloat(0.1, 1.2); 
     g_orbitSpeed[3] = generateRandomFloat(0.1, 1.2); 
     g_orbitSpeed[4] = generateRandomFloat(0.1, 1.2); 

     // Randomize offset for axis of rotation 
     g_axisOfRotation[1] = generateRandomFloat(-0.5, 0.5); 
     g_axisOfRotation[2] = generateRandomFloat(-0.5, 0.5); 
     g_axisOfRotation[3] = generateRandomFloat(-0.5, 0.5); 
     g_axisOfRotation[4] = generateRandomFloat(-0.5, 0.5); 

     // Display info for each planet 
     cout << "PLANET 1 - \tSize: " << g_scaleSize[1] << "\tSpeed: " << g_rotationSpeed[1] 
      << "\tOrbit Speed: " << g_orbitSpeed[1] << "\tAxis offset: " << g_axisOfRotation[1] << endl; 
     cout << "PLANET 2 - \tSize: " << g_scaleSize[2] << "\tSpeed: " << g_rotationSpeed[2] 
      << "\tOrbit Speed: " << g_orbitSpeed[2] << "\tAxis offset: " << g_axisOfRotation[2] << endl; 
     cout << "PLANET 3 - \tSize: " << g_scaleSize[3] << "\tSpeed: " << g_rotationSpeed[3] 
      << "\tOrbit Speed: " << g_orbitSpeed[3] << "\tAxis offset: " << g_axisOfRotation[3] << endl; 
     cout << "PLANET 4 - \tSize: " << g_scaleSize[4] << "\tSpeed: " << g_rotationSpeed[4] 
      << "\tOrbit Speed: " << g_orbitSpeed[4] << "\tAxis offset: " << g_axisOfRotation[4] << endl; 
     cout << endl; 

     render_scene(); 
    } 
} 

// error callback function 
static void error_callback(int error, const char* description) 
{ 
    cerr << description << endl; // output error description 
} 

int main(void) 
{ 
    GLFWwindow* window = NULL; // pointer to a GLFW window handle 

    glfwSetErrorCallback(error_callback); // set error callback function 

    // initialise GLFW 
    if (!glfwInit()) 
    { 
     // if failed to initialise GLFW 
     exit(EXIT_FAILURE); 
    } 

    // minimum OpenGL version 3.3 
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); 
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); 

    // create a window and its OpenGL context 
    window = glfwCreateWindow(1500, 1000, "Assignment 2", NULL, NULL); 

    // if failed to create window 
    if (window == NULL) 
    { 
     glfwTerminate(); 
     exit(EXIT_FAILURE); 
    } 

    glfwMakeContextCurrent(window); // set window context as the current context 
    glfwSwapInterval(1);   // swap buffer interval 

    // initialise GLEW 
    if (glewInit() != GLEW_OK) 
    { 
     // if failed to initialise GLEW 
     cerr << "GLEW initialisation failed" << endl; 
     exit(EXIT_FAILURE); 
    } 

    // set key callback function 
    glfwSetKeyCallback(window, key_callback); 
    glfwSetCursorPosCallback(window, cursor_position_callback); 

    // use sticky mode to avoid missing state changes from polling 
    glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE); 

    // use mouse to move camera, hence use disable cursor mode 
    glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); 

    // initialise rendering states 
    init(window); 

    // variables for simple time management 
    float lastUpdateTime = glfwGetTime(); 
    float currentTime = lastUpdateTime; 

    // the rendering loop 
    while (!glfwWindowShouldClose(window)) 
    { 
     currentTime = glfwGetTime(); 

     g_camera.update(window); // update camera 

     // only update if more than 0.02 seconds since last update 
     if (currentTime - lastUpdateTime > 0.02) 
     { 
      update_scene();  // update the scene 
      render_scene();  // render the scene 

      glfwSwapBuffers(window); // swap buffers 
      glfwPollEvents();   // poll for events 

      lastUpdateTime = currentTime; // update last update time 
     } 
    } 

    // clean up 
    glDeleteProgram(g_shaderProgramID); 
    glDeleteBuffers(1, &g_IBO); 
    glDeleteBuffers(1, &g_VBO[0]); 
    glDeleteBuffers(1, &g_VBO[1]); 
    glDeleteVertexArrays(1, &g_VAO[0]); 
    glDeleteVertexArrays(1, &g_VAO[1]); 

    // close the window and terminate GLFW 
    glfwDestroyWindow(window); 
    glfwTerminate(); 

    exit(EXIT_SUCCESS); 
} 

Camera.cpp

#include "Camera.h" 

    Camera::Camera() 
    { 
     // initialise camera member variables 
     mPosition = glm::vec3(0.0f, 0.0f, 1.0f); 
     mLookAt = glm::vec3(0.0f, 0.0f, 0.0f); 
     mUp = glm::vec3(0.0f, 1.0f, 0.0f); 

     mYaw = 0.0f; 
     mPitch = 0.0f; 

     mViewMatrix = glm::lookAt(mPosition, mLookAt, mUp); 
     mProjectionMatrix = glm::perspective(45.0f, 1.5f, 0.1f, 100.0f); 
    } 

    Camera::~Camera() 
    {} 

    void Camera::update(GLFWwindow* window) 
    { 
     // variables to store forward/back and strafe movement 
     float moveForward = 0; 
     float strafeRight = 0; 

     // update variables based on keyboard input 
     if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) 
      moveForward += MOVEMENT_SENSITIVITY; 
     if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) 
      moveForward -= MOVEMENT_SENSITIVITY; 
     if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) 
      strafeRight -= MOVEMENT_SENSITIVITY; 
     if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) 
      strafeRight += MOVEMENT_SENSITIVITY; 

     // rotate the respective unit vectors about the y-axis 
     glm::vec3 rotatedForwardVec = glm::rotateY(glm::vec3(0.0f, 0.0f, -1.0f), mYaw); 
     glm::vec3 rotatedRightVec = glm::rotateY(glm::vec3(1.0f, 0.0f, 0.0f), mYaw); 
     // rotate the rotated forward vector about the rotated right vector 
     rotatedForwardVec = glm::vec3(glm::rotate(mPitch, rotatedRightVec)*glm::vec4(rotatedForwardVec, 0.0f)); 

     // update position, look-at and up vectors 
     mPosition += rotatedForwardVec * moveForward + rotatedRightVec * strafeRight; 
     mLookAt = mPosition + rotatedForwardVec; 
     mUp = glm::cross(rotatedRightVec, rotatedForwardVec); 

     // compute the new view matrix 
     mViewMatrix = glm::lookAt(mPosition, mLookAt, mUp); 
    } 

    void Camera::updateYaw(float yaw) 
    { 
     mYaw -= yaw * ROTATION_SENSITIVITY; 
    } 

    void Camera::updatePitch(float pitch) 
    { 
     mPitch -= pitch * ROTATION_SENSITIVITY; 
    } 

    void Camera::setViewMatrix(glm::vec3 position, glm::vec3 lookAt, glm::vec3 up) 
    { 
     mPosition = position; 
     mLookAt = lookAt; 
     mUp = up; 

     mViewMatrix = glm::lookAt(mPosition, mLookAt, mUp); 
    } 

    void Camera::setProjectionMatrix(glm::mat4& matrix) 
    { 
     mProjectionMatrix = matrix; 
    } 

    glm::mat4 Camera::getViewMatrix() 
    { 
     return mViewMatrix; 
    } 

    glm::mat4 Camera::getProjectionMatrix() 
    { 
     return mProjectionMatrix; 
    } 

Camera.h

#ifndef __CAMERA_H 
#define __CAMERA_H 

#include <GLFW/glfw3.h> // include GLFW (which includes the OpenGL header) 
#include <glm/glm.hpp> // include GLM (ideally should only use the GLM headers that are actually used) 
#include <glm/gtx/transform.hpp> 
#include <glm/gtx/rotate_vector.hpp> 
using namespace glm; // to avoid having to use glm:: 

#define MOVEMENT_SENSITIVITY 0.0005f  // camera movement sensitivity 
#define ROTATION_SENSITIVITY 0.001f  // camera rotation sensitivity 

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

    void update(GLFWwindow* window); 
    void updateYaw(float yaw); 
    void updatePitch(float pitch); 
    void setViewMatrix(glm::vec3 position, glm::vec3 lookAt, glm::vec3 up); 
    void setProjectionMatrix(glm::mat4& matrix); 
    glm::mat4 getViewMatrix(); 
    glm::mat4 getProjectionMatrix(); 

private: 
    float mYaw; 
    float mPitch; 
    glm::vec3 mPosition; 
    glm::vec3 mLookAt; 
    glm::vec3 mUp; 
    glm::mat4 mViewMatrix; 
    glm::mat4 mProjectionMatrix; 
}; 

#endif 

顶点着色器

#version 330 core 

// input data (different for all executions of this shader) 
in vec3 aPosition; 
in vec3 aColor; 

// ModelViewProjection matrix 
uniform mat4 uModelViewProjectionMatrix; 

// output data (will be interpolated for each fragment) 
out vec3 vColor; 

void main() 
{ 
    // set vertex position 
    gl_Position = uModelViewProjectionMatrix * vec4(aPosition, 1.0); 

    // the color of each vertex will be interpolated 
    // to produce the color of each fragment 
    vColor = aColor; 
} 
+0

@ Rabbid76我不是使用g_viewMatrix了。我想我必须调整这个函数的向量g_camera.setViewMatrix(glm :: vec3(0,15,0),glm :: vec3(0,0,0),glm :: vec3(1,0,0) );这些值与我在功能上的看法是一样的,但是它们不指向相同的地方 – Zolly

+0

@ Rabbid76我只是试过了,但它变成了眼睛视图 – Zolly

回答

1

你必须从世界地图坐标到视口cooordinates

x y z 
-------- 
1 0 0 | x' = x 
0 0 1 | y' = z 
0 -1 0 | z' = -y 

使用此功能可以看到从上面的一幕:

g_camera.setViewMatrix(glm::vec3(0, 15.0f, 0), glm::vec3(0, 0, 0), glm::vec3(0, 0, -1.0f)); 


要窗格中,变焦和轨道,你必须建立翻译的观点和旋转矩阵,你必须连接(乘) 他们与视图矩阵。

添加成员到类Camera存储平移和旋转角度:

glm::vec3 _move; 
float  _angX; 
float  _angY; 

适应的方法Camera::update总结平移和旋转角度:

#define MOVEMENT_SENSITIVITY 0.01f 
#define ZOOM_SENSITIVITY 0.1f 
#define ROTATION_SENSITIVITY 1.0f 

void Camera::update(GLFWwindow* window) 
{ 
    if (glfwGetKey(window, GLFW_KEY_A)   == GLFW_PRESS) _move[0] -= MOVEMENT_SENSITIVITY; 
    if (glfwGetKey(window, GLFW_KEY_D)   == GLFW_PRESS) _move[0] += MOVEMENT_SENSITIVITY; 
    if (glfwGetKey(window, GLFW_KEY_S)   == GLFW_PRESS) _move[1] -= MOVEMENT_SENSITIVITY; 
    if (glfwGetKey(window, GLFW_KEY_W)   == GLFW_PRESS) _move[1] += MOVEMENT_SENSITIVITY; 
    if (glfwGetKey(window, GLFW_KEY_PAGE_DOWN) == GLFW_PRESS) _move[2] -= ZOOM_SENSITIVITY; 
    if (glfwGetKey(window, GLFW_KEY_PAGE_UP) == GLFW_PRESS) _move[2] += ZOOM_SENSITIVITY; 
    if (glfwGetKey(window, GLFW_KEY_UP)  == GLFW_PRESS) _angX -= ROTATION_SENSITIVITY; 
    if (glfwGetKey(window, GLFW_KEY_DOWN)  == GLFW_PRESS) _angX += ROTATION_SENSITIVITY; 
    if (glfwGetKey(window, GLFW_KEY_RIGHT)  == GLFW_PRESS) _angY -= ROTATION_SENSITIVITY; 
    if (glfwGetKey(window, GLFW_KEY_LEFT)  == GLFW_PRESS) _angY += ROTATION_SENSITIVITY; 
} 

注意,你必须调整灵敏度和按钮或甚至其他类型的输入以满足您的需求。要获得明确定义的行为,您应该在时间离散过程中执行更新方法。

设置平移矩阵和旋转矩阵在梅索德Camera::getViewMatrix,并将它们串联到视图矩阵:

glm::mat4 Camera::getViewMatrix() 
{ 
    glm::mat4 rotX = glm::rotate(_angX * (float)PI/180.0f, glm::vec3(mViewMatrix[0])); 
    glm::mat4 rotY = glm::rotate(_angY * (float)PI/180.0f, glm::vec3(mViewMatrix[1])); 
    glm::mat4 trans = glm::translate(glm::mat4(1.0), _move); 
    return trans * mViewMatrix * rotX * rotY; 
} 
+0

我不太确定那个代码是干什么的。当我评论它时,我设法得到了我想要的观点。但是,我无法平移或移动相机。你知道如何启用它来平移/移动,当输入'2'时也指向正确的方向吗? – Zolly

+0

@ Zolly看到我的回答的最后一部分 – Rabbid76

+0

对不起,我不明白解决方案。我不确定moveX,moveY,angDegreeX和angDegreeY的价值应该是什么。我想我现在可能会放弃这个问题。关于我的圈子显示为椭圆形的问题,你知道如何解决这个问题吗?我假设它与我的投影矩阵乘以圆的模型矩阵有关? – Zolly

相关问题