gpt4 book ai didi

c++ - 对象旋转/平移后重新计算正确的 AABB

转载 作者:太空宇宙 更新时间:2023-11-04 12:05:43 25 4
gpt4 key购买 nike

我在这里看到过这个话题,但它并没有真正帮助我解决问题:(使用 glLoadIdentity() 因为我正在使用 libqglviewer 并且由于一些奇怪的原因如果我使用 glLoadIdentity() 对象(一个常规立方体)消失:(所以我的解决方法是我每次都使用 glPopMatrix 和 glPushMatrix 保持世界矩阵完好无损我必须平移/旋转一个对象。原始矩阵被存储起来,然后在平移/旋转完成后,我再次将其弹出。

到目前为止一切正常,但是一旦我尝试重新计算边界框,我的盒子就会从与立方体相同的位置开始,但是一旦我开始旋转它,边界框有时会“内爆”,因此我需要检查最大/最小角,这样它们就不会比立方体本身小,但是当我旋转相机时,边界框会移动到一侧或另一侧。

我正在使用 GLM 加载模型,不幸的是 Legacy 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();
}

这最后一 block 是我重新计算盒子的地方:

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?但还没有设法让它与我上面的代码一起工作。

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

最佳答案

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

关于c++ - 对象旋转/平移后重新计算正确的 AABB,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12226420/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com