I've seen this topic around here but it didn't really help me solve the problem :( I've tried to implement the code kinda like the same way but something isn't working properly. Unfortunately I can't use glLoadIdentity() since I'm working with libqglviewer and for some odd reason if I do use glLoadIdentity() the object (a regular cube) disappears :( so my workaround is I use glPopMatrix and glPushMatrix to keep the world matrix intact each time I have to translate/rotate an object. The original matrix is being stored away and then once the translation/rotation is done I pop it right back again.
So far that has worked fine, but once I tried to implement the recalculation of the bounding box my box starts of at the same position as the cube but once I start rotating it the bounding box sometimes "implodes" hence I need to check the max/min corners so they don't get smaller than the cube itself, but when I rotate the camera the bounding box shifts of to one or the other side.
I'm using GLM to load the models and unfortunately Legacy OpenGL, I'm somewhat familiar with how Legacy OGL works but something isn't right with the calculations of the bounding box when it is recalculated I think.
This code is in my render function:
glPushMatrix();
glTranslatef(position.x, position.y, position.z);
glRotatef(m_angle, m_torque.x, m_torque.y, m_torque.z);
glGetFloatv(GL_MODELVIEW_MATRIX, mvMatrix);
glmDraw(pModelCube, GLM_SMOOTH); // Renders the object
glPopMatrix();
glPushMatrix();
glTranslatef(position.x, position.y, position.z);
bb->RecalculateBox(pModelCube, mvMatrix, BBid);
bb->DrawBox(bb->GetBoundingBox(BBid));
glPopMatrix();
This is my code for setting up the bounding box:
void AABB::initBox(BoundingBox* b)
{
b->min.x = 10000.0f;
b->min.y = 10000.0f;
b->min.z = 10000.0f;
b->max.x = -10000.0f;
b->max.y = -10000.0f;
b->max.z = -10000.0f;
}
BoundingBox* AABB::CreateCollisionBox(GLMmodel* model, GLMgroup* object)
{
BoundingBox* box = (BoundingBox*)malloc(sizeof(BoundingBox));
initBox(box);
for(int i = 0; i < object->numtriangles; i++)
{
for(int j = 0; j < 3; j++)
{
GLuint index = model->triangles[object->triangles[i]].vindices[j];
GLfloat x = model->vertices[index*3 + 0];
GLfloat y = model->vertices[index*3 + 1];
GLfloat z = model->vertices[index*3 + 2];
if(box->min.x > x) box->min.x = x;
if(box->min.y > y) box->min.y = y;
if(box->min.z > z) box->min.z = z;
if(box->max.x < x) box->max.x = x;
if(box->max.y < y) box->max.y = y;
if(box->max.z < z) box->max.z = z;
}
}
return box;
}
void AABB::DrawBox(BoundingBox* b)
{
if(collision)
{
// Sets color to red
glColor3f(1.0f, 0.0f, 0.0f);
}
else
{
// Sets color to yellow
glColor3f(1.0f, 1.0f, 0.0f);
}
glBegin(GL_LINE_LOOP);
glVertex3f(b->max.x, b->max.y, b->min.z);
glVertex3f(b->min.x, b->max.y, b->min.z);
glVertex3f(b->min.x, b->min.y, b->min.z);
glVertex3f(b->max.x, b->min.y, b->min.z);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex3f(b->max.x, b->min.y, b->max.z);
glVertex3f(b->max.x, b->max.y, b->max.z);
glVertex3f(b->min.x, b->max.y, b->max.z);
glVertex3f(b->min.x, b->min.y, b->max.z);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex3f(b->max.x, b->max.y, b->min.z);
glVertex3f(b->max.x, b->max.y, b->max.z);
glVertex3f(b->min.x, b->max.y, b->max.z);
glVertex3f(b->min.x, b->max.y, b->min.z);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex3f(b->max.x, b->min.y, b->max.z);
glVertex3f(b->min.x, b->min.y, b->max.z);
glVertex3f(b->min.x, b->min.y, b->min.z);
glVertex3f(b->max.z, b->min.y, b->min.z);
glEnd();
}
This final piece is where I recalculate the box:
void AABB::RecalculateBox(GLMmodel* model, float matrix[16], int &id)
{
BoundingBox* box = boxes[id]/*(BoundingBox*)malloc(sizeof(BoundingBox))*/;
initBox(box);
float dimensions[3];
// This will get the absolute dimensions of the object
glmDimensions(model, dimensions);
box->max.x = dimensions[0] / 2.0f, box->min.x = -1.0f * box->max.x;
box->max.y = dimensions[1] / 2.0f, box->min.y = -1.0f * box->max.y;
box->max.z = dimensions[2] / 2.0f; box->min.z = -1.0f * box->max.z;
box->max.x = matrix[0] * box->max.x + matrix[4] * box->max.y + matrix[8] * box->max.z + matrix[12];
box->max.y = matrix[1] * box->max.x + matrix[5] * box->max.y + matrix[9] * box->max.z + matrix[13];
box->max.z = matrix[2] * box->max.x + matrix[6] * box->max.y + matrix[10] * box->max.z + matrix[14];
box->min.x = matrix[0] * box->min.x + matrix[4] * box->min.y + matrix[8] * box->min.z + matrix[12];
box->min.y = matrix[1] * box->min.x + matrix[5] * box->min.y + matrix[9] * box->min.z + matrix[13];
box->min.z = matrix[2] * box->min.x + matrix[6] * box->min.y + matrix[10] * box->min.z + matrix[14];
box->bounds[0] = Vec(box->max.x, box->max.y, box->min.z);
box->bounds[1] = Vec(box->min.x, box->max.y, box->min.z);
box->bounds[2] = Vec(box->min.x, box->min.y, box->min.z);
box->bounds[3] = Vec(box->max.x, box->min.y, box->min.z);
box->bounds[4] = Vec(box->max.x, box->min.y, box->max.z);
box->bounds[5] = Vec(box->max.x, box->max.y, box->max.z);
box->bounds[6] = Vec(box->min.x, box->max.y, box->max.z);
box->bounds[7] = Vec(box->min.x, box->min.y, box->max.z);
//This code below is from how my bounding box was calculated before.
/*for(int i = 0; i < object->numtriangles; i++)
{
for(int j = 0; j < 3; j++)
{
GLuint index = model->triangles[object->triangles[i]].vindices[j];
GLfloat x = model->vertices[index*3 + 0];
GLfloat y = model->vertices[index*3 + 1];
GLfloat z = model->vertices[index*3 + 2];
if(box->min.x > x) box->min.x = x;
if(box->min.y > y) box->min.y = y;
if(box->min.z > z) box->min.z = z;
if(box->max.x < x) box->max.x = x;
if(box->max.y < y) box->max.y = y;
if(box->max.z < z) box->max.z = z;
}
}*/
boxes[id] = box;
}
I've been trying to follow this post How to recalculate axis-aligned bounding box after translate/rotate? but haven't managed to get it to work with my code above.
Any pointers as to where I'm going wrong would be helpful.