Mat4.pas 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. {$mode objfpc}
  2. unit Mat4;
  3. interface
  4. uses
  5. Vectors,
  6. BrowserConsole, JS, Math;
  7. type
  8. TMat4 = class
  9. public
  10. constructor Identity;
  11. constructor Translate(const tx,ty,tz: TScalar);
  12. constructor RotateZ(const Angle:TScalar);
  13. constructor RotateY(const Angle:TScalar);
  14. constructor RotateX(const Angle:TScalar);
  15. constructor Scale (const x, y, z: TScalar);
  16. constructor Ortho(const Left,Right,Bottom,Top,zNear,zFar:TScalar);
  17. constructor Perspective(const fovy,Aspect,zNear,zFar:TScalar);
  18. function Multiply (m: TMat4): TMat4;
  19. function CopyList: TScalarArray;
  20. procedure Show;
  21. public
  22. RawComponents:array[0..3, 0..3] of TScalar;
  23. end;
  24. procedure SinCos (angle: TScalar; var sinus: TScalar, var cosinus: TScalar);
  25. implementation
  26. const
  27. PI = 3.14159265359;
  28. DEG2RAD = PI/180.0;
  29. RAD2DEG = 180.0/PI;
  30. HalfPI = PI*0.5;
  31. var
  32. Matrix4x4Identity: TMat4;
  33. // TODO: this should be in math
  34. procedure SinCos (angle: TScalar; var sinus: TScalar, var cosinus: TScalar);
  35. begin
  36. sinus := sin(angle);
  37. cosinus := cos(angle);
  38. end;
  39. // NOTE: [][] doesn't typecast to array of syntax so we need this
  40. function TMat4.CopyList: TScalarArray;
  41. var
  42. x, y: integer;
  43. list: TJSArray;
  44. begin
  45. list := TJSArray.new;
  46. for x := 0 to 3 do
  47. for y := 0 to 3 do
  48. list.push(RawComponents[x,y]);
  49. result := TScalarArray(list);
  50. end;
  51. function TMat4.Multiply (m: TMat4): TMat4;
  52. begin
  53. result := TMat4.Identity;
  54. result.RawComponents[0,0]:=(m.RawComponents[0,0]*self.RawComponents[0,0])+(m.RawComponents[0,1]*self.RawComponents[1,0])+(m.RawComponents[0,2]*self.RawComponents[2,0])+(m.RawComponents[0,3]*self.RawComponents[3,0]);
  55. result.RawComponents[0,1]:=(m.RawComponents[0,0]*self.RawComponents[0,1])+(m.RawComponents[0,1]*self.RawComponents[1,1])+(m.RawComponents[0,2]*self.RawComponents[2,1])+(m.RawComponents[0,3]*self.RawComponents[3,1]);
  56. result.RawComponents[0,2]:=(m.RawComponents[0,0]*self.RawComponents[0,2])+(m.RawComponents[0,1]*self.RawComponents[1,2])+(m.RawComponents[0,2]*self.RawComponents[2,2])+(m.RawComponents[0,3]*self.RawComponents[3,2]);
  57. result.RawComponents[0,3]:=(m.RawComponents[0,0]*self.RawComponents[0,3])+(m.RawComponents[0,1]*self.RawComponents[1,3])+(m.RawComponents[0,2]*self.RawComponents[2,3])+(m.RawComponents[0,3]*self.RawComponents[3,3]);
  58. result.RawComponents[1,0]:=(m.RawComponents[1,0]*self.RawComponents[0,0])+(m.RawComponents[1,1]*self.RawComponents[1,0])+(m.RawComponents[1,2]*self.RawComponents[2,0])+(m.RawComponents[1,3]*self.RawComponents[3,0]);
  59. result.RawComponents[1,1]:=(m.RawComponents[1,0]*self.RawComponents[0,1])+(m.RawComponents[1,1]*self.RawComponents[1,1])+(m.RawComponents[1,2]*self.RawComponents[2,1])+(m.RawComponents[1,3]*self.RawComponents[3,1]);
  60. result.RawComponents[1,2]:=(m.RawComponents[1,0]*self.RawComponents[0,2])+(m.RawComponents[1,1]*self.RawComponents[1,2])+(m.RawComponents[1,2]*self.RawComponents[2,2])+(m.RawComponents[1,3]*self.RawComponents[3,2]);
  61. result.RawComponents[1,3]:=(m.RawComponents[1,0]*self.RawComponents[0,3])+(m.RawComponents[1,1]*self.RawComponents[1,3])+(m.RawComponents[1,2]*self.RawComponents[2,3])+(m.RawComponents[1,3]*self.RawComponents[3,3]);
  62. result.RawComponents[2,0]:=(m.RawComponents[2,0]*self.RawComponents[0,0])+(m.RawComponents[2,1]*self.RawComponents[1,0])+(m.RawComponents[2,2]*self.RawComponents[2,0])+(m.RawComponents[2,3]*self.RawComponents[3,0]);
  63. result.RawComponents[2,1]:=(m.RawComponents[2,0]*self.RawComponents[0,1])+(m.RawComponents[2,1]*self.RawComponents[1,1])+(m.RawComponents[2,2]*self.RawComponents[2,1])+(m.RawComponents[2,3]*self.RawComponents[3,1]);
  64. result.RawComponents[2,2]:=(m.RawComponents[2,0]*self.RawComponents[0,2])+(m.RawComponents[2,1]*self.RawComponents[1,2])+(m.RawComponents[2,2]*self.RawComponents[2,2])+(m.RawComponents[2,3]*self.RawComponents[3,2]);
  65. result.RawComponents[2,3]:=(m.RawComponents[2,0]*self.RawComponents[0,3])+(m.RawComponents[2,1]*self.RawComponents[1,3])+(m.RawComponents[2,2]*self.RawComponents[2,3])+(m.RawComponents[2,3]*self.RawComponents[3,3]);
  66. result.RawComponents[3,0]:=(m.RawComponents[3,0]*self.RawComponents[0,0])+(m.RawComponents[3,1]*self.RawComponents[1,0])+(m.RawComponents[3,2]*self.RawComponents[2,0])+(m.RawComponents[3,3]*self.RawComponents[3,0]);
  67. result.RawComponents[3,1]:=(m.RawComponents[3,0]*self.RawComponents[0,1])+(m.RawComponents[3,1]*self.RawComponents[1,1])+(m.RawComponents[3,2]*self.RawComponents[2,1])+(m.RawComponents[3,3]*self.RawComponents[3,1]);
  68. result.RawComponents[3,2]:=(m.RawComponents[3,0]*self.RawComponents[0,2])+(m.RawComponents[3,1]*self.RawComponents[1,2])+(m.RawComponents[3,2]*self.RawComponents[2,2])+(m.RawComponents[3,3]*self.RawComponents[3,2]);
  69. result.RawComponents[3,3]:=(m.RawComponents[3,0]*self.RawComponents[0,3])+(m.RawComponents[3,1]*self.RawComponents[1,3])+(m.RawComponents[3,2]*self.RawComponents[2,3])+(m.RawComponents[3,3]*self.RawComponents[3,3]);
  70. end;
  71. constructor TMat4.Scale (const x, y, z: TScalar);
  72. begin
  73. RawComponents[0,0] := x;
  74. RawComponents[0,1] := 0;
  75. RawComponents[0,2] := 0;
  76. RawComponents[0,3] := 0;
  77. RawComponents[1,0] := 0;
  78. RawComponents[1,1] := y;
  79. RawComponents[1,2] := 0;
  80. RawComponents[1,3] := 0;
  81. RawComponents[2,0] := 0;
  82. RawComponents[2,1] := 0;
  83. RawComponents[2,2] := z;
  84. RawComponents[2,3] := 0;
  85. RawComponents[3,0] := 0;
  86. RawComponents[3,1] := 0;
  87. RawComponents[3,2] := 0;
  88. RawComponents[3,3] := 1;
  89. end;
  90. constructor TMat4.RotateX(const Angle:TScalar);
  91. begin
  92. RawComponents[0,0]:=1.0;
  93. RawComponents[0,1]:=0.0;
  94. RawComponents[0,2]:=0.0;
  95. RawComponents[0,3]:=0.0;
  96. RawComponents[1,0]:=0.0;
  97. SinCos(Angle,RawComponents[1,2],RawComponents[1,1]);
  98. RawComponents[1,3]:=0.0;
  99. RawComponents[2,0]:=0.0;
  100. RawComponents[2,1]:=-RawComponents[1,2];
  101. RawComponents[2,2]:=RawComponents[1,1];
  102. RawComponents[2,3]:=0.0;
  103. RawComponents[3,0]:=0.0;
  104. RawComponents[3,1]:=0.0;
  105. RawComponents[3,2]:=0.0;
  106. RawComponents[3,3]:=1.0;
  107. end;
  108. constructor TMat4.RotateY(const Angle:TScalar);
  109. begin
  110. SinCos(Angle,RawComponents[2,0],RawComponents[0,0]);
  111. RawComponents[0,1]:=0.0;
  112. RawComponents[0,2]:=-RawComponents[2,0];
  113. RawComponents[0,3]:=0.0;
  114. RawComponents[1,0]:=0.0;
  115. RawComponents[1,1]:=1.0;
  116. RawComponents[1,2]:=0.0;
  117. RawComponents[1,3]:=0.0;
  118. RawComponents[2,1]:=0.0;
  119. RawComponents[2,2]:=RawComponents[0,0];
  120. RawComponents[2,3]:=0.0;
  121. RawComponents[3,0]:=0.0;
  122. RawComponents[3,1]:=0.0;
  123. RawComponents[3,2]:=0.0;
  124. RawComponents[3,3]:=1.0;
  125. end;
  126. constructor TMat4.RotateZ(const Angle:TScalar);
  127. begin
  128. SinCos(Angle,RawComponents[0,1],RawComponents[0,0]);
  129. RawComponents[0,2]:=0.0;
  130. RawComponents[0,3]:=0.0;
  131. RawComponents[1,0]:=-RawComponents[0,1];
  132. RawComponents[1,1]:=RawComponents[0,0];
  133. RawComponents[1,2]:=0.0;
  134. RawComponents[1,3]:=0.0;
  135. RawComponents[2,0]:=0.0;
  136. RawComponents[2,1]:=0.0;
  137. RawComponents[2,2]:=1.0;
  138. RawComponents[2,3]:=0.0;
  139. RawComponents[3,0]:=0.0;
  140. RawComponents[3,1]:=0.0;
  141. RawComponents[3,2]:=0.0;
  142. RawComponents[3,3]:=1.0;
  143. end;
  144. constructor TMat4.Translate(const tx,ty,tz: TScalar);
  145. begin
  146. RawComponents[0,0]:=1.0;
  147. RawComponents[0,1]:=0.0;
  148. RawComponents[0,2]:=0.0;
  149. RawComponents[0,3]:=0.0;
  150. RawComponents[1,0]:=0.0;
  151. RawComponents[1,1]:=1.0;
  152. RawComponents[1,2]:=0.0;
  153. RawComponents[1,3]:=0.0;
  154. RawComponents[2,0]:=0.0;
  155. RawComponents[2,1]:=0.0;
  156. RawComponents[2,2]:=1.0;
  157. RawComponents[2,3]:=0.0;
  158. RawComponents[3,0]:=tx;
  159. RawComponents[3,1]:=ty;
  160. RawComponents[3,2]:=tz;
  161. RawComponents[3,3]:=1.0;
  162. end;
  163. constructor TMat4.Ortho(const Left,Right,Bottom,Top,zNear,zFar:TScalar);
  164. var
  165. rml,tmb,fmn:TScalar;
  166. begin
  167. rml:=Right-Left;
  168. tmb:=Top-Bottom;
  169. fmn:=zFar-zNear;
  170. RawComponents[0,0]:=2.0/rml;
  171. RawComponents[0,1]:=0.0;
  172. RawComponents[0,2]:=0.0;
  173. RawComponents[0,3]:=0.0;
  174. RawComponents[1,0]:=0.0;
  175. RawComponents[1,1]:=2.0/tmb;
  176. RawComponents[1,2]:=0.0;
  177. RawComponents[1,3]:=0.0;
  178. RawComponents[2,0]:=0.0;
  179. RawComponents[2,1]:=0.0;
  180. RawComponents[2,2]:=(-2.0)/fmn;
  181. RawComponents[2,3]:=0.0;
  182. RawComponents[3,0]:=(-(Right+Left))/rml;
  183. RawComponents[3,1]:=(-(Top+Bottom))/tmb;
  184. RawComponents[3,2]:=(-(zFar+zNear))/fmn;
  185. RawComponents[3,3]:=1.0;
  186. end;
  187. constructor TMat4.Perspective(const fovy,Aspect,zNear,zFar:TScalar);
  188. var
  189. Sine,Cotangent,ZDelta,Radians:TScalar;
  190. begin
  191. Radians:=(fovy*0.5)*DEG2RAD;
  192. ZDelta:=zFar-zNear;
  193. Sine:=sin(Radians);
  194. if not ((ZDelta=0) or (Sine=0) or (aspect=0)) then begin
  195. Cotangent:=cos(Radians)/Sine;
  196. // NOTE: What happens on copy?
  197. RawComponents:=Matrix4x4Identity.RawComponents;
  198. RawComponents[0,0]:=Cotangent/aspect;
  199. RawComponents[1,1]:=Cotangent;
  200. RawComponents[2,2]:=(-(zFar+zNear))/ZDelta;
  201. RawComponents[2,3]:=-1-0;
  202. RawComponents[3,2]:=(-(2.0*zNear*zFar))/ZDelta;
  203. RawComponents[3,3]:=0.0;
  204. end;
  205. end;
  206. constructor TMat4.Identity;
  207. begin
  208. RawComponents[0,0]:=1.0;
  209. RawComponents[0,1]:=0.0;
  210. RawComponents[0,2]:=0.0;
  211. RawComponents[0,3]:=0.0;
  212. RawComponents[1,0]:=0.0;
  213. RawComponents[1,1]:=1.0;
  214. RawComponents[1,2]:=0.0;
  215. RawComponents[1,3]:=0.0;
  216. RawComponents[2,0]:=0.0;
  217. RawComponents[2,1]:=0.0;
  218. RawComponents[2,2]:=1.0;
  219. RawComponents[2,3]:=0.0;
  220. RawComponents[3,0]:=0.0;
  221. RawComponents[3,1]:=0.0;
  222. RawComponents[3,2]:=0.0;
  223. RawComponents[3,3]:=1.0;
  224. end;
  225. procedure TMat4.Show;
  226. var
  227. x, y: integer;
  228. begin
  229. for y := 0 to 3 do
  230. begin
  231. write('[');
  232. for x := 0 to 3 do
  233. begin
  234. if x < 3 then
  235. write(RawComponents[x, y], ',')
  236. else
  237. write(RawComponents[x, y]);
  238. end;
  239. write(']');
  240. end;
  241. end;
  242. begin
  243. Matrix4x4Identity := TMat4.Identity;
  244. end.