广告牌技术教程:欺骗-快速但不容易

来源:互联网 发布:dx12优化补丁 编辑:程序博客网 时间:2024/04/28 17:41

As mentioned before to get a cheating version of a billboard it is enough to reverse the orientations of the top 3x3 submatrix from the modelview matrix. The previous sections achieved this by setting this submatrix such that the appropriate transformations were reversed.

正如先前提到的要想得到一个欺骗性质的广告牌,重置top3X3子矩阵-模型视图矩阵。先前的部分被实现了通过设置子矩阵从而变换被重置。

In here an alternative approach is presented. This is also a popular approach, it even got mentioned in the bookOpenGL Game Programming.

在这里一个可选的方法被提供。这也是一个流行的方法,它甚至在OpenGL Game Programming这本书里面也提及了。

Instead of changing the modelview matrix, the vertices of the billboard are manually transformed. This transformation effectively reverses the orientations present in the modelview matrix. The end result is the same as the one presented in the previous sections.

不同于改变模型视图矩阵,广告牌的顶点被人工转换了。这个转换有效的重置了当前的模型视图矩阵的方向。最终得到和先前一样的效果。

The vertices of the billboard are defined using up and right vectors that reverse the orientations of the modelview matrix. These vectors can be extracted from the inverse of M1.

广告牌的顶点被右向量和上向量定义,这向量是重置模型视图矩阵方向的向量。这里说的向里可以从M1的转置矩阵中提取。

Fortunately, for an orthogonal matrix, the inverse is equal to the transpose. Is M1 orthogonal? It should be. If you're only usinggluLookAt to perform you're camera movements, or just doing translations and rotations to the camera, then M1 is orthogonal. If, on the other hand you mess around with the modelview matrix then you may end up with M1 not being orthogonal.

幸运的是,对于正交矩阵,逆与转置是同样效果的。M1是正交的吗?他应该是,如果你仅仅用gluLookAt来操作你的相机的移动,或者仅仅对相机做了移动旋转操作,那么M1矩阵应该是正交的。如果你乱操作模型视图矩阵,那么M1矩阵就不是正交的。

Just in case you're wondering what the $%*# is a transpose, a matrix A is a tranpose of B, AT = B, if aij = bji, for every element.

你可能纠结于转置矩阵,矩阵A是B的转置矩阵的话,那么AT=B,if aij=bji,对于每个元素。

So what is an orthogonal matrix? As mentioned before, a square matrix Q is orthogonal if Q x QT = I, where QT is the transpose of Q and I is the identity matrix. In practice this means that the multiplying any two different columns or rows returns zero. This means that the dot product is zero, and therefore that the vectors are at right angles. It also means that multiplying a vector by itself should give 1, i.e. the vectors are normalized. So now that you know you can write your own routine to see if a matrix is orthogonal.

那么正交矩阵是什么?正如先前提到的,一个方形的矩阵Q是正交的如果QXQT=I,QT是Q的转置矩阵,I是单位矩阵。实际上也就意味着任何两个不同的列或行的乘积返回零。也即是点乘积为0,因此向量是在正确的角度。同样也意味着人一个向量和自身点乘结果为1.向量是被标准化过的。因此现在你已经知道如何写一个例程测试一个矩阵是否是正交矩阵。

So we can easily get the inverse of M1. The first column of the inverse of M1 is the required right vector, and the second column represents the up required vector.
因此我们可以容易获得M1的逆矩阵。M1逆矩阵的第一列是右向量,第二列是上向量。

right = [a0,a4,a8]  

up = [a1,a5,a9]

Two examples of a quad billboard are now presented to show how to define the vertices. Assume that the quads edges have a lengthsize.

两个广告牌现在被展示怎样定义其顶点。主要这个广告牌是有长度的。

First a quad with the center at the bottom origin is presented (left figure).
首先一个中心在底部的广告牌四边形被展现。

a = center - right * (size * 0.5);

b = center + right * size * 0.5;

c = center + right * size * 0.5 + up * size;

d = center - right * size * 0.5 + up * size;

The right figure represents a quad with a centre on the middle of the quad. Its vertices are defined as:
右边的图代表中心点在四边形中心的广告牌。他的顶点如下定义:

a = center - (right + up) * size;

b = center + (right - up) * size;

c = center + (right + up) * size;

d = center - (right - up) * size;

When compared to the previous method you only get the modelview matrix once per frame. On the other hand you have to manually transform the vertices of the billboard. Overall this method is faster for quads, only 4 vertices, but harder to implement. If however you try to billboard an object with a larger number of vertices then the previous method could perform better.

当和先前的方法相比,你只在每帧获得一次模型视图矩阵。从另一方面来说,你必须人工变换广告牌的顶点。总而言之这个方法对于四边形非常快,仅仅4个顶点,但是难于实现。如果你说操纵的广告牌物体有大量的顶点那么先前的方法会更合适。

In the source code a function is provided to extract the up and right vectors
在源代码中一个函数用来提取up right向量。

void l3dBillboardGetUpRightVector(float *up, float *right);

Parameters:

up - an array of 3 floats. The function sets this to be the up vector
right - an array of 3 floats. The function sets this to be the right vector

The source code is as follows:
源代码如下:

[cpp] view plaincopyprint?
  1. void l3dBillboardGetUpRightVector(float *up,float *right) {  
  2.   
  3.     float modelview[16];  
  4.   
  5.     glGetFloatv(GL_MODELVIEW_MATRIX, modelview);  
  6.   
  7.     right[0] = modelview[0];  
  8.     right[1] = modelview[4];  
  9.     right[2] = modelview[8];  
  10.   
  11.     up[0] = modelview[1];  
  12.     up[1] = modelview[5];  
  13.     up[2] = modelview[9];  
  14. }  


If what you're after is the cylindrical version of this method then just set the up vector to [0,1,0]. You can use the functionl3dBillboardGetRightVector, provided in the source code, to get the right vector.

原创粉丝点击