首先定义了照相机的位置和朝向
POINT4D cam_pos = { 0, 0, -100, 1 };
VECTOR4D cam_dir = { 0, 0, 0, 1 };
先看看顶点数据结构,6.4有详细的解释,
1, 用三角形表示3D多边形数据,因为三角形易于渲染---3个点定义一个平面,同时很多3D算法最适合用于三角形网格。
2, 用一个矩形来裁剪几个三角形,在裁剪阶段,若在物理空间裁剪,则可能会增加多边形的顶点数;若再渲染时裁剪,则可能跨过近裁剪面,甚至跨过Z=0平面,造成投影问题。
3, 暂时不考虑增加顶点的情形,即,裁剪时要么将整个多边形剔除,要么保留。
3D流水线:模型坐标->世界坐标->相机坐标->透视坐标->屏幕坐标
先看模型格式,分了三种。
1, 多边形顶点列表
typedef struct POLY4DV1_TYP
{
int state; //状态信息
int attr; //多边形的物理属性,如材质等
int color; //多边形的颜色
POINT4D_PTR vlist; //顶点列表
int vert[3]; //顶点列表元素的索引
}POLY4DV1, * POLY4DV1_PTR;
其中,用4d其次坐标中w=1,
2,面列表,
光栅化阶段,需要一个多边形列表,即面数组或链表。
typedef struct POLYF4DV1_TYP
{
int state; //状态信息
int attr; //多边形的物理属性,如材质等
int color; //多边形的颜色
POINT4D_PTR vlist[3]; //顶点列表
POINT4D_PTR tvlist[3]; //变换后的顶点
POLYF4DV1_TYP * next; //指向列表中下一个多边形的指针
POLYF4DV1_TYP * prev; //指向列表中前一个多边形的指针
}POLYF4DV1, * POLYF4DV1_PTR;
3,基于顶点列表和多边形列表的物体
typedef struct OBJECT4DV1_TYP
{
int id; //物体的数值ID
char name[64]; //物体的字符串名称
int state; //物体状态信息
int attr; //物体的物理属性,如材质等
float avg_radius; //物体的平均半径,用于碰撞检测
float max_radius; //物体的最大半径
POINT4D world_pos; //物体在世界坐标系中的位置
VECTOR4D dir; //物体加载时在局部坐标系下的旋转角度,
VECTOR4D ux, uy, uz; //记录物体变换后的朝向
int num_vertices;//物体的顶点数
POINT4D vlist_local[64];//存储顶点局部坐标的数组
POINT4D vlist_trans[64];//存储顶点交换后坐标的数组
int num_polys; //物体的多边形数
POLY4DV1 plist[128]; //存储多边形数组
}OBJECT4DV1, * OBJECT4DV1_PTR;
在MAIN()中 ,定义个顶点
POLYF4DV1 poly1;
定义几个状态
#define POLY4DV1_STATE_ACTIVE 0x0001
#define POLY4DV1_STATE_CLIPPED 0x0002
#define POLY4DV1_STATE_CULLED 0x0004
在game_init()中,加上
srand( mytool.Start_Clock() );
math.Build_Sin_Cos_Tables();
再设置顶点的初始化
poly1.state = POLY4DV1_STATE_ACTIVE;
poly1.attr = 0;
poly1.color = RGB16Bit555( 0, 255, 0 );
poly1.vlist[0].x = 0;
poly1.vlist[0].y = 50;
poly1.vlist[0].z = 0;
poly1.vlist[0].w = 1;
poly1.vlist[1].x = 50;
poly1.vlist[1].y = -50;
poly1.vlist[1].z = 0;
poly1.vlist[1].w = 1;
poly1.vlist[2].x = -50;
poly1.vlist[2].y = -50;
poly1.vlist[2].z = 0;
poly1.vlist[2].w = 1;
在Game_Main()中,在某个时刻把游戏中的所有物体从高级表示转换为多边形,并将这些多边形插入到主多边形列表或流中,然后将主多边形列表传递给3D流水线进行处理。主多边形可能是在世界坐标系下生成的,也可能是在流水线的下游生成的。
再加上个流水线类
#include "ddraw_math.h"
#pragma once
typedef struct POLY4DV1_TYP
{
int state; //状态信息
int attr; //多边形的物理属性,如材质等
int color; //多边形的颜色
POINT4D_PTR vlist; //顶点列表
int vert[3]; //顶点列表元素的索引
}POLY4DV1, * POLY4DV1_PTR;
typedef struct POLYF4DV1_TYP
{
int state; //状态信息
int attr; //多边形的物理属性,如材质等
int color; //多边形的颜色
POINT4D_PTR vlist[3]; //顶点列表
POINT4D_PTR tvlist[3]; //变换后的顶点
POLYF4DV1_TYP * next; //指向列表中下一个多边形的指针
POLYF4DV1_TYP * prev; //指向列表中前一个多边形的指针
}POLYF4DV1, * POLYF4DV1_PTR;
typedef struct OBJECT4DV1_TYP
{
int id; //物体的数值ID
char name[64]; //物体的字符串名称
int state; //物体状态信息
int attr; //物体的物理属性,如材质等
float avg_radius; //物体的平均半径,用于碰撞检测
float max_radius; //物体的最大半径
POINT4D world_pos; //物体在世界坐标系中的位置
VECTOR4D dir; //物体加载时在局部坐标系下的旋转角度,
VECTOR4D ux, uy, uz; //记录物体变换后的朝向
int num_vertices;//物体的顶点数
POINT4D vlist_local[64];//存储顶点局部坐标的数组
POINT4D vlist_trans[64];//存储顶点交换后坐标的数组
int num_polys; //物体的多边形数
POLY4DV1 plist[128]; //存储多边形数组
}OBJECT4DV1, * OBJECT4DV1_PTR;
typedef struct RENDERLIST4DV1_TYP
{
int state; //渲染列表的状态
int attr; //渲染列表的属性
POLYF4DV1_PTR poly_ptrs[RENDERLIST4DV1_MAX_POLYS]; //索引缓存数组(多边形面)
POLYF4DV1 poly_data[RENDERLIST4DV1_MAX_POLYS]; //顶点数组
int num_polys; //渲染列表中包含的多边形数目
}RENDERLIST4DV1, *RENDERLIST4DV1_PTR;
class ddraw_liushuixian
{
public:
ddraw_liushuixian(void);
~ddraw_liushuixian(void);
public:
};
当有多部相机时,可能有多个渲染列表。
void ddraw_liushuixian::Reset_RENDERLIST4DV1(RENDERLIST4DV1_PTR rend_list)
{
rend_list->num_polys = 0; // 渲染的多边形数,默认为
}
在main.cpp中
RENDERLIST4DV1 rend_list;
ddraw_liushuixian liushuixian;
在game_main()中,每帧重置列表
void ddraw_liushuixian::Reset_RENDERLIST4DV1(RENDERLIST4DV1_PTR rend_list)
{
rend_list->num_polys = 0; // 渲染的多边形数,默认为
}
插入节点
int ddraw_liushuixian::Insert_POLYF4DV1_RENDERLIST4DV1(RENDERLIST4DV1_PTR rend_list, POLYF4DV1_PTR poly)
{
if( rend_list->num_polys >= RENDERLIST4DV1_MAX_POLYS )
return ( 0 );
rend_list->poly_ptrs[rend_list->num_polys] = &rend_list->poly_data[rend_list->num_polys];
memcpy( ( void * ) & rend_list->poly_data[rend_list->num_polys], ( void * )poly, sizeof( POLY4DV1 ) );
if( rend_list->num_polys == 0 )
{
rend_list->poly_data[0].next = NULL;
rend_list->poly_data[0].prev = NULL;
}
else
{
rend_list->poly_data[rend_list->num_polys].next = NULL;
rend_list->poly_data[rend_list->num_polys].prev = & rend_list->poly_data[rend_list->num_polys-1];
rend_list->poly_data[rend_list->num_polys-1].next = & rend_list->poly_data[rend_list->num_polys];
}
rend_list->num_polys++;
return ( 1 );
}
这里需要一个4X4矩阵
typedef struct MATRIX4X4_TYP
{
union
{
float M[4][4];
struct
{
float M00, M01, M02, M03;
float M10, M11, M12, M13;
float M20, M21, M22, M23;
float M30, M31, M32, M33;
};
};
}MATRIX4X4, * MATRIX4X4_PTR;
4*4的矩阵归一化
void ddraw_math::Mat_IDENTITY_4X4( MATRIX4X4 m )
{
const MATRIX4X4 IMAT_4X4 = { 1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1};
memcpy( ( void * ) ( m ), ( void * ) IMAT_4X4, sizeof( MATRIX4X4 ) );
}