PageRenderTime 109ms CodeModel.GetById 29ms app.highlight 72ms RepoModel.GetById 1ms app.codeStats 1ms

/isgl3d/math/Isgl3dMatrix4.h

https://github.com/edwardean/isgl3d
C++ Header | 845 lines | 697 code | 120 blank | 28 comment | 5 complexity | 464a2b7bbf2398b7a432bfa575b6e2d5 MD5 | raw file
  1/*
  2 * iSGL3D: http://isgl3d.com
  3 *
  4 * Copyright (c) 2010-2012 Stuart Caunt
  5 *
  6 * Permission is hereby granted, free of charge, to any person obtaining a copy
  7 * of this software and associated documentation files (the "Software"), to deal
  8 * in the Software without restriction, including without limitation the rights
  9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 10 * copies of the Software, and to permit persons to whom the Software is
 11 * furnished to do so, subject to the following conditions:
 12 * 
 13 * The above copyright notice and this permission notice shall be included in
 14 * all copies or substantial portions of the Software.
 15 * 
 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 22 * THE SOFTWARE.
 23 *
 24 */
 25
 26#import <Foundation/Foundation.h>
 27#import "Isgl3dMathTypes.h"
 28#import "Isgl3dVector3.h"
 29#import "Isgl3dVector4.h"
 30
 31
 32/*
 33 * Use GLKit definitions for iOS >= 5.0 and if no strict ANSI compilation is set (C/C++ language dialect)
 34 * GLKit linkage required in this case
 35 */
 36#if !(defined(__STRICT_ANSI__)) && (__IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_5_0)
 37
 38#import <GLKit/GLKMath.h>
 39
 40
 41#define Isgl3dMatrix4Identity GLKMatrix4Identity
 42
 43#define Isgl3dMatrix4Matrix GLKMatrix4Make
 44#define Isgl3dMatrix4MakeAndTranspose GLKMatrix4MakeAndTranspose
 45#define Isgl3dMatrix4MakeWithArray GLKMatrix4MakeWithArray
 46#define Isgl3dMatrix4MakeWithArrayAndTranspose GLKMatrix4MakeWithArrayAndTranspose
 47#define Isgl3dMatrix4MakeWithRows GLKMatrix4MakeWithRows
 48#define Isgl3dMatrix4MakeWithColumns GLKMatrix4MakeWithColumns
 49
 50#define Isgl3dMatrix4MakeTranslation GLKMatrix4MakeTranslation
 51#define Isgl3dMatrix4MakeScale GLKMatrix4MakeScale
 52#define Isgl3dMatrix4MakeRotation GLKMatrix4MakeRotation
 53#define Isgl3dMatrix4MakeXRotation GLKMatrix4MakeXRotation
 54#define Isgl3dMatrix4MakeYRotation GLKMatrix4MakeYRotation
 55#define Isgl3dMatrix4MakeZRotation GLKMatrix4MakeZRotation
 56#define Isgl3dMatrix4MakePerspective GLKMatrix4MakePerspective
 57#define Isgl3dMatrix4MakeFrustum GLKMatrix4MakeFrustum
 58#define Isgl3dMatrix4MakeOrtho GLKMatrix4MakeOrtho
 59#define Isgl3dMatrix4MakeLookAt GLKMatrix4MakeLookAt
 60#define Isgl3dMatrix4GetMatrix3 GLKMatrix4GetMatrix3
 61#define Isgl3dMatrix4GetMatrix2 GLKMatrix4GetMatrix2
 62#define Isgl3dMatrix4GetRow GLKMatrix4GetRow
 63#define Isgl3dMatrix4GetColumn GLKMatrix4GetColumn
 64#define Isgl3dMatrix4SetRow GLKMatrix4SetRow
 65#define Isgl3dMatrix4SetColumn GLKMatrix4SetColumn
 66#define Isgl3dMatrix4Transpose GLKMatrix4Transpose
 67#define Isgl3dMatrix4Invert GLKMatrix4Invert
 68#define Isgl3dMatrix4InvertAndTranspose GLKMatrix4InvertAndTranspose
 69#define Isgl3dMatrix4Multiply GLKMatrix4Multiply
 70#define Isgl3dMatrix4Add GLKMatrix4Add
 71#define Isgl3dMatrix4Subtract GLKMatrix4Subtract
 72#define Isgl3dMatrix4Translate GLKMatrix4Translate
 73#define Isgl3dMatrix4TranslateWithVector3 GLKMatrix4TranslateWithVector3
 74#define Isgl3dMatrix4TranslateWithVector4 GLKMatrix4TranslateWithVector4
 75#define Isgl3dMatrix4Scale GLKMatrix4Scale
 76#define Isgl3dMatrix4ScaleWithVector3 GLKMatrix4ScaleWithVector3
 77#define Isgl3dMatrix4ScaleWithVector4 GLKMatrix4ScaleWithVector4
 78#define Isgl3dMatrix4Rotate GLKMatrix4Rotate
 79#define Isgl3dMatrix4RotateWithVector3 GLKMatrix4RotateWithVector3
 80#define Isgl3dMatrix4RotateWithVector4 GLKMatrix4RotateWithVector4
 81#define Isgl3dMatrix4RotateX GLKMatrix4RotateX
 82#define Isgl3dMatrix4RotateY GLKMatrix4RotateY
 83#define Isgl3dMatrix4RotateZ GLKMatrix4RotateZ
 84#define Isgl3dMatrix4MultiplyVector3 GLKMatrix4MultiplyVector3
 85#define Isgl3dMatrix4MultiplyVector3WithTranslation GLKMatrix4MultiplyVector3WithTranslation
 86#define Isgl3dMatrix4MultiplyAndProjectVector3 GLKMatrix4MultiplyAndProjectVector3
 87#define Isgl3dMatrix4MultiplyVector3Array GLKMatrix4MultiplyVector3Array
 88#define Isgl3dMatrix4MultiplyVector3ArrayWithTranslation GLKMatrix4MultiplyVector3ArrayWithTranslation
 89#define Isgl3dMatrix4MultiplyAndProjectVector3Array GLKMatrix4MultiplyAndProjectVector3Array
 90#define Isgl3dMatrix4MultiplyVector4 GLKMatrix4MultiplyVector4
 91#define Isgl3dMatrix4MultiplyVector4Array GLKMatrix4MultiplyVector4Array
 92
 93
 94#else
 95
 96
 97#include <stddef.h>
 98#include <stdbool.h>
 99#include <math.h>
