qlcube.pas 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. {
  2. Copyright (c) 2017-2020 Karoly Balogh
  3. Rotating 3D cube on a Sinclair QL
  4. Example program for Free Pascal's Sinclair QL support
  5. This example program is in the Public Domain under the terms of
  6. Unlicense: http://unlicense.org/
  7. **********************************************************************}
  8. program qlcube;
  9. uses
  10. qdos, qlfloat;
  11. type
  12. tvertex = record
  13. x: longint;
  14. y: longint;
  15. z: longint;
  16. end;
  17. const
  18. cube: array[0..7] of tvertex = (
  19. ( x: -1; y: -1; z: -1; ), // 0
  20. ( x: 1; y: -1; z: -1; ), // 1
  21. ( x: 1; y: 1; z: -1; ), // 2
  22. ( x: -1; y: 1; z: -1; ), // 3
  23. ( x: -1; y: -1; z: 1; ), // 4
  24. ( x: 1; y: -1; z: 1; ), // 5
  25. ( x: 1; y: 1; z: 1; ), // 6
  26. ( x: -1; y: 1; z: 1; ) // 7
  27. );
  28. type
  29. tface = record
  30. v1, v2, v3: longint;
  31. edge: longint;
  32. end;
  33. const
  34. sincos_table: array[0..255] of longint = (
  35. 0, 1608, 3216, 4821, 6424, 8022, 9616, 11204,
  36. 12785, 14359, 15924, 17479, 19024, 20557, 22078, 23586,
  37. 25079, 26557, 28020, 29465, 30893, 32302, 33692, 35061,
  38. 36409, 37736, 39039, 40319, 41575, 42806, 44011, 45189,
  39. 46340, 47464, 48558, 49624, 50659, 51664, 52638, 53580,
  40. 54490, 55367, 56211, 57021, 57797, 58537, 59243, 59913,
  41. 60546, 61144, 61704, 62227, 62713, 63161, 63571, 63943,
  42. 64276, 64570, 64826, 65042, 65219, 65357, 65456, 65515,
  43. 65535, 65515, 65456, 65357, 65219, 65042, 64826, 64570,
  44. 64276, 63943, 63571, 63161, 62713, 62227, 61704, 61144,
  45. 60546, 59913, 59243, 58537, 57797, 57021, 56211, 55367,
  46. 54490, 53580, 52638, 51664, 50659, 49624, 48558, 47464,
  47. 46340, 45189, 44011, 42806, 41575, 40319, 39039, 37736,
  48. 36409, 35061, 33692, 32302, 30893, 29465, 28020, 26557,
  49. 25079, 23586, 22078, 20557, 19024, 17479, 15924, 14359,
  50. 12785, 11204, 9616, 8022, 6424, 4821, 3216, 1608,
  51. 0, -1608, -3216, -4821, -6424, -8022, -9616,-11204,
  52. -12785,-14359,-15924,-17479,-19024,-20557,-22078,-23586,
  53. -25079,-26557,-28020,-29465,-30893,-32302,-33692,-35061,
  54. -36409,-37736,-39039,-40319,-41575,-42806,-44011,-45189,
  55. -46340,-47464,-48558,-49624,-50659,-51664,-52638,-53580,
  56. -54490,-55367,-56211,-57021,-57797,-58537,-59243,-59913,
  57. -60546,-61144,-61704,-62227,-62713,-63161,-63571,-63943,
  58. -64276,-64570,-64826,-65042,-65219,-65357,-65456,-65515,
  59. -65535,-65515,-65456,-65357,-65219,-65042,-64826,-64570,
  60. -64276,-63943,-63571,-63161,-62713,-62227,-61704,-61144,
  61. -60546,-59913,-59243,-58537,-57797,-57021,-56211,-55367,
  62. -54490,-53580,-52638,-51664,-50659,-49624,-48558,-47464,
  63. -46340,-45189,-44011,-42806,-41575,-40319,-39039,-37736,
  64. -36409,-35061,-33692,-32302,-30893,-29465,-28020,-26557,
  65. -25079,-23586,-22078,-20557,-19024,-17479,-15924,-14359,
  66. -12785,-11204, -9616, -8022, -6424, -4821, -3216, -1608
  67. );
  68. function sin(x: longint): longint; inline;
  69. begin
  70. sin:=sincos_table[x and 255];
  71. end;
  72. function cos(x: longint): longint; inline;
  73. begin
  74. cos:=sincos_table[(x + 64) and 255];
  75. end;
  76. function mulfp(a, b: longint): longint; inline;
  77. begin
  78. mulfp:=sarint64((int64(a) * b),16);
  79. end;
  80. function divfp(a, b: longint): longint;
  81. begin
  82. divfp:=(int64(a) shl 16) div b;
  83. end;
  84. procedure rotate_vertex(const v: tvertex; var vr: tvertex; xa, ya, za: longint);
  85. var
  86. x,y,z: longint;
  87. s,c: longint;
  88. begin
  89. s :=sin(ya);
  90. c :=cos(ya);
  91. x :=mulfp(c,v.x) - mulfp(s,v.z);
  92. z :=mulfp(s,v.x) + mulfp(c,v.z);
  93. if za <> 0 then
  94. begin
  95. vr.x:=mulfp(cos(za),x) + mulfp(sin(za),v.y);
  96. y :=mulfp(cos(za),v.y) - mulfp(sin(za),x);
  97. end
  98. else
  99. begin
  100. vr.x:=x;
  101. y:=v.y;
  102. end;
  103. vr.z:=mulfp(cos(xa),z) - mulfp(sin(xa),y);
  104. vr.y:=mulfp(sin(xa),z) + mulfp(cos(xa),y);
  105. end;
  106. procedure perspective_vertex(const v: tvertex; zc: longint; var xr,yr: longint);
  107. var
  108. rzc: longint;
  109. begin
  110. rzc:=divfp(1 shl 16,(v.z - zc));
  111. xr:=mulfp(mulfp(v.x,zc),rzc);
  112. yr:=mulfp(mulfp(v.y,zc),rzc);
  113. end;
  114. procedure init_cube;
  115. var
  116. i: longint;
  117. begin
  118. for i:=low(cube) to high(cube) do
  119. begin
  120. cube[i].x:=cube[i].x shl 16;
  121. cube[i].y:=cube[i].y shl 16;
  122. cube[i].z:=cube[i].z shl 16;
  123. end;
  124. end;
  125. var
  126. mx, my: smallint;
  127. function min(a, b: smallint): smallint;
  128. begin
  129. if a < b then
  130. min:=a
  131. else
  132. min:=b;
  133. end;
  134. procedure draw_line(x1,y1,x2,y2: smallint);
  135. begin
  136. sd_line(stdOutputHandle,-1,x1,y1,x2,y2);
  137. end;
  138. procedure cube_redraw;
  139. var
  140. i,s,e,cx,cy,vx,vy: longint;
  141. vr: tvertex;
  142. scale: longint;
  143. rect:TQLRect;
  144. fcubex: array[low(cube)..high(cube)] of Tqlfloat;
  145. fcubey: array[low(cube)..high(cube)] of Tqlfloat;
  146. begin
  147. rect.q_x:=0;
  148. rect.q_y:=0;
  149. rect.q_width:=140;
  150. rect.q_height:=100;
  151. scale:=(min(rect.q_width,rect.q_height) div 6) shl 16;
  152. cx:=rect.q_x + rect.q_width div 2;
  153. cy:=rect.q_y + rect.q_height div 2;
  154. for i:=low(cube) to high(cube) do
  155. begin
  156. rotate_vertex(cube[i],vr,-my,-mx,0);
  157. perspective_vertex(vr,3 shl 16,vx,vy);
  158. longint_to_qlfp(@fcubex[i],cx + sarlongint(mulfp(vx,scale),16));
  159. longint_to_qlfp(@fcubey[i],cy + sarlongint(mulfp(vy,scale),16));
  160. end;
  161. sd_clear(stdOutputHandle,-1);
  162. for i:=0 to 3 do
  163. begin
  164. e:=(i+1) and 3;
  165. sd_line(stdOutputHandle,-1,@fcubex[i],@fcubey[i],@fcubex[e],@fcubey[e]);
  166. s:=i+4; e:=e+4;
  167. sd_line(stdOutputHandle,-1,@fcubex[s],@fcubey[s],@fcubex[e],@fcubey[e]);
  168. sd_line(stdOutputHandle,-1,@fcubex[i],@fcubey[i],@fcubex[s],@fcubey[s]);
  169. end;
  170. end;
  171. procedure main_loop;
  172. begin
  173. repeat
  174. inc(mx,5);
  175. inc(my,7);
  176. cube_redraw;
  177. until false;
  178. end;
  179. begin
  180. init_cube;
  181. main_loop;
  182. end.