广告牌技术教程:欺骗-快速而简单的球体化广告牌

The technique about to be presented isn't true billboarding. Instead it provides a cheap way of achieving an approximation that may be good enough in some applications.

这里将要展示的不是真正的广告牌技术。相反它提供了一些应用软件能够接受的逼近效果的方法的简单实现。

The source code for this tutorial is an extension to one of the projects on the GLUT tutorial. If you're not familiar with GLUT then maybe you should check it out to get a better grasp of the source code.

这个教程的源代码作为扩展是GLUT tutorial项目的一部分。如果你对GLUT不熟悉,那么你要想读明白它你就应该看看GLUT从而你可以很好的了解源代码。

The following image is a screenshot of the demo. It shows a snowman plus some billboarded trees. Although it is hard to tell, the trees aren't facing the camera, although it is hard to tell. Instead they are facing a plane perpendicular to the cameras viewing direction.

下面的这个图像时demo版本的场景。它展示了一个雪人和一些广告牌技术绘制的树木。虽然很难描述,但是这里的树木并不面向照相机,虽然很难说。相反,他们面向一个垂直于相机视线方向的平面。

The next diagram gives a clearer picture of what's going on. The black circle at the bottom represents the camera. The vector starting from the camera is the current viewing direction. This vector defines the orientation of the plane perpendicular to the cameras viewing direction. The objects in the scene, O1..O3, have been rotated so that their front facing vector is pointing to this plane. It is assumed that the objects in the scene are positioned in the local origin, and that they're facing the poistive Z axis.

下面的这个图形清晰的展示了所发生的的事情。底部的黑色的圈代表照相机。从相机发出的向量是当前的视线方向。这个向量定义了垂直于相机视线的平面。场景中的物体O1..O3,已经被旋转以使他们的前面的faceing向量指向这个平面。这里假设场景中的物体在局部坐标原点,并且面向z轴正方向。

An approach to achieve this effect requires the modelview matrix. As you're aware the modelview matrix stores the geometric transformations, rotations, scales and translations, you do. This matrix contains the required transformations to change the coordinates you input, world coordinates, into camera coordinates.

达到这种效果的方法是使用模型视图矩阵。正如你所了解的模型视图矩阵存储了几何变换,旋转,缩放和平移信息。这个矩阵包括改变你输入的坐标所做的变换,从世界坐标到相机坐标。

The top 3 values of the right column provide the current position of the local origin relative to the camera's position and orientation. The top 3x3 submatrix contains the scaling and rotation operations. Setting this submatrix to the identity matrix effectively reverses these operations, so that the cameras viewing direction is aligned with the worldsZ axis. The up and right vectors of the camera are also aligned with the worlds axis, which means that this type of billboard acts like a cheat to spherical billboarding. The center of the billboard is the local origin. If you're planning to do your trees with this type of billboarding then when the user looks up or down the trees will bend forwards and backwards as well, which may be a little awkward. This is because the orientation of the billboard depends on the camera's orientation as opposed to the camera's position.

最右边那列的前三个值提供了局部坐标系原点的位置,这个位置是相机坐标位置和方向相关的。最上面的3X3字矩阵包括了缩放和旋转操作。将这个子矩阵设置为单位矩阵也就意味着重置了这些操作,从而相机的视线方向与世界坐标系的z轴平行。相机的up向量和right向量同样平行于世界坐标系的轴,这意味着这种广告牌看起来是一个球体广告牌哦欺骗版本。广告牌的中心是局部坐标原点。如果你打算用这种方法放置你的树木到场景中,当用户从上或从下观察树木时将会向前或向后弯曲,可能会有一点糟糕。这是因为广告牌的方向取决于照相机的方向和相机的位置相反。

 

In practice, setting the submatrix to the identity matrix means the your object won't suffer any rotation when it is rendered. Therefore it will be rendered in the same way as if the camera was looking down the negative Z axis.

实际上,设置子矩阵为单位矩阵意味着你的物体不会受任何旋转操作的影响当他被渲染的时候。因此当物体被渲染的时候放佛相机朝着z轴的负方向。

Note that scaling is also reversed, so if you wanted a tall tree you're not going to get it with this method, unless you scale after you changed the modelview matrix.

注意缩放也被重置了,因此如果你有一个很高的树并不想使用这种方法,你就应该在改变模型视图矩阵后再缩放。

The first step is to save the current modelview matrix. Afterwards get the modelview matrix. Then reset the top 3x3 submatrix to the identity matrix. Load the matrix in to the OpenGL state machine, and render your object in the local origin. Finally restore the original modelview matrix.
第一步是保存当前的模型视图矩阵。然后得到这个模型视图矩阵。接着重置top 3X3子矩阵为单位矩阵。加载这个矩阵到OpenGL状态机,在局部坐标原点渲染你的物体。最后恢复你的原始模型视图矩阵。

float modelview[16];
int i,j;

// save the current modelview matrix
glPushMatrix();

// get the current modelview matrix
glGetFloatv(GL_MODELVIEW_MATRIX , modelview);

// undo all rotations
// beware all scaling is lost as well 
for( i=0; i<3; i++ ) 
	for( j=0; j<3; j++ ) {
		if ( i==j )
			modelview[i*4+j] = 1.0;
		else
			modelview[i*4+j] = 0.0;
	}

// set the modelview with no rotations and scaling
glLoadMatrixf(modelview);

drawObject();

// restores the modelview matrix
glPopMatrix();


With the above snippet of code, the object will be rotated to face the plane perpendicular to the cameras viewing direction. The centre for this rotation is the local origin.

使用上面的代码片段,物体将被旋转到面向垂直于相机视线方向的平面。旋转的中心是局部坐标系原点。

The above code can be divided in two functions, besides the rendering function, drawObject. The first function will setup the modelview matrix, and the second will restore the current matrix.

上面的代码可以被分为两个函数,除了渲染函数,drawObject函数。第一个函数设这模型视图矩阵,第二个恢复当前矩阵。

void billboardCheatSphericalBegin() {
	
	float modelview[16];
	int i,j;

	// save the current modelview matrix
	glPushMatrix();

	// get the current modelview matrix
	glGetFloatv(GL_MODELVIEW_MATRIX , modelview);

	// undo all rotations
	// beware all scaling is lost as well 
	for( i=0; i<3; i++ ) 
	    for( j=0; j<3; j++ ) {
		if ( i==j )
		    modelview[i*4+j] = 1.0;
		else
		    modelview[i*4+j] = 0.0;
	    }

	// set the modelview with no rotations
	glLoadMatrixf(modelview);
}



void billboardEnd() {

	// restore the previously 
	// stored modelview matrix
	glPopMatrix();
}


The source code for rendering a billboard object becomes:
渲染广告牌物体的代码如下:

billboardCheatSphericalBegin();
    drawObject();
billboardEnd();


As mentioned before, scaling operations are lost when you set the new modelview matrix. If you want to scale your objects you can do it after setting up the billboard as in the following snippet.
正如先前提到的,缩放操作丢失了,当你设置新的模型视图矩阵的时候。如果你想缩放你的物体你可以在设置广告牌后做如下代码片段。

billboardCheatSphericalBegin();
    glScalef(1,2,1);
    drawObject();
billboardEnd();


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值