this repo has no description
1#include "SDL_gpu.h"
2#include <math.h>
3#include <string.h>
4
5#ifdef _MSC_VER
6#define __func__ __FUNCTION__
7// Disable warning: selection for inlining
8#pragma warning(disable: 4514 4711)
9// Disable warning: Spectre mitigation
10#pragma warning(disable: 5045)
11#endif
12
13
14#ifndef PI
15#define PI 3.1415926f
16#endif
17
18#define RAD_PER_DEG 0.017453293f
19#define DEG_PER_RAD 57.2957795f
20
21
22// Visual C does not support static inline
23#ifndef static_inline
24 #ifdef _MSC_VER
25 #define static_inline static
26 #else
27 #define static_inline static inline
28 #endif
29#endif
30
31// Old Visual C did not support C99 (which includes a safe snprintf)
32#if defined(_MSC_VER) && (_MSC_VER < 1900)
33 #define snprintf c99_snprintf
34 // From Valentin Milea: http://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010
35 static_inline int c99_vsnprintf(char* str, size_t size, const char* format, va_list ap)
36 {
37 int count = -1;
38
39 if (size != 0)
40 count = _vsnprintf_s(str, size, _TRUNCATE, format, ap);
41 if (count == -1)
42 count = _vscprintf(format, ap);
43
44 return count;
45 }
46
47 static_inline int c99_snprintf(char* str, size_t size, const char* format, ...)
48 {
49 int count;
50 va_list ap;
51
52 va_start(ap, format);
53 count = c99_vsnprintf(str, size, format, ap);
54 va_end(ap);
55
56 return count;
57 }
58#endif
59
60
61
62GPU_MatrixStack* GPU_CreateMatrixStack(void)
63{
64 GPU_MatrixStack* stack = (GPU_MatrixStack*)SDL_malloc(sizeof(GPU_MatrixStack));
65 stack->matrix = NULL;
66 stack->size = 0;
67 stack->storage_size = 0;
68 GPU_InitMatrixStack(stack);
69 return stack;
70}
71
72
73void GPU_FreeMatrixStack(GPU_MatrixStack* stack)
74{
75 GPU_ClearMatrixStack(stack);
76 SDL_free(stack);
77}
78
79void GPU_InitMatrixStack(GPU_MatrixStack* stack)
80{
81 if(stack == NULL)
82 return;
83
84 if (stack->storage_size != 0)
85 GPU_ClearMatrixStack(stack);
86
87 stack->storage_size = 1;
88 stack->size = 1;
89
90 stack->matrix = (float**)SDL_malloc(sizeof(float*) * stack->storage_size);
91 stack->matrix[0] = (float*)SDL_malloc(sizeof(float) * 16);
92 GPU_MatrixIdentity(stack->matrix[0]);
93}
94
95void GPU_CopyMatrixStack(const GPU_MatrixStack* source, GPU_MatrixStack* dest)
96{
97 unsigned int i;
98 unsigned int matrix_size = sizeof(float) * 16;
99 if (source == NULL || dest == NULL)
100 return;
101
102 GPU_ClearMatrixStack(dest);
103 dest->matrix = (float**)SDL_malloc(sizeof(float*) * source->storage_size);
104 for (i = 0; i < source->storage_size; ++i)
105 {
106 dest->matrix[i] = (float*)SDL_malloc(matrix_size);
107 memcpy(dest->matrix[i], source->matrix[i], matrix_size);
108 }
109 dest->storage_size = source->storage_size;
110}
111
112void GPU_ClearMatrixStack(GPU_MatrixStack* stack)
113{
114 unsigned int i;
115 for (i = 0; i < stack->storage_size; ++i)
116 {
117 SDL_free(stack->matrix[i]);
118 }
119 SDL_free(stack->matrix);
120
121 stack->matrix = NULL;
122 stack->storage_size = 0;
123}
124
125
126void GPU_ResetProjection(GPU_Target* target)
127{
128 if(target == NULL)
129 return;
130
131 GPU_bool invert = (target->image != NULL);
132
133 // Set up default projection
134 float* projection_matrix = GPU_GetTopMatrix(&target->projection_matrix);
135 GPU_MatrixIdentity(projection_matrix);
136
137 if(!invert ^ GPU_GetCoordinateMode())
138 GPU_MatrixOrtho(projection_matrix, 0, target->w, target->h, 0, target->camera.z_near, target->camera.z_far);
139 else
140 GPU_MatrixOrtho(projection_matrix, 0, target->w, 0, target->h, target->camera.z_near, target->camera.z_far); // Special inverted orthographic projection because tex coords are inverted already for render-to-texture
141}
142
143// Column-major
144#define INDEX(row,col) ((col)*4 + (row))
145
146
147float GPU_VectorLength(const float* vec3)
148{
149 return sqrtf(vec3[0] * vec3[0] + vec3[1] * vec3[1] + vec3[2] * vec3[2]);
150}
151
152void GPU_VectorNormalize(float* vec3)
153{
154 float mag = GPU_VectorLength(vec3);
155 vec3[0] /= mag;
156 vec3[1] /= mag;
157 vec3[2] /= mag;
158}
159
160float GPU_VectorDot(const float* A, const float* B)
161{
162 return A[0] * B[0] + A[1] * B[1] + A[2] * B[2];
163}
164
165void GPU_VectorCross(float* result, const float* A, const float* B)
166{
167 result[0] = A[1] * B[2] - A[2] * B[1];
168 result[1] = A[2] * B[0] - A[0] * B[2];
169 result[2] = A[0] * B[1] - A[1] * B[0];
170}
171
172void GPU_VectorCopy(float* result, const float* A)
173{
174 result[0] = A[0];
175 result[1] = A[1];
176 result[2] = A[2];
177}
178
179void GPU_VectorApplyMatrix(float* vec3, const float* matrix_4x4)
180{
181 float x = matrix_4x4[0] * vec3[0] + matrix_4x4[4] * vec3[1] + matrix_4x4[8] * vec3[2] + matrix_4x4[12];
182 float y = matrix_4x4[1] * vec3[0] + matrix_4x4[5] * vec3[1] + matrix_4x4[9] * vec3[2] + matrix_4x4[13];
183 float z = matrix_4x4[2] * vec3[0] + matrix_4x4[6] * vec3[1] + matrix_4x4[10] * vec3[2] + matrix_4x4[14];
184 float w = matrix_4x4[3] * vec3[0] + matrix_4x4[7] * vec3[1] + matrix_4x4[11] * vec3[2] + matrix_4x4[15];
185 vec3[0] = x / w;
186 vec3[1] = y / w;
187 vec3[2] = z / w;
188}
189
190void GPU_Vector4ApplyMatrix(float* vec4, const float* matrix_4x4)
191{
192 float x = matrix_4x4[0] * vec4[0] + matrix_4x4[4] * vec4[1] + matrix_4x4[8] * vec4[2] + matrix_4x4[12] * vec4[3];
193 float y = matrix_4x4[1] * vec4[0] + matrix_4x4[5] * vec4[1] + matrix_4x4[9] * vec4[2] + matrix_4x4[13] * vec4[3];
194 float z = matrix_4x4[2] * vec4[0] + matrix_4x4[6] * vec4[1] + matrix_4x4[10] * vec4[2] + matrix_4x4[14] * vec4[3];
195 float w = matrix_4x4[3] * vec4[0] + matrix_4x4[7] * vec4[1] + matrix_4x4[11] * vec4[2] + matrix_4x4[15] * vec4[3];
196
197 vec4[0] = x;
198 vec4[1] = y;
199 vec4[2] = z;
200 vec4[3] = w;
201 if(w != 0.0f)
202 {
203 vec4[0] = x / w;
204 vec4[1] = y / w;
205 vec4[2] = z / w;
206 vec4[3] = 1;
207 }
208}
209
210
211// Matrix math implementations based on Wayne Cochran's (wcochran) matrix.c
212
213#define FILL_MATRIX_4x4(A, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) \
214 A[0] = a0; \
215 A[1] = a1; \
216 A[2] = a2; \
217 A[3] = a3; \
218 A[4] = a4; \
219 A[5] = a5; \
220 A[6] = a6; \
221 A[7] = a7; \
222 A[8] = a8; \
223 A[9] = a9; \
224 A[10] = a10; \
225 A[11] = a11; \
226 A[12] = a12; \
227 A[13] = a13; \
228 A[14] = a14; \
229 A[15] = a15;
230
231void GPU_MatrixCopy(float* result, const float* A)
232{
233 memcpy(result, A, 16*sizeof(float));
234}
235
236void GPU_MatrixIdentity(float* result)
237{
238 memset(result, 0, 16*sizeof(float));
239 result[0] = result[5] = result[10] = result[15] = 1;
240}
241
242
243void GPU_MatrixOrtho(float* result, float left, float right, float bottom, float top, float z_near, float z_far)
244{
245 if(result == NULL)
246 return;
247
248 {
249#ifdef ROW_MAJOR
250 float A[16];
251 FILL_MATRIX_4x4(A,
252 2/(right - left), 0, 0, -(right + left)/(right - left),
253 0, 2/(top - bottom), 0, -(top + bottom)/(top - bottom),
254 0, 0, -2/(z_far - z_near), -(z_far + z_near)/(z_far - z_near),
255 0, 0, 0, 1
256 );
257#else
258 float A[16];
259 FILL_MATRIX_4x4(A,
260 2 / (right - left), 0, 0, 0,
261 0, 2 / (top - bottom), 0, 0,
262 0, 0, -2 / (z_far - z_near), 0,
263 -(right + left) / (right - left), -(top + bottom) / (top - bottom), -(z_far + z_near) / (z_far - z_near), 1
264 );
265#endif
266
267 GPU_MultiplyAndAssign(result, A);
268 }
269}
270
271
272void GPU_MatrixFrustum(float* result, float left, float right, float bottom, float top, float z_near, float z_far)
273{
274 if(result == NULL)
275 return;
276
277 {
278 float A[16];
279 FILL_MATRIX_4x4(A,
280 2 * z_near / (right - left), 0, 0, 0,
281 0, 2 * z_near / (top - bottom), 0, 0,
282 (right + left) / (right - left), (top + bottom) / (top - bottom), -(z_far + z_near) / (z_far - z_near), -1,
283 0, 0, -(2 * z_far * z_near) / (z_far - z_near), 0
284 );
285
286 GPU_MultiplyAndAssign(result, A);
287 }
288}
289
290void GPU_MatrixPerspective(float* result, float fovy, float aspect, float z_near, float z_far)
291{
292 float fW, fH;
293
294 // Make it left-handed?
295 fovy = -fovy;
296 aspect = -aspect;
297
298 fH = tanf((fovy / 360) * PI) * z_near;
299 fW = fH * aspect;
300 GPU_MatrixFrustum(result, -fW, fW, -fH, fH, z_near, z_far);
301}
302
303void GPU_MatrixLookAt(float* matrix, float eye_x, float eye_y, float eye_z, float target_x, float target_y, float target_z, float up_x, float up_y, float up_z)
304{
305 float forward[3] = {target_x - eye_x, target_y - eye_y, target_z - eye_z};
306 float up[3] = {up_x, up_y, up_z};
307 float side[3];
308 float view[16];
309
310 GPU_VectorNormalize(forward);
311 GPU_VectorNormalize(up);
312
313 // Calculate sideways vector
314 GPU_VectorCross(side, forward, up);
315
316 // Calculate new up vector
317 GPU_VectorCross(up, side, forward);
318
319 // Set up view matrix
320 view[0] = side[0];
321 view[4] = side[1];
322 view[8] = side[2];
323 view[12] = 0.0f;
324
325 view[1] = up[0];
326 view[5] = up[1];
327 view[9] = up[2];
328 view[13] = 0.0f;
329
330 view[2] = -forward[0];
331 view[6] = -forward[1];
332 view[10] = -forward[2];
333 view[14] = 0.0f;
334
335 view[3] = view[7] = view[11] = 0.0f;
336 view[15] = 1.0f;
337
338 GPU_MultiplyAndAssign(matrix, view);
339 GPU_MatrixTranslate(matrix, -eye_x, -eye_y, -eye_z);
340}
341
342void GPU_MatrixTranslate(float* result, float x, float y, float z)
343{
344 if(result == NULL)
345 return;
346
347 {
348#ifdef ROW_MAJOR
349 float A[16];
350 FILL_MATRIX_4x4(A,
351 1, 0, 0, x,
352 0, 1, 0, y,
353 0, 0, 1, z,
354 0, 0, 0, 1
355 );
356#else
357 float A[16];
358 FILL_MATRIX_4x4(A,
359 1, 0, 0, 0,
360 0, 1, 0, 0,
361 0, 0, 1, 0,
362 x, y, z, 1
363 );
364#endif
365
366 GPU_MultiplyAndAssign(result, A);
367 }
368}
369
370void GPU_MatrixScale(float* result, float sx, float sy, float sz)
371{
372 if(result == NULL)
373 return;
374
375 {
376 float A[16];
377 FILL_MATRIX_4x4(A,
378 sx, 0, 0, 0,
379 0, sy, 0, 0,
380 0, 0, sz, 0,
381 0, 0, 0, 1
382 );
383
384 GPU_MultiplyAndAssign(result, A);
385 }
386}
387
388void GPU_MatrixRotate(float* result, float degrees, float x, float y, float z)
389{
390 float p, radians, c, s, c_, zc_, yc_, xzc_, xyc_, yzc_, xs, ys, zs;
391
392 if(result == NULL)
393 return;
394
395 p = 1/sqrtf(x*x + y*y + z*z);
396 x *= p; y *= p; z *= p;
397 radians = degrees * RAD_PER_DEG;
398 c = cosf(radians);
399 s = sinf(radians);
400 c_ = 1 - c;
401 zc_ = z*c_;
402 yc_ = y*c_;
403 xzc_ = x*zc_;
404 xyc_ = x*y*c_;
405 yzc_ = y*zc_;
406 xs = x*s;
407 ys = y*s;
408 zs = z*s;
409
410 {
411#ifdef ROW_MAJOR
412 float A[16];
413 FILL_MATRIX_4x4(A,
414 x*x*c_ + c, xyc_ - zs, xzc_ + ys, 0,
415 xyc_ + zs, y*yc_ + c, yzc_ - xs, 0,
416 xzc_ - ys, yzc_ + xs, z*zc_ + c, 0,
417 0, 0, 0, 1
418 );
419#else
420 float A[16];
421 FILL_MATRIX_4x4(A,
422 x*x*c_ + c, xyc_ + zs, xzc_ - ys, 0,
423 xyc_ - zs, y*yc_ + c, yzc_ + xs, 0,
424 xzc_ + ys, yzc_ - xs, z*zc_ + c, 0,
425 0, 0, 0, 1
426 );
427#endif
428
429 GPU_MultiplyAndAssign(result, A);
430 }
431}
432
433// Matrix multiply: result = A * B
434void GPU_MatrixMultiply(float* result, const float* A, const float* B)
435{
436 float (*matR)[4] = (float(*)[4])result;
437 float (*matA)[4] = (float(*)[4])A;
438 float (*matB)[4] = (float(*)[4])B;
439 matR[0][0] = matB[0][0] * matA[0][0] + matB[0][1] * matA[1][0] + matB[0][2] * matA[2][0] + matB[0][3] * matA[3][0];
440 matR[0][1] = matB[0][0] * matA[0][1] + matB[0][1] * matA[1][1] + matB[0][2] * matA[2][1] + matB[0][3] * matA[3][1];
441 matR[0][2] = matB[0][0] * matA[0][2] + matB[0][1] * matA[1][2] + matB[0][2] * matA[2][2] + matB[0][3] * matA[3][2];
442 matR[0][3] = matB[0][0] * matA[0][3] + matB[0][1] * matA[1][3] + matB[0][2] * matA[2][3] + matB[0][3] * matA[3][3];
443 matR[1][0] = matB[1][0] * matA[0][0] + matB[1][1] * matA[1][0] + matB[1][2] * matA[2][0] + matB[1][3] * matA[3][0];
444 matR[1][1] = matB[1][0] * matA[0][1] + matB[1][1] * matA[1][1] + matB[1][2] * matA[2][1] + matB[1][3] * matA[3][1];
445 matR[1][2] = matB[1][0] * matA[0][2] + matB[1][1] * matA[1][2] + matB[1][2] * matA[2][2] + matB[1][3] * matA[3][2];
446 matR[1][3] = matB[1][0] * matA[0][3] + matB[1][1] * matA[1][3] + matB[1][2] * matA[2][3] + matB[1][3] * matA[3][3];
447 matR[2][0] = matB[2][0] * matA[0][0] + matB[2][1] * matA[1][0] + matB[2][2] * matA[2][0] + matB[2][3] * matA[3][0];
448 matR[2][1] = matB[2][0] * matA[0][1] + matB[2][1] * matA[1][1] + matB[2][2] * matA[2][1] + matB[2][3] * matA[3][1];
449 matR[2][2] = matB[2][0] * matA[0][2] + matB[2][1] * matA[1][2] + matB[2][2] * matA[2][2] + matB[2][3] * matA[3][2];
450 matR[2][3] = matB[2][0] * matA[0][3] + matB[2][1] * matA[1][3] + matB[2][2] * matA[2][3] + matB[2][3] * matA[3][3];
451 matR[3][0] = matB[3][0] * matA[0][0] + matB[3][1] * matA[1][0] + matB[3][2] * matA[2][0] + matB[3][3] * matA[3][0];
452 matR[3][1] = matB[3][0] * matA[0][1] + matB[3][1] * matA[1][1] + matB[3][2] * matA[2][1] + matB[3][3] * matA[3][1];
453 matR[3][2] = matB[3][0] * matA[0][2] + matB[3][1] * matA[1][2] + matB[3][2] * matA[2][2] + matB[3][3] * matA[3][2];
454 matR[3][3] = matB[3][0] * matA[0][3] + matB[3][1] * matA[1][3] + matB[3][2] * matA[2][3] + matB[3][3] * matA[3][3];
455}
456
457void GPU_MultiplyAndAssign(float* result, const float* B)
458{
459 float temp[16];
460 GPU_MatrixMultiply(temp, result, B);
461 GPU_MatrixCopy(result, temp);
462}
463
464
465
466
467
468// Can be used up to two times per line evaluation...
469const char* GPU_GetMatrixString(const float* A)
470{
471 static char buffer[512];
472 static char buffer2[512];
473 static char flip = 0;
474
475 char* b = (flip? buffer : buffer2);
476 flip = !flip;
477
478 snprintf(b, 512, "%.1f %.1f %.1f %.1f\n"
479 "%.1f %.1f %.1f %.1f\n"
480 "%.1f %.1f %.1f %.1f\n"
481 "%.1f %.1f %.1f %.1f",
482 A[0], A[1], A[2], A[3],
483 A[4], A[5], A[6], A[7],
484 A[8], A[9], A[10], A[11],
485 A[12], A[13], A[14], A[15]);
486 return b;
487}
488
489void GPU_MatrixMode(GPU_Target* target, int matrix_mode)
490{
491 GPU_Target* context_target;
492 if(target == NULL)
493 return;
494
495 GPU_FlushBlitBuffer();
496 target->matrix_mode = matrix_mode;
497
498 context_target = GPU_GetContextTarget();
499 if(context_target != NULL && context_target == target->context_target)
500 context_target->context->active_target = target;
501}
502
503float* GPU_GetModel(void)
504{
505 GPU_Target* target = GPU_GetActiveTarget();
506 if(target == NULL)
507 return NULL;
508 return GPU_GetTopMatrix(&target->model_matrix);
509}
510
511float* GPU_GetView(void)
512{
513 GPU_Target* target = GPU_GetActiveTarget();
514 if(target == NULL)
515 return NULL;
516 return GPU_GetTopMatrix(&target->view_matrix);
517}
518
519float* GPU_GetProjection(void)
520{
521 GPU_Target* target = GPU_GetActiveTarget();
522 if(target == NULL)
523 return NULL;
524 return GPU_GetTopMatrix(&target->projection_matrix);
525}
526
527float* GPU_GetCurrentMatrix(void)
528{
529 GPU_MatrixStack* stack;
530 GPU_Target* target = GPU_GetActiveTarget();
531 if(target == NULL)
532 return NULL;
533 if(target->matrix_mode == GPU_MODEL)
534 stack = &target->model_matrix;
535 else if(target->matrix_mode == GPU_VIEW)
536 stack = &target->view_matrix;
537 else// if(target->matrix_mode == GPU_PROJECTION)
538 stack = &target->projection_matrix;
539
540 return GPU_GetTopMatrix(stack);
541}
542
543void GPU_PushMatrix(void)
544{
545 GPU_MatrixStack* stack;
546 GPU_Target* target = GPU_GetActiveTarget();
547 if(target == NULL)
548 return;
549
550 if(target->matrix_mode == GPU_MODEL)
551 stack = &target->model_matrix;
552 else if(target->matrix_mode == GPU_VIEW)
553 stack = &target->view_matrix;
554 else// if(target->matrix_mode == GPU_PROJECTION)
555 stack = &target->projection_matrix;
556
557 if(stack->size + 1 >= stack->storage_size)
558 {
559 // Grow matrix stack (1, 6, 16, 36, ...)
560
561 // Alloc new one
562 unsigned int new_storage_size = stack->storage_size*2 + 4;
563 float** new_stack = (float**)SDL_malloc(sizeof(float*) * new_storage_size);
564 unsigned int i;
565 for(i = 0; i < new_storage_size; ++i)
566 {
567 new_stack[i] = (float*)SDL_malloc(sizeof(float) * 16);
568 }
569 // Copy old one
570 for(i = 0; i < stack->size; ++i)
571 {
572 GPU_MatrixCopy(new_stack[i], stack->matrix[i]);
573 }
574 // Free old one
575 for(i = 0; i < stack->storage_size; ++i)
576 {
577 SDL_free(stack->matrix[i]);
578 }
579 SDL_free(stack->matrix);
580
581 // Switch to new one
582 stack->storage_size = new_storage_size;
583 stack->matrix = new_stack;
584 }
585 GPU_MatrixCopy(stack->matrix[stack->size], stack->matrix[stack->size-1]);
586 stack->size++;
587}
588
589void GPU_PopMatrix(void)
590{
591 GPU_MatrixStack* stack;
592
593 GPU_Target* target = GPU_GetActiveTarget();
594 if(target == NULL)
595 return;
596
597 // FIXME: Flushing here is not always necessary if this isn't the last target
598 GPU_FlushBlitBuffer();
599
600 if(target->matrix_mode == GPU_MODEL)
601 stack = &target->model_matrix;
602 else if(target->matrix_mode == GPU_VIEW)
603 stack = &target->view_matrix;
604 else //if(target->matrix_mode == GPU_PROJECTION)
605 stack = &target->projection_matrix;
606
607 if(stack->size == 0)
608 {
609 GPU_PushErrorCode(__func__, GPU_ERROR_USER_ERROR, "Matrix stack is empty.");
610 }
611 else if(stack->size == 1)
612 {
613 GPU_PushErrorCode(__func__, GPU_ERROR_USER_ERROR, "Matrix stack would become empty!");
614 }
615 else
616 stack->size--;
617}
618
619void GPU_SetProjection(const float* A)
620{
621 GPU_Target* target = GPU_GetActiveTarget();
622 if(target == NULL || A == NULL)
623 return;
624
625 GPU_FlushBlitBuffer();
626 GPU_MatrixCopy(GPU_GetProjection(), A);
627}
628
629void GPU_SetModel(const float* A)
630{
631 GPU_Target* target = GPU_GetActiveTarget();
632 if(target == NULL || A == NULL)
633 return;
634
635 GPU_FlushBlitBuffer();
636 GPU_MatrixCopy(GPU_GetModel(), A);
637}
638
639void GPU_SetView(const float* A)
640{
641 GPU_Target* target = GPU_GetActiveTarget();
642 if(target == NULL || A == NULL)
643 return;
644
645 GPU_FlushBlitBuffer();
646 GPU_MatrixCopy(GPU_GetView(), A);
647}
648
649void GPU_SetProjectionFromStack(GPU_MatrixStack* stack)
650{
651 GPU_Target* target = GPU_GetActiveTarget();
652 if(target == NULL || stack == NULL)
653 return;
654
655 GPU_SetProjection(GPU_GetTopMatrix(stack));
656}
657
658void GPU_SetModelFromStack(GPU_MatrixStack* stack)
659{
660 GPU_Target* target = GPU_GetActiveTarget();
661 if(target == NULL || stack == NULL)
662 return;
663
664 GPU_SetModel(GPU_GetTopMatrix(stack));
665}
666
667void GPU_SetViewFromStack(GPU_MatrixStack* stack)
668{
669 GPU_Target* target = GPU_GetActiveTarget();
670 if(target == NULL || stack == NULL)
671 return;
672
673 GPU_SetView(GPU_GetTopMatrix(stack));
674}
675
676float* GPU_GetTopMatrix(GPU_MatrixStack* stack)
677{
678 if(stack == NULL || stack->size == 0)
679 return NULL;
680 return stack->matrix[stack->size-1];
681}
682
683void GPU_LoadIdentity(void)
684{
685 float* result = GPU_GetCurrentMatrix();
686 if(result == NULL)
687 return;
688
689 GPU_FlushBlitBuffer();
690 GPU_MatrixIdentity(result);
691}
692
693void GPU_LoadMatrix(const float* A)
694{
695 float* result = GPU_GetCurrentMatrix();
696 if(result == NULL)
697 return;
698 GPU_FlushBlitBuffer();
699 GPU_MatrixCopy(result, A);
700}
701
702void GPU_Ortho(float left, float right, float bottom, float top, float z_near, float z_far)
703{
704 GPU_FlushBlitBuffer();
705 GPU_MatrixOrtho(GPU_GetCurrentMatrix(), left, right, bottom, top, z_near, z_far);
706}
707
708void GPU_Frustum(float left, float right, float bottom, float top, float z_near, float z_far)
709{
710 GPU_FlushBlitBuffer();
711 GPU_MatrixFrustum(GPU_GetCurrentMatrix(), left, right, bottom, top, z_near, z_far);
712}
713
714void GPU_Perspective(float fovy, float aspect, float z_near, float z_far)
715{
716 GPU_FlushBlitBuffer();
717 GPU_MatrixPerspective(GPU_GetCurrentMatrix(), fovy, aspect, z_near, z_far);
718}
719
720void GPU_LookAt(float eye_x, float eye_y, float eye_z, float target_x, float target_y, float target_z, float up_x, float up_y, float up_z)
721{
722 GPU_FlushBlitBuffer();
723 GPU_MatrixLookAt(GPU_GetCurrentMatrix(), eye_x, eye_y, eye_z, target_x, target_y, target_z, up_x, up_y, up_z);
724}
725
726
727void GPU_Translate(float x, float y, float z)
728{
729 GPU_FlushBlitBuffer();
730 GPU_MatrixTranslate(GPU_GetCurrentMatrix(), x, y, z);
731}
732
733void GPU_Scale(float sx, float sy, float sz)
734{
735 GPU_FlushBlitBuffer();
736 GPU_MatrixScale(GPU_GetCurrentMatrix(), sx, sy, sz);
737}
738
739void GPU_Rotate(float degrees, float x, float y, float z)
740{
741 GPU_FlushBlitBuffer();
742 GPU_MatrixRotate(GPU_GetCurrentMatrix(), degrees, x, y, z);
743}
744
745void GPU_MultMatrix(const float* A)
746{
747 float* result = GPU_GetCurrentMatrix();
748 if(result == NULL)
749 return;
750 GPU_FlushBlitBuffer();
751 GPU_MultiplyAndAssign(result, A);
752}
753
754void GPU_GetModelViewProjection(float* result)
755{
756 // MVP = P * V * M
757 GPU_MatrixMultiply(result, GPU_GetProjection(), GPU_GetView());
758 GPU_MultiplyAndAssign(result, GPU_GetModel());
759}