OpenGL 3.3 C ++绘制太阳系轨道路径线

时间:2017-07-12 08:51:52

标签: c++ opengl

我目前正致力于使用openGL创建太阳系。我已经设法制造了行星,围绕太阳行星的轨道,以及每个行星轴的旋转。

我坚持如何为行星的轨道路径动态绘制一条线。这样即使轨道路径发生变化,线也会发生变化。(那些显示大多数太阳系图像中轨道路径的细线)

希望找到一个方向,而不是回答。

感谢您的回复(如果有的话)

P.S:使用GLFW而不是GLUT库。以下是我到目前为止的内容

static void init(GLFWwindow* window)
{
    glEnable(GL_DEPTH_TEST);

    // Create the shader object
    g_shaderProgramID = loadShaders("ModelSpaceVS.vert", "ColorFS.frag");

    // Getting Locations of shader's variables
    GLuint positionIndex = glGetAttribLocation(g_shaderProgramID, "aPosition");
    GLuint colorIndex = glGetAttribLocation(g_shaderProgramID, "aColor");
    g_modelMatrixIndex = glGetUniformLocation(g_shaderProgramID, "uModelMatrix");

    // Creating camera object
    // Set camera's view matrix
    g_camera.setViewMatrix(vec3(0.0f, 15.0f, 0.0f), vec3(0.0f, 0.0f, 0.0f), vec3(0, 1, 0));

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

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


    // Initialise the model matrix to identity matrix
    //    Set to 1.0f so that during the transformation process where
    //    the matrix is multiplied, it would be 1*<value> = <value>
    //    The transformation && scale && rotate are placed in the update_scene Function
    //    as the update scene needs to update the orbitting value as well
    g_modelMatrix[0] = mat4(1.0f);
    g_modelMatrix[1] = mat4(1.0f);
    g_modelMatrix[2] = mat4(1.0f);
    g_modelMatrix[3] = mat4(1.0f);
    g_modelMatrix[4] = mat4(1.0f);

    // Generate identifier for VBO and copy data to GPU
    glGenBuffers(4, g_VBO);

    // Binding the vertices for the planet (Only 1 vertices for sun + 4 planets)
    // Transformation is not done here
    glBindBuffer(GL_ARRAY_BUFFER, g_VBO[0]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(planetOrigin), planetOrigin, GL_STATIC_DRAW);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_VBO[1]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(g_indices), g_indices, GL_STATIC_DRAW);

    // Line Vertex
    glBindBuffer(GL_ARRAY_BUFFER, g_VBO[2]);  // Binding the VBO
    glBufferData(GL_ARRAY_BUFFER, sizeof(linePos), linePos, GL_STATIC_DRAW);   // Copy data to buffer
    glBindBuffer(GL_ARRAY_BUFFER, g_VBO[3]);  // Binding the VBO
    glBufferData(GL_ARRAY_BUFFER, sizeof(lineColor), lineColor, GL_STATIC_DRAW);  // Copy data to buffer

    // generate identifiers for VAOs
    glGenVertexArrays(2, g_VAO);

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

    // Binding the VBO to a VAO
    // Lines
    glBindVertexArray(g_VAO[1]);  // Create the VAO object
    glBindBuffer(GL_ARRAY_BUFFER, g_VBO[2]);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
    glBindBuffer(GL_ARRAY_BUFFER, g_VBO[3]);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);

}

//   Keyboard Input Actions
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
// Exit the program on ESC
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
{
   // Closes the window and end the program
   glfwSetWindowShouldClose(window, GL_TRUE);
   return;
}
else if (key == GLFW_KEY_P && action == GLFW_PRESS)
{
   // Animating the planets Orbit around the sun
   // and also their own individual rotation about their own axis
   if (animate == false)
      animate = true;
   else if (animate == true)
      animate = false;
}
else if (key == GLFW_KEY_R && action == GLFW_PRESS)
{
   // Randomize the Size / Orbit Speed Around  the Sun / Rotation Speed about their own axis
   // of all the planet and the sun
   //
   //
   // Rand + 100 to prevent the orbit or rotationSpeed from being 0
   //    Or being too low that it seems to stop
   // 
   // Randomizing the orbitSpeed of planet
   // Capping the orbit Speed at 300, minimum 100
   orbitSpeed = (rand() % 200) + 100;

   // Randomizing the rotationSpeed of planet + sun
   //    upon its own axis
   // Capping the rotation Speed at 300, minimum 100
   rotationSpeed = (rand() % 200) + 100;

   // Randomizing the planet/sun size
   // Values of the rand() is to ensure the planet will never be bigger than the sun
   // rand() % 3 / 10 + 0.7 = min : 0.7, Max : 1.0
   // rand() % 5 / 10 + 0.2 = min : 0.2, Max : 0.7
   sunSize = (rand() % 2) + 3.0;
   planetSize1 = (rand() % 2) + 0.9;
   planetSize2 = (rand() % 2) + 0.9;
   planetSize3 = (rand() % 2) + 0.9;
   planetSize4 = (rand() % 2) + 0.9;
}
else if (key == GLFW_KEY_1 && action == GLFW_PRESS)
{
   // Set the camera view to a far-away top down view of the 
   // solar system
   // Looks like a RTS camera style
   // Set camera's view matrix
   g_camera.setViewMatrix(vec3(0.0f, 10.0f, 20.0f), vec3(0.0f, 0.0f, 0.0f), vec3(0, 1, 0));
}
else if (key == GLFW_KEY_2 && action == GLFW_PRESS)
{
   // Set the camera view to a top down view
   // directly looking at it from above
   // Set camera's view matrix
   g_camera.setViewMatrix(vec3(0.0f, 20.0f, 0.0f), vec3(0.0f, 0.0f, 0.0f), vec3(0, 1.0, 0));
}

}

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;
    }

     //   Frame Buffer Action
    static void framebuffer_Size_callback(GLFWwindow* window, int width, int height)
    {
    string title = "Assignment 1 - " + to_string(width) + " x " + to_string(height);

    glfwSetWindowTitle(window, title.c_str());
} 

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