100
101#if defined(__ARM_NEON__)
102#include <arm_neon.h>
103#endif
104
105
106#ifdef __cplusplus
107extern "C" {
108#endif
109
110#pragma mark -
111#pragma mark GLKit compatible Prototypes
112#pragma mark -
113
114extern const Isgl3dMatrix4 Isgl3dMatrix4Identity;
115
116
117static inline Isgl3dMatrix4 Isgl3dMatrix4Matrix(float m00, float m01, float m02, float m03,
118                                                     float m10, float m11, float m12, float m13,
119                                                     float m20, float m21, float m22, float m23,
120                                                     float m30, float m31, float m32, float m33);
121static inline Isgl3dMatrix4 Isgl3dMatrix4MakeAndTranspose(float m00, float m01, float m02, float m03,
122                                                          float m10, float m11, float m12, float m13,
123                                                          float m20, float m21, float m22, float m23,
124                                                          float m30, float m31, float m32, float m33);
125static inline Isgl3dMatrix4 Isgl3dMatrix4MakeWithArray(float values[16]);
126static inline Isgl3dMatrix4 Isgl3dMatrix4MakeWithArrayAndTranspose(float values[16]);
127static inline Isgl3dMatrix4 Isgl3dMatrix4MakeWithRows(Isgl3dVector4 row0,
128                                                      Isgl3dVector4 row1, 
129                                                      Isgl3dVector4 row2,
130                                                      Isgl3dVector4 row3);
131static inline Isgl3dMatrix4 Isgl3dMatrix4MakeTranslation(float tx, float ty, float tz);
132static inline Isgl3dMatrix4 Isgl3dMatrix4MakeScale(float sx, float sy, float sz);
133static inline Isgl3dMatrix4 Isgl3dMatrix4MakeRotation(float radians, float x, float y, float z);
134static inline Isgl3dMatrix4 Isgl3dMatrix4MakeXRotation(float radians);
135static inline Isgl3dMatrix4 Isgl3dMatrix4MakeYRotation(float radians);
136static inline Isgl3dMatrix4 Isgl3dMatrix4MakeZRotation(float radians);
137static inline Isgl3dMatrix4 Isgl3dMatrix4MakePerspective(float fovyRadians, float aspect, float nearZ, float farZ);
138static inline Isgl3dMatrix4 Isgl3dMatrix4MakeFrustum(float left, float right,
139                                                     float bottom, float top,
140                                                     float nearZ, float farZ);
141static inline Isgl3dMatrix4 Isgl3dMatrix4MakeOrtho(float left, float right,
142                                                   float bottom, float top,
143                                                   float nearZ, float farZ);
144static inline Isgl3dMatrix4 Isgl3dMatrix4MakeLookAt(float eyeX, float eyeY, float eyeZ,
145                                                    float centerX, float centerY, float centerZ,
146                                                    float upX, float upY, float upZ);
147static inline Isgl3dMatrix3 Isgl3dMatrix4GetMatrix3(Isgl3dMatrix4 matrix);
148static inline Isgl3dMatrix2 Isgl3dMatrix4GetMatrix2(Isgl3dMatrix4 matrix);
149static inline Isgl3dVector4 Isgl3dMatrix4GetRow(Isgl3dMatrix4 matrix, int row);
150static inline Isgl3dVector4 Isgl3dMatrix4GetColumn(Isgl3dMatrix4 matrix, int column);
151static inline Isgl3dMatrix4 Isgl3dMatrix4SetRow(Isgl3dMatrix4 matrix, int row, Isgl3dVector4 vector);
152static inline Isgl3dMatrix4 Isgl3dMatrix4SetColumn(Isgl3dMatrix4 matrix, int column, Isgl3dVector4 vector);
153static inline Isgl3dMatrix4 Isgl3dMatrix4Transpose(Isgl3dMatrix4 matrix);
154Isgl3dMatrix4 Isgl3dMatrix4Invert(Isgl3dMatrix4 matrix, bool *isInvertible);
155Isgl3dMatrix4 Isgl3dMatrix4InvertAndTranspose(Isgl3dMatrix4 matrix, bool *isInvertible);
156#ifndef __clang__
157static inline Isgl3dMatrix4 Isgl3dMatrix4Multiply(Isgl3dMatrix4 matrixLeft, Isgl3dMatrix4 matrixRight);
158#else
159static Isgl3dMatrix4 Isgl3dMatrix4Multiply(Isgl3dMatrix4 matrixLeft, Isgl3dMatrix4 matrixRight);
160#endif
161static inline Isgl3dMatrix4 Isgl3dMatrix4Add(Isgl3dMatrix4 matrixLeft, Isgl3dMatrix4 matrixRight);
162static inline Isgl3dMatrix4 Isgl3dMatrix4Subtract(Isgl3dMatrix4 matrixLeft, Isgl3dMatrix4 matrixRight);
163static inline Isgl3dMatrix4 Isgl3dMatrix4Translate(Isgl3dMatrix4 matrix, float tx, float ty, float tz);
164static inline Isgl3dMatrix4 Isgl3dMatrix4TranslateWithVector3(Isgl3dMatrix4 matrix, Isgl3dVector3 translationVector);
165static inline Isgl3dMatrix4 Isgl3dMatrix4TranslateWithVector4(Isgl3dMatrix4 matrix, Isgl3dVector4 translationVector);
166static inline Isgl3dMatrix4 Isgl3dMatrix4Scale(Isgl3dMatrix4 matrix, float sx, float sy, float sz);
167static inline Isgl3dMatrix4 Isgl3dMatrix4ScaleWithVector3(Isgl3dMatrix4 matrix, Isgl3dVector3 scaleVector);
168static inline Isgl3dMatrix4 Isgl3dMatrix4ScaleWithVector4(Isgl3dMatrix4 matrix, Isgl3dVector4 scaleVector);
169static inline Isgl3dMatrix4 Isgl3dMatrix4Rotate(Isgl3dMatrix4 matrix, float radians, float x, float y, float z);
170static inline Isgl3dMatrix4 Isgl3dMatrix4RotateWithVector3(Isgl3dMatrix4 matrix, float radians, Isgl3dVector3 axisVector);
171static inline Isgl3dMatrix4 Isgl3dMatrix4RotateWithVector4(Isgl3dMatrix4 matrix, float radians, Isgl3dVector4 axisVector);
172static inline Isgl3dMatrix4 Isgl3dMatrix4RotateX(Isgl3dMatrix4 matrix, float radians);
173static inline Isgl3dMatrix4 Isgl3dMatrix4RotateY(Isgl3dMatrix4 matrix, float radians);
174static inline Isgl3dMatrix4 Isgl3dMatrix4RotateZ(Isgl3dMatrix4 matrix, float radians);
175static inline Isgl3dVector3 Isgl3dMatrix4MultiplyVector3(Isgl3dMatrix4 matrixLeft, Isgl3dVector3 vectorRight);
176static inline Isgl3dVector3 Isgl3dMatrix4MultiplyVector3WithTranslation(Isgl3dMatrix4 matrixLeft, Isgl3dVector3 vectorRight);
177static inline Isgl3dVector3 Isgl3dMatrix4MultiplyAndProjectVector3(Isgl3dMatrix4 matrixLeft, Isgl3dVector3 vectorRight);
178static inline void Isgl3dMatrix4MultiplyVector3Array(Isgl3dMatrix4 matrix, Isgl3dVector3 *vectors, size_t vectorCount);
179static inline void Isgl3dMatrix4MultiplyAndProjectVector3Array(Isgl3dMatrix4 matrix, Isgl3dVector3 *vectors, size_t vectorCount);
180static inline Isgl3dVector4 Isgl3dMatrix4MultiplyVector4(Isgl3dMatrix4 matrixLeft, Isgl3dVector4 vectorRight);
181static inline void Isgl3dMatrix4MultiplyVector4Array(Isgl3dMatrix4 matrix, Isgl3dVector4 *vectors, size_t vectorCount);
182
183
184#pragma mark -
185#pragma mark GLKit compatible Implementations
186#pragma mark -
187static inline Isgl3dMatrix4 Isgl3dMatrix4Matrix(float m00, float m01, float m02, float m03,
188                                                float m10, float m11, float m12, float m13,
189                                                float m20, float m21, float m22, float m23,
190                                                float m30, float m31, float m32, float m33)
191{
192    Isgl3dMatrix4 m = { m00, m01, m02, m03,
193                        m10, m11, m12, m13,
194                        m20, m21, m22, m23,
195                        m30, m31, m32, m33 };
196    return m;
197}
198
199static inline Isgl3dMatrix4 Isgl3dMatrix4MakeAndTranspose(float m00, float m01, float m02, float m03,
200                                                          float m10, float m11, float m12, float m13,
201                                                          float m20, float m21, float m22, float m23,
202                                                          float m30, float m31, float m32, float m33)
203{
204    Isgl3dMatrix4 m = { m00, m10, m20, m30,
205                        m01, m11, m21, m31,
206                        m02, m12, m22, m32,
207                        m03, m13, m23, m33 };
208    return m;
209}
210
211static inline Isgl3dMatrix4 Isgl3dMatrix4MakeWithArray(float values[16])
212{
213    Isgl3dMatrix4 m = { values[0], values[1], values[2], values[3],
214                        values[4], values[5], values[6], values[7],
215                        values[8], values[9], values[10], values[11],
216                        values[12], values[13], values[14], values[15] };
217    return m;
218}
219
220static inline Isgl3dMatrix4 Isgl3dMatrix4MakeWithArrayAndTranspose(float values[16])
221{
222#if defined(__ARM_NEON__)
223    float32x4x4_t m = vld4q_f32(values);
224    return *(Isgl3dMatrix4 *)&m;
225#else
226    Isgl3dMatrix4 m = { values[0], values[4], values[8], values[12],
227                        values[1], values[5], values[9], values[13],
228                        values[2], values[6], values[10], values[14],
229                        values[3], values[7], values[11], values[15] };
230    return m;
231#endif
232}
233
234static inline Isgl3dMatrix4 Isgl3dMatrix4MakeWithRows(Isgl3dVector4 row0,
235                                                      Isgl3dVector4 row1, 
236                                                      Isgl3dVector4 row2,
237                                                      Isgl3dVector4 row3)
238{
239    Isgl3dMatrix4 m = { row0.v[0], row1.v[0], row2.v[0], row3.v[0],
240                        row0.v[1], row1.v[1], row2.v[1], row3.v[1],
241                        row0.v[2], row1.v[2], row2.v[2], row3.v[2],
242                        row0.v[3], row1.v[3], row2.v[3], row3.v[3] };
243    return m;
244}
245
246static inline Isgl3dMatrix4 Isgl3dMatrix4MakeWithColumns(Isgl3dVector4 column0,
247                                                         Isgl3dVector4 column1, 
248                                                         Isgl3dVector4 column2,
249                                                         Isgl3dVector4 column3)
250{
251#if defined(__ARM_NEON__)
252    float32x4x4_t m;
253    m.val[0] = vld1q_f32(column0.v);
254    m.val[1] = vld1q_f32(column1.v);
255    m.val[2] = vld1q_f32(column2.v);
256    m.val[3] = vld1q_f32(column3.v);
257    return *(Isgl3dMatrix4 *)&m;
258#else
259    Isgl3dMatrix4 m = { column0.v[0], column0.v[1], column0.v[2], column0.v[3],
260                        column1.v[0], column1.v[1], column1.v[2], column1.v[3],
261                        column2.v[0], column2.v[1], column2.v[2], column2.v[3],
262                        column3.v[0], column3.v[1], column3.v[2], column3.v[3] };
263    return m;
264#endif
265}
266
267static inline Isgl3dMatrix4 Isgl3dMatrix4MakeTranslation(float tx, float ty, float tz)
268{
269    Isgl3dMatrix4 m = Isgl3dMatrix4Identity;
270    m.m[12] = tx;
271    m.m[13] = ty;
272    m.m[14] = tz;
273    return m;
274}
275
276static inline Isgl3dMatrix4 Isgl3dMatrix4MakeScale(float sx, float sy, float sz)
277{
278    Isgl3dMatrix4 m = Isgl3dMatrix4Identity;
279    m.m[0] = sx;
280    m.m[5] = sy;
281    m.m[10] = sz;
282    return m;
283}
284
285static inline Isgl3dMatrix4 Isgl3dMatrix4MakeRotation(float radians, float x, float y, float z)
286{
287    Isgl3dVector3 v = Isgl3dVector3Normalize(Isgl3dVector3Make(x, y, z));
288    float cos = cosf(radians);
289    float cosp = 1.0f - cos;
290    float sin = sinf(radians);
291    
292    Isgl3dMatrix4 m = { cos + cosp * v.v[0] * v.v[0],
293                        cosp * v.v[0] * v.v[1] + v.v[2] * sin,
294                        cosp * v.v[0] * v.v[2] - v.v[1] * sin,
295                        0.0f,
296                        cosp * v.v[0] * v.v[1] - v.v[2] * sin,
297                        cos + cosp * v.v[1] * v.v[1],
298                        cosp * v.v[1] * v.v[2] + v.v[0] * sin,
299                        0.0f,
300                        cosp * v.v[0] * v.v[2] + v.v[1] * sin,
301                        cosp * v.v[1] * v.v[2] - v.v[0] * sin,
302                        cos + cosp * v.v[2] * v.v[2],
303                        0.0f,
304                        0.0f,
305                        0.0f,
306                        0.0f,
307                        1.0f };
308    
309    return m;
310}
311
312static inline Isgl3dMatrix4 Isgl3dMatrix4MakeXRotation(float radians)
313{
314    float cos = cosf(radians);
315    float sin = sinf(radians);
316    
317    Isgl3dMatrix4 m = { 1.0f, 0.0f, 0.0f, 0.0f,
318                        0.0f, cos, sin, 0.0f,
319                        0.0f, -sin, cos, 0.0f,
320                        0.0f, 0.0f, 0.0f, 1.0f };
321    
322    return m;
323}
324
325static inline Isgl3dMatrix4 Isgl3dMatrix4MakeYRotation(float radians)
326{
327    float cos = cosf(radians);
328    float sin = sinf(radians);
329    
330    Isgl3dMatrix4 m = { cos, 0.0f, -sin, 0.0f,
331                        0.0f, 1.0f, 0.0f, 0.0f,
332                        sin, 0.0f, cos, 0.0f,
333                        0.0f, 0.0f, 0.0f, 1.0f };
334    
335    return m;
336}
337
338static inline Isgl3dMatrix4 Isgl3dMatrix4MakeZRotation(float radians)
339{
340    float cos = cosf(radians);
341    float sin = sinf(radians);
342    
343    Isgl3dMatrix4 m = { cos, sin, 0.0f, 0.0f,
344                        -sin, cos, 0.0f, 0.0f,
345                        0.0f, 0.0f, 1.0f, 0.0f,
346                        0.0f, 0.0f, 0.0f, 1.0f };
347    
348    return m;
349}
350
351static inline Isgl3dMatrix4 Isgl3dMatrix4MakePerspective(float fovyRadians, float aspect, float nearZ, float farZ)
352{
353    float cotan = 1.0f / tanf(fovyRadians / 2.0f);
354    
355    Isgl3dMatrix4 m = { cotan / aspect, 0.0f, 0.0f, 0.0f,
356                        0.0f, cotan, 0.0f, 0.0f,
357                        0.0f, 0.0f, (farZ + nearZ) / (nearZ - farZ), -1.0f,
358                        0.0f, 0.0f, (2.0f * farZ * nearZ) / (nearZ - farZ), 0.0f };
359    
360    return m;
361}
362
363static inline Isgl3dMatrix4 Isgl3dMatrix4MakeFrustum(float left, float right,
364                                                     float bottom, float top,
365                                                     float nearZ, float farZ)
366{
367    float ral = right + left;
368    float rsl = right - left;
369    float tsb = top - bottom;
370    float tab = top + bottom;
371    float fan = farZ + nearZ;
372    float fsn = farZ - nearZ;
373    
374    Isgl3dMatrix4 m = { 2.0f * nearZ / rsl, 0.0f, 0.0f, 0.0f,
375                        0.0f, 2.0f * nearZ / tsb, 0.0f, 0.0f,
376                        ral / rsl, tab / tsb, -fan / fsn, -1.0f,
377                        0.0f, 0.0f, (-2.0f * farZ * nearZ) / fsn, 0.0f };
378    
379    return m;
380}
381
382static inline Isgl3dMatrix4 Isgl3dMatrix4MakeOrtho(float left, float right,
383                                                   float bottom, float top,
384                                                   float nearZ, float farZ)
385{
386    float ral = right + left;
387    float rsl = right - left;
388    float tab = top + bottom;
389    float tsb = top - bottom;
390    float fan = farZ + nearZ;
391    float fsn = farZ - nearZ;
392    
393    Isgl3dMatrix4 m = { 2.0f / rsl, 0.0f, 0.0f, 0.0f,
394                        0.0f, 2.0f / tsb, 0.0f, 0.0f,
395                        0.0f, 0.0f, -2.0f / fsn, 0.0f,
396                        -ral / rsl, -tab / tsb, -fan / fsn, 1.0f };
397    
398    return m;
399}
400
401static inline Isgl3dMatrix4 Isgl3dMatrix4MakeLookAt(float eyeX, float eyeY, float eyeZ,
402                                                    float centerX, float centerY, float centerZ,
403                                                    float upX, float upY, float upZ)
404{
405    Isgl3dVector3 ev = { eyeX, eyeY, eyeZ };
406    Isgl3dVector3 cv = { centerX, centerY, centerZ };
407    Isgl3dVector3 uv = { upX, upY, upZ };
408    Isgl3dVector3 n = Isgl3dVector3Normalize(Isgl3dVector3Add(ev, Isgl3dVector3Negate(cv)));
409    Isgl3dVector3 u = Isgl3dVector3Normalize(Isgl3dVector3CrossProduct(uv, n));
410    Isgl3dVector3 v = Isgl3dVector3CrossProduct(n, u);
411    
412    Isgl3dMatrix4 m = { u.v[0], v.v[0], n.v[0], 0.0f,
413                        u.v[1], v.v[1], n.v[1], 0.0f,
414                        u.v[2], v.v[2], n.v[2], 0.0f,
415                        Isgl3dVector3DotProduct(Isgl3dVector3Negate(u), ev),
416                        Isgl3dVector3DotProduct(Isgl3dVector3Negate(v), ev),
417                        Isgl3dVector3DotProduct(Isgl3dVector3Negate(n), ev),
418                        1.0f };
419    
420    return m;
421}
422
423static inline Isgl3dMatrix3 Isgl3dMatrix4GetMatrix3(Isgl3dMatrix4 matrix)
424{
425    Isgl3dMatrix3 m = { matrix.m[0], matrix.m[1], matrix.m[2],
426                        matrix.m[4], matrix.m[5], matrix.m[6],
427                        matrix.m[8], matrix.m[9], matrix.m[10] };
428    return m;
429}
430
431static inline Isgl3dMatrix2 Isgl3dMatrix4GetMatrix2(Isgl3dMatrix4 matrix)
432{
433    Isgl3dMatrix2 m = { matrix.m[0], matrix.m[1],
434                        matrix.m[4], matrix.m[5] };
435    return m;
436}
437
438static inline Isgl3dVector4 Isgl3dMatrix4GetRow(Isgl3dMatrix4 matrix, int row)
439{
440    Isgl3dVector4 v = { matrix.m[row], matrix.m[4 + row], matrix.m[8 + row], matrix.m[12 + row] };
441    return v;
442}
443
444static inline Isgl3dVector4 Isgl3dMatrix4GetColumn(Isgl3dMatrix4 matrix, int column)
445{
446#if defined(__ARM_NEON__)
447    float32x4_t v = vld1q_f32(&(matrix.m[column * 4]));
448    return *(Isgl3dVector4 *)&v;
449#else
450    Isgl3dVector4 v = { matrix.m[column * 4 + 0], matrix.m[column * 4 + 1], matrix.m[column * 4 + 2], matrix.m[column * 4 + 3] };
451    return v;
452#endif
453}
454
455static inline Isgl3dMatrix4 Isgl3dMatrix4SetRow(Isgl3dMatrix4 matrix, int row, Isgl3dVector4 vector)
456{
457    matrix.m[row] = vector.v[0];
458    matrix.m[row + 4] = vector.v[1];
459    matrix.m[row + 8] = vector.v[2];
460    matrix.m[row + 12] = vector.v[3];
461    
462    return matrix;
463}
464
465static inline Isgl3dMatrix4 Isgl3dMatrix4SetColumn(Isgl3dMatrix4 matrix, int column, Isgl3dVector4 vector)
466{
467#if defined(__ARM_NEON__)
468    float *dst = &(matrix.m[column * 4]);
469    vst1q_f32(dst, vld1q_f32(vector.v));
470    return matrix;
471#else
472    matrix.m[column * 4 + 0] = vector.v[0];
473    matrix.m[column * 4 + 1] = vector.v[1];
474    matrix.m[column * 4 + 2] = vector.v[2];
475    matrix.m[column * 4 + 3] = vector.v[3];
476    
477    return matrix;
478#endif
479}
480
481static inline Isgl3dMatrix4 Isgl3dMatrix4Transpose(Isgl3dMatrix4 matrix)
482{
483#if defined(__ARM_NEON__)
484    float32x4x4_t m = vld4q_f32(matrix.m);
485    return *(Isgl3dMatrix4 *)&m;
486#else
487    Isgl3dMatrix4 m = { matrix.m[0], matrix.m[4], matrix.m[8], matrix.m[12],
488        matrix.m[1], matrix.m[5], matrix.m[9], matrix.m[13],
489        matrix.m[2], matrix.m[6], matrix.m[10], matrix.m[14],
490        matrix.m[3], matrix.m[7], matrix.m[11], matrix.m[15] };
491    return m;
492#endif
493}
494
495#ifndef __clang__
496static inline Isgl3dMatrix4 Isgl3dMatrix4Multiply(Isgl3dMatrix4 matrixLeft, Isgl3dMatrix4 matrixRight)
497#else
498static Isgl3dMatrix4 Isgl3dMatrix4Multiply(Isgl3dMatrix4 matrixLeft, Isgl3dMatrix4 matrixRight)
499#endif
500{
501#if defined(__ARM_NEON__)
502    float32x4x4_t iMatrixLeft = *(float32x4x4_t *)&matrixLeft;
503    float32x4x4_t iMatrixRight = *(float32x4x4_t *)&matrixRight;
504    float32x4x4_t m;
505    
506    m.val[0] = vmulq_n_f32(iMatrixLeft.val[0], vgetq_lane_f32(iMatrixRight.val[0], 0));
507    m.val[1] = vmulq_n_f32(iMatrixLeft.val[0], vgetq_lane_f32(iMatrixRight.val[1], 0));
508    m.val[2] = vmulq_n_f32(iMatrixLeft.val[0], vgetq_lane_f32(iMatrixRight.val[2], 0));
509    m.val[3] = vmulq_n_f32(iMatrixLeft.val[0], vgetq_lane_f32(iMatrixRight.val[3], 0));
510    
511    m.val[0] = vmlaq_n_f32(m.val[0], iMatrixLeft.val[1], vgetq_lane_f32(iMatrixRight.val[0], 1));
512    m.val[1] = vmlaq_n_f32(m.val[1], iMatrixLeft.val[1], vgetq_lane_f32(iMatrixRight.val[1], 1));
513    m.val[2] = vmlaq_n_f32(m.val[2], iMatrixLeft.val[1], vgetq_lane_f32(iMatrixRight.val[2], 1));
514    m.val[3] = vmlaq_n_f32(m.val[3], iMatrixLeft.val[1], vgetq_lane_f32(iMatrixRight.val[3], 1));
515    
516    m.val[0] = vmlaq_n_f32(m.val[0], iMatrixLeft.val[2], vgetq_lane_f32(iMatrixRight.val[0], 2));
517    m.val[1] = vmlaq_n_f32(m.val[1], iMatrixLeft.val[2], vgetq_lane_f32(iMatrixRight.val[1], 2));
518    m.val[2] = vmlaq_n_f32(m.val[2], iMatrixLeft.val[2], vgetq_lane_f32(iMatrixRight.val[2], 2));
519    m.val[3] = vmlaq_n_f32(m.val[3], iMatrixLeft.val[2], vgetq_lane_f32(iMatrixRight.val[3], 2));
520    
521    m.val[0] = vmlaq_n_f32(m.val[0], iMatrixLeft.val[3], vgetq_lane_f32(iMatrixRight.val[0], 3));
522    m.val[1] = vmlaq_n_f32(m.val[1], iMatrixLeft.val[3], vgetq_lane_f32(iMatrixRight.val[1], 3));
523    m.val[2] = vmlaq_n_f32(m.val[2], iMatrixLeft.val[3], vgetq_lane_f32(iMatrixRight.val[2], 3));
524    m.val[3] = vmlaq_n_f32(m.val[3], iMatrixLeft.val[3], vgetq_lane_f32(iMatrixRight.val[3], 3));
525    
526    return *(Isgl3dMatrix4 *)&m;
527#else
528    Isgl3dMatrix4 m;
529    
530    m.m[0]  = matrixLeft.m[0] * matrixRight.m[0]  + matrixLeft.m[4] * matrixRight.m[1]  + matrixLeft.m[8] * matrixRight.m[2]   + matrixLeft.m[12] * matrixRight.m[3];
531	m.m[4]  = matrixLeft.m[0] * matrixRight.m[4]  + matrixLeft.m[4] * matrixRight.m[5]  + matrixLeft.m[8] * matrixRight.m[6]   + matrixLeft.m[12] * matrixRight.m[7];
532	m.m[8]  = matrixLeft.m[0] * matrixRight.m[8]  + matrixLeft.m[4] * matrixRight.m[9]  + matrixLeft.m[8] * matrixRight.m[10]  + matrixLeft.m[12] * matrixRight.m[11];
533	m.m[12] = matrixLeft.m[0] * matrixRight.m[12] + matrixLeft.m[4] * matrixRight.m[13] + matrixLeft.m[8] * matrixRight.m[14]  + matrixLeft.m[12] * matrixRight.m[15];
534    
535	m.m[1]  = matrixLeft.m[1] * matrixRight.m[0]  + matrixLeft.m[5] * matrixRight.m[1]  + matrixLeft.m[9] * matrixRight.m[2]   + matrixLeft.m[13] * matrixRight.m[3];
536	m.m[5]  = matrixLeft.m[1] * matrixRight.m[4]  + matrixLeft.m[5] * matrixRight.m[5]  + matrixLeft.m[9] * matrixRight.m[6]   + matrixLeft.m[13] * matrixRight.m[7];
537	m.m[9]  = matrixLeft.m[1] * matrixRight.m[8]  + matrixLeft.m[5] * matrixRight.m[9]  + matrixLeft.m[9] * matrixRight.m[10]  + matrixLeft.m[13] * matrixRight.m[11];
538	m.m[13] = matrixLeft.m[1] * matrixRight.m[12] + matrixLeft.m[5] * matrixRight.m[13] + matrixLeft.m[9] * matrixRight.m[14]  + matrixLeft.m[13] * matrixRight.m[15];
539    
540	m.m[2]  = matrixLeft.m[2] * matrixRight.m[0]  + matrixLeft.m[6] * matrixRight.m[1]  + matrixLeft.m[10] * matrixRight.m[2]  + matrixLeft.m[14] * matrixRight.m[3];
541	m.m[6]  = matrixLeft.m[2] * matrixRight.m[4]  + matrixLeft.m[6] * matrixRight.m[5]  + matrixLeft.m[10] * matrixRight.m[6]  + matrixLeft.m[14] * matrixRight.m[7];
542	m.m[10] = matrixLeft.m[2] * matrixRight.m[8]  + matrixLeft.m[6] * matrixRight.m[9]  + matrixLeft.m[10] * matrixRight.m[10] + matrixLeft.m[14] * matrixRight.m[11];
543	m.m[14] = matrixLeft.m[2] * matrixRight.m[12] + matrixLeft.m[6] * matrixRight.m[13] + matrixLeft.m[10] * matrixRight.m[14] + matrixLeft.m[14] * matrixRight.m[15];
544    
545	m.m[3]  = matrixLeft.m[3] * matrixRight.m[0]  + matrixLeft.m[7] * matrixRight.m[1]  + matrixLeft.m[11] * matrixRight.m[2]  + matrixLeft.m[15] * matrixRight.m[3];
546	m.m[7]  = matrixLeft.m[3] * matrixRight.m[4]  + matrixLeft.m[7] * matrixRight.m[5]  + matrixLeft.m[11] * matrixRight.m[6]  + matrixLeft.m[15] * matrixRight.m[7];
547	m.m[11] = matrixLeft.m[3] * matrixRight.m[8]  + matrixLeft.m[7] * matrixRight.m[9]  + matrixLeft.m[11] * matrixRight.m[10] + matrixLeft.m[15] * matrixRight.m[11];
548	m.m[15] = matrixLeft.m[3] * matrixRight.m[12] + matrixLeft.m[7] * matrixRight.m[13] + matrixLeft.m[11] * matrixRight.m[14] + matrixLeft.m[15] * matrixRight.m[15];
549    
550    return m;
551#endif
552}
553
554static inline Isgl3dMatrix4 Isgl3dMatrix4Add(Isgl3dMatrix4 matrixLeft, Isgl3dMatrix4 matrixRight)
555{
556#if defined(__ARM_NEON__)
557    float32x4x4_t iMatrixLeft = *(float32x4x4_t *)&matrixLeft;
558    float32x4x4_t iMatrixRight = *(float32x4x4_t *)&matrixRight;
559    float32x4x4_t m;
560    
561    m.val[0] = vaddq_f32(iMatrixLeft.val[0], iMatrixRight.val[0]);
562    m.val[1] = vaddq_f32(iMatrixLeft.val[1], iMatrixRight.val[1]);
563    m.val[2] = vaddq_f32(iMatrixLeft.val[2], iMatrixRight.val[2]);
564    m.val[3] = vaddq_f32(iMatrixLeft.val[3], iMatrixRight.val[3]);
565    
566    return *(Isgl3dMatrix4 *)&m;
567#else
568    Isgl3dMatrix4 m;
569    
570    m.m[0] = matrixLeft.m[0] + matrixRight.m[0];
571    m.m[1] = matrixLeft.m[1] + matrixRight.m[1];
572    m.m[2] = matrixLeft.m[2] + matrixRight.m[2];
573    m.m[3] = matrixLeft.m[3] + matrixRight.m[3];
574    
575    m.m[4] = matrixLeft.m[4] + matrixRight.m[4];
576    m.m[5] = matrixLeft.m[5] + matrixRight.m[5];
577    m.m[6] = matrixLeft.m[6] + matrixRight.m[6];
578    m.m[7] = matrixLeft.m[7] + matrixRight.m[7];
579    
580    m.m[8] = matrixLeft.m[8] + matrixRight.m[8];
581    m.m[9] = matrixLeft.m[9] + matrixRight.m[9];
582    m.m[10] = matrixLeft.m[10] + matrixRight.m[10];
583    m.m[11] = matrixLeft.m[11] + matrixRight.m[11];
584    
585    m.m[12] = matrixLeft.m[12] + matrixRight.m[12];
586    m.m[13] = matrixLeft.m[13] + matrixRight.m[13];
587    m.m[14] = matrixLeft.m[14] + matrixRight.m[14];
588    m.m[15] = matrixLeft.m[15] + matrixRight.m[15];
589    
590    return m;
591#endif
592}
593
594static inline Isgl3dMatrix4 Isgl3dMatrix4Subtract(Isgl3dMatrix4 matrixLeft, Isgl3dMatrix4 matrixRight)
595{
596#if defined(__ARM_NEON__)
597    float32x4x4_t iMatrixLeft = *(float32x4x4_t *)&matrixLeft;
598    float32x4x4_t iMatrixRight = *(float32x4x4_t *)&matrixRight;
599    float32x4x4_t m;
600    
601    m.val[0] = vsubq_f32(iMatrixLeft.val[0], iMatrixRight.val[0]);
602    m.val[1] = vsubq_f32(iMatrixLeft.val[1], iMatrixRight.val[1]);
603    m.val[2] = vsubq_f32(iMatrixLeft.val[2], iMatrixRight.val[2]);
604    m.val[3] = vsubq_f32(iMatrixLeft.val[3], iMatrixRight.val[3]);
605    
606    return *(Isgl3dMatrix4 *)&m;
607#else
608    Isgl3dMatrix4 m;
609    
610    m.m[0] = matrixLeft.m[0] - matrixRight.m[0];
611    m.m[1] = matrixLeft.m[1] - matrixRight.m[1];
612    m.m[2] = matrixLeft.m[2] - matrixRight.m[2];
613    m.m[3] = matrixLeft.m[3] - matrixRight.m[3];
614    
615    m.m[4] = matrixLeft.m[4] - matrixRight.m[4];
616    m.m[5] = matrixLeft.m[5] - matrixRight.m[5];
617    m.m[6] = matrixLeft.m[6] - matrixRight.m[6];
618    m.m[7] = matrixLeft.m[7] - matrixRight.m[7];
619    
620    m.m[8] = matrixLeft.m[8] - matrixRight.m[8];
621    m.m[9] = matrixLeft.m[9] - matrixRight.m[9];
622    m.m[10] = matrixLeft.m[10] - matrixRight.m[10];
623    m.m[11] = matrixLeft.m[11] - matrixRight.m[11];
624    
625    m.m[12] = matrixLeft.m[12] - matrixRight.m[12];
626    m.m[13] = matrixLeft.m[13] - matrixRight.m[13];
627    m.m[14] = matrixLeft.m[14] - matrixRight.m[14];
628    m.m[15] = matrixLeft.m[15] - matrixRight.m[15];
629    
630    return m;
631#endif
632}
633
634static inline Isgl3dMatrix4 Isgl3dMatrix4Translate(Isgl3dMatrix4 matrix, float tx, float ty, float tz)
635{
636    Isgl3dMatrix4 m = { matrix.m[0], matrix.m[1], matrix.m[2], matrix.m[3],
637                        matrix.m[4], matrix.m[5], matrix.m[6], matrix.m[7],
638                        matrix.m[8], matrix.m[9], matrix.m[10], matrix.m[11],
639                        matrix.m[0] * tx + matrix.m[4] * ty + matrix.m[8] * tz + matrix.m[12],
640                        matrix.m[1] * tx + matrix.m[5] * ty + matrix.m[9] * tz + matrix.m[13],
641                        matrix.m[2] * tx + matrix.m[6] * ty + matrix.m[10] * tz + matrix.m[14],
642                        matrix.m[15] };
643    return m;
644}
645
646static inline Isgl3dMatrix4 Isgl3dMatrix4TranslateWithVector3(Isgl3dMatrix4 matrix, Isgl3dVector3 translationVector)
647{
648    Isgl3dMatrix4 m = { matrix.m[0], matrix.m[1], matrix.m[2], matrix.m[3],
649                        matrix.m[4], matrix.m[5], matrix.m[6], matrix.m[7],
650                        matrix.m[8], matrix.m[9], matrix.m[10], matrix.m[11],
651                        matrix.m[0] * translationVector.v[0] + matrix.m[4] * translationVector.v[1] + matrix.m[8] * translationVector.v[2] + matrix.m[12],
652                        matrix.m[1] * translationVector.v[0] + matrix.m[5] * translationVector.v[1] + matrix.m[9] * translationVector.v[2] + matrix.m[13],
653                        matrix.m[2] * translationVector.v[0] + matrix.m[6] * translationVector.v[1] + matrix.m[10] * translationVector.v[2] + matrix.m[14],
654                        matrix.m[15] };
655    return m;
656}
657
658static inline Isgl3dMatrix4 Isgl3dMatrix4TranslateWithVector4(Isgl3dMatrix4 matrix, Isgl3dVector4 translationVector)
659{
660    Isgl3dMatrix4 m = { matrix.m[0], matrix.m[1], matrix.m[2], matrix.m[3],
661                        matrix.m[4], matrix.m[5], matrix.m[6], matrix.m[7],
662                        matrix.m[8], matrix.m[9], matrix.m[10], matrix.m[11],
663                        matrix.m[0] * translationVector.v[0] + matrix.m[4] * translationVector.v[1] + matrix.m[8] * translationVector.v[2] + matrix.m[12],
664                        matrix.m[1] * translationVector.v[0] + matrix.m[5] * translationVector.v[1] + matrix.m[9] * translationVector.v[2] + matrix.m[13],
665                        matrix.m[2] * translationVector.v[0] + matrix.m[6] * translationVector.v[1] + matrix.m[10] * translationVector.v[2] + matrix.m[14],
666                        matrix.m[15] };
667    return m;
668}
669
670static inline Isgl3dMatrix4 Isgl3dMatrix4Scale(Isgl3dMatrix4 matrix, float sx, float sy, float sz)
671{
672#if defined(__ARM_NEON__)
673    float32x4x4_t iMatrix = *(float32x4x4_t *)&matrix;
674    float32x4x4_t m;
675    
676    m.val[0] = vmulq_n_f32(iMatrix.val[0], (float32_t)sx);
677    m.val[1] = vmulq_n_f32(iMatrix.val[1], (float32_t)sy);
678    m.val[2] = vmulq_n_f32(iMatrix.val[2], (float32_t)sz);
679    m.val[3] = iMatrix.val[3];
680    
681    return *(Isgl3dMatrix4 *)&m;
682#else
683    Isgl3dMatrix4 m = { matrix.m[0] * sx, matrix.m[1] * sx, matrix.m[2] * sx, matrix.m[3] * sx,
684                        matrix.m[4] * sy, matrix.m[5] * sy, matrix.m[6] * sy, matrix.m[7] * sy,
685                        matrix.m[8] * sz, matrix.m[9] * sz, matrix.m[10] * sz, matrix.m[11] * sz,
686                        matrix.m[12], matrix.m[13], matrix.m[14], matrix.m[15] };
687    return m;
688#endif
689}
690
691static inline Isgl3dMatrix4 Isgl3dMatrix4ScaleWithVector3(Isgl3dMatrix4 matrix, Isgl3dVector3 scaleVector)
692{
693#if defined(__ARM_NEON__)
694    float32x4x4_t iMatrix = *(float32x4x4_t *)&matrix;
695    float32x4x4_t m;
696    
697    m.val[0] = vmulq_n_f32(iMatrix.val[0], (float32_t)scaleVector.v[0]);
698    m.val[1] = vmulq_n_f32(iMatrix.val[1], (float32_t)scaleVector.v[1]);
699    m.val[2] = vmulq_n_f32(iMatrix.val[2], (float32_t)scaleVector.v[2]);
700    m.val[3] = iMatrix.val[3];
701    
702    return *(Isgl3dMatrix4 *)&m;
703#else
704    Isgl3dMatrix4 m = { matrix.m[0] * scaleVector.v[0], matrix.m[1] * scaleVector.v[0], matrix.m[2] * scaleVector.v[0], matrix.m[3] * scaleVector.v[0],
705        matrix.m[4] * scaleVector.v[1], matrix.m[5] * scaleVector.v[1], matrix.m[6] * scaleVector.v[1], matrix.m[7] * scaleVector.v[1],
706        matrix.m[8] * scaleVector.v[2], matrix.m[9] * scaleVector.v[2], matrix.m[10] * scaleVector.v[2], matrix.m[11] * scaleVector.v[2],
707        matrix.m[12], matrix.m[13], matrix.m[14], matrix.m[15] };
708    return m;
709#endif
710}
711
712static inline Isgl3dMatrix4 Isgl3dMatrix4ScaleWithVector4(Isgl3dMatrix4 matrix, Isgl3dVector4 scaleVector)
713{
714#if defined(__ARM_NEON__)
715    float32x4x4_t iMatrix = *(float32x4x4_t *)&matrix;
716    float32x4x4_t m;
717    
718    m.val[0] = vmulq_n_f32(iMatrix.val[0], (float32_t)scaleVector.v[0]);
719    m.val[1] = vmulq_n_f32(iMatrix.val[1], (float32_t)scaleVector.v[1]);
720    m.val[2] = vmulq_n_f32(iMatrix.val[2], (float32_t)scaleVector.v[2]);
721    m.val[3] = iMatrix.val[3];
722    
723    return *(Isgl3dMatrix4 *)&m;
724#else
725    Isgl3dMatrix4 m = { matrix.m[0] * scaleVector.v[0], matrix.m[1] * scaleVector.v[0], matrix.m[2] * scaleVector.v[0], matrix.m[3] * scaleVector.v[0],
726        matrix.m[4] * scaleVector.v[1], matrix.m[5] * scaleVector.v[1], matrix.m[6] * scaleVector.v[1], matrix.m[7] * scaleVector.v[1],
727        matrix.m[8] * scaleVector.v[2], matrix.m[9] * scaleVector.v[2], matrix.m[10] * scaleVector.v[2], matrix.m[11] * scaleVector.v[2],
728        matrix.m[12], matrix.m[13], matrix.m[14], matrix.m[15] };
729    return m;
730#endif
731}
732
733static inline Isgl3dMatrix4 Isgl3dMatrix4Rotate(Isgl3dMatrix4 matrix, float radians, float x, float y, float z)
734{
735    Isgl3dMatrix4 rm = Isgl3dMatrix4MakeRotation(radians, x, y, z);
736    return Isgl3dMatrix4Multiply(matrix, rm);
737}
738
739static inline Isgl3dMatrix4 Isgl3dMatrix4RotateWithVector3(Isgl3dMatrix4 matrix, float radians, Isgl3dVector3 axisVector)
740{
741    Isgl3dMatrix4 rm = Isgl3dMatrix4MakeRotation(radians, axisVector.v[0], axisVector.v[1], axisVector.v[2]);
742    return Isgl3dMatrix4Multiply(matrix, rm);
743}
744
745static inline Isgl3dMatrix4 Isgl3dMatrix4RotateWithVector4(Isgl3dMatrix4 matrix, float radians, Isgl3dVector4 axisVector)
746{
747    Isgl3dMatrix4 rm = Isgl3dMatrix4MakeRotation(radians, axisVector.v[0], axisVector.v[1], axisVector.v[2]);
748    return Isgl3dMatrix4Multiply(matrix, rm);    
749}
750
751static inline Isgl3dMatrix4 Isgl3dMatrix4RotateX(Isgl3dMatrix4 matrix, float radians)
752{
753    Isgl3dMatrix4 rm = Isgl3dMatrix4MakeXRotation(radians);
754    return Isgl3dMatrix4Multiply(matrix, rm);
755}
756
757static inline Isgl3dMatrix4 Isgl3dMatrix4RotateY(Isgl3dMatrix4 matrix, float radians)
758{
759    Isgl3dMatrix4 rm = Isgl3dMatrix4MakeYRotation(radians);
760    return Isgl3dMatrix4Multiply(matrix, rm);
761}
762
763static inline Isgl3dMatrix4 Isgl3dMatrix4RotateZ(Isgl3dMatrix4 matrix, float radians)
764{
765    Isgl3dMatrix4 rm = Isgl3dMatrix4MakeZRotation(radians);
766    return Isgl3dMatrix4Multiply(matrix, rm);
767}
768
769static inline Isgl3dVector3 Isgl3dMatrix4MultiplyVector3(Isgl3dMatrix4 matrixLeft, Isgl3dVector3 vectorRight)
770{
771    Isgl3dVector4 v4 = Isgl3dMatrix4MultiplyVector4(matrixLeft, Isgl3dVector4Make(vectorRight.v[0], vectorRight.v[1], vectorRight.v[2], 0.0f));
772    return Isgl3dVector3Make(v4.v[0], v4.v[1], v4.v[2]);
773}
774
775static inline Isgl3dVector3 Isgl3dMatrix4MultiplyVector3WithTranslation(Isgl3dMatrix4 matrixLeft, Isgl3dVector3 vectorRight)
776{
777    Isgl3dVector4 v4 = Isgl3dMatrix4MultiplyVector4(matrixLeft, Isgl3dVector4Make(vectorRight.v[0], vectorRight.v[1], vectorRight.v[2], 1.0f));
778    return Isgl3dVector3Make(v4.v[0], v4.v[1], v4.v[2]);
779}
780
781static inline Isgl3dVector3 Isgl3dMatrix4MultiplyAndProjectVector3(Isgl3dMatrix4 matrixLeft, Isgl3dVector3 vectorRight)
782{
783    Isgl3dVector4 v4 = Isgl3dMatrix4MultiplyVector4(matrixLeft, Isgl3dVector4Make(vectorRight.v[0], vectorRight.v[1], vectorRight.v[2], 1.0f));
784    return Isgl3dVector3MultiplyScalar(Isgl3dVector3Make(v4.v[0], v4.v[1], v4.v[2]), 1.0f / v4.v[3]);
785}
786
787static inline void Isgl3dMatrix4MultiplyVector3Array(Isgl3dMatrix4 matrix, Isgl3dVector3 *vectors, size_t vectorCount)
788{
789    int i;
790    for (i=0; i < vectorCount; i++)
791        vectors[i] = Isgl3dMatrix4MultiplyVector3(matrix, vectors[i]);
792}
793
794static inline void Isgl3dMatrix4MultiplyVector3ArrayWithTranslation(Isgl3dMatrix4 matrix, Isgl3dVector3 *vectors, size_t vectorCount)
795{
796    int i;
797    for (i=0; i < vectorCount; i++)
798        vectors[i] = Isgl3dMatrix4MultiplyVector3WithTranslation(matrix, vectors[i]);
799}
800
801static inline void Isgl3dMatrix4MultiplyAndProjectVector3Array(Isgl3dMatrix4 matrix, Isgl3dVector3 *vectors, size_t vectorCount)
802{
803    int i;
804    for (i=0; i < vectorCount; i++)
805        vectors[i] = Isgl3dMatrix4MultiplyAndProjectVector3(matrix, vectors[i]);
806}
807
808static inline Isgl3dVector4 Isgl3dMatrix4MultiplyVector4(Isgl3dMatrix4 matrixLeft, Isgl3dVector4 vectorRight)
809{
810#if defined(__ARM_NEON__)
811    float32x4x4_t iMatrix = *(float32x4x4_t *)&matrixLeft;
812    float32x4_t v;
813    
814    iMatrix.val[0] = vmulq_n_f32(iMatrix.val[0], (float32_t)vectorRight.v[0]);
815    iMatrix.val[1] = vmulq_n_f32(iMatrix.val[1], (float32_t)vectorRight.v[1]);
816    iMatrix.val[2] = vmulq_n_f32(iMatrix.val[2], (float32_t)vectorRight.v[2]);
817    iMatrix.val[3] = vmulq_n_f32(iMatrix.val[3], (float32_t)vectorRight.v[3]);
818    
819    iMatrix.val[0] = vaddq_f32(iMatrix.val[0], iMatrix.val[1]);
820    iMatrix.val[2] = vaddq_f32(iMatrix.val[2], iMatrix.val[3]);
821    
822    v = vaddq_f32(iMatrix.val[0], iMatrix.val[2]);
823    
824    return *(Isgl3dVector4 *)&v;
825#else
826    Isgl3dVector4 v = { matrixLeft.m[0] * vectorRight.v[0] + matrixLeft.m[4] * vectorRight.v[1] + matrixLeft.m[8] * vectorRight.v[2] + matrixLeft.m[12] * vectorRight.v[3],
827        matrixLeft.m[1] * vectorRight.v[0] + matrixLeft.m[5] * vectorRight.v[1] + matrixLeft.m[9] * vectorRight.v[2] + matrixLeft.m[13] * vectorRight.v[3],
828        matrixLeft.m[2] * vectorRight.v[0] + matrixLeft.m[6] * vectorRight.v[1] + matrixLeft.m[10] * vectorRight.v[2] + matrixLeft.m[14] * vectorRight.v[3],
829        matrixLeft.m[3] * vectorRight.v[0] + matrixLeft.m[7] * vectorRight.v[1] + matrixLeft.m[11] * vectorRight.v[2] + matrixLeft.m[15] * vectorRight.v[3] };
830    return v;
831#endif
832}
833
834static inline void Isgl3dMatrix4MultiplyVector4Array(Isgl3dMatrix4 matrix, Isgl3dVector4 *vectors, size_t vectorCount)
835{
836    int i;
837    for (i=0; i < vectorCount; i++)
838        vectors[i] = Isgl3dMatrix4MultiplyVector4(matrix, vectors[i]);
839}
840
841#ifdef __cplusplus
842}
843#endif
844
845#endif