MATRICES.PAS 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. UNIT matrices;
  2. {Все украдено с исходников POV-Ray
  3. Ported to PAS by IE
  4. }
  5. INTERFACE
  6. Uses Uvector;
  7. CONST
  8. M_PI =3.1415926535897932384626;
  9. M_PI_2 =1.57079632679489661923;
  10. TWO_M_PI =6.283185307179586476925286766560;
  11. M_PI_180 =0.01745329251994329576;
  12. M_PI_360 =0.00872664625997164788;
  13. type
  14. DBL = double;
  15. UV_VECT = array [0..1] of DBL;
  16. VECTOR_4D = array [0..3] of DBL;
  17. TMATRIX = array [0..3,0..3] of DBL;
  18. TTRANSFORM = record
  19. matrix, inverse : TMATRIX;
  20. end;
  21. Procedure MZero (var result:TMATRIX);
  22. Procedure MIdentity (var result:TMATRIX);
  23. Procedure MTimes (var result:TMATRIX; matrix1,matrix2:TMATRIX);
  24. {Procedure MAdd (var result:TMATRIX; matrix1,matrix2:TMATRIX);
  25. Procedure MSub (var result:TMATRIX; matrix1,matrix2:TMATRIX);
  26. Procedure MScale (var result:TMATRIX; matrix1:TMATRIX; DBL amount);}
  27. Procedure MTranspose (var result:TMATRIX; matrix1:TMATRIX);
  28. Procedure MTransPoint (var result:tVec;vector:tVec;trans:TTRANSFORM);
  29. Procedure MInvTransPoint (var result:tVec;vector:tVec;trans:TTRANSFORM);
  30. Procedure MTransDirection (var result:tVec;vector:tVec;trans:TTRANSFORM);
  31. Procedure MInvTransDirection (var result:tVec;vector:tVec;trans:TTRANSFORM);
  32. Procedure MTransNormal (var result:tVec;vector:tVec;trans:TTRANSFORM);
  33. Procedure MInvTransNormal (var result:tVec;vector:tVec;trans:TTRANSFORM);
  34. Procedure Compute_Matrix_Transform (var result:TTRANSFORM; matrix:TMATRIX);
  35. Procedure Compute_Scaling_Transform (var result:TTRANSFORM; vector:tVec);
  36. {Procedure Compute_Inversion_Transform (var result:TTRANSFORM);}
  37. Procedure Compute_Translation_Transform (var result:TTRANSFORM; vector:tVec);
  38. Procedure Compute_Rotation_Transform (var transform:TTRANSFORM; vector:tVec);
  39. {Procedure Compute_Look_At_Transform (var transform:TTRANSFORM; Look_At, Up, Right:tVec);}
  40. Procedure Compose_Transforms (var Original_Transform, New_Transform:TTRANSFORM);
  41. Procedure Compute_Axis_Rotation_Transform (var transform:TTRANSFORM; V1:tVec; angle:DBL);
  42. Procedure Compute_Coordinate_Transform (var trans:TTRANSFORM; origin, up:tVec; r,len:DBL);
  43. Procedure MInvers (var r,m:TMATRIX);
  44. IMPLEMENTATION
  45. {-------------------------------------------------------------}
  46. Procedure MZero (var result:TMATRIX);
  47. var
  48. i, j:integer;
  49. begin
  50. for i := 0 to 3 do
  51. for j := 0 to 3 do
  52. result[i,j] := 0.0;
  53. end;
  54. {-------------------------------------------------------------}
  55. Procedure MIdentity (var result:TMATRIX);
  56. var
  57. i, j:integer;
  58. begin
  59. for i := 0 to 3 do
  60. for j := 0 to 3 do
  61. if i=j then
  62. result[i,j] := 1.0
  63. else
  64. result[i,j] := 0.0;
  65. end;
  66. {-------------------------------------------------------------}
  67. Procedure MTimes (var result:TMATRIX; matrix1,matrix2:TMATRIX);
  68. var
  69. i, j, k : integer;
  70. temp_matrix : TMATRIX;
  71. begin
  72. for i := 0 to 3 do
  73. for j := 0 to 3 do
  74. begin
  75. temp_matrix[i,j] := 0.0;
  76. for k := 0 to 3 do
  77. temp_matrix[i,j] := temp_matrix[i,j]+matrix1[i,k] * matrix2[k,j];
  78. end;
  79. for i := 0 to 3 do
  80. for j := 0 to 3 do
  81. result[i,j] := temp_matrix[i,j];
  82. end;
  83. {-------------------------------------------------------------}
  84. Procedure MTranspose (var result:TMATRIX; matrix1:TMATRIX);
  85. var
  86. i, j : integer;
  87. temp_matrix : TMATRIX;
  88. begin
  89. for i := 0 to 3 do
  90. for j := 0 to 3 do
  91. temp_matrix[i,j] := matrix1[j,i];
  92. for i := 0 to 3 do
  93. for j := 0 to 3 do
  94. result[i,j] := temp_matrix[i,j];
  95. end;
  96. {-------------------------------------------------------------}
  97. Procedure MTransPoint (var result:tVec;vector:tVec; trans:TTRANSFORM);
  98. var
  99. I : integer;
  100. answer_array : array [0..3] of DBL;
  101. matrix : TMATRIX;
  102. begin
  103. matrix := trans.matrix;
  104. for i := 0 to 2 do
  105. answer_array[i] := vector.X * matrix[0,i] +
  106. vector.Y * matrix[1,i] +
  107. vector.Z * matrix[2,i] + matrix[3,i];
  108. result.X := answer_array[0];
  109. result.Y := answer_array[1];
  110. result.Z := answer_array[2];
  111. end;
  112. {-------------------------------------------------------------}
  113. Procedure MInvTransPoint (var result:tVec;vector:tVec;trans:TTRANSFORM);
  114. var
  115. I : integer;
  116. answer_array : array [0..3] of DBL;
  117. matrix : TMATRIX;
  118. begin
  119. matrix := trans.inverse;
  120. for i := 0 to 3 do
  121. answer_array[i] := vector.X * matrix[0,i] +
  122. vector.Y * matrix[1,i] +
  123. vector.Z * matrix[2,i] + matrix[3,i];
  124. result.X := answer_array[0];
  125. result.Y := answer_array[1];
  126. result.Z := answer_array[2];
  127. end;
  128. {-------------------------------------------------------------}
  129. Procedure MTransDirection (var result:tVec;vector:tVec;trans:TTRANSFORM);
  130. var
  131. I : integer;
  132. answer_array : array [0..3] of DBL;
  133. matrix : TMATRIX;
  134. begin
  135. matrix := trans.matrix;
  136. for i := 0 to 3 do
  137. answer_array[i] := vector.X * matrix[0,i] +
  138. vector.Y * matrix[1,i] +
  139. vector.Z * matrix[2,i];
  140. result.X := answer_array[0];
  141. result.Y := answer_array[1];
  142. result.Z := answer_array[2];
  143. end;
  144. {-------------------------------------------------------------}
  145. Procedure MInvTransDirection (var result:tVec;vector:tVec;trans:TTRANSFORM);
  146. var
  147. I : integer;
  148. answer_array : array [0..3] of DBL;
  149. matrix : TMATRIX;
  150. begin
  151. matrix := trans.inverse;
  152. for i := 0 to 3 do
  153. answer_array[i] := vector.X * matrix[0,i] +
  154. vector.Y * matrix[1,i] +
  155. vector.Z * matrix[2,i];
  156. result.X := answer_array[0];
  157. result.Y := answer_array[1];
  158. result.Z := answer_array[2];
  159. end;
  160. {-------------------------------------------------------------}
  161. Procedure MTransNormal (var result:tVec;vector:tVec;trans:TTRANSFORM);
  162. var
  163. I : integer;
  164. answer_array : array [0..3] of DBL;
  165. matrix : TMATRIX;
  166. begin
  167. matrix := trans.matrix;
  168. for i := 0 to 3 do
  169. answer_array[i] := vector.X * matrix[i,0] +
  170. vector.Y * matrix[i,1] +
  171. vector.Z * matrix[i,2];
  172. result.X := answer_array[0];
  173. result.Y := answer_array[1];
  174. result.Z := answer_array[2];
  175. end;
  176. {-------------------------------------------------------------}
  177. Procedure MInvTransNormal (var result:tVec;vector:tVec;trans:TTRANSFORM);
  178. var
  179. I : integer;
  180. answer_array : array [0..3] of DBL;
  181. matrix : TMATRIX;
  182. begin
  183. matrix := trans.inverse;
  184. for i := 0 to 3 do
  185. answer_array[i] := vector.X * matrix[i,0] +
  186. vector.Y * matrix[i,1] +
  187. vector.Z * matrix[i,2];
  188. result.X := answer_array[0];
  189. result.Y := answer_array[1];
  190. result.Z := answer_array[2];
  191. end;
  192. {-------------------------------------------------------------}
  193. Procedure Compute_Matrix_Transform (var result:TTRANSFORM; matrix:TMATRIX);
  194. var
  195. I : INTEGER;
  196. begin
  197. for i := 0 to 3 do
  198. begin
  199. result.matrix[i,0] := matrix[i,0];
  200. result.matrix[i,1] := matrix[i,1];
  201. result.matrix[i,2] := matrix[i,2];
  202. result.matrix[i,3] := matrix[i,3];
  203. end;
  204. MInvers(result.inverse, result.matrix);
  205. end;
  206. {-------------------------------------------------------------}
  207. Procedure Compute_Scaling_Transform (var result:TTRANSFORM; vector:tVec);
  208. begin
  209. MIdentity (result.matrix);
  210. result.matrix[0,0] := vector.X;
  211. result.matrix[1,1] := vector.Y;
  212. result.matrix[2,2] := vector.Z;
  213. MIdentity (result.inverse);
  214. result.inverse[0,0] := 1.0 / vector.X;
  215. result.inverse[1,1] := 1.0 / vector.Y;
  216. result.inverse[2,2] := 1.0 / vector.Z;
  217. end;
  218. {-------------------------------------------------------------}
  219. Procedure Compute_Translation_Transform (var result:TTRANSFORM; vector:tVec);
  220. begin
  221. MIdentity (result.matrix);
  222. result.matrix[3,0] := vector.X;
  223. result.matrix[3,1] := vector.Y;
  224. result.matrix[3,2] := vector.Z;
  225. MIdentity (result.inverse);
  226. result.inverse[3,0] := -vector.X;
  227. result.inverse[3,1] := -vector.Y;
  228. result.inverse[3,2] := -vector.Z;
  229. end;
  230. {-------------------------------------------------------------}
  231. Procedure Compute_Rotation_Transform (var transform:TTRANSFORM; vector:tVec);
  232. var
  233. cosx, cosy, cosz, sinx, siny, sinz : DBL;
  234. Matrix : TMATRIX;
  235. Radian_Vector : tVec;
  236. begin
  237. VLinear (Radian_Vector, vector, vector, M_PI_180,0);
  238. MIdentity (transform.matrix);
  239. cosx := cos (Radian_Vector.X);
  240. sinx := sin (Radian_Vector.X);
  241. cosy := cos (Radian_Vector.Y);
  242. siny := sin (Radian_Vector.Y);
  243. cosz := cos (Radian_Vector.Z);
  244. sinz := sin (Radian_Vector.Z);
  245. transform.matrix[1,1] := cosx;
  246. transform.matrix[2,2] := cosx;
  247. transform.matrix[1,2] := sinx;
  248. transform.matrix[2,1] := 0.0 - sinx;
  249. MTranspose (transform.inverse, transform.matrix);
  250. MIdentity (Matrix);
  251. Matrix[0,0] := cosy;
  252. Matrix[2,2] := cosy;
  253. Matrix[0,2] := 0.0 - siny;
  254. Matrix[2,0] := siny;
  255. MTimes (transform.matrix, transform.matrix, Matrix);
  256. MTranspose (Matrix, Matrix);
  257. MTimes (transform.inverse, Matrix, transform.inverse);
  258. MIdentity (Matrix);
  259. Matrix[0,0] := cosz;
  260. Matrix[1,1] := cosz;
  261. Matrix[0,1] := sinz;
  262. Matrix[1,0] := 0.0 - sinz;
  263. MTimes(transform.matrix, transform.matrix, Matrix);
  264. MTranspose (Matrix, Matrix);
  265. MTimes (transform.inverse, Matrix, transform.inverse);
  266. end;
  267. {-------------------------------------------------------------}
  268. Procedure Compose_Transforms (var Original_Transform, New_Transform:TTRANSFORM);
  269. begin
  270. MTimes(Original_Transform.matrix, Original_Transform.matrix, New_Transform.matrix);
  271. MTimes(Original_Transform.inverse, New_Transform.inverse, Original_Transform.inverse);
  272. end;
  273. {-------------------------------------------------------------}
  274. Procedure Compute_Axis_Rotation_Transform (var transform:TTRANSFORM; V1:tVec; angle:DBL);
  275. var
  276. l, cosx, sinx: DBL;
  277. begin
  278. VNorm(V1, 1);
  279. MIdentity(transform.matrix);
  280. cosx := cos(angle);
  281. sinx := sin(angle);
  282. transform.matrix[0,0] := V1.X * V1.X + cosx * (1.0 - V1.X * V1.X);
  283. transform.matrix[0,1] := V1.X * V1.Y * (1.0 - cosx) + V1.Z * sinx;
  284. transform.matrix[0,2] := V1.X * V1.Z * (1.0 - cosx) - V1.Y * sinx;
  285. transform.matrix[1,0] := V1.X * V1.Y * (1.0 - cosx) - V1.Z * sinx;
  286. transform.matrix[1,1] := V1.Y * V1.Y + cosx * (1.0 - V1.Y * V1.Y);
  287. transform.matrix[1,2] := V1.Y * V1.Z * (1.0 - cosx) + V1.X * sinx;
  288. transform.matrix[2,0] := V1.X * V1.Z * (1.0 - cosx) + V1.Y * sinx;
  289. transform.matrix[2,1] := V1.Y * V1.Z * (1.0 - cosx) - V1.X * sinx;
  290. transform.matrix[2,2] := V1.Z * V1.Z + cosx * (1.0 - V1.Z * V1.Z);
  291. MTranspose(transform.inverse, transform.matrix);
  292. end;
  293. {-------------------------------------------------------------}
  294. Procedure Compute_Coordinate_Transform (var trans:TTRANSFORM; origin, up:tVec; r,len:DBL);
  295. var
  296. trans2 : TTRANSFORM ;
  297. tmpv : tVec;
  298. begin
  299. VSet(tmpv, r, r, len);
  300. Compute_Scaling_Transform(trans, tmpv);
  301. if abs(up.Z) > (1.0 - EPS) then
  302. begin
  303. VSet(tmpv, 1.0, 0.0, 0.0);
  304. if Up.Z > 0 then up.Z := 1.0
  305. else up.Z := -1.0;
  306. end
  307. else
  308. VSet(tmpv, -up.Y, up.X, 0.0);
  309. Compute_Axis_Rotation_Transform(trans2, tmpv, ArcCos(up.Z) );
  310. Compose_Transforms(trans, trans2);
  311. Compute_Translation_Transform(trans2, origin);
  312. Compose_Transforms(trans, trans2);
  313. end;
  314. {-------------------------------------------------------------}
  315. Procedure MInvers (var r,m:TMATRIX);
  316. var
  317. d00, d01, d02, d03 : DBL;
  318. d10, d11, d12, d13 : DBL;
  319. d20, d21, d22, d23 : DBL;
  320. d30, d31, d32, d33 : DBL;
  321. m00, m01, m02, m03 : DBL;
  322. m10, m11, m12, m13 : DBL;
  323. m20, m21, m22, m23 : DBL;
  324. m30, m31, m32, m33 : DBL;
  325. D : DBL;
  326. begin
  327. m00 := m[0,0]; m01 := m[0,1]; m02 := m[0,2]; m03 := m[0,3];
  328. m10 := m[1,0]; m11 := m[1,1]; m12 := m[1,2]; m13 := m[1,3];
  329. m20 := m[2,0]; m21 := m[2,1]; m22 := m[2,2]; m23 := m[2,3];
  330. m30 := m[3,0]; m31 := m[3,1]; m32 := m[3,2]; m33 := m[3,3];
  331. d00 := m11*m22*m33 + m12*m23*m31 + m13*m21*m32 - m31*m22*m13 - m32*m23*m11 - m33*m21*m12;
  332. d01 := m10*m22*m33 + m12*m23*m30 + m13*m20*m32 - m30*m22*m13 - m32*m23*m10 - m33*m20*m12;
  333. d02 := m10*m21*m33 + m11*m23*m30 + m13*m20*m31 - m30*m21*m13 - m31*m23*m10 - m33*m20*m11;
  334. d03 := m10*m21*m32 + m11*m22*m30 + m12*m20*m31 - m30*m21*m12 - m31*m22*m10 - m32*m20*m11;
  335. d10 := m01*m22*m33 + m02*m23*m31 + m03*m21*m32 - m31*m22*m03 - m32*m23*m01 - m33*m21*m02;
  336. d11 := m00*m22*m33 + m02*m23*m30 + m03*m20*m32 - m30*m22*m03 - m32*m23*m00 - m33*m20*m02;
  337. d12 := m00*m21*m33 + m01*m23*m30 + m03*m20*m31 - m30*m21*m03 - m31*m23*m00 - m33*m20*m01;
  338. d13 := m00*m21*m32 + m01*m22*m30 + m02*m20*m31 - m30*m21*m02 - m31*m22*m00 - m32*m20*m01;
  339. d20 := m01*m12*m33 + m02*m13*m31 + m03*m11*m32 - m31*m12*m03 - m32*m13*m01 - m33*m11*m02;
  340. d21 := m00*m12*m33 + m02*m13*m30 + m03*m10*m32 - m30*m12*m03 - m32*m13*m00 - m33*m10*m02;
  341. d22 := m00*m11*m33 + m01*m13*m30 + m03*m10*m31 - m30*m11*m03 - m31*m13*m00 - m33*m10*m01;
  342. d23 := m00*m11*m32 + m01*m12*m30 + m02*m10*m31 - m30*m11*m02 - m31*m12*m00 - m32*m10*m01;
  343. d30 := m01*m12*m23 + m02*m13*m21 + m03*m11*m22 - m21*m12*m03 - m22*m13*m01 - m23*m11*m02;
  344. d31 := m00*m12*m23 + m02*m13*m20 + m03*m10*m22 - m20*m12*m03 - m22*m13*m00 - m23*m10*m02;
  345. d32 := m00*m11*m23 + m01*m13*m20 + m03*m10*m21 - m20*m11*m03 - m21*m13*m00 - m23*m10*m01;
  346. d33 := m00*m11*m22 + m01*m12*m20 + m02*m10*m21 - m20*m11*m02 - m21*m12*m00 - m22*m10*m01;
  347. D := m00*d00 - m01*d01 + m02*d02 - m03*d03;
  348. if (D = 0.0) then
  349. begin
  350. WriteLn('Singular matrix in MInvers.\n');
  351. Halt(255);
  352. end;
  353. r[0,0] := d00/D; r[0,1] := -d10/D; r[0,2] := d20/D; r[0,3] := -d30/D;
  354. r[1,0] := -d01/D; r[1,1] := d11/D; r[1,2] := -d21/D; r[1,3] := d31/D;
  355. r[2,0] := d02/D; r[2,1] := -d12/D; r[2,2] := d22/D; r[2,3] := -d32/D;
  356. r[3,0] := -d03/D; r[3,1] := d13/D; r[3,2] := -d23/D; r[3,3] := d33/D;
  357. end;
  358. END.