2012-09-01 48 views
1

我在这里看到了这个主题,但它并没有真正帮助我解决问题:(我尝试以相同的方式实现代码,不幸的是我不能使用glLoadIdentity(),因为我正在使用libqglviewer,并且出于某种奇怪的原因,如果我使用glLoadIdentity()对象(常规多维数据集)消失:(所以我的解决方法是我使用glPopMatrix和glPushMatrix保持世界矩阵每次我必须翻译/旋转一个对象原始矩阵正在被储存起来,然后一旦完成翻译/旋转,我再次弹出它的右后方在对象的旋转/平移之后重新计算AABB

到目前为止,工作得很好,但是一旦我试图实现边界框的重新计算,我的盒子就从s开始作为立方体的ame位置,但一旦我开始旋转边界框有时会“内爆”,因此我需要检查最大/最小转角,使它们不会小于立方体本身,但是当我旋转相机时,边界框转移到一边或另一边。

我正在使用GLM来加载模型,不幸的是遗留OpenGL,我对Legacy OGL的工作原理有些熟悉,但我认为重新计算边界框时计算不正确。

此代码是在我的渲染功能:

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(); 

这是我设置的边框代码:

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(); 
} 

这最后一块是我重新计算框:

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; 
} 

我一直在试图关注这个帖子How to recalculate axis-aligned bounding box after translate/rotate?,但还没有设法得到它窝rk与我的代码上面。

任何关于我哪里出错的指针都会有帮助。

回答

1
  1. 您应该使用一个函数库或者编写自己的函数来进行向量矩阵乘法,手工操作容易出错(如此处)。
  2. 与矩阵相乘时,您将覆盖矢量分量,但仍需要旧值进行读取(例如box-> max.x)。您应该将结果存储在一个新框(boxTransformed)中(一旦完成,您可以复制回旧的框)。
  3. 转换后,您应该采用boxTransformed的最大和最小向量的分量最大值和最小值来生成新的边界框。