找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 4389|回复: 3

【算法】在文曲星平台上,用gvmaker实现3D场景渲染!(附:文曲星GVMaker开发环境下载,GVMaker模拟器下载,源码下载)

[复制链接]

1109

主题

1649

回帖

7万

积分

用户组: 管理员

一只技术宅

UID
1
精华
244
威望
743 点
宅币
24180 个
贡献
46222 次
宅之契约
0 份
在线时间
2294 小时
注册时间
2014-1-26
发表于 2017-3-17 12:14:42 | 显示全部楼层 |阅读模式

欢迎访问技术宅的结界,请注册或者登录吧。

您需要 登录 才可以下载或查看,没有账号?立即注册→加入我们

×
注:本文所指的“文曲星”是“文曲星A2008”机型。。

wqx.png
QQ图片20170316224846.png

    文曲星不支持浮点数运算,而且运行也十分缓慢——其实不是文曲星慢,而是它上面运行的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色)

  1. #define FIXED 1024
  2. #define FIXED_SHIFT 10
  3. #define MSTACK_SIZE 16 // 矩阵栈的大小

  4. #define VP_WIDTH 320
  5. #define VP_HEIGHT 240

  6. #define VP_CENTERX 160
  7. #define VP_CENTERY 120

  8. #define VP_RIGHT 319
  9. #define VP_BOTTOM 239

  10. // 触屏判断
  11. struct point
  12. {
  13.         int x;
  14.         int y;
  15. };
  16. struct point pt;
  17. struct point pt_old;

  18. //向量
  19. struct vec3
  20. {
  21.         long x,y,z;
  22. };

  23. struct vec4
  24. {
  25.         long x,y,z,w;
  26. };

  27. // 矩阵
  28. struct mat4
  29. {
  30.         struct vec4 x,y,z,w;
  31. };

  32. // 矩阵栈
  33. struct mat4 m_stack[MSTACK_SIZE];
  34. int m_stacktop; // 栈顶
  35. struct mat4 m; // 临时矩阵(gvmaker不能把结构体变量作为局部变量定义)
  36. struct mat4 m_modelview; // 模型矩阵
  37. struct mat4 m_projection; // 投影矩阵

  38. struct vec3 eye_pos; // 眼睛位置
  39. long eye_yaw, eye_pitch; // 眼睛角度
  40. struct vec3 eye_xaxis; // 眼睛右方向
  41. struct vec3 eye_yaxis; // 眼睛上方向
  42. struct vec3 eye_zaxis; // 眼睛前方向

  43. long time_global; // 全局时间
  44. long time_delta; // 帧时间

  45. void mat_init();
  46. void mat_push();
  47. void mat_pop();
  48. void mat_mult();
  49. void mat_transpose();
  50. void mat_load_identity();
  51. void mat_load_RotXAxis(long deg);
  52. void mat_load_RotYAxis(long deg);
  53. void mat_load_RotZAxis(long deg);
  54. void mat_load_RotAxis(long ax, long ay, long az, long deg);
  55. void mat_load_EulerRotation(long yaw, long pitch, long roll);
  56. void mat_load_view_lh(long x, long y, long z, long yaw, long pitch, long roll);
  57. void mat_load_perspective_lh(long fovy, long aspect, long zn, long zf);
  58. void mat_load_modelview();
  59. void mat_load_projection();
  60. void mat_set_modelview();
  61. void mat_set_projection();
  62. void mat_print(int x, int y);

  63. long tan(long deg)
  64. {
  65.         return (sin(deg) << FIXED_SHIFT) / cos(deg);
  66. }

  67. long cot(long deg)
  68. {
  69.         return (cos(deg) << FIXED_SHIFT) / sin(deg);
  70. }

  71. // 初始化矩阵栈
  72. void mat_init()
  73. {
  74.         m_stacktop = 0;
  75.         mat_load_identity();
  76. }

  77. // 压入新矩阵
  78. void mat_push()
  79. {
  80.         m_stacktop = (m_stacktop + 1) % MSTACK_SIZE;
  81. }

  82. // 压入栈顶
  83. void mat_pushtop()
  84. {
  85.         int prev;
  86.         prev = m_stacktop;
  87.         m_stacktop = (m_stacktop + 1) % MSTACK_SIZE;
  88.         memcpy(&m_stack[m_stacktop].x.x, &m_stack[prev].x.x, 64);
  89. }

  90. // 弹出矩阵
  91. void mat_pop()
  92. {
  93.         m_stacktop = m_stacktop - 1;
  94.         if(m_stacktop < 0)
  95.                 m_stacktop = m_stacktop + MSTACK_SIZE;
  96. }

  97. // 将栈顶两个矩阵做矩阵乘法
  98. void mat_mult()
  99. {
  100.         long ptr2;
  101.         ptr2 = m_stacktop;
  102.         mat_pop();

  103.         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);
  104.         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);
  105.         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);
  106.         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);

  107.         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);
  108.         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);
  109.         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);
  110.         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);

  111.         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);
  112.         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);
  113.         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);
  114.         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);

  115.         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);
  116.         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);
  117.         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);
  118.         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);
  119.        
  120.         memcpy(&m_stack[m_stacktop].x.x, &m.x.x, 64);
  121. }

  122. // 矩阵转置
  123. void mat_transpose()
  124. {
  125.         long t;
  126.        
  127.         t = m_stack[m_stacktop].x.y;
  128.         m_stack[m_stacktop].x.y = m_stack[m_stacktop].y.x;
  129.         m_stack[m_stacktop].y.x = t;
  130.        
  131.         t = m_stack[m_stacktop].x.z;
  132.         m_stack[m_stacktop].x.z = m_stack[m_stacktop].z.x;
  133.         m_stack[m_stacktop].z.x = t;
  134.        
  135.         t = m_stack[m_stacktop].x.w;
  136.         m_stack[m_stacktop].x.w = m_stack[m_stacktop].w.x;
  137.         m_stack[m_stacktop].w.x = t;
  138.        
  139.         t = m_stack[m_stacktop].y.z;
  140.         m_stack[m_stacktop].y.z = m_stack[m_stacktop].z.y;
  141.         m_stack[m_stacktop].z.y = t;
  142.        
  143.         t = m_stack[m_stacktop].y.w;
  144.         m_stack[m_stacktop].y.w = m_stack[m_stacktop].w.y;
  145.         m_stack[m_stacktop].w.y = t;
  146.        
  147.         t = m_stack[m_stacktop].z.w;
  148.         m_stack[m_stacktop].z.w = m_stack[m_stacktop].w.z;
  149.         m_stack[m_stacktop].w.z = t;
  150. }

  151. // 载入单位矩阵
  152. void mat_load_identity()
  153. {
  154.         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;
  155.         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;
  156.         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;
  157.         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;
  158. }

  159. // 载入平移矩阵
  160. void mat_load_translate(long x, long y, long z)
  161. {
  162.         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;
  163.         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;
  164.         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;
  165.         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;
  166. }

  167. // 载入绕X轴旋转矩阵
  168. void mat_load_RotXAxis(long deg)
  169. {
  170.         m_stack[m_stacktop].x.x = FIXED;
  171.         m_stack[m_stacktop].x.y = 0;
  172.         m_stack[m_stacktop].x.z = 0;
  173.         m_stack[m_stacktop].x.w = 0;
  174.        
  175.         m_stack[m_stacktop].y.x = 0;
  176.         m_stack[m_stacktop].y.y = cos(deg);
  177.         m_stack[m_stacktop].y.z =-sin(deg);
  178.         m_stack[m_stacktop].y.w = 0;
  179.        
  180.         m_stack[m_stacktop].z.x = 0;
  181.         m_stack[m_stacktop].z.y = sin(deg);
  182.         m_stack[m_stacktop].z.z = cos(deg);
  183.         m_stack[m_stacktop].z.w = 0;
  184.        
  185.         m_stack[m_stacktop].w.x = 0;
  186.         m_stack[m_stacktop].w.y = 0;
  187.         m_stack[m_stacktop].w.z = 0;
  188.         m_stack[m_stacktop].w.w = FIXED;
  189. }

  190. // 载入绕Y轴旋转矩阵
  191. void mat_load_RotYAxis(long deg)
  192. {
  193.         m_stack[m_stacktop].x.x = cos(deg);
  194.         m_stack[m_stacktop].x.y = 0;
  195.         m_stack[m_stacktop].x.z = sin(deg);
  196.         m_stack[m_stacktop].x.w = 0;
  197.        
  198.         m_stack[m_stacktop].y.x = 0;
  199.         m_stack[m_stacktop].y.y = FIXED;
  200.         m_stack[m_stacktop].y.z = 0;
  201.         m_stack[m_stacktop].y.w = 0;
  202.        
  203.         m_stack[m_stacktop].z.x =-sin(deg);
  204.         m_stack[m_stacktop].z.y = 0;
  205.         m_stack[m_stacktop].z.z = cos(deg);
  206.         m_stack[m_stacktop].z.w = 0;
  207.        
  208.         m_stack[m_stacktop].w.x = 0;
  209.         m_stack[m_stacktop].w.y = 0;
  210.         m_stack[m_stacktop].w.z = 0;
  211.         m_stack[m_stacktop].w.w = FIXED;
  212. }

  213. // 载入绕Z轴旋转矩阵
  214. void mat_load_RotZAxis(long deg)
  215. {
  216.         m_stack[m_stacktop].x.x = cos(deg);
  217.         m_stack[m_stacktop].x.y = sin(deg);
  218.         m_stack[m_stacktop].x.z = 0;
  219.         m_stack[m_stacktop].x.w = 0;
  220.        
  221.         m_stack[m_stacktop].y.x =-sin(deg);
  222.         m_stack[m_stacktop].y.y = cos(deg);
  223.         m_stack[m_stacktop].y.z = 0;
  224.         m_stack[m_stacktop].y.w = 0;
  225.        
  226.         m_stack[m_stacktop].z.x = 0;
  227.         m_stack[m_stacktop].z.y = 0;
  228.         m_stack[m_stacktop].z.z = FIXED;
  229.         m_stack[m_stacktop].z.w = 0;
  230.        
  231.         m_stack[m_stacktop].w.x = 0;
  232.         m_stack[m_stacktop].w.y = 0;
  233.         m_stack[m_stacktop].w.z = 0;
  234.         m_stack[m_stacktop].w.w = FIXED;
  235. }

  236. // 载入绕轴旋转矩阵
  237. void mat_load_RotAxis(long ax, long ay, long az, long deg)
  238. {
  239.         m_stack[m_stacktop].x.x = (((FIXED - cos(deg)) * ax >> FIXED_SHIFT) * ax >> FIXED_SHIFT) + cos(deg);
  240.         m_stack[m_stacktop].x.y = (((FIXED - cos(deg)) * ax >> FIXED_SHIFT) * ay >> FIXED_SHIFT) - sin(deg) * az >> FIXED_SHIFT;
  241.         m_stack[m_stacktop].x.z = (((FIXED - cos(deg)) * ax >> FIXED_SHIFT) * az >> FIXED_SHIFT) + sin(deg) * ay >> FIXED_SHIFT;
  242.         m_stack[m_stacktop].x.w = 0;
  243.                                   
  244.         m_stack[m_stacktop].y.x = (((FIXED - cos(deg)) * ay >> FIXED_SHIFT) * ax >> FIXED_SHIFT) + sin(deg) * az >> FIXED_SHIFT;
  245.         m_stack[m_stacktop].y.y = (((FIXED - cos(deg)) * ay >> FIXED_SHIFT) * ay >> FIXED_SHIFT) + cos(deg);
  246.         m_stack[m_stacktop].y.z = (((FIXED - cos(deg)) * ay >> FIXED_SHIFT) * az >> FIXED_SHIFT) - sin(deg) * ax >> FIXED_SHIFT;
  247.         m_stack[m_stacktop].y.w = 0;
  248.                                   
  249.         m_stack[m_stacktop].z.x = (((FIXED - cos(deg)) * az >> FIXED_SHIFT) * ax >> FIXED_SHIFT) - sin(deg) * ay >> FIXED_SHIFT;
  250.         m_stack[m_stacktop].z.y = (((FIXED - cos(deg)) * az >> FIXED_SHIFT) * ay >> FIXED_SHIFT) + sin(deg) * ax >> FIXED_SHIFT;
  251.         m_stack[m_stacktop].z.z = (((FIXED - cos(deg)) * az >> FIXED_SHIFT) * az >> FIXED_SHIFT) + cos(deg);
  252.         m_stack[m_stacktop].z.w = 0;
  253.        
  254.         m_stack[m_stacktop].w.x = 0;
  255.         m_stack[m_stacktop].w.y = 0;
  256.         m_stack[m_stacktop].w.z = 0;
  257.         m_stack[m_stacktop].w.w = FIXED;
  258. }

  259. // 载入欧拉角旋转矩阵
  260. void mat_load_EulerRotation(long yaw, long pitch, long roll)
  261. {
  262.         mat_load_RotZAxis(roll);
  263.        
  264.         mat_push();
  265.         mat_load_RotXAxis(pitch);
  266.        
  267.         mat_mult();
  268.        
  269.         mat_push();
  270.         mat_load_RotYAxis(yaw);
  271.        
  272.         mat_mult();
  273. }

  274. // 载入左手坐标系观察矩阵
  275. void mat_load_view_lh(long x, long y, long z, long yaw, long pitch, long roll)
  276. {
  277.         long t;
  278.         mat_load_EulerRotation(yaw, pitch, roll);
  279.        
  280.         eye_xaxis.x = m_stack[m_stacktop].x.x;
  281.         eye_xaxis.y = m_stack[m_stacktop].x.y;
  282.         eye_xaxis.z = m_stack[m_stacktop].x.z;
  283.         eye_yaxis.x = m_stack[m_stacktop].y.x;
  284.         eye_yaxis.y = m_stack[m_stacktop].y.y;
  285.         eye_yaxis.z = m_stack[m_stacktop].y.z;
  286.         eye_zaxis.x = m_stack[m_stacktop].z.x;
  287.         eye_zaxis.y = m_stack[m_stacktop].z.y;
  288.         eye_zaxis.z = m_stack[m_stacktop].z.z;
  289.        
  290.         m_stack[m_stacktop].w.x = -((eye_xaxis.x * x >> FIXED_SHIFT) + (eye_xaxis.y * y >> FIXED_SHIFT) + (eye_xaxis.z * z >> FIXED_SHIFT));
  291.         m_stack[m_stacktop].w.y = -((eye_yaxis.x * x >> FIXED_SHIFT) + (eye_yaxis.y * y >> FIXED_SHIFT) + (eye_yaxis.z * z >> FIXED_SHIFT));
  292.         m_stack[m_stacktop].w.z = -((eye_zaxis.x * x >> FIXED_SHIFT) + (eye_zaxis.y * y >> FIXED_SHIFT) + (eye_zaxis.z * z >> FIXED_SHIFT));
  293.         m_stack[m_stacktop].w.w = FIXED;
  294.        
  295.         t = m_stack[m_stacktop].x.y;
  296.         m_stack[m_stacktop].x.y = m_stack[m_stacktop].y.x;
  297.         m_stack[m_stacktop].y.x = t;
  298.        
  299.         t = m_stack[m_stacktop].x.z;
  300.         m_stack[m_stacktop].x.z = m_stack[m_stacktop].z.x;
  301.         m_stack[m_stacktop].z.x = t;
  302.        
  303.         t = m_stack[m_stacktop].y.z;
  304.         m_stack[m_stacktop].y.z = m_stack[m_stacktop].z.y;
  305.         m_stack[m_stacktop].z.y = t;
  306.        
  307.         m_stack[m_stacktop].x.w = 0;
  308.         m_stack[m_stacktop].y.w = 0;
  309.         m_stack[m_stacktop].z.w = 0;
  310. }

  311. // 载入左手坐标系投影矩阵
  312. void mat_load_perspective_lh(long fovy, long aspect, long zn, long zf)
  313. {
  314.         long xscale,yscale;
  315.         long zdiff;
  316.         zdiff = zf-zn;
  317.         yscale = cot(fovy / 2);
  318.         xscale = (yscale << FIXED_SHIFT) / aspect;
  319.         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;
  320.         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;
  321.         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;
  322.         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;
  323. }

  324. // 将模型矩阵复制到栈顶
  325. void mat_load_modelview()
  326. {
  327.         memcpy(&m_stack[m_stacktop].x.x, &m_modelview.x.x, 64);
  328. }

  329. // 将投影矩阵复制到栈顶
  330. void mat_load_projection()
  331. {
  332.         memcpy(&m_stack[m_stacktop].x.x, &m_projection.x.x, 64);
  333. }

  334. // 将栈顶的矩阵复制到模型矩阵
  335. void mat_set_modelview()
  336. {
  337.         memcpy(&m_modelview.x.x, &m_stack[m_stacktop].x.x, 64);
  338. }

  339. // 将栈顶的矩阵复制到投影矩阵
  340. void mat_set_projection()
  341. {
  342.         memcpy(&m_projection.x.x, &m_stack[m_stacktop].x.x, 64);
  343. }

  344. // 打印矩阵的值到屏幕上
  345. void mat_print(int x, int y)
  346. {
  347.         char buf[256];
  348.         sprintf(buf, "%d:",m_stacktop);
  349.         TextOut(x,y,buf);y=y+GetFontSize();
  350.         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);
  351.         TextOut(x,y,buf);y=y+GetFontSize();
  352.         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);
  353.         TextOut(x,y,buf);y=y+GetFontSize();
  354.         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);
  355.         TextOut(x,y,buf);y=y+GetFontSize();
  356.         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);
  357.         TextOut(x,y,buf);
  358. }

  359. // 线性插值
  360. long m_lerp(long v1, long v2, long s)
  361. {
  362.         return v1 + ((v2 - v1) * s >> FIXED_SHIFT);
  363. }

  364. // 画线
  365. void g_draw_line(long x1, long y1, long x2, long y2)
  366. {
  367.         // gvmaker原版的画线函数不能处理坐标超出屏幕外的情况
  368.         // 所以要做一个插值处理
  369.         if(x1 < 0)
  370.         {
  371.                 if(x2 < 0)
  372.                         return; // 防止除零异常
  373.                 y1 = y1 + (y2 - y1) *-x1 / (x2 - x1);
  374.                 x1 = 0;
  375.         }
  376.         if(y1 < 0)
  377.         {
  378.                 if(y2 < 0)
  379.                         return;
  380.                 x1 = x1 + (x2 - x1) *-y1 / (y2 - y1);
  381.                 y1 = 0;
  382.         }
  383.         if(x2 < 0)
  384.         {
  385.                 if(x1 <= 0)
  386.                         return;
  387.                 y2 = y2 + (y1 - y2) *-x2 / (x1 - x2);
  388.                 x2 = 0;
  389.         }
  390.         if(y2 < 0)
  391.         {
  392.                 if(y1 <= 0)
  393.                         return;
  394.                 x2 = x2 + (x1 - x2) *-y2 / (y1 - y2);
  395.                 y2 = 0;
  396.         }
  397.         if(x1 > VP_RIGHT)
  398.         {
  399.                 if(x2 > VP_RIGHT)
  400.                         return;
  401.                 y1 = y1 + (y2 - y1) * (x1 - VP_RIGHT) / (x1 - x2);
  402.                 x1 = VP_RIGHT;
  403.         }
  404.         if(y1 > VP_BOTTOM)
  405.         {
  406.                 if(y2 > VP_BOTTOM)
  407.                         return;
  408.                 x1 = x1 + (x2 - x1) * (y1 - VP_BOTTOM) / (y1 - y2);
  409.                 y1 = VP_BOTTOM;
  410.         }
  411.         if(x2 > VP_RIGHT)
  412.         {
  413.                 if(x1 >= VP_RIGHT)
  414.                         return;
  415.                 y2 = y2 + (y1 - y2) * (x2 - VP_RIGHT) / (x2 - x1);
  416.                 x2 = VP_RIGHT;
  417.         }
  418.         if(y2 > VP_BOTTOM)
  419.         {
  420.                 if(y1 >= VP_BOTTOM)
  421.                         return;
  422.                 x2 = x2 + (x1 - x2) * (y2 - VP_BOTTOM) / (y2 - y1);
  423.                 y2 = VP_BOTTOM;
  424.         }
  425.         if(x1 == x2)
  426.                 VLine(x1, y1, y2);
  427.         else if(y1 == y2)
  428.                 HLine(x1, x2, y1);
  429.         else
  430.                 Line(x1,y1,x2,y2);
  431. }

  432. // 画3D线,坐标将经过矩阵变换和投影处理。
  433. void g_draw_3d_line(long x1, long y1, long z1, long x2, long y2, long z2)
  434. {
  435.         long pxt, pyt, pzt, pwt; // 临时坐标
  436.         long px1, py1, pz1, pw1; // 坐标1
  437.         long px2, py2, pz2, pw2; // 坐标2
  438.         long ls;
  439.        
  440.         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;
  441.         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;
  442.         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;
  443.         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;
  444.        
  445.         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);
  446.         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);
  447.         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);
  448.         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);
  449.        
  450.         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;
  451.         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;
  452.         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;
  453.         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;
  454.        
  455.         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);
  456.         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);
  457.         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);
  458.         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);
  459.        
  460.         // 处理近视距剪切
  461.         if(pz1 < FIXED)
  462.         {
  463.                 if(pz2 < FIXED)
  464.                         return;
  465.                
  466.                 if(pz1 == pz2)
  467.                         return;
  468.                
  469.                 ls = ((pz2 - FIXED) << FIXED_SHIFT) / (pz2 - pz1);
  470.                
  471.                 px1 = m_lerp(px2, px1, ls);
  472.                 py1 = m_lerp(py2, py1, ls);
  473.                 pz1 = m_lerp(pz2, pz1, ls);
  474.                 pw1 = m_lerp(pw2, pw1, ls);
  475.         }
  476.        
  477.         if(pz2 < FIXED)
  478.         {
  479.                 if(pz1 < FIXED)
  480.                         return;
  481.                
  482.                 if(pz1 == pz2)
  483.                         return;
  484.                
  485.                 ls = ((pz1 - FIXED) << FIXED_SHIFT) / (pz1 - pz2);
  486.                
  487.                 px2 = m_lerp(px1, px2, ls);
  488.                 py2 = m_lerp(py1, py2, ls);
  489.                 pz2 = m_lerp(pz1, pz2, ls);
  490.                 pw2 = m_lerp(pw1, pw2, ls);
  491.         }
  492.        
  493.         // 投影
  494.         px1 = px1 * VP_CENTERX / pw1 + VP_CENTERX;
  495.         py1 = VP_CENTERY - py1 * VP_CENTERY / pw1;
  496.         px2 = px2 * VP_CENTERX / pw2 + VP_CENTERX;
  497.         py2 = VP_CENTERY - py2 * VP_CENTERY / pw2;
  498.         g_draw_line(px1,py1,px2,py2);
  499. }

  500. // 用线条画长方体
  501. void g_draw_cube(long dx, long dy, long dz)
  502. {
  503.         // Up
  504.         g_draw_3d_line(-dx, dy, dz, dx, dy, dz);
  505.         g_draw_3d_line( dx, dy, dz, dx, dy,-dz);
  506.         g_draw_3d_line( dx, dy,-dz,-dx, dy,-dz);
  507.         g_draw_3d_line(-dx, dy,-dz,-dx, dy, dz);
  508.        
  509.         // Down
  510.         g_draw_3d_line(-dx,-dy, dz, dx,-dy, dz);
  511.         g_draw_3d_line( dx,-dy, dz, dx,-dy,-dz);
  512.         g_draw_3d_line( dx,-dy,-dz,-dx,-dy,-dz);
  513.         g_draw_3d_line(-dx,-dy,-dz,-dx,-dy, dz);
  514.        
  515.         // Pillars
  516.         g_draw_3d_line(-dx, dy, dz,-dx,-dy, dz);
  517.         g_draw_3d_line( dx, dy, dz, dx,-dy, dz);
  518.         g_draw_3d_line( dx, dy,-dz, dx,-dy,-dz);
  519.         g_draw_3d_line(-dx, dy,-dz,-dx,-dy,-dz);
  520. }

  521. // 输出16进制数
  522. void XDigitOut(int x, int y, long digit)
  523. {
  524.         int ch;
  525.         int w;
  526.         int shifts;
  527.        
  528.         w = GetFontSize() / 2;
  529.        
  530.         if(!digit)
  531.         {
  532.                 TextOut(x, y, "00000000");
  533.                 return;
  534.         }
  535.        
  536.         x=x+w*7;
  537.         shifts=32;
  538.         while(shifts)
  539.         {
  540.                 ch=digit&0xF;
  541.                 if(ch>=10)
  542.                         CharOut(x, y, ch-10+'A');
  543.                 else
  544.                         CharOut(x, y, ch+'0');
  545.                 x=x-w;
  546.                 digit=digit>>4;
  547.                 shifts=shifts-4;
  548.         }
  549. }

  550. void main()
  551. {
  552.         long i;
  553.         int x,y;
  554.        
  555.         SetFontSize(12);
  556.         SetLCDMode(0);
  557.        
  558.         eye_pos.x=0;
  559.         eye_pos.y=3 << FIXED_SHIFT;
  560.         eye_pos.z=-10 << FIXED_SHIFT;
  561.        
  562.         mat_init();
  563.        
  564.         time_global = GetTickCount();
  565.        
  566.         for(;;)
  567.         {
  568.                 // 帧时间处理
  569.                 i = GetTickCount();
  570.                 time_delta = i - time_global;
  571.                 time_global = i;
  572.                
  573.                 ClearScreen();
  574.                
  575.                 // 设置投影矩阵
  576.                 mat_load_perspective_lh(60, (VP_WIDTH << FIXED_SHIFT) / VP_HEIGHT, FIXED, 1000 << FIXED_SHIFT);
  577.                 mat_set_projection();
  578.                
  579.                 // 设置旋转立方体的矩阵
  580.                 mat_load_RotYAxis(time_global * 60 / 1000);
  581.                 mat_push();
  582.                 mat_load_translate(0,FIXED,0);
  583.                 mat_mult();
  584.                 mat_push();
  585.                 mat_load_view_lh(eye_pos.x, eye_pos.y, eye_pos.z, eye_yaw, eye_pitch, 0);
  586.                 mat_mult();
  587.                 mat_set_modelview();
  588.                
  589.                 // 画立方体
  590.                 g_draw_cube(FIXED, FIXED, FIXED);
  591.                
  592.                 // 设置地面的矩阵
  593.                 mat_load_view_lh(eye_pos.x, eye_pos.y, eye_pos.z, eye_yaw, eye_pitch, 0);
  594.                 mat_set_modelview();
  595.                
  596.                 // 画地面
  597.                 for(x = -10; x <= 10; x++)
  598.                 {
  599.                         g_draw_3d_line( x << FIXED_SHIFT, 0, 10 << FIXED_SHIFT, x << FIXED_SHIFT, 0, -10 << FIXED_SHIFT);
  600.                 }
  601.                 for(y = -10; y <= 10; y++)
  602.                 {
  603.                         g_draw_3d_line( 10 << FIXED_SHIFT, 0, y << FIXED_SHIFT,-10 << FIXED_SHIFT, 0, y << FIXED_SHIFT);
  604.                 }
  605.                
  606.                 // 根据触屏操作来转动镜头
  607.                 if(GetMousePos(pt) == 2)
  608.                 {
  609.                         eye_yaw = eye_yaw + pt_old.x - pt.x;
  610.                         eye_pitch = eye_pitch + pt_old.y - pt.y;
  611.                         if(eye_yaw < 0)
  612.                                 eye_yaw = eye_yaw + 360;
  613.                         if(eye_yaw > 360)
  614.                                 eye_yaw = eye_yaw - 360;
  615.                         if(eye_pitch < 0)
  616.                                 eye_pitch = eye_pitch + 360;
  617.                         if(eye_pitch > 360)
  618.                                 eye_pitch = eye_pitch - 360;
  619.                 }
  620.                 pt_old.x = pt.x;
  621.                 pt_old.y = pt.y;
  622.                
  623.                 // 键盘移动操作
  624.                 if(CheckKey(KEY_LEFT))
  625.                 {
  626.                         eye_pos.x = eye_pos.x - eye_xaxis.x * time_delta * 10 / 1000;
  627.                         eye_pos.y = eye_pos.y - eye_xaxis.y * time_delta * 10 / 1000;
  628.                         eye_pos.z = eye_pos.z - eye_xaxis.z * time_delta * 10 / 1000;
  629.                 }
  630.                 if(CheckKey(KEY_RIGHT))
  631.                 {
  632.                         eye_pos.x = eye_pos.x + eye_xaxis.x * time_delta * 10 / 1000;
  633.                         eye_pos.y = eye_pos.y + eye_xaxis.y * time_delta * 10 / 1000;
  634.                         eye_pos.z = eye_pos.z + eye_xaxis.z * time_delta * 10 / 1000;
  635.                 }
  636.                 if(CheckKey(KEY_UP))
  637.                 {
  638.                         eye_pos.x = eye_pos.x + eye_zaxis.x * time_delta * 10 / 1000;
  639.                         eye_pos.y = eye_pos.y + eye_zaxis.y * time_delta * 10 / 1000;
  640.                         eye_pos.z = eye_pos.z + eye_zaxis.z * time_delta * 10 / 1000;
  641.                 }
  642.                 if(CheckKey(KEY_DOWN))
  643.                 {
  644.                         eye_pos.x = eye_pos.x - eye_zaxis.x * time_delta * 10 / 1000;
  645.                         eye_pos.y = eye_pos.y - eye_zaxis.y * time_delta * 10 / 1000;
  646.                         eye_pos.z = eye_pos.z - eye_zaxis.z * time_delta * 10 / 1000;
  647.                 }
  648.                
  649.                 Refresh();
  650.         }
  651. }
