How to implement collision detection between spheres in OpenGL/C++?

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

New contributor

Ahmed is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật