palmcube.pas 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. {
  2. Copyright (c) 2018 Karoly Balogh
  3. Rotating 3D cube on PalmOS
  4. Example program for Free Pascal's PalmOS bindings
  5. This example program is in the Public Domain under the terms of
  6. Unlicense: http://unlicense.org/
  7. **********************************************************************}
  8. {$APPID FPCB}
  9. {$APPNAME FPC Cube}
  10. program palmcube;
  11. uses
  12. event_, sysevent, systemmgr, window, font,
  13. errorbase, rect;
  14. type
  15. tvertex = record
  16. x: longint;
  17. y: longint;
  18. z: longint;
  19. end;
  20. const
  21. cube: array[0..7] of tvertex = (
  22. ( x: -1; y: -1; z: -1; ), // 0
  23. ( x: 1; y: -1; z: -1; ), // 1
  24. ( x: 1; y: 1; z: -1; ), // 2
  25. ( x: -1; y: 1; z: -1; ), // 3
  26. ( x: -1; y: -1; z: 1; ), // 4
  27. ( x: 1; y: -1; z: 1; ), // 5
  28. ( x: 1; y: 1; z: 1; ), // 6
  29. ( x: -1; y: 1; z: 1; ) // 7
  30. );
  31. type
  32. tface = record
  33. v1, v2, v3: longint;
  34. edge: longint;
  35. end;
  36. const
  37. faces: array[0..11] of tface = (
  38. ( v1: 0; v2: 2; v3: 1; edge: 6), // front
  39. ( v1: 2; v2: 0; v3: 3; edge: 6),
  40. ( v1: 0; v2: 1; v3: 4; edge: 5), // top
  41. ( v1: 1; v2: 5; v3: 4; edge: 3),
  42. ( v1: 3; v2: 0; v3: 7; edge: 5), // left
  43. ( v1: 0; v2: 4; v3: 7; edge: 3),
  44. ( v1: 1; v2: 2; v3: 5; edge: 5), // right
  45. ( v1: 1; v2: 6; v3: 5; edge: 6),
  46. ( v1: 2; v2: 3; v3: 6; edge: 5), // bottom
  47. ( v1: 3; v2: 7; v3: 6; edge: 3),
  48. ( v1: 4; v2: 5; v3: 6; edge: 3), // back
  49. ( v1: 6; v2: 7; v3: 4; edge: 3)
  50. );
  51. const
  52. sincos_table: array[0..255] of longint = (
  53. 0, 1608, 3216, 4821, 6424, 8022, 9616, 11204,
  54. 12785, 14359, 15924, 17479, 19024, 20557, 22078, 23586,
  55. 25079, 26557, 28020, 29465, 30893, 32302, 33692, 35061,
  56. 36409, 37736, 39039, 40319, 41575, 42806, 44011, 45189,
  57. 46340, 47464, 48558, 49624, 50659, 51664, 52638, 53580,
  58. 54490, 55367, 56211, 57021, 57797, 58537, 59243, 59913,
  59. 60546, 61144, 61704, 62227, 62713, 63161, 63571, 63943,
  60. 64276, 64570, 64826, 65042, 65219, 65357, 65456, 65515,
  61. 65535, 65515, 65456, 65357, 65219, 65042, 64826, 64570,
  62. 64276, 63943, 63571, 63161, 62713, 62227, 61704, 61144,
  63. 60546, 59913, 59243, 58537, 57797, 57021, 56211, 55367,
  64. 54490, 53580, 52638, 51664, 50659, 49624, 48558, 47464,
  65. 46340, 45189, 44011, 42806, 41575, 40319, 39039, 37736,
  66. 36409, 35061, 33692, 32302, 30893, 29465, 28020, 26557,
  67. 25079, 23586, 22078, 20557, 19024, 17479, 15924, 14359,
  68. 12785, 11204, 9616, 8022, 6424, 4821, 3216, 1608,
  69. 0, -1608, -3216, -4821, -6424, -8022, -9616,-11204,
  70. -12785,-14359,-15924,-17479,-19024,-20557,-22078,-23586,
  71. -25079,-26557,-28020,-29465,-30893,-32302,-33692,-35061,
  72. -36409,-37736,-39039,-40319,-41575,-42806,-44011,-45189,
  73. -46340,-47464,-48558,-49624,-50659,-51664,-52638,-53580,
  74. -54490,-55367,-56211,-57021,-57797,-58537,-59243,-59913,
  75. -60546,-61144,-61704,-62227,-62713,-63161,-63571,-63943,
  76. -64276,-64570,-64826,-65042,-65219,-65357,-65456,-65515,
  77. -65535,-65515,-65456,-65357,-65219,-65042,-64826,-64570,
  78. -64276,-63943,-63571,-63161,-62713,-62227,-61704,-61144,
  79. -60546,-59913,-59243,-58537,-57797,-57021,-56211,-55367,
  80. -54490,-53580,-52638,-51664,-50659,-49624,-48558,-47464,
  81. -46340,-45189,-44011,-42806,-41575,-40319,-39039,-37736,
  82. -36409,-35061,-33692,-32302,-30893,-29465,-28020,-26557,
  83. -25079,-23586,-22078,-20557,-19024,-17479,-15924,-14359,
  84. -12785,-11204, -9616, -8022, -6424, -4821, -3216, -1608
  85. );
  86. function sin(x: longint): longint; inline;
  87. begin
  88. sin:=sincos_table[x and 255];
  89. end;
  90. function cos(x: longint): longint; inline;
  91. begin
  92. cos:=sincos_table[(x + 64) and 255];
  93. end;
  94. function mulfp(a, b: longint): longint; inline;
  95. begin
  96. mulfp:=sarint64((int64(a) * b),16);
  97. end;
  98. function divfp(a, b: longint): longint;
  99. begin
  100. divfp:=(int64(a) shl 16) div b;
  101. end;
  102. procedure rotate_vertex(const v: tvertex; var vr: tvertex; xa, ya, za: longint);
  103. var
  104. x,y,z: longint;
  105. s,c: longint;
  106. begin
  107. s :=sin(ya);
  108. c :=cos(ya);
  109. x :=mulfp(c,v.x) - mulfp(s,v.z);
  110. z :=mulfp(s,v.x) + mulfp(c,v.z);
  111. if za <> 0 then
  112. begin
  113. vr.x:=mulfp(cos(za),x) + mulfp(sin(za),v.y);
  114. y :=mulfp(cos(za),v.y) - mulfp(sin(za),x);
  115. end
  116. else
  117. begin
  118. vr.x:=x;
  119. y:=v.y;
  120. end;
  121. vr.z:=mulfp(cos(xa),z) - mulfp(sin(xa),y);
  122. vr.y:=mulfp(sin(xa),z) + mulfp(cos(xa),y);
  123. end;
  124. procedure perspective_vertex(const v: tvertex; zc: longint; var xr,yr: longint);
  125. var
  126. rzc: longint;
  127. begin
  128. rzc:=divfp(1 shl 16,(v.z - zc));
  129. xr:=mulfp(mulfp(v.x,zc),rzc);
  130. yr:=mulfp(mulfp(v.y,zc),rzc);
  131. end;
  132. procedure init_cube;
  133. var
  134. i: longint;
  135. begin
  136. for i:=low(cube) to high(cube) do
  137. begin
  138. cube[i].x:=cube[i].x shl 16;
  139. cube[i].y:=cube[i].y shl 16;
  140. cube[i].z:=cube[i].z shl 16;
  141. end;
  142. end;
  143. function min(a, b: smallint): smallint;
  144. begin
  145. if a < b then
  146. min:=a
  147. else
  148. min:=b;
  149. end;
  150. procedure paintcube(tx,ty: longint);
  151. var
  152. i,cx,cy,vx,vy: longint;
  153. rcube: array[low(cube)..high(cube)] of tvertex;
  154. w, h: smallint;
  155. vr: tvertex;
  156. scale: longint;
  157. sx,sy: string[64];
  158. begin
  159. WinGetWindowExtent(w,h);
  160. scale:=(min(h,w) div 5) shl 16;
  161. cx:=w div 2;
  162. cy:=h div 2;
  163. for i:=low(cube) to high(cube) do
  164. begin
  165. rotate_vertex(cube[i],vr,-ty,-tx,0);
  166. perspective_vertex(vr,3 shl 16,vx,vy);
  167. rcube[i].x:=cx + sarlongint(mulfp(vx,scale),16);
  168. rcube[i].y:=cy + sarlongint(mulfp(vy,scale),16);
  169. end;
  170. str(tx,sx);
  171. str(ty,sy);
  172. sx:='FPC Cube! X:'+sx+' Y:'+sy;
  173. WinEraseWindow();
  174. WinDrawChars(@sx[1],length(sx),1,h-FntLineHeight);
  175. for i:=low(faces) to high(faces) do
  176. begin
  177. with faces[i] do
  178. begin
  179. if (edge and 1) > 0 then
  180. WinDrawLine(rcube[v1].x,rcube[v1].y,
  181. rcube[v2].x,rcube[v2].y);
  182. if (edge and 2) > 0 then
  183. WinDrawLine(rcube[v2].x,rcube[v2].y,
  184. rcube[v3].x,rcube[v3].y);
  185. if (edge and 4) > 0 then
  186. WinDrawLine(rcube[v3].x,rcube[v3].y,
  187. rcube[v1].x,rcube[v1].y);
  188. end;
  189. end;
  190. end;
  191. function CreateOffscreenWin(var offScreen: WinHandle; var screen: WinHandle; var r: RectangleType): boolean;
  192. var
  193. err: word;
  194. w, h: smallint;
  195. begin
  196. WinGetWindowExtent(w,h);
  197. offScreen:=WinCreateOffscreenWindow(w,h,screenFormat,err);
  198. screen:= WinGetDrawWindow();
  199. if err = 0 then
  200. WinSetDrawWindow(offScreen);
  201. r.topLeft.x:=0;
  202. r.topLeft.y:=0;
  203. r.extent.x:=h;
  204. r.extent.y:=w;
  205. CreateOffscreenWin:=err = 0;
  206. end;
  207. procedure EventLoop;
  208. var
  209. event: EventType;
  210. prevX,prevY: smallint;
  211. offscreen: boolean;
  212. offScrWin, scrWin: WinHandle;
  213. r: RectangleType;
  214. begin
  215. prevX:=-1;
  216. prevY:=-1;
  217. offScreen:=CreateOffscreenWin(offScrWin,scrWin,r);
  218. repeat
  219. EvtGetEvent(event, evtWaitForever);
  220. if not SysHandleEvent(event) and
  221. ((event.screenX<>prevX) or (event.screenY<>prevY)) then
  222. begin
  223. prevX:=event.screenX;
  224. prevY:=event.screenY;
  225. paintcube(prevX,prevY);
  226. if offscreen then
  227. WinCopyRectangle(offScrWin, scrWin, r, 0, 0, winPaint);
  228. end;
  229. until (event.eType = appStopEvent);
  230. if offscreen then
  231. WinDeleteWindow(offScrWin, false);
  232. end;
  233. begin
  234. init_cube;
  235. EventLoop;
  236. end.