The Battle for Wesnoth  1.13.4+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
SDL_gpu_GL_matrix.c
Go to the documentation of this file.
1 #include "SDL_gpu.h"
2 #include "SDL_gpu_GL_matrix.h"
3 #include <math.h>
4 #include <string.h>
5 
6 #ifdef _MSC_VER
7 #define __func__ __FUNCTION__
8 #endif
9 
10 #ifndef M_PI
11 #define M_PI 3.1415926f
12 #endif
13 
14 
15 // static inline only supported in Visual C++ from version 2015 but can use static __inline instead for older versions
16 #ifndef static_inline
17  #ifdef _MSC_VER
18  #if _MSC_VER < 1900
19  #define static_inline static __inline
20  #else
21  #define static_inline static inline
22  #endif
23  #else
24  #define static_inline static inline
25  #endif
26 #endif
27 
28 // Visual C does not support C99 (which includes a safe snprintf)
29 #ifdef _MSC_VER
30 #define snprintf c99_snprintf
31 // From Valentin Milea: http://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010
32 static_inline int c99_vsnprintf(char* str, size_t size, const char* format, va_list ap)
33 {
34  int count = -1;
35 
36  if (size != 0)
37  count = _vsnprintf_s(str, size, _TRUNCATE, format, ap);
38  if (count == -1)
39  count = _vscprintf(format, ap);
40 
41  return count;
42 }
43 
44 static_inline int c99_snprintf(char* str, size_t size, const char* format, ...)
45 {
46  int count;
47  va_list ap;
48 
49  va_start(ap, format);
50  count = c99_vsnprintf(str, size, format, ap);
51  va_end(ap);
52 
53  return count;
54 }
55 #endif
56 
57 
58 // Implementations based on Wayne Cochran's (wcochran) matrix.c
59 
60 // Column-major
61 #define INDEX(row,col) ((col)*4 + (row))
62 
63 void GPU_MatrixCopy(float* result, const float* A)
64 {
65  memcpy(result, A, 16*sizeof(float));
66 }
67 
69 {
70  memset(result, 0, 16*sizeof(float));
71  result[0] = result[5] = result[10] = result[15] = 1;
72 }
73 
74 // Matrix multiply: result = A * B
75 void GPU_Multiply4x4(float* result, float* A, float* B)
76 {
77  int r, c, i;
78  float s;
79  for(r = 0; r < 4; r++)
80  {
81  for(c = 0; c < 4; c++)
82  {
83  s = 0;
84  for(i = 0; i < 4; i++)
85  s += A[INDEX(r,i)]*B[INDEX(i,c)];
86 
87  result[INDEX(r,c)] = s;
88  }
89  }
90 }
91 
92 void GPU_MultiplyAndAssign(float* result, float* A)
93 {
94  float temp[16];
95  GPU_Multiply4x4(temp, result, A);
96  GPU_MatrixCopy(result, temp);
97 }
98 
99 
100 
101 
102 
103 // Can be used up to two times per line evaluation...
104 const char* GPU_GetMatrixString(float* A)
105 {
106  static char buffer[512];
107  static char buffer2[512];
108  static char flip = 0;
109 
110  char* b = (flip? buffer : buffer2);
111  flip = !flip;
112 
113  snprintf(b, 512, "%.1f %.1f %.1f %.1f\n"
114  "%.1f %.1f %.1f %.1f\n"
115  "%.1f %.1f %.1f %.1f\n"
116  "%.1f %.1f %.1f %.1f",
117  A[0], A[1], A[2], A[3],
118  A[4], A[5], A[6], A[7],
119  A[8], A[9], A[10], A[11],
120  A[12], A[13], A[14], A[15]);
121  return b;
122 }
123 
124 void GPU_MatrixMode(int matrix_mode)
125 {
127  if(target == NULL || target->context == NULL)
128  return;
129 
130  target->context->matrix_mode = matrix_mode;
131 }
132 
133 float* GPU_GetModelView(void)
134 {
136  GPU_MatrixStack* stack;
137 
138  if(target == NULL || target->context == NULL)
139  return NULL;
140  stack = &target->context->modelview_matrix;
141  if(stack->size == 0)
142  return NULL;
143  return stack->matrix[stack->size-1];
144 }
145 
146 float* GPU_GetProjection(void)
147 {
149  GPU_MatrixStack* stack;
150 
151  if(target == NULL || target->context == NULL)
152  return NULL;
153  stack = &target->context->projection_matrix;
154  if(stack->size == 0)
155  return NULL;
156  return stack->matrix[stack->size-1];
157 }
158 
160 {
162  GPU_MatrixStack* stack;
163 
164  if(target == NULL || target->context == NULL)
165  return NULL;
166  if(target->context->matrix_mode == GPU_MODELVIEW)
167  stack = &target->context->modelview_matrix;
168  else
169  stack = &target->context->projection_matrix;
170 
171  if(stack->size == 0)
172  return NULL;
173  return stack->matrix[stack->size-1];
174 }
175 
177 {
179  GPU_MatrixStack* stack;
180 
181  if(target == NULL || target->context == NULL)
182  return;
183 
184  stack = (target->context->matrix_mode == GPU_MODELVIEW? &target->context->modelview_matrix : &target->context->projection_matrix);
185  if(stack->size + 1 >= GPU_MATRIX_STACK_MAX)
186  {
187  GPU_PushErrorCode(__func__, GPU_ERROR_USER_ERROR, "Matrix stack is full (%d)", GPU_MATRIX_STACK_MAX);
188  return;
189  }
190  GPU_MatrixCopy(stack->matrix[stack->size], stack->matrix[stack->size-1]);
191  stack->size++;
192 }
193 
195 {
197  GPU_MatrixStack* stack;
198 
199  if(target == NULL || target->context == NULL)
200  return;
201 
202  stack = (target->context->matrix_mode == GPU_MODELVIEW? &target->context->modelview_matrix : &target->context->projection_matrix);
203  if(stack->size == 0)
204  {
205  GPU_PushErrorCode(__func__, GPU_ERROR_USER_ERROR, "Matrix stack is empty.");
206  return;
207  }
208  stack->size--;
209 }
210 
212 {
213  float* result = GPU_GetCurrentMatrix();
214  if(result == NULL)
215  return;
216  GPU_MatrixIdentity(result);
217 }
218 
219 void GPU_Ortho(float left, float right, float bottom, float top, float near, float far)
220 {
221  float* result = GPU_GetCurrentMatrix();
222  if(result == NULL)
223  return;
224 
225  {
226 #ifdef ROW_MAJOR
227  float A[16] = {2/(right - left), 0, 0, -(right + left)/(right - left),
228  0, 2/(top - bottom), 0, -(top + bottom)/(top - bottom),
229  0, 0, -2/(far - near), -(far + near)/(far - near),
230  0, 0, 0, 1};
231 #else
232  float A[16] = { 2 / (right - left), 0, 0, 0,
233  0, 2 / (top - bottom), 0, 0,
234  0, 0, -2 / (far - near), 0,
235  -(right + left) / (right - left), -(top + bottom) / (top - bottom), -(far + near) / (far - near), 1 };
236 #endif
237 
238  GPU_MultiplyAndAssign(result, A);
239  }
240 }
241 
242 void GPU_Frustum(float right, float left, float bottom, float top, float near, float far)
243 {
244  float* result = GPU_GetCurrentMatrix();
245  if(result == NULL)
246  return;
247 
248  {
249 #ifdef ROW_MAJOR
250  float A[16] = {2 * near / (right - left), 0, 0, 0,
251  0, 2 * near / (top - bottom), 0, 0,
252  (right + left) / (right - left), (top + bottom) / (top - bottom), -(far + near) / (far - near), -1,
253  0, 0, -(2 * far * near) / (far - near), 0};
254 #else
255  float A[16] = { 2 * near / (right - left), 0, (right + left) / (right - left), 0,
256  0, 2 * near / (top - bottom), (top + bottom) / (top - bottom), 0,
257  0, 0, -(far + near) / (far - near), -(2 * far * near) / (far - near),
258  0, 0, -1, 0 };
259 #endif
260 
261  GPU_MultiplyAndAssign(result, A);
262  }
263 }
264 
265 void GPU_Translate(float x, float y, float z)
266 {
267  float* result = GPU_GetCurrentMatrix();
268  if(result == NULL)
269  return;
270 
271  {
272 #ifdef ROW_MAJOR
273  float A[16] = {1, 0, 0, x,
274  0, 1, 0, y,
275  0, 0, 1, z,
276  0, 0, 0, 1};
277 #else
278  float A[16] = { 1, 0, 0, 0,
279  0, 1, 0, 0,
280  0, 0, 1, 0,
281  x, y, z, 1 };
282 #endif
283 
284  GPU_MultiplyAndAssign(result, A);
285  }
286 }
287 
288 void GPU_Scale(float sx, float sy, float sz)
289 {
290  float* result = GPU_GetCurrentMatrix();
291  if(result == NULL)
292  return;
293 
294  {
295  float A[16] = { sx, 0, 0, 0,
296  0, sy, 0, 0,
297  0, 0, sz, 0,
298  0, 0, 0, 1 };
299 
300  GPU_MultiplyAndAssign(result, A);
301  }
302 }
303 
304 void GPU_Rotate(float degrees, float x, float y, float z)
305 {
306  float p, radians, c, s, c_, zc_, yc_, xzc_, xyc_, yzc_, xs, ys, zs;
307  float* result;
308 
309  p = 1/sqrtf(x*x + y*y + z*z);
310  x *= p; y *= p; z *= p;
311  radians = degrees * (M_PI/180);
312  c = cosf(radians);
313  s = sinf(radians);
314  c_ = 1 - c;
315  zc_ = z*c_;
316  yc_ = y*c_;
317  xzc_ = x*zc_;
318  xyc_ = x*y*c_;
319  yzc_ = y*zc_;
320  xs = x*s;
321  ys = y*s;
322  zs = z*s;
323 
324  result = GPU_GetCurrentMatrix();
325  if(result == NULL)
326  return;
327 
328  {
329 #ifdef ROW_MAJOR
330  float A[16] = {x*x*c_ + c, xyc_ - zs, xzc_ + ys, 0,
331  xyc_ + zs, y*yc_ + c, yzc_ - xs, 0,
332  xzc_ - ys, yzc_ + xs, z*zc_ + c, 0,
333  0, 0, 0, 1};
334 #else
335  float A[16] = { x*x*c_ + c, xyc_ + zs, xzc_ - ys, 0,
336  xyc_ - zs, y*yc_ + c, yzc_ + xs, 0,
337  xzc_ + ys, yzc_ - xs, z*zc_ + c, 0,
338  0, 0, 0, 1 };
339 #endif
340 
341  GPU_MultiplyAndAssign(result, A);
342  }
343 }
344 
345 void GPU_MultMatrix(float* A)
346 {
347  float* result = GPU_GetCurrentMatrix();
348  if(result == NULL)
349  return;
350  GPU_MultiplyAndAssign(result, A);
351 }
352 
353 void GPU_GetModelViewProjection(float* result)
354 {
355  // MVP = P * MV
357 }
float matrix[GPU_MATRIX_STACK_MAX][16]
Definition: SDL_gpu.h:237
GLdouble GLdouble z
Definition: glew.h:1527
void GPU_Translate(float x, float y, float z)
void GPU_PushMatrix()
void GPU_Ortho(float left, float right, float bottom, float top, float near, float far)
void GPU_MatrixMode(int matrix_mode)
void GPU_PopMatrix()
void GPU_MultiplyAndAssign(float *result, float *A)
#define INDEX(row, col)
#define GPU_MODELVIEW
GPU_MatrixStack projection_matrix
Definition: SDL_gpu.h:270
void GPU_Multiply4x4(float *result, float *A, float *B)
GPU_Target * GPU_GetContextTarget(void)
Definition: SDL_gpu.c:882
#define M_PI
void GPU_Scale(float sx, float sy, float sz)
GLint GLint GLint GLint GLint GLint y
Definition: glew.h:1220
void GPU_MatrixCopy(float *result, const float *A)
void GPU_Rotate(float degrees, float x, float y, float z)
float * GPU_GetProjection(void)
void GPU_PushErrorCode(const char *function, GPU_ErrorEnum error, const char *details,...)
Definition: SDL_gpu.c:503
void GPU_GetModelViewProjection(float *result)
GLdouble GLdouble GLdouble b
Definition: glew.h:6966
GLuint64EXT * result
Definition: glew.h:10727
void GPU_Frustum(float right, float left, float bottom, float top, float near, float far)
GLfloat GLfloat p
Definition: glew.h:12766
GLuint GLuint GLsizei count
Definition: glew.h:1221
lu_byte right
Definition: lparser.cpp:1020
GLuint buffer
Definition: glew.h:1648
void GPU_MatrixIdentity(float *result)
GPU_MatrixStack modelview_matrix
Definition: SDL_gpu.h:271
GLint left
Definition: glew.h:5907
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: glew.h:1222
#define GPU_MATRIX_STACK_MAX
Definition: SDL_gpu.h:230
size_t i
Definition: function.cpp:1057
GLint GLint GLint GLint GLint x
Definition: glew.h:1220
GLdouble GLdouble GLdouble r
Definition: glew.h:1374
GPU_Context * context
Definition: SDL_gpu.h:303
void GPU_MultMatrix(float *A)
GLsizeiptr size
Definition: glew.h:1649
const char * GPU_GetMatrixString(float *A)
int matrix_mode
Definition: SDL_gpu.h:269
float * GPU_GetCurrentMatrix(void)
void GPU_LoadIdentity(void)
float * GPU_GetModelView(void)
unsigned int size
Definition: SDL_gpu.h:236
GLint GLint bottom
Definition: glew.h:5907
#define c
Definition: glew.h:12743
GLdouble s
Definition: glew.h:1358
#define static_inline
GLenum target
Definition: glew.h:5190