zgl_matrix.pas 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. unit zgl_matrix;
  2. {$mode delphi}
  3. {$I zgl_config.cfg}
  4. interface
  5. uses
  6. Math,
  7. zgl_window,
  8. zgl_types,
  9. zgl_gltypeconst,
  10. zgl_pasOpenGL,
  11. zgl_file;
  12. const
  13. // это всё для тестов, позже надо будет переименовать названия матриц или пронумеровать их просто.
  14. projectionMatrix = 0;
  15. viewMatrix = 1;
  16. viewProjectionMatrix = 2;
  17. modelMatrix = 3;
  18. modelViewProjectionMatrix = 4;
  19. type
  20. // матрицы уже есть, но пока будем использовать одномерные матрицы вместо двумерных.
  21. PMatrix4x4s = ^TMatrix4x4s;
  22. PMatrix4x4d = ^TMatrix4x4d;
  23. // Single matrix.
  24. TMatrix4x4s = array [0..15] of Single;
  25. // Double matrix (not used in ZenGL).
  26. TMatrix4x4d = array [0..15] of Double;
  27. // RU: матрица перспективы, заполняет матрицу "zgl_MatrixS[projectionMatrix]".
  28. // EN: perspective matrix, fills the matrix "zgl_MatrixS[projectionMatrix]".
  29. procedure Matrix4x4_Perspective(fovy, aspect, _near, _far: Single);
  30. // RU: ортографическая матрица, заполняет матрицу "zgl_MatrixS[projectionMatrix]".
  31. // EN: orthographic matrix, fills the matrix "zgl_MatrixS[projectionMatrix]".
  32. procedure Matrix4x4_Orthographic(Left, Right, Bottom, Top, _Near, _Far: Single);
  33. // RU: загрузка шейдера, компиляция и проверка на успех компиляции.
  34. // EN: loading the shader, compiling and checking for compilation success.
  35. function LoadAndCreateShader(name: string; shade: GLuint): Boolean;
  36. // RU: матрица вращения.
  37. // EN:
  38. procedure Matrix4x4_Rotation(mat4x4: PMatrix4x4s; Const X, Y, Z: Single);
  39. // RU: матрица перемещения.
  40. // EN:
  41. procedure Matrix4x4_Translation(mat4x4: PMatrix4x4s; Const X, Y, Z: Single);
  42. // RU: перемножение матриц.
  43. // EN:
  44. procedure Matrix4x4Multiply4x4(A, B: PMatrix4x4s; C: PMatrix4x4s);
  45. var
  46. // RU: массив матриц: projectionMatrix, viewMatrix, viewProjectionMatrix,
  47. // modelMatrix, modelViewProjectionMatrix; и ещё пять не занятых.
  48. // EN: matrix array: projectionMatrix, viewMatrix, viewProjectionMatrix,
  49. // modelMatrix, modelViewProjectionMatrix; and five more unoccupied.
  50. zgl_MatrixS: array[0..9, 0..15] of Single;
  51. implementation
  52. procedure Matrix4x4_Perspective(fovy, aspect, _near, _far: Single);
  53. var
  54. f: Single;
  55. begin
  56. f := 1 / tan(fovy * Pi / 180);
  57. zgl_Matrixs[projectionMatrix, 0] := f / aspect;
  58. zgl_Matrixs[projectionMatrix, 1] := 0;
  59. zgl_Matrixs[projectionMatrix, 2] := 0;
  60. zgl_Matrixs[projectionMatrix, 3] := 0;
  61. zgl_Matrixs[projectionMatrix, 4] := 0;
  62. zgl_Matrixs[projectionMatrix, 5] := f;
  63. zgl_Matrixs[projectionMatrix, 6] := 0;
  64. zgl_Matrixs[projectionMatrix, 7] := 0;
  65. zgl_Matrixs[projectionMatrix, 8] := 0;
  66. zgl_Matrixs[projectionMatrix, 9] := 0;
  67. zgl_Matrixs[projectionMatrix, 10] := (_far + _near) / (_near - _far);
  68. zgl_Matrixs[projectionMatrix, 11] := 2 * _far * _near / (_near - _far);
  69. zgl_Matrixs[projectionMatrix, 12] := 0;
  70. zgl_Matrixs[projectionMatrix, 13] := 0;
  71. zgl_Matrixs[projectionMatrix, 14] := - 1;
  72. zgl_Matrixs[projectionMatrix, 15] := 0;
  73. end;
  74. procedure Matrix4x4_Orthographic(Left, Right, Bottom, Top, _Near, _Far: Single);
  75. var
  76. f: Single;
  77. begin
  78. f := Right - Left;
  79. zgl_Matrixs[projectionMatrix, 0] := 2 / f;
  80. zgl_Matrixs[projectionMatrix, 1] := 0;
  81. zgl_Matrixs[projectionMatrix, 2] := 0;
  82. zgl_Matrixs[projectionMatrix, 3] := -(Right + Left) / f;
  83. f := Top - Bottom;
  84. zgl_Matrixs[projectionMatrix, 4] := 0;
  85. zgl_Matrixs[projectionMatrix, 5] := 2 / f;
  86. zgl_Matrixs[projectionMatrix, 6] := 0;
  87. zgl_Matrixs[projectionMatrix, 7] := -(top + Bottom) / f;
  88. f := _Far - _Near;
  89. zgl_Matrixs[projectionMatrix, 8] := 0;
  90. zgl_Matrixs[projectionMatrix, 9] := 0;
  91. zgl_Matrixs[projectionMatrix, 10] := - 2 / f;
  92. zgl_Matrixs[projectionMatrix, 11] := -(_Far + _Near) / f;
  93. zgl_Matrixs[projectionMatrix, 12] := 0;
  94. zgl_Matrixs[projectionMatrix, 13] := 0;
  95. zgl_Matrixs[projectionMatrix, 14] := 0;
  96. zgl_Matrixs[projectionMatrix, 15] := 1;
  97. end;
  98. function LoadAndCreateShader(name: string; shade: GLuint): Boolean;
  99. var
  100. Ftext: zglTFile;
  101. Fmem: zglTMemory;
  102. status: GLint;
  103. begin
  104. Result := False;
  105. // RU: проверка существования загружаемого файла.
  106. // EN: Checking the existence of the downloaded file.
  107. if not file_Exists(name) then
  108. Exit;
  109. // RU: открываем файл.
  110. // EN: open the file.
  111. if file_Open(Ftext, name, FOM_OPENR)then
  112. begin
  113. Fmem.Size := file_GetSize(Ftext);
  114. Fmem.Position := 0;
  115. // RU: подготавливаем память для загрузки шейдера.
  116. // EN: prepare memory for loading the shader.
  117. zgl_GetMem(Fmem.Memory, Fmem.Size);
  118. // RU: загружаем шейдер в память.
  119. // EN: load the shader into memory.
  120. file_Read(Ftext, Fmem.Memory^, Fmem.Size);
  121. file_Close(Ftext);
  122. // RU: исходный код шейдера и его компиляция. Обратите внимание, "Fmem.Memory"
  123. // это указатель на память, где находится строка. И мы передаём указатель
  124. // на данный участок памяти. Это работает правильно, потому что данные
  125. // должны идти под двойным указателем (PPGLchar).
  126. // EN: shader source code and its compilation. Note that "Fmem.Memory" is a
  127. // pointer to the memory where the string is located. And we pass a
  128. // pointer to this memory location. This works correctly because the data
  129. // must go under a double pointer (PPGLchar).
  130. glShaderSource(shade, 1, @Fmem.Memory, @Fmem.Size);
  131. glCompileShader(shade);
  132. // RU: освобождаем память, данный текст больше не нужен.
  133. // EN: freeing up memory, this text is no longer needed.
  134. zgl_FreeMem(Fmem.Memory);
  135. end;
  136. // RU: проверяем на успех компиляции шейдера.
  137. // EN: check for success of shader compilation.
  138. glGetShaderiv(shade, GL_COMPILE_STATUS, @status);
  139. if status <> 1 then
  140. Exit;
  141. Result := True;
  142. end;
  143. procedure Matrix4x4_Rotation(mat4x4: PMatrix4x4s; const X, Y, Z: Single);
  144. Var
  145. cosX, sinX, cosY, sinY, cosZ, sinZ, sinXsinY, cosXsinY: Single;
  146. Begin
  147. cosX := Cos(X);
  148. sinX := Sin(X);
  149. cosY := Cos(Y);
  150. sinY := Sin(Y);
  151. cosZ := Cos(Z);
  152. sinZ := Sin(Z);
  153. mat4x4[0] := cosY * cosZ;
  154. mat4x4[1] := cosY * sinZ;
  155. mat4x4[2] := -sinY;
  156. If mat4x4[2] = -0 Then
  157. mat4x4[2] := 0;
  158. mat4x4[3] := 0.0;
  159. sinXsinY := sinX * sinY;
  160. cosXsinY := cosX * sinY;
  161. mat4x4[4] := (sinXsinY * cosZ) - (cosX * sinZ);
  162. mat4x4[5] := (sinXsinY * sinZ) + (cosX * cosZ);
  163. mat4x4[6] := (sinX * cosY);
  164. mat4x4[7] := 0.0;
  165. mat4x4[8] := (cosXsinY * cosZ) + (sinX * sinZ);
  166. mat4x4[9] := (cosXsinY * sinZ) - (sinX * cosZ);
  167. mat4x4[10] := (cosX * cosY);
  168. mat4x4[11] := 0.0;
  169. mat4x4[12] := 0.0;
  170. mat4x4[13] := 0.0;
  171. mat4x4[14] := 0.0;
  172. mat4x4[15] := 1.0;
  173. end;
  174. // изменить процедуру, тут можно многое сразу заполнить нулями, как и в других матрицах. Будет только вопрос в одном, будет ли это быстрее?
  175. procedure Matrix4x4_Translation(mat4x4: PMatrix4x4s; Const X, Y, Z: Single);
  176. Begin
  177. mat4x4[0] := 1.0;
  178. mat4x4[1] := 0.0;
  179. mat4x4[2] := 0.0;
  180. mat4x4[3] := 0.0;
  181. mat4x4[4] := 0.0;
  182. mat4x4[5] := 1.0;
  183. mat4x4[6] := 0.0;
  184. mat4x4[7] := 0.0;
  185. mat4x4[8] := 0.0;
  186. mat4x4[9] := 0.0;
  187. mat4x4[10] := 1.0;
  188. mat4x4[11] := 0.0;
  189. mat4x4[12] := X;
  190. mat4x4[13] := Y;
  191. mat4x4[14] := Z;
  192. mat4x4[15] := 1.0;
  193. End;
  194. {/$If defined(CPUAARCH64) or defined(CPUARM)}
  195. procedure Matrix4x4Multiply4x4(A, B: PMatrix4x4s; C: PMatrix4x4s);
  196. begin
  197. C[0] := A[0] * B[0] + A[4] * B[1] + A[8] * B[2] + A[12] * B[3];
  198. C[1] := A[1] * B[0] + A[5] * B[1] + A[9] * B[2] + A[13] * B[3];
  199. C[2] := A[2] * B[0] + A[6] * B[1] + A[10] * B[2] + A[14] * B[3];
  200. C[3] := A[3] * B[0] + A[7] * B[1] + A[11] * B[2] + A[15] * B[3];
  201. C[4] := A[0] * B[4] + A[4] * B[5] + A[8] * B[6] + A[12] * B[7];
  202. C[5] := A[1] * B[4] + A[5] * B[5] + A[9] * B[6] + A[13] * B[7];
  203. C[6] := A[2] * B[4] + A[6] * B[5] + A[10] * B[6] + A[14] * B[7];
  204. C[7] := A[3] * B[4] + A[7] * B[5] + A[11] * B[6] + A[15] * B[7];
  205. C[8] := A[0] * B[8] + A[4] * B[9] + A[8] * B[10] + A[12] * B[11];
  206. C[9] := A[1] * B[8] + A[5] * B[9] + A[9] * B[10] + A[13] * B[11];
  207. C[10] := A[2] * B[8] + A[6] * B[9] + A[10] * B[10] + A[14] * B[11];
  208. C[11] := A[3] * B[8] + A[7] * B[9] + A[11] * B[10] + A[15] * B[11];
  209. C[12] := A[0] * B[12] + A[4] * B[13] + A[8] * B[14] + A[12] * B[15];
  210. C[13] := A[1] * B[12] + A[5] * B[13] + A[9] * B[14] + A[13] * B[15];
  211. C[14] := A[2] * B[12] + A[6] * B[13] + A[10] * B[14] + A[14] * B[15];
  212. C[15] := A[3] * B[12] + A[7] * B[13] + A[11] * B[14] + A[15] * B[15];
  213. End;
  214. {/$Else}
  215. (* требуется переделка под процедуру, когда переделаю, тогда будем всё тестировать по полной, сейчас нужен рабочий код.
  216. Function Matrix4x4Multiply4x4(Const A,B:Matrix4x4):Matrix4x4;
  217. Asm
  218. movss xmm0, dword ptr [edx]
  219. movups xmm1, [eax]
  220. shufps xmm0, xmm0, 0
  221. movss xmm2, dword ptr [edx+4]
  222. mulps xmm0, xmm1
  223. shufps xmm2, xmm2, 0
  224. movups xmm3, [eax+10h]
  225. movss xmm7, dword ptr [edx+8]
  226. mulps xmm2, xmm3
  227. shufps xmm7, xmm7, 0
  228. addps xmm0, xmm2
  229. movups xmm4, [eax+20h]
  230. movss xmm2, dword ptr [edx+0Ch]
  231. mulps xmm7, xmm4
  232. shufps xmm2, xmm2, 0
  233. addps xmm0, xmm7
  234. movups xmm5, [eax+30h]
  235. movss xmm6, dword ptr [edx+10h]
  236. mulps xmm2, xmm5
  237. movss xmm7, dword ptr [edx+14h]
  238. shufps xmm6, xmm6, 0
  239. addps xmm0, xmm2
  240. shufps xmm7, xmm7, 0
  241. movlps qword ptr [ecx], xmm0
  242. movhps qword ptr [ecx+8], xmm0
  243. mulps xmm7, xmm3
  244. movss xmm0, dword ptr [edx+18h]
  245. mulps xmm6, xmm1
  246. shufps xmm0, xmm0, 0
  247. addps xmm6, xmm7
  248. mulps xmm0, xmm4
  249. movss xmm2, dword ptr [edx+24h]
  250. addps xmm6, xmm0
  251. movss xmm0, dword ptr [edx+1Ch]
  252. movss xmm7, dword ptr [edx+20h]
  253. shufps xmm0, xmm0, 0
  254. shufps xmm7, xmm7, 0
  255. mulps xmm0, xmm5
  256. mulps xmm7, xmm1
  257. addps xmm6, xmm0
  258. shufps xmm2, xmm2, 0
  259. movlps qword ptr [ecx+10h], xmm6
  260. movhps qword ptr [ecx+18h], xmm6
  261. mulps xmm2, xmm3
  262. movss xmm6, dword ptr [edx+28h]
  263. addps xmm7, xmm2
  264. shufps xmm6, xmm6, 0
  265. movss xmm2, dword ptr [edx+2Ch]
  266. mulps xmm6, xmm4
  267. shufps xmm2, xmm2, 0
  268. addps xmm7, xmm6
  269. mulps xmm2, xmm5
  270. movss xmm0, dword ptr [edx+34h]
  271. addps xmm7, xmm2
  272. shufps xmm0, xmm0, 0
  273. movlps qword ptr [ecx+20h], xmm7
  274. movss xmm2, dword ptr [edx+30h]
  275. movhps qword ptr [ecx+28h], xmm7
  276. mulps xmm0, xmm3
  277. shufps xmm2, xmm2, 0
  278. movss xmm6, dword ptr [edx+38h]
  279. mulps xmm2, xmm1
  280. shufps xmm6, xmm6, 0
  281. addps xmm2, xmm0
  282. mulps xmm6, xmm4
  283. movss xmm7, dword ptr [edx+3Ch]
  284. shufps xmm7, xmm7, 0
  285. addps xmm2, xmm6
  286. mulps xmm7, xmm5
  287. addps xmm2, xmm7
  288. movups [ecx+30h], xmm2
  289. End; *)
  290. {/$ENDIF}
  291. end.