OpenGL的广告牌矩阵(Opengl Billboard matrix)

2019-10-18 11:11发布

我写在OpenGL的专用网和动画格式的浏览器。

在渲染过程中的变换矩阵对于每个骨(节点)创建并应用到骨附接至顶点。

这是可能的骨被标记为“布告板式”,这是大多数人都知道,意味着它应该总是面对摄像机。

这样的想法是产生它用来改造它附加到顶点时骨基质,使顶点被布告板式。

在我的测试模型,它应该是这样的:

不过目前看起来是这样的:

请注意,尽管其不正确的方向,这是布告板式。 正如无论相机看起来哪个方向,这些顶点总是面临着在那个方位方向。

我对生成矩阵标记为布告板式是骨头代码:

    mat4        view;
    glGetFloatv(GL_MODELVIEW_MATRIX, (float*)&view);

    vec4 camPos = vec4(-view[3].x, -view[3].y, -view[3].z,1);
    vec3 camUp  = vec3(view[0].y, view[1].y, view[2].y);

    // zero the translation in the matrix, so we can use the matrix to transform
    // camera postion to world coordinates using the view matrix
    view[3].x = view[3].y = view[3].z = 0;

    // the view matrix is how to get to the gluLookAt pos from what we gave as
    // input for the camera position, so to go the other way we need to reverse
    // the rotation.  Transposing the matrix will do this.
    {
        float * matrix = (float*)&view;
        float   temp[16];
        // copy this into temp
        memcpy(temp, matrix, sizeof(float) * 16);
        matrix[1] = temp[4];    matrix[4] = temp[1];
        matrix[2] = temp[8];    matrix[8] = temp[2];
        matrix[6] = temp[9];    matrix[9] = temp[6];
    }

    // get the correct position of the camera in world space
    camPos  = view * camPos;

    //vec3 pos = pivot;

    vec3 look = glm::normalize(vec3(camPos.x-pos.x,camPos.y-pos.y,camPos.z-pos.z));
    vec3 right = glm::cross(camUp,look);
    vec3 up = glm::cross(look,right);


    mat4 bmatrix;
    bmatrix[0].x = right.x;
    bmatrix[0].y = right.y;
    bmatrix[0].z = right.z;
    bmatrix[0].w = 0;

    bmatrix[1].x = up.x;
    bmatrix[1].y = up.y;
    bmatrix[1].z = up.z;
    bmatrix[1].w = 0;

    bmatrix[2].x = look.x;
    bmatrix[2].y = look.y;
    bmatrix[2].z = look.z;
    bmatrix[2].w = 0;

    bmatrix[3].x = pos.x;
    bmatrix[3].y = pos.y;
    bmatrix[3].z = pos.z;
    bmatrix[3].w = 1;

我使用GLM做所涉及的数学。

虽然这部分代码是基于关闭教程这里 ,代码的其他部分都基于一个类似于我建立一个开源项目。 但是,这种程序对DirectX写的,我没有多少运气直接转换。 对于广告牌效果的(工作)的DirectX代码如下所示:

    D3DXMatrixRotationY(&CameraRotationMatrixY, -Camera.GetPitch());
    D3DXMatrixRotationZ(&CameraRotationMatrixZ, Camera.GetYaw());
    D3DXMatrixMultiply(&CameraRotationMatrix, &CameraRotationMatrixY, &CameraRotationMatrixZ);
    D3DXQuaternionRotationMatrix(&CameraRotation, &CameraRotationMatrix);
    D3DXMatrixTransformation(&CameraRotationMatrix, NULL, NULL, NULL, &ModelBaseData->PivotPoint, &CameraRotation, NULL);

    D3DXMatrixDecompose(&Scaling, &Rotation, &Translation, &BaseMatrix);
    D3DXMatrixTransformation(&RotationMatrix, NULL, NULL, NULL, &ModelBaseData->PivotPoint, &Rotation, NULL);

    D3DXMatrixMultiply(&TempMatrix, &CameraRotationMatrix, &RotationMatrix);
    D3DXMatrixMultiply(&BaseMatrix, &TempMatrix, &BaseMatrix);

