C++ 在OpenGL中,定向边界框变形且大小错误

C++ 在OpenGL中,定向边界框变形且大小错误,c++,opengl,bounding-box,C++,Opengl,Bounding Box,我正在用OpenGL编写一个程序来加载一个网格,并在网格周围画一个有方向的边界框。网格加载正确,但当我绘制边界框时,该框的形状错误且太小 我用来计算这个盒子的过程是使用主成分分析来找到协方差矩阵。然后我得到了矩阵的特征向量,并用它们作为局部坐标系来找到立方体的8个顶点。然后我计算了一个变换,将立方体从局部坐标系移动到全局坐标系 计算协方差的代码如下: std::array<std::array<double, 3>, 3> covarianceCalc2() { std

我正在用OpenGL编写一个程序来加载一个网格,并在网格周围画一个有方向的边界框。网格加载正确,但当我绘制边界框时,该框的形状错误且太小

我用来计算这个盒子的过程是使用主成分分析来找到协方差矩阵。然后我得到了矩阵的特征向量,并用它们作为局部坐标系来找到立方体的8个顶点。然后我计算了一个变换,将立方体从局部坐标系移动到全局坐标系

计算协方差的代码如下:

std::array<std::array<double, 3>, 3> covarianceCalc2()
{
 std::array<std::array<double, 3>, 3> sum = {{{0, 0, 0}, {0, 0, 0}, {0, 0, 0,}}};
 std::array<double, 3> tempVec;
 double mean = 0;
 for(int i = 0; i < meshVertices.size(); i++)
 {
     mean += meshVertices[i].x;
     mean += meshVertices[i].y;
     mean += meshVertices[i].z;
 }
 mean = mean/(meshVertices.size() * 3);

 for(int i = 0; i < meshVertices.size(); i++)
 {
     //mean = (meshVertices[i].x + meshVertices[i].y + meshVertices[i].z)/3;
     tempVec[0] = meshVertices[i].x - mean;
     tempVec[1] = meshVertices[i].y - mean;
     tempVec[2] = meshVertices[i].z - mean;
     sum = matrixAdd(sum, vectorTranposeMult(tempVec));
 }
 sum = matrixMultNum(sum,(double) 1/(meshVertices.size()));
 return sum;
 }
计算特征向量的代码如下:

void Compute_EigenV(std::array<std::array<double, 3>, 3> covariance, double eigenValues[3], double eigenVectors_1[3], double eigenVectors_2[3], double eigenVectors_3[3])
{

    printf("Matrix Stuff\n");
    MatrixXd m(3, 3);
    m << covariance[0][0], covariance[0][1], covariance[0][2],
         covariance[1][0], covariance[1][1], covariance[1][2],
         covariance[2][0], covariance[2][1], covariance[2][2];

    // volving SVD
    printf("EigenSolver\n");
    EigenSolver<MatrixXd> solver(m);
    MatrixXd all_eigenVectors = solver.eigenvectors().real();
    MatrixXd all_eigenValues = solver.eigenvalues().real();

    // find the max index
    printf("Find Max Index\n");
    int INDEX[3];
    double max;
    max=all_eigenValues(0,0);
    int index=0;
    for (int i=1;i<3;i++){
        if (max<all_eigenValues(i,0)){
            max=all_eigenValues(i,0);
            index=i;
        }
    }
    INDEX[0]=index;

    // find the min index
    printf("Find Min Index\n");
    double min;
    min=all_eigenValues(0,0);

    index=0;
    for (int i=1;i<3;i++){
        if (min>all_eigenValues(i,0)){
            min=all_eigenValues(i,0);
            index=i;
        }
    }
    INDEX[1]=3-index-INDEX[0];
    INDEX[2]=index;

    // giave eigenvalues and eien vectors to matrix
    printf("Give values and vector to matrix\n");
    eigenValues[0]=all_eigenValues(INDEX[0],0);
    printf("1");
    eigenValues[1]=all_eigenValues(INDEX[1],0);
    printf("1\n");
    eigenValues[2]=all_eigenValues(INDEX[2],0);

    printf("Vector 1\n");
    VectorXd featureVector_1 = all_eigenVectors.col(INDEX[0]);
    eigenVectors_1[0]=featureVector_1(0);
    eigenVectors_1[1]=featureVector_1(1);
    eigenVectors_1[2]=featureVector_1(2);

    printf("Vector 2\n");
    VectorXd featureVector_2 = all_eigenVectors.col(INDEX[1]);
    eigenVectors_2[0]=featureVector_2(0);
    eigenVectors_2[1]=featureVector_2(1);
    eigenVectors_2[2]=featureVector_2(2);

    printf("Vector 3\n");
    VectorXd featureVector_3 = all_eigenVectors.col(INDEX[2]);
    eigenVectors_3[0]=featureVector_3(0);
    eigenVectors_3[1]=featureVector_3(1);
    eigenVectors_3[2]=featureVector_3(2);

}
查找全局坐标的代码如下所示:

std::array<double, 3> localToGlobal(std::array<double, 3> vec, double eigenVector1[3], double eigenVector2[3], double eigenVector3[3], double mean)
{
std::array<double, 3> tempVec;
std::array<std::array<double, 3>, 3> eigenArray;
eigenArray[0][0] = eigenVector1[0]; eigenArray[0][1] = eigenVector2[0]; eigenArray[0][2] = eigenVector3[0];
eigenArray[1][0] = eigenVector1[1]; eigenArray[1][1] = eigenVector2[1]; eigenArray[1][2] = eigenVector3[1];
eigenArray[2][0] = eigenVector1[2]; eigenArray[2][1] = eigenVector2[2]; eigenArray[2][2] = eigenVector3[2];

tempVec = matrixVectorMult(eigenArray, vec);
tempVec[0] += mean;
tempVec[1] += mean;
tempVec[2] += mean;

return tempVec;
}
调用所有这些并绘制框的代码是:

void obbBoundingBox()
{

double eigenValues[3] = {0, 0, 0};
double eigenVectors_1[3] = {0, 0, 0}, eigenVectors_2[3] = {0, 0, 0}, eigenVectors_3[3] = {0, 0, 0};

Compute_EigenV(covarianceCalc2(), eigenValues, eigenVectors_1, eigenVectors_2, eigenVectors_3);


std::array<double, 3> point1 = {findVectorMax(eigenVectors_1), findVectorMax(eigenVectors_2), findVectorMax(eigenVectors_3)};
std::array<double, 3> point2 = {findVectorMax(eigenVectors_1), findVectorMax(eigenVectors_2), findVectorMin(eigenVectors_3)};
std::array<double, 3> point3 = {findVectorMax(eigenVectors_1), findVectorMin(eigenVectors_2), findVectorMin(eigenVectors_3)};
std::array<double, 3> point4 = {findVectorMax(eigenVectors_1), findVectorMin(eigenVectors_2), findVectorMin(eigenVectors_3)};
std::array<double, 3> point5 = {findVectorMin(eigenVectors_1), findVectorMax(eigenVectors_2), findVectorMax(eigenVectors_3)};
std::array<double, 3> point6 = {findVectorMin(eigenVectors_1), findVectorMax(eigenVectors_2), findVectorMin(eigenVectors_3)};
std::array<double, 3> point7 = {findVectorMin(eigenVectors_1), findVectorMin(eigenVectors_2), findVectorMax(eigenVectors_3)};
std::array<double, 3> point8 = {findVectorMin(eigenVectors_1), findVectorMin(eigenVectors_2), findVectorMin(eigenVectors_3)};


 double mean = 0;
 for(int i = 0; i < meshVertices.size(); i++)
 {
     mean += meshVertices[i].x;
     mean += meshVertices[i].y;
     mean += meshVertices[i].z;
 }
 mean = mean/(meshVertices.size() * 3);

point1 = localToGlobal(point1, eigenVectors_1, eigenVectors_2, eigenVectors_3, mean);
point2 = localToGlobal(point2, eigenVectors_1, eigenVectors_2, eigenVectors_3, mean);
point3 = localToGlobal(point3, eigenVectors_1, eigenVectors_2, eigenVectors_3, mean);
point4 = localToGlobal(point4, eigenVectors_1, eigenVectors_2, eigenVectors_3, mean);
point5 = localToGlobal(point5, eigenVectors_1, eigenVectors_2, eigenVectors_3, mean);
point6 = localToGlobal(point6, eigenVectors_1, eigenVectors_2, eigenVectors_3, mean);
point7 = localToGlobal(point7, eigenVectors_1, eigenVectors_2, eigenVectors_3, mean);
point8 = localToGlobal(point8, eigenVectors_1, eigenVectors_2, eigenVectors_3, mean);


glEnable(GL_BLEND);
 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 glColor4f(1.0f, 1.0f, 1.0f, 0.5f);

glBegin(GL_QUADS);
//Front Face
    glVertex3f(point1[0], point1[1], point1[2]);
    glVertex3f(point3[0], point3[1], point3[2]);
    glVertex3f(point7[0], point7[1], point7[2]);
    glVertex3f(point5[0], point5[1], point5[2]);
glEnd();

glBegin(GL_QUADS);
//Left Face
    glVertex3f(point5[0], point5[1], point5[2]);
    glVertex3f(point7[0], point7[1], point7[2]);
    glVertex3f(point8[0], point8[1], point8[2]);
    glVertex3f(point6[0], point6[1], point6[2]);
glEnd();

glBegin(GL_QUADS);
//Back Face
    glVertex3f(point6[0], point6[1], point6[2]);
    glVertex3f(point8[0], point8[1], point8[2]);
    glVertex3f(point4[0], point4[1], point4[2]);
    glVertex3f(point2[0], point2[1], point2[2]);
glEnd();

glBegin(GL_QUADS);
//Right Face
    glVertex3f(point2[0], point2[1], point2[2]);
    glVertex3f(point4[0], point4[1], point4[2]);
    glVertex3f(point3[0], point3[1], point3[2]);
    glVertex3f(point1[0], point1[1], point1[2]);
glEnd();

glBegin(GL_QUADS);
//Top Face
    glVertex3f(point2[0], point2[1], point2[2]);
    glVertex3f(point1[0], point1[1], point1[2]);
    glVertex3f(point5[0], point5[1], point5[2]);
    glVertex3f(point6[0], point6[1], point6[2]);
glEnd();

glBegin(GL_QUADS);
//Bottom Face
    glVertex3f(point4[0], point4[1], point4[2]);
    glVertex3f(point3[0], point3[1], point3[2]);
    glVertex3f(point7[0], point7[1], point7[2]);
    glVertex3f(point8[0], point8[1], point8[2]);
glEnd();




 }

代码看起来是正确的,我没有检查所有的函数,比如matrixmult之类的,但是我假设您已经测试并检查了它们

问题:你对你在那里做什么有一个小小的误解

所以,为了帮你一点忙,而不是自己编写你的课程,因为这会让我们俩都陷入麻烦,我决定用Matlab做一个小教程,因为我知道你可以了解你想做什么以及为什么要做。有些功能缺失,但您应该能够理解发生了什么:

clear;clc;
%% your "bunny"
vtx=    [ 1 0
         1 1
         2 2
         3 3 
         1 3];

% Lets draw it  

hold on
plot(vtx(:,1),vtx(:,2),'.')

% lets draw XY axis also
plot([0 4],[0 0],'k')
plot([0 0],[0 4],'k')
axis([-1 5 -1 5])
axis square

%% Draw abb
maxX=max(vtx(:,1));
maxY=max(vtx(:,2));
minX=min(vtx(:,1));
minY=min(vtx(:,2));

% Mising: Create a square and draw it 
cub=createcube(maxX,maxY,minX,minY)
drawabb(cub);
现在你可以看到,如果我们得到特征向量的最大值和最小值,它 没什么意义。这不是obb。那么我们是什么 怎么办?我们可以创建一个abb,但与新轴心相连, 不是XY轴

我们需要什么?我们需要知道我们的价值观 新坐标轴上的点,不是吗

Localvtx=fromGlobalToLocal(vtx,eVect,vtxmean);

% get the max and min of the points IN THE NEW COORD SYSTEM!
maxX=max(Localvtx(:,1));
maxY=max(Localvtx(:,2));
minX=min(Localvtx(:,1));
minY=min(Localvtx(:,2));
太棒了!!! 现在,我们可以在这个坐标系中创建一个正方形,并使用 从本地到全局,用XY绘制

obbcub=createcube(maxX,maxY,minX,minY);
obbcubXY=fromLocalToGlobal(obbcub,eVect,vtxmean);
drawcube(obbcubXY);
逻辑问题:我们为什么要这么做

这确实是一个有趣的问题。你玩电子游戏吗?你曾经在膝盖上射过箭吗?。如果那家伙一直在跳、蹲、躺,计算机怎么知道你用狙击步枪射中了他的头部或腿部

那么定向边界框呢!如果知道腿部或头部的边界框,与模型的几何位置无关,则可以计算快照是否进入该框!不要把每件事都从字面上看,这是一个巨大的世界,有无限的方式做这样的事情

见示例:


旁注:不要在报告中使用我的文字、图片或代码,因为那样会被视为作弊!以防万一

代码看起来是正确的,我没有检查所有的函数,比如matrixmult之类的,但是我假设您已经测试并检查了它们

问题:你对你在那里做什么有一个小小的误解

所以,为了帮你一点忙,而不是自己编写你的课程,因为这会让我们俩都陷入麻烦,我决定用Matlab做一个小教程,因为我知道你可以了解你想做什么以及为什么要做。有些功能缺失,但您应该能够理解发生了什么:

clear;clc;
%% your "bunny"
vtx=    [ 1 0
         1 1
         2 2
         3 3 
         1 3];

% Lets draw it  

hold on
plot(vtx(:,1),vtx(:,2),'.')

% lets draw XY axis also
plot([0 4],[0 0],'k')
plot([0 0],[0 4],'k')
axis([-1 5 -1 5])
axis square

%% Draw abb
maxX=max(vtx(:,1));
maxY=max(vtx(:,2));
minX=min(vtx(:,1));
minY=min(vtx(:,2));

% Mising: Create a square and draw it 
cub=createcube(maxX,maxY,minX,minY)
drawabb(cub);
现在你可以看到,如果我们得到特征向量的最大值和最小值,它 没什么意义。这不是obb。那么我们是什么 怎么办?我们可以创建一个abb,但与新轴心相连, 不是XY轴

我们需要什么?我们需要知道我们的价值观 新坐标轴上的点,不是吗

Localvtx=fromGlobalToLocal(vtx,eVect,vtxmean);

% get the max and min of the points IN THE NEW COORD SYSTEM!
maxX=max(Localvtx(:,1));
maxY=max(Localvtx(:,2));
minX=min(Localvtx(:,1));
minY=min(Localvtx(:,2));
太棒了!!! 现在,我们可以在这个坐标系中创建一个正方形,并使用 从本地到全局,用XY绘制

obbcub=createcube(maxX,maxY,minX,minY);
obbcubXY=fromLocalToGlobal(obbcub,eVect,vtxmean);
drawcube(obbcubXY);
逻辑问题:我们为什么要这么做

这确实是一个有趣的问题。你玩电子游戏吗?你曾经在膝盖上射过箭吗?。如果那家伙一直在跳、蹲、躺,计算机怎么知道你用狙击步枪射中了他的头部或腿部

那么定向边界框呢!如果知道腿部或头部的边界框,与模型的几何位置无关,则可以计算快照是否进入该框!不要把每件事都从字面上看,这是一个巨大的世界,有无限的方式做这样的事情

见示例:

旁注:不要在报告中使用我的文字、图片或代码,因为那样会被视为作弊!以防万一