Billboard矩阵

来源:互联网 发布:淘宝的人工服务在哪里 编辑:程序博客网 时间:2024/05/21 22:58

    这几天在研究Impostor,按照传统的方法可以做出来不错的效果,采用GamaStura的方法很快就可以做出来不错的效果,但是因为要扩展一下,在原先的质量上提高,而且用Instance来画,这样只需要一个quad mesh,别的信息都放在Instance Buffer上。因此需要有个Billboard矩阵,也就是说需要将一个quad mesh转换到世界坐标系。

    关于Billboard矩阵如何推导,NeHe和FlipCode都有相应的文章来讲解,NeHe讲解的更透彻一点。这虽然算是个很古老的技术,但是用到的时候还是要费一些脑细胞来挣扎一下,顺便就记录下来吧,正好可以理清思路。

http://www.flipcode.com/archives/Billboarding-Excerpt_From_iReal-Time_Renderingi_2E.shtml

http://nehe.gamedev.net/article/billboarding_how_to/18011/

    计算BillBoard矩阵之前我们需要知道CameraPos和BillBoard的中心位置CenterPos,然后可以计算出来LookAt向量look=normalize(CameraPos-CenterPos);然后我们需要计算Billboard矩阵的right向量,计算right需要Billboard矩阵的up向量,这时候我们还没有办法知道up向量,但是有一点事确定的Billboard的up位于look和主Camera的up构成平面上,而right是垂直于这个平面的,所以right=look x 主camera up;然后就可以计算出来Billboard矩阵的up。


    有了look,up,right在加上Billboar的中心位置p就可以构建出Billboard矩阵了



    上面推导的方法适合于所有类型的Billboard,按x,y,z轴或者任意轴旋转的Billboard矩阵都可以按照上面的思路来推导。NeHe的教程中也给出了各种不同类型的Billboard矩阵的计算方法。


//*****************************************************************************// This only needs to be done once for all the particles, because the view// matrix does not change any between them.  If you were to modify the view// matrix at all, you would need to recalculate the camera pos and up vector.//*****************************************************************************void GetCameraPosAndUp(Vertex3f &camPos, Vector3f &camUp){Matrix44fview;glGetFloatv(GL_MODELVIEW_MATRIX, view.matrix);// The values in the view matrix for the camera are the negative values of// the camera. This is because of the way gluLookAt works; I'm don't fully// understand why gluLookAt does what it does, but I know doing this works:)// I know that gluLookAt creates a the look vector as (eye - center), the// resulting direction vector is a vector from center to eye (the oposite// of what are view direction really is).camPos= Vertex3f(-view.matrix[12], -view.matrix[13], -view.matrix[14]);camUp= Vector3f(view.matrix[1], view.matrix[5], view.matrix[9]);// zero the translation in the matrix, so we can use the matrix to transform// camera postion to world coordinates using the view matrixview.matrix[12] = view.matrix[13] = view.matrix[14] = 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.view.TransposeRotation();// get the correct position of the camera in world spacecamPos= view * camPos;}//*****************************************************************************// Create the billboard matrix: a rotation matrix created from an arbitrary set// of axis.  Store those axis values in the first 3 columns of the matrix.  Col// 1 is the X axis, col 2 is the Y axis, and col 3 is the Z axis.  We are// rotating right into X, up into Y, and look into Z.  The rotation matrix// created from the rows will translate the arbitrary axis set to the global// axis set.  Lastly, OpenGl stores the matrices by columns, so enter the data// into the array columns first.//*****************************************************************************void CreateBillboardMatrix(Matrix44f &bbmat, const Vector3f &right, const Vector3f &up, const Vector3f &look, const Vertex3f &pos){bbmat.matrix[0] = right.x;bbmat.matrix[1] = right.y;bbmat.matrix[2] = right.z;bbmat.matrix[3] = 0;bbmat.matrix[4] = up.x;bbmat.matrix[5] = up.y;bbmat.matrix[6] = up.z;bbmat.matrix[7] = 0;bbmat.matrix[8] = look.x;bbmat.matrix[9] = look.y;bbmat.matrix[10] = look.z;bbmat.matrix[11] = 0;// Add the translation in as well.bbmat.matrix[12] = pos.x;bbmat.matrix[13] = pos.y;bbmat.matrix[14] = pos.z;bbmat.matrix[15] = 1;}//*****************************************************************************//*****************************************************************************void BillboardPoint(const Vertex3f &pos, const Vertex3f &camPos, const Vector3f &camUp){// create the look vector: pos -> camPosVector3flook= camPos - pos;look.Normalize();// right hand rule cross productsVector3fright= camUp.Cross(look);Vector3fup= look.Cross(right);Matrix44fbbmat;CreateBillboardMatrix(bbmat, right, up, look, pos);// apply the billboardglMultMatrixf(bbmat.matrix);};//*****************************************************************************//*****************************************************************************void BillboardAxisX(const Vertex3f &pos, const Vertex3f &camPos){// create the look vector: pos -> camPosVector3flook= camPos - pos;// we are billboarding along the X axis - zero the look value for xlook.x = 0;look.Normalize();// right hand rule cross products - the up vector is the +x AxisVector3fup= Vector3f(1,0,0);Vector3fright= up.Cross(look);Matrix44fbbmat;CreateBillboardMatrix(bbmat, right, up, look, pos);// apply the billboardglMultMatrixf(bbmat.matrix);};//*****************************************************************************//*****************************************************************************void BillboardAxisY(const Vertex3f &pos, const Vertex3f &camPos){// create the look vector: pos -> camPosVector3flook= camPos - pos;// we are billboarding along the Y axis - zero the look value for ylook.y = 0;look.Normalize();// right hand rule cross products - the up vector is the +y AxisVector3fup= Vector3f(0,1,0);Vector3fright= up.Cross(look);Matrix44fbbmat;CreateBillboardMatrix(bbmat, right, up, look, pos);// apply the billboardglMultMatrixf(bbmat.matrix);};//*****************************************************************************//*****************************************************************************void BillboardAxisZ(const Vertex3f &pos, const Vertex3f &camPos){// create the look vector: pos -> camPosVector3flook= camPos - pos;// we are billboarding along the Z axis - zero the look value for zlook.z = 0;look.Normalize();// right hand rule cross products - the up vector is the +z AxisVector3fup= Vector3f(0,0,1);Vector3fright= up.Cross(look);Matrix44fbbmat;CreateBillboardMatrix(bbmat, right, up, look, pos);// apply the billboardglMultMatrixf(bbmat.matrix);};//*****************************************************************************//*****************************************************************************void BillboardAxis(const Vertex3f &pos, const Vector3f &axis, const Vertex3f &camPos){// create the look vector: pos -> camPosVector3flook= camPos - pos;look.Normalize();// billboard about the direction vectorVector3fup= axis;Vector3fright= up.Cross(look);// watch out when the look vector is almost equal to the up vector the right// vector gets close to zeroed, normalize itright.Normalize();// the billboard won't actually face the direction of the look vector we// created earlier, that was just used as a tempory vector to create the// right vector so we could calculate the correct look vector from that.look = right.Cross(up);Matrix44fbbmat;CreateBillboardMatrix(bbmat, right, up, look, pos);// apply the billboardglMultMatrixf(bbmat.matrix);};


0 0
原创粉丝点击