我正在为一个专有的网格& OpenGL中的动画格式。
在渲染过程中,会为每个骨骼(节点)创建变换矩阵,并将其应用于骨骼所附着的顶点。
骨骼有可能被标记为“Billboarded”,大多数人都知道,这意味着它应该始终面向相机。
因此,我们的想法是为该骨骼生成一个矩阵,当用于变换它所附着的顶点时,会使顶点成为广告牌。
在我的测试模型上,它应该如下所示:
但目前看起来像这样:
请注意,尽管方向不正确,但它是广告牌。无论相机在哪个方向看,这些顶点始终朝向该方向。
我生成标记为广告牌的骨骼矩阵的代码是:
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进行数学计算。
虽然代码的这一部分基于教程here,但代码的其他部分基于类似于我正在构建的开源程序。然而,该程序是为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);
请注意,结果存储在directX版本的baseMatrix中。
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;
}
答案 0 :(得分:3)
创建并行视图广告牌矩阵就像将总模型视图矩阵的左上3×3子矩阵设置为标识一样简单。只有某些情况下您实际需要实际的外观向量。
无论如何,你的想法太复杂了。你对矩阵的修补完全忽略了这一点。也就是说,模型视图转换假设摄像机始终位于(0,0,0)并且相反地移动世界和模型。您尝试做的是在模型空间中找到指向相机的矢量。这只是转换后指向(0,0,0)的向量。
所以我们要做的就是反转模型视图矩阵并用它转换(0,0,0,1)。那是你的外观矢量。对于右向和向上矢量的计算,将模型视图矩阵的第一(X)和第二(Y)列与该外观矢量正交化。
答案 1 :(得分:0)
自己想出来。事实证明我正在使用的模型格式使用不同的轴进行广告牌。大多数广告牌实施(包括我使用的实施)使用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的建议没有成功,此时他没有提供任何额外的解释,所以我不确定为什么。不管怎样,谢谢!