复制代码
Src: main.txt (23.31 KB, 下载次数: 6)
Bin: main.gvm (8.82 KB, 下载次数: 5)

回复

使用道具 举报

30

主题

207

回帖

2734

积分

用户组: 版主

UID
1821
精华
7
威望
69 点
宅币
2118 个
贡献
206 次
宅之契约
0 份
在线时间
470 小时
注册时间
2016-7-12
发表于 2017-3-17 18:07:24 | 显示全部楼层
本帖最后由 Ayala 于 2017-3-17 18:28 编辑
    但定点数的缺点在于做乘除法的时候,会严重地损失精度,尤其是圆周率,32位浮点数能存储3.1415927,而定点数假设小数点在第10位,那么它只能用 3216 来表示圆周率(3216 = π×1024 取整)。而如果我把小数点放在第16位的位置上(1.0用65536表示)的话,我虽然能精确到1/65536,但我能存储的最大的数值也从之前的4294966272变成了65536,而且我每次做乘除法的时候,我都要用一个64位的整数来存储中间值,这会严重降低运算的效率(然而x86平台还好)

这个问题其实可以用1024* PI*2**8 (定点数 π×1024 * 256 =0xC90FE)来解决 当然也可以用 1024*PI*2**15更高数值
另外PI*1024 取整也应该是3216.990877≈3217 而不是 3216
回复 赞! 靠!