//   Update Scene Function
//      Updates the "planet" solitary rotation about its own axis
//      Updates the "planet" orbit around a point around the "sun"
static void update_scene(GLFWwindow* window, double frameTime)
{
    static float rotateAngleY = 0.0f;
    static float rotateAngleY1 = 0.0f;
    static float rotateAngleY2 = 0.0f;
    static float rotateAngleY3 = 0.0f;
    static float sunRotateAngleY = 0.0f;
    static float orbitAngle1 = 0.0f;
    static float orbitAngle2 = 0.0f;
    static float orbitAngle3 = 0.0f;
    static float orbitAngle4 = 0.0f;

    if (animate == true)
    {
       rotateAngleY += 1.5 * rotationSpeed * frameTime;
       rotateAngleY1 += 1.0 * rotationSpeed * frameTime;
       rotateAngleY2 -= 2.0 * rotationSpeed * frameTime;
       rotateAngleY3 -= 2.5 * rotationSpeed * frameTime;
       sunRotateAngleY += 0.1 * rotationSpeed * frameTime;

       orbitAngle1 += 0.6 * orbitSpeed * frameTime;
       orbitAngle2 += 0.5 * orbitSpeed * frameTime;
       orbitAngle3 += 0.2 * orbitSpeed * frameTime;
       orbitAngle4 += 0.1 * orbitSpeed * frameTime;
    }

    // Updating the Scene the rotate the individual planets
    // Each of the planet needs their initial translate/scale value
    //    if the transform/scale here is vec(0.0,0.0,0.0) || vec3(1.0,1.0,1.0)
    //    They will be rendered on the origin, which is where the sun is
    //    at the same size
    //
    // rotate(radians(orbitAngle1), vec3(0.0f, 1.0f, 0.0f))  - Controls Orbit Rotation of Planet
    // rotate(radians(rotateAngleY), vec3(1.0f, 1.0f, 0.0f)) - Controls Orbit About Own Axis
    // rotate(radians(-60.0f), vec3(0.0f, 0.0f, 1.0f))       - Controls the rotation of a planet on display(without movement)
    g_modelMatrix[0] = translate(vec3(0.0f, 0.0, 0.0f)) * rotate(radians(sunRotateAngleY), vec3(0.0, 1.0, 0.0f))
                      * scale(vec3(1.0f, 1.0f, 1.0f) * sunSize);

    g_modelMatrix[1] = rotate(radians(orbitAngle1), vec3(0.0f, 1.0f, 0.0f)) * translate(vec3(2.0f, 0.0f, 0.0f) + (sunSize/10)) * rotate(radians(rotateAngleY), vec3(0.0f, 1.0f, 0.0f))
                   * rotate(radians(-60.0f), vec3(0.0f, 0.0f, 1.0f)) * scale(vec3(1.0f, 1.0f, 1.0f) * planetSize1);

    g_modelMatrix[2] = rotate(radians(orbitAngle2), vec3(0.0f, 1.0f, 0.0f)) * translate(vec3(4.0f, 0.0f, 0.0f) + (sunSize/10)) * rotate(radians(rotateAngleY1), vec3(0.0f, 1.0f, 0.0f))
                   * rotate(radians(-45.0f), vec3(0.0f, 0.0f, 1.0f)) * scale(vec3(1.0f, 1.0f, 1.0f)* planetSize2);

    g_modelMatrix[3] = rotate(radians(orbitAngle3), vec3(0.0f, 1.0f, 0.0f)) * translate(vec3(6.0f, 0.0f, 0.0f) + (sunSize/10)) * rotate(radians(rotateAngleY2), vec3(0.0f, 1.0f, 0.0f))
                   * rotate(radians(45.0f), vec3(0.0f, 0.0f, 1.0f)) * scale(vec3(1.0f, 1.0f, 1.0f) * planetSize3);

    g_modelMatrix[4] = rotate(radians(orbitAngle4), vec3(0.0f, 1.0f, 0.0f)) * translate(vec3(8.0f, 0.0f, 0.0f) + (sunSize/10)) * rotate(radians(rotateAngleY), vec3(0.0f, 1.0f, 0.0f))
                   * rotate(radians(60.0f), vec3(0.0f, 0.0f, 1.0f)) * scale(vec3(1.0f, 1.0f, 1.0f) * planetSize4);

}

