I’m currently developing an OpenGL/C++ project featuring various objects in a 3D scene, such as a spaceship and a fuel tank. While the spaceship is represented by a 3D model, I encountered difficulties loading a model for the fuel tank. As a workaround, I approximated the fuel tank using a cube primitive and applied a texture to it.
Despite successfully rendering both objects, I’m unsure how to proceed with determining their sizes. Specifically, I aim to estimate their radii by enclosing them with spheres dynamically. However, I’m uncertain about the process, especially regarding the cube approximation for the fuel tank.
Her’s the initilization and rendering part
void init()
{
//// Load shaders and use the resulting shader program
skyboxShader = InitShader("skybox_vshader.glsl", "skybox_fshader.glsl");
glUseProgram(skyboxShader);
// Skybox VAO
glGenVertexArrays(1, &skyboxVAO);
glGenBuffers(1, &skyboxVBO);
glBindVertexArray(skyboxVAO);
glBindBuffer(GL_ARRAY_BUFFER, skyboxVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxVertices), &skyboxVertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
skyboxTexture = loadCubemap(faces);
glUseProgram(0);
// Create a vertex array object for the fuel tank
glGenVertexArrays(1, &vaoFuelTank);
glBindVertexArray(vaoFuelTank);
// Create and initialize a vertex buffer object
glGenBuffers(1, &vboFuelTank);
glBindBuffer(GL_ARRAY_BUFFER, vboFuelTank);
glBufferData(GL_ARRAY_BUFFER, sizeof(fuelTankVertices), fuelTankVertices, GL_STATIC_DRAW);
// Specify the layout of the vertex data
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
glEnableVertexAttribArray(0);
// Texture coordinate attribute
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
// Render the cube
glBindVertexArray(vaoFuelTank);
glDrawArrays(GL_TRIANGLES, 0, 36);
glBindVertexArray(0);
// Create a vertex array object
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// Create and initialize a vertex buffer object
glGenBuffers(1, &vbo1);
glBindBuffer(GL_ARRAY_BUFFER, vbo1);
glBufferData(GL_ARRAY_BUFFER, sun.getInterleavedVertexSize(), sun.getInterleavedVertices(), GL_STATIC_DRAW);
// Create and initialize an index buffer object
glGenBuffers(1, &ibo1);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo1);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sun.getIndexSize(), sun.getIndices(), GL_STATIC_DRAW);
// Load shaders and use the resulting shader program
program = InitShader("vshader.glsl", "fshader.glsl");
glUseProgram(program);
// set up vertex arrays
vPosition = glGetAttribLocation(program, "vertexPosition");
glEnableVertexAttribArray(vPosition);
vNormal = glGetAttribLocation(program, "vertexNormal");
glEnableVertexAttribArray(vNormal);
vTexture = glGetAttribLocation(program, "vertexTexture");
glEnableVertexAttribArray(vTexture);
initLight();
initTexture();
modelUnifrom = glGetUniformLocation(program, "model");
viewUniform = glGetUniformLocation(program, "view");
projectionUniform = glGetUniformLocation(program, "projection");
projection = glm::perspective(glm::radians(camera.Zoom), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
glUniformMatrix4fv(projectionUniform, 1, GL_FALSE, glm::value_ptr(projection));
// don't forget to enable shader before setting uniforms
ourShader.use();
projection = glm::perspective(glm::radians(camera.Zoom), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
// view/projection transformations
view = camera.GetViewMatrix();
ourShader.setMat4("projection", projection);
ourShader.setMat4("view", view);
// render the loaded model
model = glm::mat4(1.0f);
model = glm::translate(model, glm::vec3(0.0f, -5.0f, 0.f));
model = glm::scale(model, glm::vec3(0.09f, 0.09f, 0.09f));
ourShader.setMat4("model", model);
glEnable(GL_DEPTH_TEST | GL_TEXTURE_2D);
glClearColor(1.0, 1.0, 1.0, 1.0);
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Get the view matrix from the camera
view = camera.GetViewMatrix();
// Remove translation from the view matrix for the skybox
glm::mat4 skyboxView = glm::mat4(glm::mat3(view)); // Remove translation
glDisable(GL_DEPTH_TEST); // disabling the depth test for the skybox
// Render the skybox
glUseProgram(skyboxShader);
// Remove translation from the view matrix to keep the skybox centered around the camera
glUniformMatrix4fv(glGetUniformLocation(skyboxShader, "view"), 1, GL_FALSE, glm::value_ptr(glm::mat4(glm::mat3(view))));
glBindVertexArray(skyboxVAO);
glBindBuffer(GL_ARRAY_BUFFER, skyboxVBO);
glBindTexture(GL_TEXTURE_CUBE_MAP, skyboxTexture);
trans = glm::mat4(1.0f);
trans = glm::scale(trans, glm::vec3(.5f, .5f, .5f)); // Scale the skybox
glUniformMatrix4fv(glGetUniformLocation(skyboxShader, "model"), 1, GL_FALSE, glm::value_ptr(trans));
glUniformMatrix4fv(glGetUniformLocation(skyboxShader, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
glDrawArrays(GL_TRIANGLES, 0, 36);
glEnable(GL_DEPTH_TEST); // enabnling the depth test for the rest of the planets
//// Set view matrix for rendering objects
glUseProgram(program);
glUniformMatrix4fv(glGetUniformLocation(program, "view"), 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(viewUniform, 1, GL_FALSE, glm::value_ptr(view));
glUniform3fv(cameraUniform, 1, glm::value_ptr(camera.Position));
// Draw Sun
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo1);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo1);
glBindTexture(GL_TEXTURE_2D, sunTexture);
glVertexAttribPointer(vPosition, 3, GL_FLOAT, GL_FALSE, sun.getInterleavedStride(), BUFFER_OFFSET(0));
glVertexAttribPointer(vNormal, 3, GL_FLOAT, false, sun.getInterleavedStride(), (void*)(3 * sizeof(float)));
glVertexAttribPointer(vTexture, 2, GL_FLOAT, false, sun.getInterleavedStride(), (void*)(6 * sizeof(float)));
trans = glm::mat4(1.0f);
trans = glm::scale(trans, glm::vec3(1.0f, 1.0f, 1.0f));
trans = glm::rotate(trans, rotating, glm::vec3(0.0f, 1.0f, 0.0f));
glUniformMatrix4fv(modelUnifrom, 1, GL_FALSE, glm::value_ptr(trans));
glDrawElements(GL_TRIANGLES, sun.getIndexCount(), GL_UNSIGNED_INT, (void*)0);
//mercury
glBindTexture(GL_TEXTURE_2D, mercuryTexture);
trans = glm::mat4(0.7f);
trans = glm::rotate(trans, mercuryRotation, glm::vec3(0.0f, 1.0f, 0.0f));
trans = glm::scale(trans, glm::vec3(0.15f, 0.15f, 0.15f));
trans = glm::translate(trans, glm::vec3(2.3f, 0.0f, 0.0f));
trans = glm::rotate(trans, mercuryRotation, glm::vec3(0.0, 1.0, 0.0));
// Send transformation matrix to the shader
glUniformMatrix4fv(modelUnifrom, 1, GL_FALSE, glm::value_ptr(trans));
glDrawElements(GL_TRIANGLES, sun.getIndexCount(), GL_UNSIGNED_INT, (void*)0);
//draw venus
glBindTexture(GL_TEXTURE_2D, venusTexture);
trans = glm::mat4(0.7f);
trans = glm::rotate(trans, venusRotation, glm::vec3(0.0, 1.0, 0.0));
trans = glm::scale(trans, glm::vec3(0.18f, 0.18f, 0.18f));
trans = glm::translate(trans, glm::vec3(2.6f, 0.f, 0.f));
trans = glm::rotate(trans, venusRotation, glm::vec3(0.0f, 1.0f, 0.0f));
// Send transformation matrix to the shader
glUniformMatrix4fv(modelUnifrom, 1, GL_FALSE, glm::value_ptr(trans));
glDrawElements(GL_TRIANGLES, sun.getIndexCount(), GL_UNSIGNED_INT, (void*)0);
//draw earth
glBindTexture(GL_TEXTURE_2D, earthTexture);
trans = glm::mat4(1.0f);
trans = glm::rotate(trans, earthRotation, glm::vec3(0.0, 1.0, 0.0));
trans = glm::scale(trans, glm::vec3(0.19f, 0.19f, 0.19f));
trans = glm::translate(trans, glm::vec3(2.3f, 0.f, 0.f));
trans = glm::rotate(trans, earthRotation, glm::vec3(0.0, 1.0, 0.0));
// Send transformation matrix to the shader
glUniformMatrix4fv(modelUnifrom, 1, GL_FALSE, glm::value_ptr(trans));
glDrawElements(GL_TRIANGLES, sun.getIndexCount(), GL_UNSIGNED_INT, (void*)0);
//draw Mars
glBindTexture(GL_TEXTURE_2D, marsTexture);
trans = glm::mat4(1.0f);
trans = glm::rotate(trans, marsRotation, glm::vec3(0.0f, 1.0f, 0.0f));
trans = glm::scale(trans, glm::vec3(0.2f, 0.2f, 0.2f));
trans = glm::translate(trans, glm::vec3(2.8f, 0.f, 0.f));
trans = glm::rotate(trans, marsRotation, glm::vec3(0.0f, 1.0f, 0.0f));
// Send transformation matrix to the shader
glUniformMatrix4fv(modelUnifrom, 1, GL_FALSE, glm::value_ptr(trans));
glDrawElements(GL_TRIANGLES, sun.getIndexCount(), GL_UNSIGNED_INT, (void*)0);
//Draw Jupiter
glBindTexture(GL_TEXTURE_2D, jupiterTexture);
trans = glm::mat4(1.0f);
trans = glm::rotate(trans, jupiterRotation, glm::vec3(0.0f, 1.0f, 0.0f));
trans = glm::scale(trans, glm::vec3(0.40f, 0.40f, 0.40f));
trans = glm::translate(trans, glm::vec3(1.8f, 0.f, 0.f));
trans = glm::rotate(trans, jupiterRotation, glm::vec3(0.0, 1.0, 0.0));
// Send transformation matrix to the shader
glUniformMatrix4fv(modelUnifrom, 1, GL_FALSE, glm::value_ptr(trans));
glDrawElements(GL_TRIANGLES, sun.getIndexCount(), GL_UNSIGNED_INT, (void*)0);
//Draw Saturn
glBindTexture(GL_TEXTURE_2D, saturnTexture);
trans = glm::mat4(1.0f);
trans = glm::rotate(trans, saturnRotation, glm::vec3(0.0f, 1.0f, 0.0f));
trans = glm::scale(trans, glm::vec3(0.40f, 0.40f, 0.40f));
trans = glm::translate(trans, glm::vec3(2.3f, 0.f, 0.f));
trans = glm::rotate(trans, saturnRotation, glm::vec3(0.0, 1.0, 0.0));
// Send transformation matrix to the shader
glUniformMatrix4fv(modelUnifrom, 1, GL_FALSE, glm::value_ptr(trans));
glDrawElements(GL_TRIANGLES, sun.getIndexCount(), GL_UNSIGNED_INT, (void*)0);
//Ring
trans = glm::mat4(1.0f);
trans = glm::rotate(trans, saturnRotation, glm::vec3(0.0f, 1.0f, 0.0f));
trans = glm::scale(trans, glm::vec3(0.24f, 0.24f, 0.24f));
trans = glm::translate(trans, glm::vec3(3.4f, 0.f, 0.f));
trans = glm::rotate(trans, saturnRotation, glm::vec3(0.0, 1.0, 0.0));
//Draw Uranus
glBindTexture(GL_TEXTURE_2D, uruansTexture);
trans = glm::mat4(1.0f);
trans = glm::rotate(trans, uransRotation, glm::vec3(0.0f, 1.0f, 0.0f));
trans = glm::scale(trans, glm::vec3(0.25f, 0.25f, 0.25f));
trans = glm::translate(trans, glm::vec3(4.3f, 0.f, 0.f));
trans = glm::rotate(trans, uransRotation, glm::vec3(0.0, 1.0, 0.0));
// Send transformation matrix to the shader
glUniformMatrix4fv(modelUnifrom, 1, GL_FALSE, glm::value_ptr(trans));
glDrawElements(GL_TRIANGLES, sun.getIndexCount(), GL_UNSIGNED_INT, (void*)0);
// //Draw Neptune
glBindTexture(GL_TEXTURE_2D, neptunTexture);
trans = glm::mat4(1.0f);
trans = glm::rotate(trans, neptuneRotation, glm::vec3(0.0f, 1.0f, 0.0f));
trans = glm::scale(trans, glm::vec3(0.20f, 0.20f, 0.20f));
trans = glm::translate(trans, glm::vec3(5.4f, 0.f, 0.f));
trans = glm::rotate(trans, neptuneRotation, glm::vec3(0.0, 1.0, 0.0));
// Send transformation matrix to the shader
glUniformMatrix4fv(modelUnifrom, 1, GL_FALSE, glm::value_ptr(trans));
glDrawElements(GL_TRIANGLES, sun.getIndexCount(), GL_UNSIGNED_INT, (void*)0);
//fuel
glBindVertexArray(vaoFuelTank);
glBindTexture(GL_TEXTURE_2D, fuelTankTexture);
trans = glm::mat4(1.0f);
trans = glm::translate(trans, glm::vec3(0.0f, 0.0f, -2.0f)); // Adjust the position of the fuel tank
trans = glm::scale(trans, glm::vec3(0.05f)); // Adjust the scale of the fuel tank
// Send transformation matrix to the shader
glUniformMatrix4fv(modelUnifrom, 1, GL_FALSE, glm::value_ptr(trans));
glDrawArrays(GL_TRIANGLES, 0, 36);
//spaceship
glEnable(GL_DEPTH_TEST);
ourShader.use();
glBindTexture(GL_TEXTURE_2D, spaceShipTexture);
glm::vec3 spaceshipPos = glm::vec3(0.0f, 0.0f, 0.0f);
// Camera offset
glm::vec3 cameraOffset = glm::vec3(0.0f, 1.0f, -0.5f);
// Calculate camera position
glm::vec3 cameraPos = spaceshipPos + cameraOffset;
glm::vec3 cameraTarget = spaceshipPos;
// Calculate view matrix using look-at
view = glm::lookAt(cameraPos, cameraTarget, camera.Up);
ourShader.setMat4("view", view);
ourModel.Draw(ourShader);
}
Could someone provide guidance on:
Strategies for dynamically placing spheres around existing objects, considering both 3D models and cube approximations with textures.
Techniques for accurately determining the radii of the placed spheres, accounting for variations in object representation.
Suggestions on integrating this functionality into my existing OpenGL rendering loop, ensuring compatibility with both 3D models and cube approximations.
Any advice, code examples, or recommended resources for addressing these challenges within OpenGL/C++ would be greatly appreciated!
Thank you for your insights!
When attempting to implement collision detection in my OpenGL project, I tried using sphere-sphere collision detection algorithms. I expected the collisions to accurately detect when objects intersected and trigger appropriate responses. However, the collisions were not detected accurately, leading to objects passing through each other
Ahmed is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.