我目前正致力于使用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);
}