//   Render Scene Function
static void render_scene()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);   // Clear colour buffer && clear depth buffer
    glUseProgram(g_shaderProgramID);

    // Make VAO active
    glBindVertexArray(g_VAO[0]);     
    // Sun Object
    // compute multiplication of model, view and projection matrices
    mat4 MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix[0];
    glUniformMatrix4fv(g_modelMatrixIndex, 1, GL_FALSE, &MVP[0][0]);
    glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);

    // Planet 1
    MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix[1];
    glUniformMatrix4fv(g_modelMatrixIndex, 1, GL_FALSE, &MVP[0][0]);
    glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);

    // Planet 2
    MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix[2];
    glUniformMatrix4fv(g_modelMatrixIndex, 1, GL_FALSE, &MVP[0][0]);
    glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);

    // Planet 3
    MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix[3];
    glUniformMatrix4fv(g_modelMatrixIndex, 1, GL_FALSE, &MVP[0][0]);
    glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);

    // Planet 4
    MVP = g_camera.getProjectionMatrix() * g_camera.getViewMatrix() * g_modelMatrix[4];
    glUniformMatrix4fv(g_modelMatrixIndex, 1, GL_FALSE, &MVP[0][0]);
    glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);

    glFlush();  // Flushing the pipelines
}
//   ------------------------------------------------------------------------------------
//   Main Function
int main(void)
{
    srand(time(NULL));
    GLFWwindow* window = NULL; // Creating of window variable

    glfwSetErrorCallback(error_callback);

    // Initialise glfw
    //    if false = failed initialization
    if (!glfwInit())
    {
       cout << "glfw Initialisation failed" << endl;
       exit(EXIT_FAILURE);
    }

    // Declaring the version of OpenGL
    //    Version 3.3 in this case
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);

    // Creating the window object
    window = glfwCreateWindow(1080, 720, "Assignment 2 - 1080 x 720", NULL, NULL);

    // Check if the Creating of window Object succeeded
    if (window == NULL)
    {
       cout << "Creation of window failed" << endl;
       glfwTerminate();
       exit(EXIT_FAILURE);
    }

    // Making Context Current
    glfwMakeContextCurrent(window);

    // Determine Swap Buffer Interval
    glfwSwapInterval(1);

    // Set a background color for window
    //    Black - Solar System in space
    glClearColor(0.0, 0.0, 0.0, 1.0);

    // Initialise GLEW
    if (glewInit() != GLEW_OK)
    {
       cout << "Initialisation of GLEW failed" << endl;
       exit(EXIT_FAILURE);
    }

    // Keyboard/Mouse Input/Callbacks
    glfwSetFramebufferSizeCallback(window, framebuffer_Size_callback);
    glfwSetKeyCallback(window, key_callback);
    glfwSetCursorPosCallback(window, cursor_position_callback);

    // Init function
    init(window);

    // Frame Variables
    double lastUpdateTime = glfwGetTime(); // last update time
    double elapsedTime = lastUpdateTime;   // time elapsed since last update
    double frameTime = 0.0f;            // frame time
    int frameCount = 0;                 // number of frames since last update

    // Rendering Loop
    while (!glfwWindowShouldClose(window))
    {
       g_camera.update(window);
       update_scene(window, frameTime);
       render_scene();

       // Swap Buffer
       glfwSwapBuffers(window);
       // Poll Events
       glfwPollEvents();

       frameCount++;
       elapsedTime = glfwGetTime() - lastUpdateTime;   // current time - last update time

       if (elapsedTime >= 1.0f)   // if time since last update >= to 1 second
       {
          frameTime = 1.0f / frameCount;   // calculate frame time

          string str = "FPS = " + to_string(frameCount) + "; FT = " + to_string(frameTime);

          glfwSetWindowTitle(window, str.c_str());  // update window title

          frameCount = 0;               // reset frame count
          lastUpdateTime += elapsedTime;   // update last update time
       }

    }

    // Cleaning Up Shader Program
    glDeleteProgram(g_shaderProgramID);
    // Cleaning Up Vertexes
    glDeleteBuffers(14, g_VBO);
    glDeleteVertexArrays(2, g_VAO);

    // Destroying the window before terminating the program
    glfwDestroyWindow(window);
    glfwTerminate();

    exit(EXIT_SUCCESS);
}

0 个答案:

没有答案