layout: post title: Alternative3D Code Reading Notes ---
1. 向量和矩阵乘法
stage3d和alternative3d都使用列向量:
Figure 1. 列向量乘法
按照AGAL的文档 What is AGAL ,
m44 destination, source1, source2的作用为:destination.x = (source1.x * source2[0].x) + (source1.y * source2[0].y) + (source1.z * source2[0].z) + (source1.w * source2[0].w)
destination.y = (source1.x * source2[1].x) + (source1.y * source2[1].y) + (source1.z * source2[1].z) + (source1.w * source2[1].w)
destination.z = (source1.x * source2[2].x) + (source1.y * source2[2].y) + (source1.z * source2[2].z) + (source1.w * source2[2].w)
destination.w = (source1.x * source2[3].x) + (source1.y * source2[3].y) + (source1.z * source2[3].z) + (source1.w * source2[3].w)
因此在上通过
Context3D.setProgramConstantsFromByteArray传矩阵到显卡时,需要按行来上传。2. 世界坐标与视角
游戏中第一人称人物的头顶z,左手y,看着x 人物的视角用Eular坐标表示:yaw表示身体垂直方向的旋转,pitch表示低头,roll为0
2.1. Eular角对应的矩阵
| yaw | pitch | roll |
|---|---|---|
z
|
y
|
x
|
按照我们人的特性,肯定是先yaw,再pitch,再roll 这三次旋转表示为 r(yaw) = r(z) r(pitch) = r (y) r(roll) = r(x)
为了得到一个代表欧拉旋转的矩形,需要把这几个矩阵方向连接得(注意我们是列向量,矩阵从右乘到左):
其中:
得:
Math3D.vector3DAngleVectors
/**
注意上述公式计算出的R(Eula}可以表示为[R(front), R(Left), R(Up)]
而下面的函数计算的是R(front), R(Right), R(Up)
*/
public static function vector3DAngleVectors( angles:Vector3D, forward:Vector3D, right:Vector3D, up:Vector3D ):void{
var angle:Number;
var sr:Number;
var sp:Number;
var sy:Number;
var cr:Number;
var cp:Number;
var cy:Number;
angle = angles.y * (Math.PI*2 / 360);
sy = Math.sin(angle);
cy = Math.cos(angle);
angle = angles.x * (Math.PI*2 / 360);
sp = Math.sin(angle);
cp = Math.cos(angle);
angle = angles.z * (Math.PI*2 / 360);
sr = Math.sin(angle);
cr = Math.cos(angle);
if (forward)
{
forward.x = cp*cy;
forward.y = cp*sy;
forward.z = -sp;
}
if (right)
{
right.x = (-1*sr*sp*cy+-1*cr*-sy);
right.y = (-1*sr*sp*sy+-1*cr*cy);
right.z = -1*sr*cp;
}
if (up)
{
up.x = (cr*sp*cy+-sr*-sy);
up.y = (cr*sp*sy+-sr*cy);
up.z = cr*cp;
}
}
2.2. 从世界坐标变换到摄像机坐标
首先我们定义四个坐标系:
- C(world),世界
- C(camera_translate),经过位移后摄像机坐标
- C(camera_translate_rotate),经过位移,再经过yaw, pitch, roll的摄像机坐标,在此坐标系内,x方向的为可见,z方向为上方
- C(camera_translate_rotate_flip),用来投影的坐标,在此坐标内,-z方向的为可见,y为上方
对应于一个顶点P
- P(world) = M(translate) * M(rotate) * M(flip) * P(camera)
假设摄像机在世界的位置为pos
3. 缩放的实现
缩放有两种实现方式:
- 设置ViewPort
- 设置ScissorRectangle + 设置投影矩阵
当需要达到UI不缩放,3D缩放的效果时(主要为了提高性能),需要用到后者。方法如下:
- 初始化
- 通过
Context3D.configureBackBuffer设定ViewPort参数 - 获得3D的x,y轴缩放比例
- 应用x,y缩放比例到投影矩阵
- 通过
- 渲染
- 设置ScissorRectangle
- 将3D部分应用投影变换后,调用drawTriangles
- 关闭ScissorRectangle
- 将UI按照整个ViewPort渲染
一开始可能以为,只要设置投影矩阵的x,y轴缩放就行了。只这样做的话,的确会使得场景变小,但是ViewPort内的可见物体也更多了。因为原先被视锥裁剪掉的三角形,现在有部分因为又落入了视锥内。加上ScissorRectangle正好抵消的这种作用。

0 评论:
Post a Comment