使用道具 举报

1109

主题

1649

回帖

7万

积分

用户组: 管理员

一只技术宅

UID
1
精华
244
威望
743 点
宅币
24180 个
贡献
46222 次
宅之契约
0 份
在线时间
2294 小时
注册时间
2014-1-26
 楼主| 发表于 2017-3-17 20:06:54 | 显示全部楼层
Ayala 发表于 2017-3-17 18:07
这个问题其实可以用1024* PI*2**8 (定点数 π×1024 * 256 =0xC90FE)来解决 当然也可以用 1024*PI*2**15更 ...

其实是说错,不是取整,而是“商”,所以是没有四舍五入的
回复 赞! 靠!

使用道具 举报

1109

主题

1649

回帖

7万

积分

用户组: 管理员

一只技术宅

UID
1
精华
244
威望
743 点
宅币
24180 个
贡献
46222 次
宅之契约
0 份
在线时间
2294 小时
注册时间
2014-1-26
 楼主| 发表于 2017-9-15 17:52:06 | 显示全部楼层
另外因为文曲星的解释器特征,优化方面侧重于多调用它的函数进行绘图,少进行自己的绘图方式。比如它的画线函数,其实虽然明明可以自己写一个不使用乘除法的画线函数,但依然还是推荐使用它自己的画线函数(VLine、HLine、Line)。因为自己写的画线函数在运行的时候需要GVMaker虚拟机对其进行指令层面的判断和模拟执行的操作,而它自己的画线函数则是用文曲星本机的处理器指令执行的。
回复 赞! 靠!

使用道具 举报

QQ|Archiver|小黑屋|技术宅的结界 ( 滇ICP备16008837号 )|网站地图

GMT+8, 2024-3-29 04:04 , Processed in 0.045360 second(s), 35 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表