- UID
- 1
- 精华
- 积分
- 76365
- 威望
- 点
- 宅币
- 个
- 贡献
- 次
- 宅之契约
- 份
- 最后登录
- 1970-1-1
- 在线时间
- 小时
|
注:本文所指的“文曲星”是“文曲星A2008”机型。。
文曲星不支持浮点数运算,而且运行也十分缓慢——其实不是文曲星慢,而是它上面运行的gvmaker虚拟机太慢了。所以我使用定点数来代替浮点数进行运算。
所谓定点数,就是小数点位置被固定到指定位置的一种数据类型,比如我存储1.0,对于定点数,我把小数点固定在第10位,那么我实际存储的数值就是0x400(十进制1024)。这样的话,我的定点数的精度,最低也是1/1024。
定点数的加减法和整数无异,直接+ - 就好。但乘除法的话,如果你用一个定点数去乘一个定点数,并且你直接用的是整数的乘法的处理方式的话,你需要把得到的积再除以定点数表示的1.0,你才能得到正确的结果。比如你的定点数1.0用整数方式存储是1024的话,为了得到2.0 * 2.0 = 4.0的效果,你实际做的整数乘法是2048 * 2048,得到的是4194304,你需要再除以1024(也就是你的定点数的1.0),你才能得到4096。同理除法也需要经过这样的处理,只不过除法是先让被除数乘上定点数1.0,再除以除数。比如1.0 / 2.0 = 0.5,用定点数做运算的话,就是1024 * 1024 / 2048 = 512。
和浮点数做对比,定点数运算比较快,并且它的精度是可控的——因为浮点数的小数点位置是浮动的,它的精度与数值的大小有密切的关系,所以用定点数能保证精度的统一,而浮点数则不能。
但定点数的缺点在于做乘除法的时候,会严重地损失精度,尤其是圆周率,32位浮点数能存储3.1415927,而定点数假设小数点在第10位,那么它只能用 3216 来表示圆周率(3216 = π×1024 取整)。而如果我把小数点放在第16位的位置上(1.0用65536表示)的话,我虽然能精确到1/65536,但我能存储的最大的数值也从之前的4294966272变成了65536,而且我每次做乘除法的时候,我都要用一个64位的整数来存储中间值,这会严重降低运算的效率(然而x86平台还好)。
有关3D渲染的算法,其实就是很简单的矩阵变换和投影,其它并没有什么玄妙。顺带一提,很多人以为用了DirectX或者OpenGL才能算真3D,但其实3D渲染的“真伪”只取决于你用的算法,和你使用的媒介无关。事实上就算你用的是正交投影,某种程度上也算是“真3D”的。我之前就写过一篇帖子,讲如何用VB自带的Line进行3D画面的绘制的。
文曲星运行用户程序,用的是一款叫“gvmaker”的开发环境,和它的启动器。这里放出下载:
gvmaker开发环境:
GVmaker2.4开发环境_20071011_113832.rar
(6.08 MB, 下载次数: 21)
文曲星端的gvmaker启动器:
GVM2008.prg
(69.67 KB, 下载次数: 9)
源码:(320x240,64K色)
- #define FIXED 1024
- #define FIXED_SHIFT 10
- #define MSTACK_SIZE 16 // 矩阵栈的大小
- #define VP_WIDTH 320
- #define VP_HEIGHT 240
- #define VP_CENTERX 160
- #define VP_CENTERY 120
- #define VP_RIGHT 319
- #define VP_BOTTOM 239
- // 触屏判断
- struct point
- {
- int x;
- int y;
- };
- struct point pt;
- struct point pt_old;
- //向量
- struct vec3
- {
- long x,y,z;
- };
- struct vec4
- {
- long x,y,z,w;
- };
- // 矩阵
- struct mat4
- {
- struct vec4 x,y,z,w;
- };
- // 矩阵栈
- struct mat4 m_stack[MSTACK_SIZE];
- int m_stacktop; // 栈顶
- struct mat4 m; // 临时矩阵(gvmaker不能把结构体变量作为局部变量定义)
- struct mat4 m_modelview; // 模型矩阵
- struct mat4 m_projection; // 投影矩阵
- struct vec3 eye_pos; // 眼睛位置
- long eye_yaw, eye_pitch; // 眼睛角度
- struct vec3 eye_xaxis; // 眼睛右方向
- struct vec3 eye_yaxis; // 眼睛上方向
- struct vec3 eye_zaxis; // 眼睛前方向
- long time_global; // 全局时间
- long time_delta; // 帧时间
- void mat_init();
- void mat_push();
- void mat_pop();
- void mat_mult();
- void mat_transpose();
- void mat_load_identity();
- void mat_load_RotXAxis(long deg);
- void mat_load_RotYAxis(long deg);
- void mat_load_RotZAxis(long deg);
- void mat_load_RotAxis(long ax, long ay, long az, long deg);
- void mat_load_EulerRotation(long yaw, long pitch, long roll);
- void mat_load_view_lh(long x, long y, long z, long yaw, long pitch, long roll);
- void mat_load_perspective_lh(long fovy, long aspect, long zn, long zf);
- void mat_load_modelview();
- void mat_load_projection();
- void mat_set_modelview();
- void mat_set_projection();
- void mat_print(int x, int y);
- long tan(long deg)
- {
- return (sin(deg) << FIXED_SHIFT) / cos(deg);
- }
- long cot(long deg)
- {
- return (cos(deg) << FIXED_SHIFT) / sin(deg);
- }
- // 初始化矩阵栈
- void mat_init()
- {
- m_stacktop = 0;
- mat_load_identity();
- }
- // 压入新矩阵
- void mat_push()
- {
- m_stacktop = (m_stacktop + 1) % MSTACK_SIZE;
- }
- // 压入栈顶
- void mat_pushtop()
- {
- int prev;
- prev = m_stacktop;
- m_stacktop = (m_stacktop + 1) % MSTACK_SIZE;
- memcpy(&m_stack[m_stacktop].x.x, &m_stack[prev].x.x, 64);
- }
- // 弹出矩阵
- void mat_pop()
- {
- m_stacktop = m_stacktop - 1;
- if(m_stacktop < 0)
- m_stacktop = m_stacktop + MSTACK_SIZE;
- }
- // 将栈顶两个矩阵做矩阵乘法
- void mat_mult()
- {
- long ptr2;
- ptr2 = m_stacktop;
- mat_pop();
- m.x.x = (m_stack[m_stacktop].x.x * m_stack[ptr2].x.x >> FIXED_SHIFT) + (m_stack[m_stacktop].x.y * m_stack[ptr2].y.x >> FIXED_SHIFT) + (m_stack[m_stacktop].x.z * m_stack[ptr2].z.x >> FIXED_SHIFT) + (m_stack[m_stacktop].x.w * m_stack[ptr2].w.x >> FIXED_SHIFT);
- m.x.y = (m_stack[m_stacktop].x.x * m_stack[ptr2].x.y >> FIXED_SHIFT) + (m_stack[m_stacktop].x.y * m_stack[ptr2].y.y >> FIXED_SHIFT) + (m_stack[m_stacktop].x.z * m_stack[ptr2].z.y >> FIXED_SHIFT) + (m_stack[m_stacktop].x.w * m_stack[ptr2].w.y >> FIXED_SHIFT);
- m.x.z = (m_stack[m_stacktop].x.x * m_stack[ptr2].x.z >> FIXED_SHIFT) + (m_stack[m_stacktop].x.y * m_stack[ptr2].y.z >> FIXED_SHIFT) + (m_stack[m_stacktop].x.z * m_stack[ptr2].z.z >> FIXED_SHIFT) + (m_stack[m_stacktop].x.w * m_stack[ptr2].w.z >> FIXED_SHIFT);
- m.x.w = (m_stack[m_stacktop].x.x * m_stack[ptr2].x.w >> FIXED_SHIFT) + (m_stack[m_stacktop].x.y * m_stack[ptr2].y.w >> FIXED_SHIFT) + (m_stack[m_stacktop].x.z * m_stack[ptr2].z.w >> FIXED_SHIFT) + (m_stack[m_stacktop].x.w * m_stack[ptr2].w.w >> FIXED_SHIFT);
- m.y.x = (m_stack[m_stacktop].y.x * m_stack[ptr2].x.x >> FIXED_SHIFT) + (m_stack[m_stacktop].y.y * m_stack[ptr2].y.x >> FIXED_SHIFT) + (m_stack[m_stacktop].y.z * m_stack[ptr2].z.x >> FIXED_SHIFT) + (m_stack[m_stacktop].y.w * m_stack[ptr2].w.x >> FIXED_SHIFT);
- m.y.y = (m_stack[m_stacktop].y.x * m_stack[ptr2].x.y >> FIXED_SHIFT) + (m_stack[m_stacktop].y.y * m_stack[ptr2].y.y >> FIXED_SHIFT) + (m_stack[m_stacktop].y.z * m_stack[ptr2].z.y >> FIXED_SHIFT) + (m_stack[m_stacktop].y.w * m_stack[ptr2].w.y >> FIXED_SHIFT);
- m.y.z = (m_stack[m_stacktop].y.x * m_stack[ptr2].x.z >> FIXED_SHIFT) + (m_stack[m_stacktop].y.y * m_stack[ptr2].y.z >> FIXED_SHIFT) + (m_stack[m_stacktop].y.z * m_stack[ptr2].z.z >> FIXED_SHIFT) + (m_stack[m_stacktop].y.w * m_stack[ptr2].w.z >> FIXED_SHIFT);
- m.y.w = (m_stack[m_stacktop].y.x * m_stack[ptr2].x.w >> FIXED_SHIFT) + (m_stack[m_stacktop].y.y * m_stack[ptr2].y.w >> FIXED_SHIFT) + (m_stack[m_stacktop].y.z * m_stack[ptr2].z.w >> FIXED_SHIFT) + (m_stack[m_stacktop].y.w * m_stack[ptr2].w.w >> FIXED_SHIFT);
- m.z.x = (m_stack[m_stacktop].z.x * m_stack[ptr2].x.x >> FIXED_SHIFT) + (m_stack[m_stacktop].z.y * m_stack[ptr2].y.x >> FIXED_SHIFT) + (m_stack[m_stacktop].z.z * m_stack[ptr2].z.x >> FIXED_SHIFT) + (m_stack[m_stacktop].z.w * m_stack[ptr2].w.x >> FIXED_SHIFT);
- m.z.y = (m_stack[m_stacktop].z.x * m_stack[ptr2].x.y >> FIXED_SHIFT) + (m_stack[m_stacktop].z.y * m_stack[ptr2].y.y >> FIXED_SHIFT) + (m_stack[m_stacktop].z.z * m_stack[ptr2].z.y >> FIXED_SHIFT) + (m_stack[m_stacktop].z.w * m_stack[ptr2].w.y >> FIXED_SHIFT);
- m.z.z = (m_stack[m_stacktop].z.x * m_stack[ptr2].x.z >> FIXED_SHIFT) + (m_stack[m_stacktop].z.y * m_stack[ptr2].y.z >> FIXED_SHIFT) + (m_stack[m_stacktop].z.z * m_stack[ptr2].z.z >> FIXED_SHIFT) + (m_stack[m_stacktop].z.w * m_stack[ptr2].w.z >> FIXED_SHIFT);
- m.z.w = (m_stack[m_stacktop].z.x * m_stack[ptr2].x.w >> FIXED_SHIFT) + (m_stack[m_stacktop].z.y * m_stack[ptr2].y.w >> FIXED_SHIFT) + (m_stack[m_stacktop].z.z * m_stack[ptr2].z.w >> FIXED_SHIFT) + (m_stack[m_stacktop].z.w * m_stack[ptr2].w.w >> FIXED_SHIFT);
- m.w.x = (m_stack[m_stacktop].w.x * m_stack[ptr2].x.x >> FIXED_SHIFT) + (m_stack[m_stacktop].w.y * m_stack[ptr2].y.x >> FIXED_SHIFT) + (m_stack[m_stacktop].w.z * m_stack[ptr2].z.x >> FIXED_SHIFT) + (m_stack[m_stacktop].w.w * m_stack[ptr2].w.x >> FIXED_SHIFT);
- m.w.y = (m_stack[m_stacktop].w.x * m_stack[ptr2].x.y >> FIXED_SHIFT) + (m_stack[m_stacktop].w.y * m_stack[ptr2].y.y >> FIXED_SHIFT) + (m_stack[m_stacktop].w.z * m_stack[ptr2].z.y >> FIXED_SHIFT) + (m_stack[m_stacktop].w.w * m_stack[ptr2].w.y >> FIXED_SHIFT);
- m.w.z = (m_stack[m_stacktop].w.x * m_stack[ptr2].x.z >> FIXED_SHIFT) + (m_stack[m_stacktop].w.y * m_stack[ptr2].y.z >> FIXED_SHIFT) + (m_stack[m_stacktop].w.z * m_stack[ptr2].z.z >> FIXED_SHIFT) + (m_stack[m_stacktop].w.w * m_stack[ptr2].w.z >> FIXED_SHIFT);
- m.w.w = (m_stack[m_stacktop].w.x * m_stack[ptr2].x.w >> FIXED_SHIFT) + (m_stack[m_stacktop].w.y * m_stack[ptr2].y.w >> FIXED_SHIFT) + (m_stack[m_stacktop].w.z * m_stack[ptr2].z.w >> FIXED_SHIFT) + (m_stack[m_stacktop].w.w * m_stack[ptr2].w.w >> FIXED_SHIFT);
-
- memcpy(&m_stack[m_stacktop].x.x, &m.x.x, 64);
- }
- // 矩阵转置
- void mat_transpose()
- {
- long t;
-
- t = m_stack[m_stacktop].x.y;
- m_stack[m_stacktop].x.y = m_stack[m_stacktop].y.x;
- m_stack[m_stacktop].y.x = t;
-
- t = m_stack[m_stacktop].x.z;
- m_stack[m_stacktop].x.z = m_stack[m_stacktop].z.x;
- m_stack[m_stacktop].z.x = t;
-
- t = m_stack[m_stacktop].x.w;
- m_stack[m_stacktop].x.w = m_stack[m_stacktop].w.x;
- m_stack[m_stacktop].w.x = t;
-
- t = m_stack[m_stacktop].y.z;
- m_stack[m_stacktop].y.z = m_stack[m_stacktop].z.y;
- m_stack[m_stacktop].z.y = t;
-
- t = m_stack[m_stacktop].y.w;
- m_stack[m_stacktop].y.w = m_stack[m_stacktop].w.y;
- m_stack[m_stacktop].w.y = t;
-
- t = m_stack[m_stacktop].z.w;
- m_stack[m_stacktop].z.w = m_stack[m_stacktop].w.z;
- m_stack[m_stacktop].w.z = t;
- }
- // 载入单位矩阵
- void mat_load_identity()
- {
- m_stack[m_stacktop].x.x=FIXED;m_stack[m_stacktop].x.y=0;m_stack[m_stacktop].x.z=0;m_stack[m_stacktop].x.w=0;
- m_stack[m_stacktop].y.y=FIXED;m_stack[m_stacktop].y.x=0;m_stack[m_stacktop].y.z=0;m_stack[m_stacktop].y.w=0;
- m_stack[m_stacktop].z.z=FIXED;m_stack[m_stacktop].z.x=0;m_stack[m_stacktop].z.y=0;m_stack[m_stacktop].z.w=0;
- m_stack[m_stacktop].w.w=FIXED;m_stack[m_stacktop].w.x=0;m_stack[m_stacktop].w.y=0;m_stack[m_stacktop].w.z=0;
- }
- // 载入平移矩阵
- void mat_load_translate(long x, long y, long z)
- {
- m_stack[m_stacktop].x.x=FIXED;m_stack[m_stacktop].x.y=0;m_stack[m_stacktop].x.z=0;m_stack[m_stacktop].x.w=0;
- m_stack[m_stacktop].y.y=FIXED;m_stack[m_stacktop].y.x=0;m_stack[m_stacktop].y.z=0;m_stack[m_stacktop].y.w=0;
- m_stack[m_stacktop].z.z=FIXED;m_stack[m_stacktop].z.x=0;m_stack[m_stacktop].z.y=0;m_stack[m_stacktop].z.w=0;
- m_stack[m_stacktop].w.w=FIXED;m_stack[m_stacktop].w.x=x;m_stack[m_stacktop].w.y=y;m_stack[m_stacktop].w.z=z;
- }
- // 载入绕X轴旋转矩阵
- void mat_load_RotXAxis(long deg)
- {
- m_stack[m_stacktop].x.x = FIXED;
- m_stack[m_stacktop].x.y = 0;
- m_stack[m_stacktop].x.z = 0;
- m_stack[m_stacktop].x.w = 0;
-
- m_stack[m_stacktop].y.x = 0;
- m_stack[m_stacktop].y.y = cos(deg);
- m_stack[m_stacktop].y.z =-sin(deg);
- m_stack[m_stacktop].y.w = 0;
-
- m_stack[m_stacktop].z.x = 0;
- m_stack[m_stacktop].z.y = sin(deg);
- m_stack[m_stacktop].z.z = cos(deg);
- m_stack[m_stacktop].z.w = 0;
-
- m_stack[m_stacktop].w.x = 0;
- m_stack[m_stacktop].w.y = 0;
- m_stack[m_stacktop].w.z = 0;
- m_stack[m_stacktop].w.w = FIXED;
- }
- // 载入绕Y轴旋转矩阵
- void mat_load_RotYAxis(long deg)
- {
- m_stack[m_stacktop].x.x = cos(deg);
- m_stack[m_stacktop].x.y = 0;
- m_stack[m_stacktop].x.z = sin(deg);
- m_stack[m_stacktop].x.w = 0;
-
- m_stack[m_stacktop].y.x = 0;
- m_stack[m_stacktop].y.y = FIXED;
- m_stack[m_stacktop].y.z = 0;
- m_stack[m_stacktop].y.w = 0;
-
- m_stack[m_stacktop].z.x =-sin(deg);
- m_stack[m_stacktop].z.y = 0;
- m_stack[m_stacktop].z.z = cos(deg);
- m_stack[m_stacktop].z.w = 0;
-
- m_stack[m_stacktop].w.x = 0;
- m_stack[m_stacktop].w.y = 0;
- m_stack[m_stacktop].w.z = 0;
- m_stack[m_stacktop].w.w = FIXED;
- }
- // 载入绕Z轴旋转矩阵
- void mat_load_RotZAxis(long deg)
- {
- m_stack[m_stacktop].x.x = cos(deg);
- m_stack[m_stacktop].x.y = sin(deg);
- m_stack[m_stacktop].x.z = 0;
- m_stack[m_stacktop].x.w = 0;
-
- m_stack[m_stacktop].y.x =-sin(deg);
- m_stack[m_stacktop].y.y = cos(deg);
- m_stack[m_stacktop].y.z = 0;
- m_stack[m_stacktop].y.w = 0;
-
- m_stack[m_stacktop].z.x = 0;
- m_stack[m_stacktop].z.y = 0;
- m_stack[m_stacktop].z.z = FIXED;
- m_stack[m_stacktop].z.w = 0;
-
- m_stack[m_stacktop].w.x = 0;
- m_stack[m_stacktop].w.y = 0;
- m_stack[m_stacktop].w.z = 0;
- m_stack[m_stacktop].w.w = FIXED;
- }
- // 载入绕轴旋转矩阵
- void mat_load_RotAxis(long ax, long ay, long az, long deg)
- {
- m_stack[m_stacktop].x.x = (((FIXED - cos(deg)) * ax >> FIXED_SHIFT) * ax >> FIXED_SHIFT) + cos(deg);
- m_stack[m_stacktop].x.y = (((FIXED - cos(deg)) * ax >> FIXED_SHIFT) * ay >> FIXED_SHIFT) - sin(deg) * az >> FIXED_SHIFT;
- m_stack[m_stacktop].x.z = (((FIXED - cos(deg)) * ax >> FIXED_SHIFT) * az >> FIXED_SHIFT) + sin(deg) * ay >> FIXED_SHIFT;
- m_stack[m_stacktop].x.w = 0;
-
- m_stack[m_stacktop].y.x = (((FIXED - cos(deg)) * ay >> FIXED_SHIFT) * ax >> FIXED_SHIFT) + sin(deg) * az >> FIXED_SHIFT;
- m_stack[m_stacktop].y.y = (((FIXED - cos(deg)) * ay >> FIXED_SHIFT) * ay >> FIXED_SHIFT) + cos(deg);
- m_stack[m_stacktop].y.z = (((FIXED - cos(deg)) * ay >> FIXED_SHIFT) * az >> FIXED_SHIFT) - sin(deg) * ax >> FIXED_SHIFT;
- m_stack[m_stacktop].y.w = 0;
-
- m_stack[m_stacktop].z.x = (((FIXED - cos(deg)) * az >> FIXED_SHIFT) * ax >> FIXED_SHIFT) - sin(deg) * ay >> FIXED_SHIFT;
- m_stack[m_stacktop].z.y = (((FIXED - cos(deg)) * az >> FIXED_SHIFT) * ay >> FIXED_SHIFT) + sin(deg) * ax >> FIXED_SHIFT;
- m_stack[m_stacktop].z.z = (((FIXED - cos(deg)) * az >> FIXED_SHIFT) * az >> FIXED_SHIFT) + cos(deg);
- m_stack[m_stacktop].z.w = 0;
-
- m_stack[m_stacktop].w.x = 0;
- m_stack[m_stacktop].w.y = 0;
- m_stack[m_stacktop].w.z = 0;
- m_stack[m_stacktop].w.w = FIXED;
- }
- // 载入欧拉角旋转矩阵
- void mat_load_EulerRotation(long yaw, long pitch, long roll)
- {
- mat_load_RotZAxis(roll);
-
- mat_push();
- mat_load_RotXAxis(pitch);
-
- mat_mult();
-
- mat_push();
- mat_load_RotYAxis(yaw);
-
- mat_mult();
- }
- // 载入左手坐标系观察矩阵
- void mat_load_view_lh(long x, long y, long z, long yaw, long pitch, long roll)
- {
- long t;
- mat_load_EulerRotation(yaw, pitch, roll);
-
- eye_xaxis.x = m_stack[m_stacktop].x.x;
- eye_xaxis.y = m_stack[m_stacktop].x.y;
- eye_xaxis.z = m_stack[m_stacktop].x.z;
- eye_yaxis.x = m_stack[m_stacktop].y.x;
- eye_yaxis.y = m_stack[m_stacktop].y.y;
- eye_yaxis.z = m_stack[m_stacktop].y.z;
- eye_zaxis.x = m_stack[m_stacktop].z.x;
- eye_zaxis.y = m_stack[m_stacktop].z.y;
- eye_zaxis.z = m_stack[m_stacktop].z.z;
-
- m_stack[m_stacktop].w.x = -((eye_xaxis.x * x >> FIXED_SHIFT) + (eye_xaxis.y * y >> FIXED_SHIFT) + (eye_xaxis.z * z >> FIXED_SHIFT));
- m_stack[m_stacktop].w.y = -((eye_yaxis.x * x >> FIXED_SHIFT) + (eye_yaxis.y * y >> FIXED_SHIFT) + (eye_yaxis.z * z >> FIXED_SHIFT));
- m_stack[m_stacktop].w.z = -((eye_zaxis.x * x >> FIXED_SHIFT) + (eye_zaxis.y * y >> FIXED_SHIFT) + (eye_zaxis.z * z >> FIXED_SHIFT));
- m_stack[m_stacktop].w.w = FIXED;
-
- t = m_stack[m_stacktop].x.y;
- m_stack[m_stacktop].x.y = m_stack[m_stacktop].y.x;
- m_stack[m_stacktop].y.x = t;
-
- t = m_stack[m_stacktop].x.z;
- m_stack[m_stacktop].x.z = m_stack[m_stacktop].z.x;
- m_stack[m_stacktop].z.x = t;
-
- t = m_stack[m_stacktop].y.z;
- m_stack[m_stacktop].y.z = m_stack[m_stacktop].z.y;
- m_stack[m_stacktop].z.y = t;
-
- m_stack[m_stacktop].x.w = 0;
- m_stack[m_stacktop].y.w = 0;
- m_stack[m_stacktop].z.w = 0;
- }
- // 载入左手坐标系投影矩阵
- void mat_load_perspective_lh(long fovy, long aspect, long zn, long zf)
- {
- long xscale,yscale;
- long zdiff;
- zdiff = zf-zn;
- yscale = cot(fovy / 2);
- xscale = (yscale << FIXED_SHIFT) / aspect;
- m_stack[m_stacktop].x.x = xscale; m_stack[m_stacktop].x.y = 0; m_stack[m_stacktop].x.z = 0; m_stack[m_stacktop].x.w = 0;
- m_stack[m_stacktop].y.x = 0; m_stack[m_stacktop].y.y = yscale; m_stack[m_stacktop].y.z = 0; m_stack[m_stacktop].y.w = 0;
- m_stack[m_stacktop].z.x = 0; m_stack[m_stacktop].z.y = 0; m_stack[m_stacktop].z.z = (zf<<FIXED_SHIFT)/zdiff; m_stack[m_stacktop].z.w = FIXED;
- m_stack[m_stacktop].w.x = 0; m_stack[m_stacktop].w.y = 0; m_stack[m_stacktop].w.z = -zn*zf/zdiff; m_stack[m_stacktop].w.w = 0;
- }
- // 将模型矩阵复制到栈顶
- void mat_load_modelview()
- {
- memcpy(&m_stack[m_stacktop].x.x, &m_modelview.x.x, 64);
- }
- // 将投影矩阵复制到栈顶
- void mat_load_projection()
- {
- memcpy(&m_stack[m_stacktop].x.x, &m_projection.x.x, 64);
- }
- // 将栈顶的矩阵复制到模型矩阵
- void mat_set_modelview()
- {
- memcpy(&m_modelview.x.x, &m_stack[m_stacktop].x.x, 64);
- }
- // 将栈顶的矩阵复制到投影矩阵
- void mat_set_projection()
- {
- memcpy(&m_projection.x.x, &m_stack[m_stacktop].x.x, 64);
- }
- // 打印矩阵的值到屏幕上
- void mat_print(int x, int y)
- {
- char buf[256];
- sprintf(buf, "%d:",m_stacktop);
- TextOut(x,y,buf);y=y+GetFontSize();
- sprintf(buf, "%d,%d,%d,%d", m_stack[m_stacktop].x.x,m_stack[m_stacktop].x.y,m_stack[m_stacktop].x.z,m_stack[m_stacktop].x.w);
- TextOut(x,y,buf);y=y+GetFontSize();
- sprintf(buf, "%d,%d,%d,%d", m_stack[m_stacktop].y.x,m_stack[m_stacktop].y.y,m_stack[m_stacktop].y.z,m_stack[m_stacktop].y.w);
- TextOut(x,y,buf);y=y+GetFontSize();
- sprintf(buf, "%d,%d,%d,%d", m_stack[m_stacktop].z.x,m_stack[m_stacktop].z.y,m_stack[m_stacktop].z.z,m_stack[m_stacktop].z.w);
- TextOut(x,y,buf);y=y+GetFontSize();
- sprintf(buf, "%d,%d,%d,%d", m_stack[m_stacktop].w.x,m_stack[m_stacktop].w.y,m_stack[m_stacktop].w.z,m_stack[m_stacktop].w.w);
- TextOut(x,y,buf);
- }
- // 线性插值
- long m_lerp(long v1, long v2, long s)
- {
- return v1 + ((v2 - v1) * s >> FIXED_SHIFT);
- }
- // 画线
- void g_draw_line(long x1, long y1, long x2, long y2)
- {
- // gvmaker原版的画线函数不能处理坐标超出屏幕外的情况
- // 所以要做一个插值处理
- if(x1 < 0)
- {
- if(x2 < 0)
- return; // 防止除零异常
- y1 = y1 + (y2 - y1) *-x1 / (x2 - x1);
- x1 = 0;
- }
- if(y1 < 0)
- {
- if(y2 < 0)
- return;
- x1 = x1 + (x2 - x1) *-y1 / (y2 - y1);
- y1 = 0;
- }
- if(x2 < 0)
- {
- if(x1 <= 0)
- return;
- y2 = y2 + (y1 - y2) *-x2 / (x1 - x2);
- x2 = 0;
- }
- if(y2 < 0)
- {
- if(y1 <= 0)
- return;
- x2 = x2 + (x1 - x2) *-y2 / (y1 - y2);
- y2 = 0;
- }
- if(x1 > VP_RIGHT)
- {
- if(x2 > VP_RIGHT)
- return;
- y1 = y1 + (y2 - y1) * (x1 - VP_RIGHT) / (x1 - x2);
- x1 = VP_RIGHT;
- }
- if(y1 > VP_BOTTOM)
- {
- if(y2 > VP_BOTTOM)
- return;
- x1 = x1 + (x2 - x1) * (y1 - VP_BOTTOM) / (y1 - y2);
- y1 = VP_BOTTOM;
- }
- if(x2 > VP_RIGHT)
- {
- if(x1 >= VP_RIGHT)
- return;
- y2 = y2 + (y1 - y2) * (x2 - VP_RIGHT) / (x2 - x1);
- x2 = VP_RIGHT;
- }
- if(y2 > VP_BOTTOM)
- {
- if(y1 >= VP_BOTTOM)
- return;
- x2 = x2 + (x1 - x2) * (y2 - VP_BOTTOM) / (y2 - y1);
- y2 = VP_BOTTOM;
- }
- if(x1 == x2)
- VLine(x1, y1, y2);
- else if(y1 == y2)
- HLine(x1, x2, y1);
- else
- Line(x1,y1,x2,y2);
- }
- // 画3D线,坐标将经过矩阵变换和投影处理。
- void g_draw_3d_line(long x1, long y1, long z1, long x2, long y2, long z2)
- {
- long pxt, pyt, pzt, pwt; // 临时坐标
- long px1, py1, pz1, pw1; // 坐标1
- long px2, py2, pz2, pw2; // 坐标2
- long ls;
-
- pxt = (x1 * m_modelview.x.x >> FIXED_SHIFT) + (y1 * m_modelview.y.x >> FIXED_SHIFT) + (z1 * m_modelview.z.x >> FIXED_SHIFT) + m_modelview.w.x;
- pyt = (x1 * m_modelview.x.y >> FIXED_SHIFT) + (y1 * m_modelview.y.y >> FIXED_SHIFT) + (z1 * m_modelview.z.y >> FIXED_SHIFT) + m_modelview.w.y;
- pzt = (x1 * m_modelview.x.z >> FIXED_SHIFT) + (y1 * m_modelview.y.z >> FIXED_SHIFT) + (z1 * m_modelview.z.z >> FIXED_SHIFT) + m_modelview.w.z;
- pwt = (x1 * m_modelview.x.w >> FIXED_SHIFT) + (y1 * m_modelview.y.w >> FIXED_SHIFT) + (z1 * m_modelview.z.w >> FIXED_SHIFT) + m_modelview.w.w;
-
- px1 = (pxt * m_projection.x.x >> FIXED_SHIFT) + (pyt * m_projection.y.x >> FIXED_SHIFT) + (pzt * m_projection.z.x >> FIXED_SHIFT) + (pwt * m_projection.w.x >> FIXED_SHIFT);
- py1 = (pxt * m_projection.x.y >> FIXED_SHIFT) + (pyt * m_projection.y.y >> FIXED_SHIFT) + (pzt * m_projection.z.y >> FIXED_SHIFT) + (pwt * m_projection.w.y >> FIXED_SHIFT);
- pz1 = (pxt * m_projection.x.z >> FIXED_SHIFT) + (pyt * m_projection.y.z >> FIXED_SHIFT) + (pzt * m_projection.z.z >> FIXED_SHIFT) + (pwt * m_projection.w.z >> FIXED_SHIFT);
- pw1 = (pxt * m_projection.x.w >> FIXED_SHIFT) + (pyt * m_projection.y.w >> FIXED_SHIFT) + (pzt * m_projection.z.w >> FIXED_SHIFT) + (pwt * m_projection.w.w >> FIXED_SHIFT);
-
- pxt = (x2 * m_modelview.x.x >> FIXED_SHIFT) + (y2 * m_modelview.y.x >> FIXED_SHIFT) + (z2 * m_modelview.z.x >> FIXED_SHIFT) + m_modelview.w.x;
- pyt = (x2 * m_modelview.x.y >> FIXED_SHIFT) + (y2 * m_modelview.y.y >> FIXED_SHIFT) + (z2 * m_modelview.z.y >> FIXED_SHIFT) + m_modelview.w.y;
- pzt = (x2 * m_modelview.x.z >> FIXED_SHIFT) + (y2 * m_modelview.y.z >> FIXED_SHIFT) + (z2 * m_modelview.z.z >> FIXED_SHIFT) + m_modelview.w.z;
- pwt = (x2 * m_modelview.x.w >> FIXED_SHIFT) + (y2 * m_modelview.y.w >> FIXED_SHIFT) + (z2 * m_modelview.z.w >> FIXED_SHIFT) + m_modelview.w.w;
-
- px2 = (pxt * m_projection.x.x >> FIXED_SHIFT) + (pyt * m_projection.y.x >> FIXED_SHIFT) + (pzt * m_projection.z.x >> FIXED_SHIFT) + (pwt * m_projection.w.x >> FIXED_SHIFT);
- py2 = (pxt * m_projection.x.y >> FIXED_SHIFT) + (pyt * m_projection.y.y >> FIXED_SHIFT) + (pzt * m_projection.z.y >> FIXED_SHIFT) + (pwt * m_projection.w.y >> FIXED_SHIFT);
- pz2 = (pxt * m_projection.x.z >> FIXED_SHIFT) + (pyt * m_projection.y.z >> FIXED_SHIFT) + (pzt * m_projection.z.z >> FIXED_SHIFT) + (pwt * m_projection.w.z >> FIXED_SHIFT);
- pw2 = (pxt * m_projection.x.w >> FIXED_SHIFT) + (pyt * m_projection.y.w >> FIXED_SHIFT) + (pzt * m_projection.z.w >> FIXED_SHIFT) + (pwt * m_projection.w.w >> FIXED_SHIFT);
-
- // 处理近视距剪切
- if(pz1 < FIXED)
- {
- if(pz2 < FIXED)
- return;
-
- if(pz1 == pz2)
- return;
-
- ls = ((pz2 - FIXED) << FIXED_SHIFT) / (pz2 - pz1);
-
- px1 = m_lerp(px2, px1, ls);
- py1 = m_lerp(py2, py1, ls);
- pz1 = m_lerp(pz2, pz1, ls);
- pw1 = m_lerp(pw2, pw1, ls);
- }
-
- if(pz2 < FIXED)
- {
- if(pz1 < FIXED)
- return;
-
- if(pz1 == pz2)
- return;
-
- ls = ((pz1 - FIXED) << FIXED_SHIFT) / (pz1 - pz2);
-
- px2 = m_lerp(px1, px2, ls);
- py2 = m_lerp(py1, py2, ls);
- pz2 = m_lerp(pz1, pz2, ls);
- pw2 = m_lerp(pw1, pw2, ls);
- }
-
- // 投影
- px1 = px1 * VP_CENTERX / pw1 + VP_CENTERX;
- py1 = VP_CENTERY - py1 * VP_CENTERY / pw1;
- px2 = px2 * VP_CENTERX / pw2 + VP_CENTERX;
- py2 = VP_CENTERY - py2 * VP_CENTERY / pw2;
- g_draw_line(px1,py1,px2,py2);
- }
- // 用线条画长方体
- void g_draw_cube(long dx, long dy, long dz)
- {
- // Up
- g_draw_3d_line(-dx, dy, dz, dx, dy, dz);
- g_draw_3d_line( dx, dy, dz, dx, dy,-dz);
- g_draw_3d_line( dx, dy,-dz,-dx, dy,-dz);
- g_draw_3d_line(-dx, dy,-dz,-dx, dy, dz);
-
- // Down
- g_draw_3d_line(-dx,-dy, dz, dx,-dy, dz);
- g_draw_3d_line( dx,-dy, dz, dx,-dy,-dz);
- g_draw_3d_line( dx,-dy,-dz,-dx,-dy,-dz);
- g_draw_3d_line(-dx,-dy,-dz,-dx,-dy, dz);
-
- // Pillars
- g_draw_3d_line(-dx, dy, dz,-dx,-dy, dz);
- g_draw_3d_line( dx, dy, dz, dx,-dy, dz);
- g_draw_3d_line( dx, dy,-dz, dx,-dy,-dz);
- g_draw_3d_line(-dx, dy,-dz,-dx,-dy,-dz);
- }
- // 输出16进制数
- void XDigitOut(int x, int y, long digit)
- {
- int ch;
- int w;
- int shifts;
-
- w = GetFontSize() / 2;
-
- if(!digit)
- {
- TextOut(x, y, "00000000");
- return;
- }
-
- x=x+w*7;
- shifts=32;
- while(shifts)
- {
- ch=digit&0xF;
- if(ch>=10)
- CharOut(x, y, ch-10+'A');
- else
- CharOut(x, y, ch+'0');
- x=x-w;
- digit=digit>>4;
- shifts=shifts-4;
- }
- }
- void main()
- {
- long i;
- int x,y;
-
- SetFontSize(12);
- SetLCDMode(0);
-
- eye_pos.x=0;
- eye_pos.y=3 << FIXED_SHIFT;
- eye_pos.z=-10 << FIXED_SHIFT;
-
- mat_init();
-
- time_global = GetTickCount();
-
- for(;;)
- {
- // 帧时间处理
- i = GetTickCount();
- time_delta = i - time_global;
- time_global = i;
-
- ClearScreen();
-
- // 设置投影矩阵
- mat_load_perspective_lh(60, (VP_WIDTH << FIXED_SHIFT) / VP_HEIGHT, FIXED, 1000 << FIXED_SHIFT);
- mat_set_projection();
-
- // 设置旋转立方体的矩阵
- mat_load_RotYAxis(time_global * 60 / 1000);
- mat_push();
- mat_load_translate(0,FIXED,0);
- mat_mult();
- mat_push();
- mat_load_view_lh(eye_pos.x, eye_pos.y, eye_pos.z, eye_yaw, eye_pitch, 0);
- mat_mult();
- mat_set_modelview();
-
- // 画立方体
- g_draw_cube(FIXED, FIXED, FIXED);
-
- // 设置地面的矩阵
- mat_load_view_lh(eye_pos.x, eye_pos.y, eye_pos.z, eye_yaw, eye_pitch, 0);
- mat_set_modelview();
-
- // 画地面
- for(x = -10; x <= 10; x++)
- {
- g_draw_3d_line( x << FIXED_SHIFT, 0, 10 << FIXED_SHIFT, x << FIXED_SHIFT, 0, -10 << FIXED_SHIFT);
- }
- for(y = -10; y <= 10; y++)
- {
- g_draw_3d_line( 10 << FIXED_SHIFT, 0, y << FIXED_SHIFT,-10 << FIXED_SHIFT, 0, y << FIXED_SHIFT);
- }
-
- // 根据触屏操作来转动镜头
- if(GetMousePos(pt) == 2)
- {
- eye_yaw = eye_yaw + pt_old.x - pt.x;
- eye_pitch = eye_pitch + pt_old.y - pt.y;
- if(eye_yaw < 0)
- eye_yaw = eye_yaw + 360;
- if(eye_yaw > 360)
- eye_yaw = eye_yaw - 360;
- if(eye_pitch < 0)
- eye_pitch = eye_pitch + 360;
- if(eye_pitch > 360)
- eye_pitch = eye_pitch - 360;
- }
- pt_old.x = pt.x;
- pt_old.y = pt.y;
-
- // 键盘移动操作
- if(CheckKey(KEY_LEFT))
- {
- eye_pos.x = eye_pos.x - eye_xaxis.x * time_delta * 10 / 1000;
- eye_pos.y = eye_pos.y - eye_xaxis.y * time_delta * 10 / 1000;
- eye_pos.z = eye_pos.z - eye_xaxis.z * time_delta * 10 / 1000;
- }
- if(CheckKey(KEY_RIGHT))
- {
- eye_pos.x = eye_pos.x + eye_xaxis.x * time_delta * 10 / 1000;
- eye_pos.y = eye_pos.y + eye_xaxis.y * time_delta * 10 / 1000;
- eye_pos.z = eye_pos.z + eye_xaxis.z * time_delta * 10 / 1000;
- }
- if(CheckKey(KEY_UP))
- {
- eye_pos.x = eye_pos.x + eye_zaxis.x * time_delta * 10 / 1000;
- eye_pos.y = eye_pos.y + eye_zaxis.y * time_delta * 10 / 1000;
- eye_pos.z = eye_pos.z + eye_zaxis.z * time_delta * 10 / 1000;
- }
- if(CheckKey(KEY_DOWN))
- {
- eye_pos.x = eye_pos.x - eye_zaxis.x * time_delta * 10 / 1000;
- eye_pos.y = eye_pos.y - eye_zaxis.y * time_delta * 10 / 1000;
- eye_pos.z = eye_pos.z - eye_zaxis.z * time_delta * 10 / 1000;
- }
-
- Refresh();
- }
- }
复制代码 Src:
main.txt
(23.31 KB, 下载次数: 6)
Bin:
main.gvm
(8.82 KB, 下载次数: 5)
|
|