请注意,结果存储在baseMatrix的DirectX版本。

EDIT2:这里是我想出了当我试图根据datenwolf的建议修改我的代码。 我敢肯定我犯了一些错误依然。 这种尝试创建与相机对象的一端直接严重扭曲的结果。

    mat4        view;
    glGetFloatv(GL_MODELVIEW_MATRIX, (float*)&view);

    vec3 pos = vec3(calculatedMatrix[3].x,calculatedMatrix[3].y,calculatedMatrix[3].z);

    mat4 inverted = glm::inverse(view);

    vec4 plook = inverted * vec4(0,0,0,1);
    vec3 look = vec3(plook.x,plook.y,plook.z);
    vec3 right = orthogonalize(vec3(view[0].x,view[1].x,view[2].x),look);
    vec3 up = orthogonalize(vec3(view[0].y,view[1].y,view[2].y),look);

    mat4 bmatrix;
    bmatrix[0].x = right.x;
    bmatrix[0].y = right.y;
    bmatrix[0].z = right.z;
    bmatrix[0].w = 0;

    bmatrix[1].x = up.x;
    bmatrix[1].y = up.y;
    bmatrix[1].z = up.z;
    bmatrix[1].w = 0;

    bmatrix[2].x = look.x;
    bmatrix[2].y = look.y;
    bmatrix[2].z = look.z;
    bmatrix[2].w = 0;

    bmatrix[3].x = pos.x;
    bmatrix[3].y = pos.y;
    bmatrix[3].z = pos.z;
    bmatrix[3].w = 1;

    calculatedMatrix = bmatrix;

vec3 orthogonalize(vec3 toOrtho, vec3 orthoAgainst) {
    float bottom = (orthoAgainst.x*orthoAgainst.x)+(orthoAgainst.y*orthoAgainst.y)+(orthoAgainst.z*orthoAgainst.z);
    float top = (toOrtho.x*orthoAgainst.x)+(toOrtho.y*orthoAgainst.y)+(toOrtho.z*orthoAgainst.z);
    return toOrtho - top/bottom*orthoAgainst;
}

Answer 1:

创建平行,以查看广告牌矩阵是作为总模型视图矩阵的左上方的3×3子矩阵设为身份一样简单。 只有某些情况下,你实际需要实际的注视向量。

总之,你想过于复杂。 你与矩阵中所有的修修补补完全不得要领。 即,该模型视图变换假定摄像机总是在(0,0,0),并在相对的移动世界和模型。 你尝试做的是发现对相机指向在模型空间中的向量。 这很简单,就是将改造后朝(0,0,0)点的载体。

所以我们要做的就是反转模型视图矩阵,并用它变换(0,0,0,1)。 那是你的注视向量。 为了您的权利,向上向量计算正交第1(X)和针对注视向量模型视图矩阵的第二(Y)列。



Answer 2:

理解了它自己。 事实证明,我使用的模型格式采用不同轴的广告牌效果。 大多数产生广告牌实现(包括我使用的)使用X,Y坐标到布告板式对象位置。 我读的格式使用Y和Z.

要查找的事情是,有一个广告牌效果的影响,但方向错误。 为了解决这个问题我打了不同的相机向量,直到我来到了正确的矩阵计算:

    bmatrix[1].x = right.x;
    bmatrix[1].y = right.y;
    bmatrix[1].z = right.z;
    bmatrix[1].w = 0;

    bmatrix[2].x = up.x;
    bmatrix[2].y = up.y;
    bmatrix[2].z = up.z;
    bmatrix[2].w = 0;

    bmatrix[0].x = look.x;
    bmatrix[0].y = look.y;
    bmatrix[0].z = look.z;
    bmatrix[0].w = 0;

    bmatrix[3].x = pos.x;
    bmatrix[3].y = pos.y;
    bmatrix[3].z = pos.z;
    bmatrix[3].w = 1;

我试图追随datenwolf的建议没有成功,此时他还没有提供的任何补充说明,所以我不清楚为什么。 不管怎么说,多谢拉!



文章来源: Opengl Billboard matrix