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