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

C++ OpenGL 3.3 C++;绘制太阳系的轨道路径线,c++,opengl,C++,Opengl,我目前正在做一项关于使用openGL创建太阳系的作业。我已经成功地创建了行星,行星围绕太阳的轨道,以及每个行星轴的旋转 我被困在如何动态地为行星的轨道画一条线上。因此,即使轨道路径改变,直线也会改变。(在大多数太阳系图像中显示轨道路径的细线) 希望得到一个方向,而不是答案 感谢您的回复(如有) 附言:使用GLFW而不是GLUT库。以下是我到目前为止的情况 static void init(GLFWwindow* window) { glEnable(GL_DEPTH_TEST);

我目前正在做一项关于使用openGL创建太阳系的作业。我已经成功地创建了行星,行星围绕太阳的轨道,以及每个行星轴的旋转

我被困在如何动态地为行星的轨道画一条线上。因此,即使轨道路径改变,直线也会改变。(在大多数太阳系图像中显示轨道路径的细线)

希望得到一个方向,而不是答案

感谢您的回复(如有)

附言:使用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);
}
static void init(GLFWwindow*window)
{
glEnable(GLU深度试验);
//创建着色器对象
g_shaderProgramID=加载着色器(“ModelSpaceVS.vert”、“ColorFS.frag”);
//获取着色器变量的位置
GLuint positionIndex=glGetAttribLocation(g_shaderProgramID,“aPosition”);
GLuint colorIndex=glGetAttribLocation(g_shaderProgramID,“aColor”);
g_ModelMatrixinIndex=glGetUniformLocation(g_shaderProgramID,“uModelMatrix”);
//创建摄影机对象
//设置摄影机的视图矩阵
g_camera.setViewMatrix(vec3(0.0f,15.0f,0.0f),vec3(0.0f,0.0f,0.0f),vec3(0,1,0));
//窗口纵横比
int宽度、高度;
glfwGetFramebufferSize(窗口、宽度和高度);
浮动aspectRatio=静态铸件(宽度)/高度;
//设置相机的投影矩阵
g_camera.setProjectionMatrix(透视图(45.0f,aspectRatio,0.1f,100.0f));
//将模型矩阵初始化为单位矩阵
//设置为1.0f,以便在转换过程中
//如果矩阵相乘,则为1*=
//变换&&scale&&rotate放置在更新场景函数中
//因为更新场景也需要更新动态观察值
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);
//为VBO生成标识符并将数据复制到GPU
glGenBuffers(4,g_VBO);
//绑定行星的顶点(对于太阳+4个行星,仅1个顶点)
//转换不是在这里完成的
glBindBuffer(GL_数组_BUFFER,g_VBO[0]);
glBufferData(GL_数组_缓冲区、sizeof(planetOrigin)、planetOrigin、GL_静态_绘图);
glBindBuffer(GL_元素数组缓冲区,g_VBO[1]);
glBufferData(GL_元素、数组、缓冲区、sizeof(g_索引)、g_索引、GL_静态图);
//线顶点
glBindBuffer(GL_ARRAY_BUFFER,g_VBO[2]);//绑定VBO
glBufferData(GL_数组_BUFFER,sizeof(linePos),linePos,GL_STATIC_DRAW);//将数据复制到缓冲区
glBindBuffer(GL_ARRAY_BUFFER,g_VBO[3]);//绑定VBO
glBufferData(GL_数组_BUFFER,sizeof(lineColor),lineColor,GL_STATIC_DRAW);//将数据复制到缓冲区
//为VAO生成标识符
Glgenvertexarray(2,g_VAO);
//创建VAO并指定VBO数据
glBindVertexArray(g_VAO[0]);
glBindBuffer(GL_数组_BUFFER,g_VBO[0]);
glBindBuffer(GL_元素数组缓冲区,g_VBO[1]);
//交错属性
glVertexAttribute指针(位置索引,3,GL_浮点,GL_假,大小(顶点),重新解释投射(偏移(顶点,位置));
glVertexAttribute指针(颜色索引,3,GL_浮点,GL_假,大小(顶点),重新解释(偏移(顶点,颜色));
GlenableVertexAttributeArray(positionIndex);//启用顶点属性
GlenableVertexAttributeArray(colorIndex);
//将VBO绑定到VAO
//线条
glBindVertexArray(g_VAO[1]);//创建VAO对象
glBindBuffer(GL_数组_BUFFER,g_VBO[2]);
glvertexattributepointer(0,3,GL_FLOAT,GL_FALSE,0,0);
glBindBuffer(GL_数组_BUFFER,g_VBO[3]);
glvertexattributepointer(1,3,GL_FLOAT,GL_FALSE,0,0);
GlenableVertexAttributeArray(0);
GlenableVertexAttributeArray(1);
}
//键盘输入动作
静态无效键_回调(GLFWwindow*窗口、int键、int扫描码、int操作、int mods)
{
//退出ESC上的程序
如果(键==GLFW\U键\转义和操作==GLFW\U按)
{
//关闭窗口并结束程序
glfwSetWindowShouldClose(窗口,GL_TRUE);
返回;
}
否则如果(键==GLFW\U键P&&action==GLFW\U按)
{
//设置行星绕太阳运行的动画
//还有他们自己绕着自己的轴旋转
如果(动画==假)
动画=真;
else if(animate==true)
动画=假;
}
否则如果(键==GLFW\U键&&action==GLFW\U按)
{
//随机化大小/围绕太阳的环绕速度/围绕其自身轴的旋转速度
//所有的行星和太阳
//
//
//Rand+100以防止轨道或旋转速度为0
//或者太低以至于它似乎停止了
// 
//随机化行星的轨道速度
//将轨道速度限制在300,最小为100
轨道速度=(rand()%200)+100;
//随机化行星+太阳的旋转速度
//以自己的轴线
//将转速限制在300,最小值为100
旋转速度=(rand()%200)+100;
//随机化行星/太阳大小
//rand()的值是为了确保行星永远不会比太阳大
//rand()%3/10+0.7=最小值:0.7,最大值:1.0
//rand()%5/10+0.2=最小值:0.2,最大值: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;
}
否则如果(键==GLFW\U键1&&action==GLFW\U按)
{
//将相机视图设置为相机的一个遥远的自顶向下视图
//太阳系
//看起来像RTS相机样式
//设置摄影机的视图矩阵
g_camera.setViewMatrix(vec3(0.0f,10.0f,20.0f),vec3(0.0f,0.0f,0.0f),vec3(0,1,0));
}
否则如果(键==GLFW\U键2&&action==GLFW\U按)
{
//将相机视图设置为自顶向下视图
//直接从上面看
//设置摄像机的vi