这个DEMO与上个DEMO的区别在于
1, 相机是UVN相机,而不是欧拉相机,变成全屏的了。
没有2.
UVN相机模型,就是在知道准确坐标的时候进行聚焦。欧拉相机是知道大概方向时的扫描。
其中,N是指相机位置指向目标位置的向量,相当于Z轴;V指的是上向量,相当于Y轴,假设v=<0,1,0>;接着求U,U相当于右向量X,计算方法是U=V×N,接着计算V的正确值V=N×U。
可见,U,V,N三向量互相垂直
首先,坦克个数换为16个,
#define NUM_OBJECTS 16
摄像机位置发生改变
POINT4D cam_pos = {0,0,0,1};
并增加了目标物体的位置
POINT4D cam_target = {0,0,0,1};
并在GAME_INIT()中作相应改变
liushuixian.Init_CAM4DV1( *math, &cam, // the camera object
CAM_MODEL_UVN, // euler camera model
&cam_pos, // initial camera position
&cam_dir, // initial camera angles
&cam_target, // no initial target
50.0, // near and far clipping planes
8000.0,
90.0, // field of view in degrees
WINDOW_WIDTH, // size of final screen viewport
WINDOW_HEIGHT);
模型默认位置的Z坐标也改变了
obj.world_pos.z = 0;
由于这里要做的是改变摄像机位置和朝向,对着固定目标。让摄像机做圆周运动。
摄像机的各个参数设置
static float view_ang = 0;
static float camera_distance = 1750;
static VECTOR4D pos = {0 ,0,0};
在局部坐标系中,进行局部坐标变换
liushuixian.Transform_OBJECT4DV1( & obj, & mrot, TRANSFORM_LOCAL_ONLY, 1);
下一步设置摄像机的位置
cam.pos.x = camera_distance * cosf( view_ang );
cam.pos.y = camera_distance * sinf( view_ang );
cam.pos.z = 2 * camera_distance * sinf( view_ang );
if ( ( view_ang += 1) > 360 )
{
view_ang = 0;
}
紧接着是进行UVN模型相机函数的调用,这里有个简单模式UVN_MODE_SIMPLE和和球面坐标模式UVN_MODE_SPHERICAL。简单模式就是提供目标位置和观察参考点;球面坐标模式的分量X和Y被用作观察向量的方位角和仰角。
先定义UVN的两个模式
#define UVN_MODE_SIMPLE 0
#define UVN_MODE_SPHERICAL 1
4D向量的归一化函数加上。类似于3D向量
void ddraw_math::VECTOR4D_Normalize( VECTOR4D_PTR va )
{
float length = sqrtf( va->x * va->x + va->y * va->y + va->z * va->z );
if ( length < EPSILON_E5 )
{
return;
}
float length_inv = 1 / length;
va->x *= length_inv;
va->y *= length_inv;
va->z *= length_inv;
va->z = 1;
}
构建UVN相机矩阵
void ddraw_liushuixian::Build_CAM4DV1_Matrix_UVN( ddraw_math math2,CAM4DV1_PTR cam, int mode )
{
MATRIX4X4 mt_inv, //相机平移矩阵的逆矩阵
mt_uvn, //UVN相机变换矩阵
mtmp; //用于存储临时矩阵
//第1步,根据相机位置计算相机平移矩阵的逆矩阵
math2.Mat_Init_4X4( & mt_inv, 1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
-cam->pos.x, -cam->pos.y, -cam->pos.z, 1 );
if ( mode == UVN_MODE_SPHERICAL )
{
//使用球面坐标模式,需要重新计算目标点
//提取方位角和仰角
float phi = cam->dir.x; //仰角
float theta = cam->dir.y; //方位角
//计算三角函数
float sin_phi = sinf( phi );
float cos_phi = cosf( phi );
float sin_theta = sinf( theta );
float cos_theta = cosf( theta );
//计算目标点在单位球面上的位置(X,Y,Z)
cam->target.x = -1 * sin_phi * sin_theta;
cam->target.y = 1 * cos_phi;
cam->target.z = 1 * sin_phi * cos_theta;
}
//根据观察点和摄像机位置构建UVN
math2.VECTOR4D_Build( & cam->pos, & cam->target, & cam->n );
math2.VECTOR4D_INITXYZ( & cam->v, 0, 1, 0 );
math2.VECTOR4D_CROSS( & cam->v, & cam->n, & cam->u );
math2.VECTOR4D_CROSS( & cam->n, & cam->u, & cam->v );
//归一化
math2.VECTOR4D_Normalize( & cam->u );
math2.VECTOR4D_Normalize( & cam->v );
math2.VECTOR4D_Normalize( & cam->n );
//将UVN代入,得到UVN旋转矩阵
math2.Mat_Init_4X4( & mt_uvn, cam->u.x, cam->v.x, cam->n.x, 0,
cam->u.y, cam->v.y, cam->n.y, 0,
cam->u.z, cam->v.z, cam->n.z, 0,
0, 0, 0, 1 );
//将平移矩阵乘以矩阵UVN矩阵,并将结果存储到相机变换矩阵mcam中
math2.Mat_Mul_4X4( & mt_inv, & mt_uvn, & cam->mcam );
}
继续,在GAME_MAIN()中
创建UVN相机坐标系
liushuixian.Build_CAM4DV1_Matrix_UVN( math, & cam, UVN_MODE_SIMPLE );
物体的Z轴改了
obj.world_pos.z = z * OBJECT_SPACING + OBJECT_SPACING / 2;