Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Added kazmath to git

  • Loading branch information...
commit 471ff83ae753eb8cc572b8eea0ce9287078ca366 1 parent 00bbe4e
@Kazade authored
View
7 CMakeLists.txt
@@ -0,0 +1,7 @@
+PROJECT(Kazmath)
+
+SET(CMAKE_C_FLAGS "-std=c99")
+SET(CMAKE_INSTALL_PREFIX, "/usr")
+
+ADD_SUBDIRECTORY(src bin)
+
View
74 build-linux/kazmath.cbp
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="kazmath" />
+ <Option pch_mode="2" />
+ <Option compiler="gcc" />
+ <Build>
+ <Target title="Debug">
+ <Option output="bin/Debug/libkazmath" prefix_auto="1" extension_auto="1" />
+ <Option object_output="obj/Debug/" />
+ <Option type="3" />
+ <Option compiler="gcc" />
+ <Option createDefFile="1" />
+ <Option createStaticLib="1" />
+ <Compiler>
+ <Add option="-g" />
+ </Compiler>
+ </Target>
+ <Target title="Release">
+ <Option output="bin/Release/libkazmath" prefix_auto="1" extension_auto="1" />
+ <Option object_output="obj/Release/" />
+ <Option type="3" />
+ <Option compiler="gcc" />
+ <Option createDefFile="1" />
+ <Option createStaticLib="1" />
+ <Compiler>
+ <Add option="-O2" />
+ </Compiler>
+ <Linker>
+ <Add option="-s" />
+ </Linker>
+ </Target>
+ </Build>
+ <Compiler>
+ <Add option="-Wall" />
+ <Add option="-std=c99" />
+ </Compiler>
+ <Unit filename="../src/mat4.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="../src/mat4.h" />
+ <Unit filename="../src/plane.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="../src/plane.h" />
+ <Unit filename="../src/quaternion.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="../src/quaternion.h" />
+ <Unit filename="../src/utility.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="../src/utility.h" />
+ <Unit filename="../src/vec2.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="../src/vec2.h" />
+ <Unit filename="../src/vec3.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="../src/vec3.h" />
+ <Unit filename="../src/vec4.c">
+ <Option compilerVar="CC" />
+ </Unit>
+ <Unit filename="../src/vec4.h" />
+ <Extensions>
+ <envvars />
+ <code_completion />
+ <debugger />
+ <lib_finder disable_auto="1" />
+ </Extensions>
+ </Project>
+</CodeBlocks_project_file>
View
68 build-linux/kazmath.depend
@@ -0,0 +1,68 @@
+# depslib dependency file v1.0
+1207417327 source:/home/luke/Projects/KazEngine3/kazengine/src/kazmath/src/mat4.c
+ "utility.h"
+ "vec3.h"
+ "mat4.h"
+ "quaternion.h"
+ <memory.h>
+ <assert.h>
+
+1217749462 /home/luke/Projects/KazEngine3/kazengine/src/kazmath/src/utility.h
+ <math.h>
+ <stdbool.h>
+
+1217749537 /home/luke/Projects/KazEngine3/kazengine/src/kazmath/src/vec3.h
+ <assert.h>
+
+1217797533 /home/luke/Projects/KazEngine3/kazengine/src/kazmath/src/mat4.h
+ "utility.h"
+
+1207504867 /home/luke/Projects/KazEngine3/kazengine/src/kazmath/src/quaternion.h
+ "utility.h"
+
+1217796589 source:/home/luke/Projects/KazEngine3/kazengine/src/kazmath/src/plane.c
+ <assert.h>
+ "vec3.h"
+ "vec4.h"
+ "plane.h"
+
+1207417327 /home/luke/Projects/KazEngine3/kazengine/src/kazmath/src/vec4.h
+ "utility.h"
+
+1217796426 /home/luke/Projects/KazEngine3/kazengine/src/kazmath/src/plane.h
+ "utility.h"
+
+1207417327 source:/home/luke/Projects/KazEngine3/kazengine/src/kazmath/src/quaternion.c
+ <assert.h>
+ <memory.h>
+ "utility.h"
+ "mat4.h"
+ "vec3.h"
+ "quaternion.h"
+
+1207505105 source:/home/luke/Projects/KazEngine3/kazengine/src/kazmath/src/utility.c
+ "utility.h"
+
+1207417327 source:/home/luke/Projects/KazEngine3/kazengine/src/kazmath/src/vec2.c
+ <assert.h>
+ "mat4.h"
+ "vec2.h"
+ "utility.h"
+
+1207501857 /home/luke/Projects/KazEngine3/kazengine/src/kazmath/src/vec2.h
+
+1207417327 source:/home/luke/Projects/KazEngine3/kazengine/src/kazmath/src/vec3.c
+ <assert.h>
+ <memory.h>
+ "utility.h"
+ "vec4.h"
+ "mat4.h"
+ "vec3.h"
+
+1207417327 source:/home/luke/Projects/KazEngine3/kazengine/src/kazmath/src/vec4.c
+ <memory.h>
+ <assert.h>
+ "utility.h"
+ "vec4.h"
+ "mat4.h"
+
View
16 build-linux/kazmath.layout
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_layout_file>
+ <ActiveTarget name="Debug" />
+ <File name="../src/mat4.c" open="1" top="0" tabpos="4">
+ <Cursor position="9261" topLine="288" />
+ </File>
+ <File name="../src/mat4.h" open="1" top="0" tabpos="3">
+ <Cursor position="1945" topLine="3" />
+ </File>
+ <File name="../src/plane.c" open="1" top="0" tabpos="1">
+ <Cursor position="3334" topLine="93" />
+ </File>
+ <File name="../src/plane.h" open="1" top="0" tabpos="2">
+ <Cursor position="984" topLine="6" />
+ </File>
+</CodeBlocks_layout_file>
View
27 src/CMakeLists.txt
@@ -0,0 +1,27 @@
+SET(KAZMATH_HEADERS
+vec2.h
+vec3.h
+vec4.h
+mat4.h
+plane.h
+utility.h
+quaternion.h
+)
+
+SET(KAZMATH_SRCS
+mat4.c
+plane.c
+vec4.c
+quaternion.c
+vec2.c
+vec3.c
+utility.c
+)
+
+#ADD_LIBRARY(Kazmath STATIC ${KAZMATH_SRCS})
+#INSTALL(TARGETS Kazmath ARCHIVE DESTINATION lib)
+
+ADD_LIBRARY(Kazmath SHARED ${KAZMATH_SRCS})
+INSTALL(TARGETS Kazmath LIBRARY DESTINATION lib)
+
+INSTALL(FILES ${KAZMATH_HEADERS} DESTINATION include/kazmath)
View
213 src/mat3.c
@@ -0,0 +1,213 @@
+/*
+Copyright 2007 Luke Benstead
+
+This file is part of KazMath.
+
+KazMath is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser Public License as published by
+the Free Software Foundation; either version 3 of the License, or
+(at your option) any later version.
+
+KazMath is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser Public License for more details.
+
+You should have received a copy of the GNU Lesser Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+#include "utility.h"
+#include "vec3.h"
+#include "mat3.h"
+#include "quaternion.h"
+
+#include <memory.h>
+#include <assert.h>
+
+/** Sets pOut to an identity matrix returns pOut*/
+kmMat3* kmMat3Identity(kmMat3* pOut)
+{
+ memset(pOut->m_Mat, 0, sizeof(float) * 9);
+ pOut->m_Mat[0] = pOut->m_Mat[3] = pOut->m_Mat[8] = 1.0f;
+ return pOut;
+}
+
+kmScalar kmMat3Determinant(const kmMat3* pIn)
+{
+ kmScalar output;
+ /*
+ calculating the determinant following the rule of sarus,
+ | 0 1 2 | 0 1 |
+ m = | 3 4 5 | 3 5 |
+ | 6 7 8 | 6 7 |
+ now sum up the products of the diagonals going to the right (i.e. 0,4,8)
+ and substract the products of the other diagonals (i.e. 2,4,6)
+ */
+
+ output = pIn->m_Mat[0] * pIn->m_Mat[4] * pIn->m_Mat[8] + pIn->m_Mat[1] * pIn->m_Mat[5] * pIn->m_Mat[6] + pIn->m_Mat[2] * pIn->m_Mat[3] * pIn->m_Mat[7];
+ output -= pIn->m_Mat[2] * pIn->m_Mat[4] * pIn->m_Mat[6] + pIn->m_Mat[0] * pIn->m_Mat[5] * pIn->m_Mat[7] + pIn->m_Mat[1] * pIn->m_Mat[3] * pIn->m_Mat[8];
+
+ return output;
+}
+
+
+kmMat3* kmMat3Adjugate(kmMat3* pOut, const kmMat3* pIn)
+{
+ pOut->m_Mat[0] = pIn->m_Mat[4] * pIn->m_Mat[8] - pIn->m_Mat[5] * pIn->m_Mat[7];
+ pOut->m_Mat[1] = pIn->m_Mat[2] * pIn->m_Mat[7] - pIn->m_Mat[1] * pIn->m_Mat[8];
+ pOut->m_Mat[2] = pIn->m_Mat[1] * pIn->m_Mat[5] - pIn->m_Mat[2] * pIn->m_Mat[4];
+ pOut->m_Mat[3] = pIn->m_Mat[5] * pIn->m_Mat[6] - pIn->m_Mat[3] * pIn->m_Mat[8];
+ pOut->m_Mat[4] = pIn->m_Mat[0] * pIn->m_Mat[8] - pIn->m_Mat[2] * pIn->m_Mat[6];
+ pOut->m_Mat[5] = pIn->m_Mat[2] * pIn->m_Mat[3] - pIn->m_Mat[0] * pIn->m_Mat[5];
+ pOut->m_Mat[6] = pIn->m_Mat[3] * pIn->m_Mat[7] - pIn->m_Mat[4] * pIn->m_Mat[6];
+ pOut->m_Mat[7] = pIn->m_Mat[1] * pIn->m_Mat[6] - pIn->m_Mat[9] * pIn->m_Mat[7];
+ pOut->m_Mat[8] = pIn->m_Mat[0] * pIn->m_Mat[4] - pIn->m_Mat[1] * pIn->m_Mat[3];
+
+ return pOut;
+}
+
+kmMat3* kmMat3Inverse(kmMat3* pOut, kmScalar pDeterminate, const kmMat3* pM)
+{
+ if(pDeterminate == 0.0)
+ return NULL;
+
+ kmScalar detInv = 1.0 / pDeterminate;
+
+ kmMat3 adjugate;
+ kmMat3Adjugate(&adjugate, pM);
+
+ kmMat3ScalarMultiply(pOut, &adjugate, detInv);
+
+ return pOut;
+}
+
+/** Returns true if pIn is an identity matrix */
+bool kmMat3IsIdentity(const kmMat3* pIn)
+{
+ static const float identity [] = { 1.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f};
+
+ return (memcmp(identity, pIn->m_Mat, sizeof(float) * 9) == 0);
+}
+
+/** Sets pOut to the transpose of pIn, returns pOut */
+kmMat3* kmMat3Transpose(kmMat3* pOut, const kmMat3* pIn)
+{
+ for (int z = 0; z < 4; ++z)
+ for (int x = 0; x < 4; ++x)
+ pOut->m_Mat[(z * 4) + x] = pIn->m_Mat[(x * 4) + z];
+
+ return pOut;
+}
+
+/* Multiplies pM1 with pM2, stores the result in pOut, returns pOut */
+kmMat3* kmMat3Multiply(kmMat3* pOut, const kmMat3* pM1, const kmMat3* pM2)
+{
+ float mat[9];
+
+ const float *m1 = pM1->m_Mat, *m2 = pM2->m_Mat;
+
+ mat[0] = m1[0] * m2[0] + m1[3] * m2[1] + m1[6] * m2[2];
+ mat[1] = m1[1] * m2[0] + m1[4] * m2[1] + m1[7] * m2[2];
+ mat[2] = m1[2] * m2[0] + m1[5] * m2[1] + m1[8] * m2[2];
+
+ mat[3] = m1[0] * m2[3] + m1[3] * m2[4] + m1[6] * m2[5];
+ mat[4] = m1[1] * m2[3] + m1[4] * m2[4] + m1[7] * m2[5];
+ mat[5] = m1[2] * m2[3] + m1[5] * m2[4] + m1[8] * m2[5];
+
+ mat[6] = m1[0] * m2[6] + m1[3] * m2[7] + m1[6] * m2[8];
+ mat[7] = m1[1] * m2[6] + m1[4] * m2[7] + m1[7] * m2[8];
+ mat[8] = m1[2] * m2[6] + m1[5] * m2[7] + m1[8] * m2[8];
+
+ memcpy(pOut->m_Mat, mat, sizeof(float)*9);
+
+ return pOut;
+}
+
+kmMat3* kmMat3ScalarMultiply(kmMat3* pOut, const kmMat3* pM, const kmScalar pFactor)
+{
+ float mat[9];
+
+ for(int i = 0; i < 9; i++)
+ {
+ mat[0] = pM->m_Mat[9] * pFactor;
+ }
+
+ memcpy(pOut->m_Mat, mat, sizeof(float)*9);
+
+ return pOut;
+}
+
+/** Assigns the value of pIn to pOut */
+kmMat3* kmMat3Assign(kmMat3* pOut, const kmMat3* pIn)
+{
+ assert(pOut != pIn); //You have tried to self-assign!!
+
+ memcpy(pOut->m_Mat, pIn->m_Mat, sizeof(float)*9);
+
+ return pOut;
+}
+
+/** Returns true if the 2 matrices are equal (approximately) */
+bool kmMat3AreEqual(const kmMat3* pMat1, const kmMat3* pMat2)
+{
+ assert(pMat1 != pMat2); //You are comparing the same thing!
+
+ for (int i = 0; i < 9; ++i)
+ {
+ if (!(pMat1->m_Mat[i] + kmEpsilon > pMat2->m_Mat[i] &&
+ pMat1->m_Mat[i] - kmEpsilon < pMat2->m_Mat[i]))
+ return false;
+ }
+
+ return true;
+}
+
+/* Rotation around the z axis so everything stays planar in XY */
+kmMat3* kmMat3Rotation(kmMat3* pOut, const float radians)
+{
+ /*
+ | cos(A) -sin(A) 0 |
+ M = | sin(A) cos(A) 0 |
+ | 0 0 1 |
+ */
+
+ pOut->m_Mat[0] = cosf(radians);
+ pOut->m_Mat[1] = sinf(radians);
+ pOut->m_Mat[2] = 0.0f;
+
+ pOut->m_Mat[3] = -sinf(radians);;
+ pOut->m_Mat[4] = cosf(radians);
+ pOut->m_Mat[5] = 0.0f;
+
+ pOut->m_Mat[6] = 0.0f;
+ pOut->m_Mat[7] = 0.0f;
+ pOut->m_Mat[8] = 1.0f;
+
+ return pOut;
+}
+
+/** Builds a scaling matrix */
+kmMat3* kmMat3Scaling(kmMat3* pOut, const kmScalar x, const kmScalar y)
+{
+ memset(pOut->m_Mat, 0, sizeof(float) * 9);
+ pOut->m_Mat[0] = x;
+ pOut->m_Mat[4] = y;
+ pOut->m_Mat[8] = 1.0;
+
+ return pOut;
+}
+
+kmMat3* kmMat3Translation(kmMat3* pOut, const kmScalar x, const kmScalar y)
+{
+ memset(pOut->m_Mat, 0, sizeof(float) * 9);
+ pOut->m_Mat[2] = x;
+ pOut->m_Mat[5] = y;
+ pOut->m_Mat[8] = 1.0;
+
+ return pOut;
+}
+
+
View
57 src/mat3.h
@@ -0,0 +1,57 @@
+/*
+Copyright 2007 Luke Benstead
+
+This file is part of KazMath.
+
+KazMath is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser Public License as published by
+the Free Software Foundation; either version 3 of the License, or
+(at your option) any later version.
+
+KazMath is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser Public License for more details.
+
+You should have received a copy of the GNU Lesser Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef MAT3_H_INCLUDED
+#define MAT3_H_INCLUDED
+
+#include "utility.h"
+
+struct kmVec3;
+struct kmQuaternion;
+
+typedef struct kmMat3{
+ kmScalar m_Mat[9];
+} kmMat3;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+kmMat3* kmMat3Adjugate(kmMat3* pOut, const kmMat3* pIn);
+kmMat3* kmMat3Identity(kmMat3* pOut);
+kmMat3* kmMat3Inverse(kmMat3* pOut, const kmScalar pDeterminate, const kmMat3* pM);
+bool kmMat3IsIdentity(const kmMat3* pIn);
+kmMat3* kmMat3Transpose(kmMat3* pOut, const kmMat3* pIn);
+kmScalar kmMat3Determinant(const kmMat3* pIn);
+kmMat3* kmMat3Multiply(kmMat3* pOut, const kmMat3* pM1, const kmMat3* pM2);
+kmMat3* kmMat3ScalarMultiply(kmMat3* pOut, const kmMat3* pM, kmScalar pFactor);
+
+kmMat3* kmMat3Assign(kmMat3* pOut, const kmMat3* pIn);
+bool kmMat3AreEqual(const kmMat3* pM1, const kmMat3* pM2);
+
+kmMat3* kmMat3Rotation(kmMat3* pOut, const kmScalar radians);
+kmMat3* kmMat3Scaling(kmMat3* pOut, const kmScalar x, const kmScalar y);
+kmMat3* kmMat3Translation(kmMat3* pOut, const kmScalar x, const kmScalar y);
+
+#ifdef __cplusplus
+}
+#endif
+#endif // MAT3_H_INCLUDED
+
View
442 src/mat4.c
@@ -0,0 +1,442 @@
+/*
+Copyright 2007 Luke Benstead
+
+This file is part of KazMath.
+
+KazMath is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser Public License as published by
+the Free Software Foundation; either version 3 of the License, or
+(at your option) any later version.
+
+KazMath is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser Public License for more details.
+
+You should have received a copy of the GNU Lesser Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+#include "utility.h"
+#include "vec3.h"
+#include "mat4.h"
+#include "quaternion.h"
+
+#include <memory.h>
+#include <assert.h>
+
+/** Sets pOut to an identity matrix returns pOut*/
+kmMat4* kmMat4Identity(kmMat4* pOut)
+{
+ memset(pOut->m_Mat, 0, sizeof(float) * 16);
+ pOut->m_Mat[0] = pOut->m_Mat[5] = pOut->m_Mat[10] = pOut->m_Mat[15] = 1.0f;
+ return pOut;
+}
+
+kmMat4* kmMat4Inverse(kmMat4* pOut, const kmMat4* pM)
+{
+ float mat[16];
+
+ for (int i = 0; i < 16; i++)
+ {
+ mat[i] = pM->m_Mat[i];
+ }
+
+ kmMat4Identity(pOut);
+
+
+ for (int j = 0; j < 4; ++j) // Find largest pivot in column j among rows j..3
+ {
+ int i1 = j; // Row with largest pivot candidate
+
+ for (int i = j + 1; i < 4; ++i)
+ {
+ if (fabs(mat[i*4 + j]) > fabs(mat[i1*4 + j]))
+ i1 = i;
+ }
+
+ // Swap rows i1 and j in a and b to put pivot on diagonal
+ float temp[4];
+ for(int k = 0; k < 4; k++)
+ {
+ temp[k] = mat[i1 * 4 + k];
+ }
+
+ for(int k = 0; k < 4; k++)
+ {
+ mat[i1 * 4 + k] = mat[j * 4 + k];
+ mat[j * 4 + k] = temp[k];
+ }
+
+ for(int k = 0; k < 4; k++)
+ {
+ temp[k] = pOut->m_Mat[i1 * 4 + k];
+ }
+
+ for(int k = 0; k < 4; k++)
+ {
+ pOut->m_Mat[i1 * 4 + k] = pOut->m_Mat[j * 4 + k];
+ pOut->m_Mat[j * 4 + k] = temp[k];
+ }
+
+ // Scale row j to have a unit diagonal
+ if (!mat[j*4 + j])
+ {
+ // Singular matrix - can't invert
+
+ return pOut;
+ }
+
+ for(int k = 0; k < 4; k++)
+ {
+ pOut->m_Mat[j * 4 + k] /= mat[j * 4 + j];
+ mat[j * 4 + k] /= mat[j * 4 + j];
+ }
+
+ // Eliminate off-diagonal elems in col j of a, doing identical ops to b
+ for (int i = 0; i < 4; ++i)
+ {
+ if (i != j)
+ {
+ for(int k = 0; k < 4; k++)
+ {
+ pOut->m_Mat[i*4 + k] -= mat[i*4 + j] * pOut->m_Mat[j*4 + k];
+ mat[i*4 + k] -= mat[i*4 + j] * mat[j*4 + k];
+ }
+ }
+ }
+ }
+
+ return pOut;
+}
+
+/** Returns true if pIn is an identity matrix */
+bool kmMat4IsIdentity(const kmMat4* pIn)
+{
+ static const float identity [] = { 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f
+ };
+
+ return (memcmp(identity, pIn->m_Mat, sizeof(float) * 16) == 0);
+}
+
+/** Sets pOut to the transpose of pIn, returns pOut */
+kmMat4* kmMat4Transpose(kmMat4* pOut, const kmMat4* pIn)
+{
+ for (int z = 0; z < 4; ++z)
+ for (int x = 0; x < 4; ++x)
+ pOut->m_Mat[(z * 4) + x] = pIn->m_Mat[(x * 4) + z];
+
+ return pOut;
+}
+
+/* Multiplies pM1 with pM2, stores the result in pOut, returns pOut */
+kmMat4* kmMat4Multiply(kmMat4* pOut, const kmMat4* pM1, const kmMat4* pM2)
+{
+ float mat[16];
+
+ const float *m1 = pM1->m_Mat, *m2 = pM2->m_Mat;
+
+ mat[0] = m1[0] * m2[0] + m1[4] * m2[1] + m1[8] * m2[2] + m1[12] * m2[3];
+ mat[1] = m1[1] * m2[0] + m1[5] * m2[1] + m1[9] * m2[2] + m1[13] * m2[3];
+ mat[2] = m1[2] * m2[0] + m1[6] * m2[1] + m1[10] * m2[2] + m1[14] * m2[3];
+ mat[3] = m1[3] * m2[0] + m1[7] * m2[1] + m1[11] * m2[2] + m1[15] * m2[3];
+
+ mat[4] = m1[0] * m2[4] + m1[4] * m2[5] + m1[8] * m2[6] + m1[12] * m2[7];
+ mat[5] = m1[1] * m2[4] + m1[5] * m2[5] + m1[9] * m2[6] + m1[13] * m2[7];
+ mat[6] = m1[2] * m2[4] + m1[6] * m2[5] + m1[10] * m2[6] + m1[14] * m2[7];
+ mat[7] = m1[3] * m2[4] + m1[7] * m2[5] + m1[11] * m2[6] + m1[15] * m2[7];
+
+ mat[8] = m1[0] * m2[8] + m1[4] * m2[9] + m1[8] * m2[10] + m1[12] * m2[11];
+ mat[9] = m1[1] * m2[8] + m1[5] * m2[9] + m1[9] * m2[10] + m1[13] * m2[11];
+ mat[10] = m1[2] * m2[8] + m1[6] * m2[9] + m1[10] * m2[10] + m1[14] * m2[11];
+ mat[11] = m1[3] * m2[8] + m1[7] * m2[9] + m1[11] * m2[10] + m1[15] * m2[11];
+
+ mat[12] = m1[0] * m2[12] + m1[4] * m2[13] + m1[8] * m2[14] + m1[12] * m2[15];
+ mat[13] = m1[1] * m2[12] + m1[5] * m2[13] + m1[9] * m2[14] + m1[13] * m2[15];
+ mat[14] = m1[2] * m2[12] + m1[6] * m2[13] + m1[10] * m2[14] + m1[14] * m2[15];
+ mat[15] = m1[3] * m2[12] + m1[7] * m2[13] + m1[11] * m2[14] + m1[15] * m2[15];
+
+
+ memcpy(pOut->m_Mat, mat, sizeof(float)*16);
+
+ return pOut;
+}
+
+kmMat4* kmMat4MultiplyTranspose(kmMat4* pOut, const kmMat4* pM1, const kmMat4* pM2)
+{
+ assert(0);
+ return pOut;
+}
+
+/** Assigns the value of pIn to pOut */
+kmMat4* kmMat4Assign(kmMat4* pOut, const kmMat4* pIn)
+{
+ assert(pOut != pIn); //You have tried to self-assign!!
+
+ memcpy(pOut->m_Mat, pIn->m_Mat, sizeof(float)*16);
+
+ return pOut;
+}
+
+/** Returns true if the 2 matrices are equal (approximately) */
+bool kmMat4AreEqual(const kmMat4* pMat1, const kmMat4* pMat2)
+{
+ assert(pMat1 != pMat2); //You are comparing the same thing!
+
+ for (int i = 0; i < 16; ++i)
+ {
+ if (!(pMat1->m_Mat[i] + kmEpsilon > pMat2->m_Mat[i] &&
+ pMat1->m_Mat[i] - kmEpsilon < pMat2->m_Mat[i]))
+ return false;
+ }
+
+ return true;
+}
+
+/// Build a matrix from an axis and an angle. Result is stored in pOut. pOut is returned.
+kmMat4* kmMat4RotationAxis(kmMat4* pOut, const kmVec3* axis, kmScalar radians)
+{
+ float rcos = cosf(radians);
+ float rsin = sinf(radians);
+
+ pOut->m_Mat[0] = rcos + axis->x * axis->x * (1 - rcos);
+ pOut->m_Mat[1] = axis->z * rsin + axis->y * axis->x * (1 - rcos);
+ pOut->m_Mat[2] = -axis->y * rsin + axis->z * axis->x * (1 - rcos);
+ pOut->m_Mat[3] = 0.0f;
+
+ pOut->m_Mat[4] = -axis->z * rsin + axis->x * axis->y * (1 - rcos);
+ pOut->m_Mat[5] = rcos + axis->y * axis->y * (1 - rcos);
+ pOut->m_Mat[6] = axis->x * rsin + axis->z * axis->y * (1 - rcos);
+ pOut->m_Mat[7] = 0.0f;
+
+ pOut->m_Mat[8] = axis->y * rsin + axis->x * axis->z * (1 - rcos);
+ pOut->m_Mat[9] = -axis->x * rsin + axis->y * axis->z * (1 - rcos);
+ pOut->m_Mat[10] = rcos + axis->z * axis->z * (1 - rcos);
+ pOut->m_Mat[11] = 0.0f;
+
+ pOut->m_Mat[12] = 0.0f;
+ pOut->m_Mat[13] = 0.0f;
+ pOut->m_Mat[14] = 0.0f;
+ pOut->m_Mat[15] = 1.0f;
+
+ return pOut;
+}
+
+/// Builds an X-axis rotation matrix and stores it in pOut, returns pOut
+kmMat4* kmMat4RotationX(kmMat4* pOut, const float radians)
+{
+ /*
+ | 1 0 0 0 |
+ M = | 0 cos(A) -sin(A) 0 |
+ | 0 sin(A) cos(A) 0 |
+ | 0 0 0 1 |
+
+ */
+
+ pOut->m_Mat[0] = 1.0f;
+ pOut->m_Mat[1] = 0.0f;
+ pOut->m_Mat[2] = 0.0f;
+ pOut->m_Mat[3] = 0.0f;
+
+ pOut->m_Mat[4] = 0.0f;
+ pOut->m_Mat[5] = cosf(radians);
+ pOut->m_Mat[6] = sinf(radians);
+ pOut->m_Mat[7] = 0.0f;
+
+ pOut->m_Mat[8] = 0.0f;
+ pOut->m_Mat[9] = -sinf(radians);
+ pOut->m_Mat[10] = cosf(radians);
+ pOut->m_Mat[11] = 0.0f;
+
+ pOut->m_Mat[12] = 0.0f;
+ pOut->m_Mat[13] = 0.0f;
+ pOut->m_Mat[14] = 0.0f;
+ pOut->m_Mat[15] = 1.0f;
+
+ return pOut;
+}
+
+kmMat4* kmMat4RotationY(kmMat4* pOut, const float radians)
+{
+ /*
+ | cos(A) 0 sin(A) 0 |
+ M = | 0 1 0 0 |
+ | -sin(A) 0 cos(A) 0 |
+ | 0 0 0 1 |
+ */
+
+ pOut->m_Mat[0] = cosf(radians);
+ pOut->m_Mat[1] = 0.0f;
+ pOut->m_Mat[2] = -sinf(radians);
+ pOut->m_Mat[3] = 0.0f;
+
+ pOut->m_Mat[4] = 0.0f;
+ pOut->m_Mat[5] = 1.0f;
+ pOut->m_Mat[6] = 0.0f;
+ pOut->m_Mat[7] = 0.0f;
+
+ pOut->m_Mat[8] = sinf(radians);
+ pOut->m_Mat[9] = 0.0f;
+ pOut->m_Mat[10] = cosf(radians);
+ pOut->m_Mat[11] = 0.0f;
+
+ pOut->m_Mat[12] = 0.0f;
+ pOut->m_Mat[13] = 0.0f;
+ pOut->m_Mat[14] = 0.0f;
+ pOut->m_Mat[15] = 1.0f;
+
+ return pOut;
+}
+
+kmMat4* kmMat4RotationZ(kmMat4* pOut, const float radians)
+{
+ /*
+ | cos(A) -sin(A) 0 0 |
+ M = | sin(A) cos(A) 0 0 |
+ | 0 0 1 0 |
+ | 0 0 0 1 |
+ */
+
+ pOut->m_Mat[0] = cosf(radians);
+ pOut->m_Mat[1] = sinf(radians);
+ pOut->m_Mat[2] = 0.0f;
+ pOut->m_Mat[3] = 0.0f;
+
+ pOut->m_Mat[4] = -sinf(radians);;
+ pOut->m_Mat[5] = cosf(radians);
+ pOut->m_Mat[6] = 0.0f;
+ pOut->m_Mat[7] = 0.0f;
+
+ pOut->m_Mat[8] = 0.0f;
+ pOut->m_Mat[9] = 0.0f;
+ pOut->m_Mat[10] = 1.0f;
+ pOut->m_Mat[11] = 0.0f;
+
+ pOut->m_Mat[12] = 0.0f;
+ pOut->m_Mat[13] = 0.0f;
+ pOut->m_Mat[14] = 0.0f;
+ pOut->m_Mat[15] = 1.0f;
+
+ return pOut;
+}
+
+kmMat4* kmMat4RotationPitchYawRoll(kmMat4* pOut, const kmScalar pitch, const kmScalar yaw, const kmScalar roll)
+{
+ double cr = cos(pitch);
+ double sr = sin(pitch);
+ double cp = cos(yaw);
+ double sp = sin(yaw);
+ double cy = cos(roll);
+ double sy = sin(roll);
+
+ pOut->m_Mat[0] = (kmScalar) cp * cy;
+ pOut->m_Mat[4] = (kmScalar) cp * sy;
+ pOut->m_Mat[8] = (kmScalar) - sp;
+
+ double srsp = sr * sp;
+ double crsp = cr * sp;
+
+ pOut->m_Mat[1] = (kmScalar) srsp * cy - cr * sy;
+ pOut->m_Mat[5] = (kmScalar) srsp * sy + cr * cy;
+ pOut->m_Mat[9] = (kmScalar) sr * cp;
+
+ pOut->m_Mat[2] = (kmScalar) crsp * cy + sr * sy;
+ pOut->m_Mat[6] = (kmScalar) crsp * sy - sr * cy;
+ pOut->m_Mat[10] = (kmScalar) cr * cp;
+
+ pOut->m_Mat[3] = pOut->m_Mat[7] = pOut->m_Mat[11] = 0.0;
+ pOut->m_Mat[15] = 1.0;
+
+ return pOut;
+}
+
+/** Converts a quaternion to a rotation matrix, stored in pOut, returns pOut */
+kmMat4* kmMat4RotationQuaternion(kmMat4* pOut, const kmQuaternion* pQ)
+{
+ pOut->m_Mat[ 0] = 1.0f - 2.0f * (pQ->y * pQ->y + pQ->z * pQ->z );
+ pOut->m_Mat[ 4] = 2.0f * (pQ->x * pQ->y + pQ->z * pQ->w);
+ pOut->m_Mat[ 8] = 2.0f * (pQ->x * pQ->z - pQ->y * pQ->w);
+ pOut->m_Mat[12] = 0.0f;
+
+ // Second row
+ pOut->m_Mat[ 1] = 2.0f * ( pQ->x * pQ->y - pQ->z * pQ->w );
+ pOut->m_Mat[ 5] = 1.0f - 2.0f * ( pQ->x * pQ->x + pQ->z * pQ->z );
+ pOut->m_Mat[ 9] = 2.0f * (pQ->z * pQ->y + pQ->x * pQ->w );
+ pOut->m_Mat[13] = 0.0f;
+
+ // Third row
+ pOut->m_Mat[ 2] = 2.0f * ( pQ->x * pQ->z + pQ->y * pQ->w );
+ pOut->m_Mat[ 6] = 2.0f * ( pQ->y * pQ->z - pQ->x * pQ->w );
+ pOut->m_Mat[10] = 1.0f - 2.0f * ( pQ->x * pQ->x + pQ->y * pQ->y );
+ pOut->m_Mat[14] = 0.0f;
+
+ // Fourth row
+ pOut->m_Mat[ 3] = 0;
+ pOut->m_Mat[ 7] = 0;
+ pOut->m_Mat[11] = 0;
+ pOut->m_Mat[15] = 1.0f;
+
+ return pOut;
+}
+
+/** Builds a scaling matrix */
+kmMat4* kmMat4Scaling(kmMat4* pOut, const kmScalar x, const kmScalar y, const kmScalar z)
+{
+ memset(pOut->m_Mat, 0, sizeof(float) * 16);
+ pOut->m_Mat[0] = x;
+ pOut->m_Mat[5] = y;
+ pOut->m_Mat[10] = z;
+ pOut->m_Mat[15] = 1.0f;
+
+ return pOut;
+}
+
+kmMat4* kmMat4Translation(kmMat4* pOut, const kmScalar x, const kmScalar y, const kmScalar z)
+{
+ //FIXME: Write a test for this
+ //assert(0);
+ memset(pOut->m_Mat, 0, sizeof(float) * 16);
+
+ pOut->m_Mat[12] = x;
+ pOut->m_Mat[13] = y;
+ pOut->m_Mat[14] = z;
+
+ return pOut;
+}
+
+kmVec3* kmMat4GetUpVec3(kmVec3* pOut, const kmMat4* pIn)
+{
+ pOut->x = pIn->m_Mat[4];
+ pOut->y = pIn->m_Mat[5];
+ pOut->z = pIn->m_Mat[6];
+
+ kmVec3Normalize(pOut, pOut);
+
+ return pOut;
+}
+
+kmVec3* kmMat4GetRightVec3(kmVec3* pOut, const kmMat4* pIn)
+{
+ pOut->x = pIn->m_Mat[0];
+ pOut->y = pIn->m_Mat[1];
+ pOut->z = pIn->m_Mat[2];
+
+ kmVec3Normalize(pOut, pOut);
+
+ return pOut;
+}
+
+kmVec3* kmMat4GetForwardVec3(kmVec3* pOut, const kmMat4* pIn)
+{
+ pOut->x = pIn->m_Mat[8];
+ pOut->y = pIn->m_Mat[9];
+ pOut->z = pIn->m_Mat[10];
+
+ kmVec3Normalize(pOut, pOut);
+
+ return pOut;
+}
+
View
63 src/mat4.h
@@ -0,0 +1,63 @@
+/*
+Copyright 2007 Luke Benstead
+
+This file is part of KazMath.
+
+KazMath is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser Public License as published by
+the Free Software Foundation; either version 3 of the License, or
+(at your option) any later version.
+
+KazMath is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser Public License for more details.
+
+You should have received a copy of the GNU Lesser Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef MAT4_H_INCLUDED
+#define MAT4_H_INCLUDED
+
+#include "utility.h"
+
+struct kmVec3;
+struct kmQuaternion;
+
+typedef struct kmMat4{
+ kmScalar m_Mat[16];
+} kmMat4;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+kmMat4* kmMat4Identity(kmMat4* pOut);
+kmMat4* kmMat4Inverse(kmMat4* pOut, const kmMat4* pM);
+bool kmMat4IsIdentity(const kmMat4* pIn);
+kmMat4* kmMat4Transpose(kmMat4* pOut, const kmMat4* pIn);
+kmMat4* kmMat4Multiply(kmMat4* pOut, const kmMat4* pM1, const kmMat4* pM2);
+kmMat4* kmMat4MultiplyTranspose(kmMat4* pOut, const kmMat4* pM1, const kmMat4* pM2);
+
+kmMat4* kmMat4Assign(kmMat4* pOut, const kmMat4* pIn);
+bool kmMat4AreEqual(const kmMat4* pM1, const kmMat4* pM2);
+
+kmMat4* kmMat4RotationAxis(kmMat4* pOut, const struct kmVec3* axis, kmScalar radians);
+kmMat4* kmMat4RotationX(kmMat4* pOut, const float radians);
+kmMat4* kmMat4RotationY(kmMat4* pOut, const float radians);
+kmMat4* kmMat4RotationZ(kmMat4* pOut, const float radians);
+kmMat4* kmMat4RotationPitchYawRoll(kmMat4* pOut, const kmScalar pitch, const kmScalar yaw, const kmScalar roll);
+kmMat4* kmMat4RotationQuaternion(kmMat4* pOut, const struct kmQuaternion* pQ);
+kmMat4* kmMat4Scaling(kmMat4* pOut, const kmScalar x, const kmScalar y, const kmScalar z);
+kmMat4* kmMat4Translation(kmMat4* pOut, const kmScalar x, const kmScalar y, const kmScalar z);
+
+struct kmVec3* kmMat4GetUpVec3(struct kmVec3* pOut, const kmMat4* pIn);
+struct kmVec3* kmMat4GetRightVec3(struct kmVec3* pOut, const kmMat4* pIn);
+struct kmVec3* kmMat4GetForwardVec3(struct kmVec3* pOut, const kmMat4* pIn);
+
+#ifdef __cplusplus
+}
+#endif
+#endif // MAT4_H_INCLUDED
View
156 src/plane.c
@@ -0,0 +1,156 @@
+/*
+Copyright 2007 Luke Benstead
+
+This file is part of KazMath.
+
+KazMath is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser Public License as published by
+the Free Software Foundation; either version 3 of the License, or
+(at your option) any later version.
+
+KazMath is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser Public License for more details.
+
+You should have received a copy of the GNU Lesser Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include <assert.h>
+
+#include "vec3.h"
+#include "vec4.h"
+#include "plane.h"
+
+kmScalar kmPlaneDot(const kmPlane* pP, const kmVec4* pV)
+{
+ //a*x + b*y + c*z + d*w
+
+ return (pP->a * pV->x +
+ pP->b * pV->y +
+ pP->c * pV->z +
+ pP->d * pV->w);
+}
+
+kmScalar kmPlaneDotCoord(const kmPlane* pP, const kmVec3* pV)
+{
+ return (pP->a * pV->x +
+ pP->b * pV->y +
+ pP->c * pV->z + pP->d);
+}
+
+kmScalar kmPlaneDotNormal(const kmPlane* pP, const kmVec3* pV)
+{
+ return (pP->a * pV->x +
+ pP->b * pV->y +
+ pP->c * pV->z);
+}
+
+kmPlane* kmPlaneFromPointNormal(kmPlane* pOut, const kmVec3* pPoint, const kmVec3* pNormal)
+{
+ /*
+ Planea = Nx
+ Planeb = Ny
+ Planec = Nz
+ Planed = −N⋅P
+ */
+
+
+ pOut->a = pNormal->x;
+ pOut->b = pNormal->y;
+ pOut->c = pNormal->z;
+ pOut->d = -kmVec3Dot(pNormal, pPoint);
+
+ return pOut;
+}
+
+kmPlane* kmPlaneFromPoints(kmPlane* pOut, const kmVec3* p1, const kmVec3* p2, const kmVec3* p3)
+{
+ /*
+ v = (B − A) × (C − A)
+ n = 1⁄|v| v
+ Outa = nx
+ Outb = ny
+ Outc = nz
+ Outd = −n⋅A
+ */
+
+ kmVec3 n, v1, v2;
+ kmVec3Subtract(&v1, p2, p1); //Create the vectors for the 2 sides of the triangle
+ kmVec3Subtract(&v2, p3, p1);
+ kmVec3Cross(&n, &v1, &v2); //Use the cross product to get the normal
+
+ kmVec3Normalize(&n, &n); //Normalize it and assign to pOut->m_N
+
+ pOut->a = n.x;
+ pOut->b = n.y;
+ pOut->c = n.z;
+ pOut->d = kmVec3Dot(kmVec3Scale(&n, &n, -1.0), p1);
+
+ return pOut;
+}
+
+kmVec3* kmPlaneIntersectLine(kmVec3* pOut, const kmPlane* pP, const kmVec3* pV1, const kmVec3* pV2)
+{
+ /*
+ n = (Planea, Planeb, Planec)
+ d = V − U
+ Out = U − d⋅(Pd + n⋅U)⁄(d⋅n) [iff d⋅n ≠ 0]
+ */
+
+ assert(0);
+
+ kmVec3 d;
+ kmVec3Subtract(&d, pV2, pV1); //Get the direction vector
+
+
+ //TODO: Continue here!
+ /*if (fabs(kmVec3Dot(&pP->m_N, &d)) > kmEpsilon)
+ {
+ //If we get here then the plane and line are parallel (i.e. no intersection)
+ pOut = nullptr; //Set to nullptr
+
+ return pOut;
+ } */
+}
+
+kmPlane* kmPlaneNormalize(kmPlane* pOut, const kmPlane* pP)
+{
+ kmVec3 n;
+ n.x = pP->a;
+ n.y = pP->b;
+ n.z = pP->c;
+
+ kmScalar l = 1.0 / kmVec3Length(&n); //Get 1/length
+ kmVec3Normalize(&n, &n); //Normalize the vector and assign to pOut
+
+ pOut->a = n.x;
+ pOut->b = n.y;
+ pOut->c = n.z;
+
+ pOut->d = pP->d * l; //Scale the D value and assign to pOut
+
+ return pOut;
+}
+
+kmPlane* kmPlaneScale(kmPlane* pOut, const kmPlane* pP, kmScalar s)
+{
+ assert(0);
+}
+
+POINT_CLASSIFICATION kmPlaneClassifyPoint(const kmPlane* pIn, const kmVec3* pP)
+{
+ // This function will determine if a point is on, in front of, or behind
+ // the plane. First we store the dot product of the plane and the point.
+ float distance = pIn->a * pP->x + pIn->b * pP->y + pIn->c * pP->z + pIn->d;
+
+ // Simply put if the dot product is greater than 0 then it is infront of it.
+ // If it is less than 0 then it is behind it. And if it is 0 then it is on it.
+ if(distance > 0.001) return POINT_INFRONT_OF_PLANE;
+ if(distance < -0.001) return POINT_BEHIND_PLANE;
+
+ return POINT_ON_PLANE;
+}
+
View
56 src/plane.h
@@ -0,0 +1,56 @@
+/*
+Copyright 2007 Luke Benstead
+
+This file is part of KazMath.
+
+KazMath is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser Public License as published by
+the Free Software Foundation; either version 3 of the License, or
+(at your option) any later version.
+
+KazMath is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser Public License for more details.
+
+You should have received a copy of the GNU Lesser Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PLANE_H_INCLUDED
+#define PLANE_H_INCLUDED
+
+#include "utility.h"
+
+struct kmVec3;
+
+typedef struct kmPlane {
+ kmScalar a, b, c, d;
+} kmPlane;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum POINT_CLASSIFICATION {
+ POINT_INFRONT_OF_PLANE = 0,
+ POINT_BEHIND_PLANE,
+ POINT_ON_PLANE,
+} POINT_CLASSIFICATION;
+
+kmScalar kmPlaneDot(const kmPlane* pP, const struct kmVec4* pV);
+kmScalar kmPlaneDotCoord(const kmPlane* pP, const struct kmVec3* pV);
+kmScalar kmPlaneDotNormal(const kmPlane* pP, const struct kmVec3* pV);
+kmPlane* kmPlaneFromPointNormal(kmPlane* pOut, const struct kmVec3* pPoint, const struct kmVec3* pNormal);
+kmPlane* kmPlaneFromPoints(kmPlane* pOut, const struct kmVec3* p1, const struct kmVec3* p2, const struct kmVec3* p3);
+kmVec3* kmPlaneIntersectLine(struct kmVec3* pOut, const kmPlane* pP, const struct kmVec3* pV1, const struct kmVec3* pV2);
+kmPlane* kmPlaneNormalize(kmPlane* pOut, const kmPlane* pP);
+kmPlane* kmPlaneScale(kmPlane* pOut, const kmPlane* pP, kmScalar s);
+POINT_CLASSIFICATION kmPlaneClassifyPoint(const kmPlane* pIn, const kmVec3* pP); /** Classifys a point against a plane */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // PLANE_H_INCLUDED
View
468 src/quaternion.c
@@ -0,0 +1,468 @@
+/*
+Copyright 2007 Luke Benstead
+
+This file is part of KazMath.
+
+KazMath is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser Public License as published by
+the Free Software Foundation; either version 3 of the License, or
+(at your option) any later version.
+
+KazMath is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser Public License for more details.
+
+You should have received a copy of the GNU Lesser Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include <assert.h>
+#include <memory.h>
+
+#include "utility.h"
+#include "mat4.h"
+#include "vec3.h"
+#include "quaternion.h"
+
+///< Returns pOut, sets pOut to the conjugate of pIn
+kmQuaternion* kmQuaternionConjugate(kmQuaternion* pOut, const kmQuaternion* pIn)
+{
+ pOut->x = -pIn->x;
+ pOut->y = -pIn->y;
+ pOut->z = -pIn->z;
+ pOut->w = pIn->w;
+
+ return pOut;
+}
+
+///< Returns the dot product of the 2 quaternions
+kmScalar kmQuaternionDot(const kmQuaternion* q1, const kmQuaternion* q2)
+{
+ // A dot B = B dot A = AtBt + AxBx + AyBy + AzBz
+
+ return (q1->w * q2->w +
+ q1->x * q2->x +
+ q1->y * q2->y +
+ q1->z * q2->z);
+}
+
+///< Returns the exponential of the quaternion
+kmQuaternion* kmQuaternionExp(kmQuaternion* pOut, const kmQuaternion* pIn)
+{
+ assert(0);
+
+ return pOut;
+}
+
+///< Makes the passed quaternion an identity quaternion
+kmQuaternion* kmQuaternionIdentity(kmQuaternion* pOut)
+{
+ pOut->x = 0.0;
+ pOut->y = 0.0;
+ pOut->z = 0.0;
+ pOut->w = 1.0;
+
+ return pOut;
+}
+
+///< Returns the inverse of the passed Quaternion
+kmQuaternion* kmQuaternionInverse(kmQuaternion* pOut,
+ const kmQuaternion* pIn)
+{
+ kmScalar l = kmQuaternionLength(pIn);
+
+ if (fabs(l) > kmEpsilon)
+ {
+ pOut->x = 0.0;
+ pOut->y = 0.0;
+ pOut->z = 0.0;
+ pOut->w = 0.0;
+
+ return pOut;
+ }
+
+ kmQuaternion* tmp = 0;
+
+ ///Get the conjugute and divide by the length
+ kmQuaternionScale(pOut,
+ kmQuaternionConjugate(tmp, pIn), 1.0 / l);
+
+ return pOut;
+}
+
+///< Returns true if the quaternion is an identity quaternion
+bool kmQuaternionIsIdentity(const kmQuaternion* pIn)
+{
+ return (pIn->x == 0.0 && pIn->y == 0.0 && pIn->z == 0.0 &&
+ pIn->w == 1.0);
+}
+
+///< Returns the length of the quaternion
+kmScalar kmQuaternionLength(const kmQuaternion* pIn)
+{
+ return sqrtf(kmQuaternionLengthSq(pIn));
+}
+
+///< Returns the length of the quaternion squared (prevents a sqrt)
+kmScalar kmQuaternionLengthSq(const kmQuaternion* pIn)
+{
+ return pIn->x * pIn->x + pIn->y * pIn->y +
+ pIn->z * pIn->z + pIn->w * pIn->w;
+}
+
+///< Returns the natural logarithm
+kmQuaternion* kmQuaternionLn(kmQuaternion* pOut,
+ const kmQuaternion* pIn)
+{
+ /*
+ A unit quaternion, is defined by:
+ Q == (cos(theta), sin(theta) * v) where |v| = 1
+ The natural logarithm of Q is, ln(Q) = (0, theta * v)
+ */
+
+ assert(0);
+
+ return pOut;
+}
+
+///< Multiplies 2 quaternions together
+extern
+kmQuaternion* kmQuaternionMultiply(kmQuaternion* pOut,
+ const kmQuaternion* q1,
+ const kmQuaternion* q2)
+{
+ pOut->w = q1->w * q2->w - q1->x * q2->x - q1->y * q2->y - q1->z * q2->z;
+ pOut->x = q1->w * q2->x + q1->x * q2->w + q1->y * q2->z - q1->z * q2->y;
+ pOut->y = q1->w * q2->y + q1->y * q2->w + q1->z * q2->x - q1->x * q2->z;
+ pOut->z = q1->w * q2->z + q1->z * q2->w + q1->x * q2->y - q1->y * q2->x;
+
+ return pOut;
+}
+
+///< Normalizes a quaternion
+kmQuaternion* kmQuaternionNormalize(kmQuaternion* pOut,
+ const kmQuaternion* pIn)
+{
+ kmScalar length = kmQuaternionLength(pIn);
+ assert(fabs(length) > kmEpsilon);
+ kmQuaternionScale(pOut, pIn, 1.0f / length);
+
+ return pOut;
+}
+
+///< Rotates a quaternion around an axis
+kmQuaternion* kmQuaternionRotationAxis(kmQuaternion* pOut,
+ const kmVec3* pV,
+ kmScalar angle)
+{
+ kmScalar rad = angle * 0.5f;
+ kmScalar scale = sinf(rad);
+
+ pOut->w = cosf(rad);
+ pOut->x = pV->x * scale;
+ pOut->y = pV->y * scale;
+ pOut->z = pV->z * scale;
+
+ return pOut;
+}
+
+///< Creates a quaternion from a rotation matrix
+kmQuaternion* kmQuaternionRotationMatrix(kmQuaternion* pOut,
+ const kmMat4* pIn)
+{
+/*
+Note: The OpenGL matrices are transposed from the description below
+taken from the Matrix and Quaternion FAQ
+
+ if ( mat[0] > mat[5] && mat[0] > mat[10] ) { // Column 0:
+ S = sqrt( 1.0 + mat[0] - mat[5] - mat[10] ) * 2;
+ X = 0.25 * S;
+ Y = (mat[4] + mat[1] ) / S;
+ Z = (mat[2] + mat[8] ) / S;
+ W = (mat[9] - mat[6] ) / S;
+ } else if ( mat[5] > mat[10] ) { // Column 1:
+ S = sqrt( 1.0 + mat[5] - mat[0] - mat[10] ) * 2;
+ X = (mat[4] + mat[1] ) / S;
+ Y = 0.25 * S;
+ Z = (mat[9] + mat[6] ) / S;
+ W = (mat[2] - mat[8] ) / S;
+ } else { // Column 2:
+ S = sqrt( 1.0 + mat[10] - mat[0] - mat[5] ) * 2;
+ X = (mat[2] + mat[8] ) / S;
+ Y = (mat[9] + mat[6] ) / S;
+ Z = 0.25 * S;
+ W = (mat[4] - mat[1] ) / S;
+ }
+*/
+
+ kmScalar T = pIn->m_Mat[0] + pIn->m_Mat[5] + pIn->m_Mat[10];
+
+ if (T > kmEpsilon) {
+ //If the trace is greater than zero we always use this calculation:
+ /* S = sqrt(T) * 2;
+ X = ( mat[9] - mat[6] ) / S;
+ Y = ( mat[2] - mat[8] ) / S;
+ Z = ( mat[4] - mat[1] ) / S;
+ W = 0.25 * S;*/
+
+ kmScalar s = sqrtf(T) * 2;
+ pOut->x = (pIn->m_Mat[9] - pIn->m_Mat[6]) / s;
+ pOut->y = (pIn->m_Mat[8] - pIn->m_Mat[2]) / s;
+ pOut->z = (pIn->m_Mat[1] - pIn->m_Mat[4]) / s;
+ pOut->w = 0.25 * s;
+
+ kmQuaternionNormalize(pOut, pOut);
+ return pOut;
+ }
+
+ //Otherwise the calculation depends on which major diagonal element has the greatest value.
+
+ if (pIn->m_Mat[0] > pIn->m_Mat[5] && pIn->m_Mat[0] > pIn->m_Mat[10]) {
+ kmScalar s = sqrtf(1 + pIn->m_Mat[0] - pIn->m_Mat[5] - pIn->m_Mat[10]) * 2;
+ pOut->x = 0.25 * s;
+ pOut->y = (pIn->m_Mat[1] + pIn->m_Mat[4]) / s;
+ pOut->z = (pIn->m_Mat[8] + pIn->m_Mat[2]) / s;
+ pOut->w = (pIn->m_Mat[9] - pIn->m_Mat[6]) / s;
+ }
+ else if (pIn->m_Mat[5] > pIn->m_Mat[10]) {
+ kmScalar s = sqrtf(1 + pIn->m_Mat[5] - pIn->m_Mat[0] - pIn->m_Mat[10]) * 2;
+ pOut->x = (pIn->m_Mat[1] + pIn->m_Mat[4]) / s;
+ pOut->y = 0.25 * s;
+ pOut->z = (pIn->m_Mat[9] + pIn->m_Mat[6]) / s;
+ pOut->w = (pIn->m_Mat[8] - pIn->m_Mat[2]) / s;
+ }
+ else {
+ kmScalar s = sqrt(1 + pIn->m_Mat[10] - pIn->m_Mat[0] - pIn->m_Mat[5]) * 2;
+ pOut->x = (pIn->m_Mat[8] + pIn->m_Mat[2] ) / s;
+ pOut->y = (pIn->m_Mat[6] + pIn->m_Mat[9] ) / s;
+ pOut->z = 0.25 * s;
+ pOut->w = (pIn->m_Mat[1] - pIn->m_Mat[4] ) / s;
+ }
+
+ kmQuaternionNormalize(pOut, pOut);
+ return pOut;
+}
+
+///< Create a quaternion from yaw, pitch and roll
+kmQuaternion* kmQuaternionRotationYawPitchRoll(kmQuaternion* pOut,
+ kmScalar yaw,
+ kmScalar pitch,
+ kmScalar roll)
+{
+ kmScalar ex, ey, ez; // temp half euler angles
+ kmScalar cr, cp, cy, sr, sp, sy, cpcy, spsy; // temp vars in roll,pitch yaw
+
+ ex = kmDegreesToRadians(pitch) / 2.0; // convert to rads and half them
+ ey = kmDegreesToRadians(yaw) / 2.0;
+ ez = kmDegreesToRadians(roll) / 2.0;
+
+ cr = cosf(ex);
+ cp = cosf(ey);
+ cy = cosf(ez);
+
+ sr = sinf(ex);
+ sp = sinf(ey);
+ sy = sinf(ez);
+
+ cpcy = cp * cy;
+ spsy = sp * sy;
+
+ pOut->w = cr * cpcy + sr * spsy;
+
+ pOut->x = sr * cpcy - cr * spsy;
+ pOut->y = cr * sp * cy + sr * cp * sy;
+ pOut->z = cr * cp * sy - sr * sp * cy;
+
+ kmQuaternionNormalize(pOut, pOut);
+
+ return pOut;
+}
+
+///< Interpolate between 2 quaternions
+kmQuaternion* kmQuaternionSlerp(kmQuaternion* pOut,
+ const kmQuaternion* q1,
+ const kmQuaternion* q2,
+ kmScalar t)
+{
+
+ /*float CosTheta = Q0.DotProd(Q1);
+ float Theta = acosf(CosTheta);
+ float SinTheta = sqrtf(1.0f-CosTheta*CosTheta);
+
+ float Sin_T_Theta = sinf(T*Theta)/SinTheta;
+ float Sin_OneMinusT_Theta = sinf((1.0f-T)*Theta)/SinTheta;
+
+ Quaternion Result = Q0*Sin_OneMinusT_Theta;
+ Result += (Q1*Sin_T_Theta);
+
+ return Result;*/
+
+ kmScalar ct = kmQuaternionDot(q1, q2);
+ kmScalar theta = acosf(ct);
+ kmScalar st = sqrtf(1.0 - kmSQR(ct));
+
+ kmScalar stt = sinf(t * theta) / st;
+ kmScalar somt = sinf((1.0 - t) * theta) / st;
+
+ kmQuaternion temp, temp2;
+ kmQuaternionScale(&temp, q1, somt);
+ kmQuaternionScale(&temp2, q2, stt);
+ kmQuaternionAdd(pOut, &temp, &temp2);
+
+ return pOut;
+}
+
+///< Get the axis and angle of rotation from a quaternion
+void kmQuaternionToAxisAngle(const kmQuaternion* pIn,
+ kmVec3* pAxis,
+ kmScalar* pAngle)
+{
+ kmScalar tempAngle; // temp angle
+ kmScalar scale; // temp vars
+
+ tempAngle = acosf(pIn->w);
+ scale = sqrtf(kmSQR(pIn->x) + kmSQR(pIn->y) + kmSQR(pIn->z));
+
+ if (((scale > -kmEpsilon) && scale < kmEpsilon)
+ || (scale < 360.0f + kmEpsilon && scale > 360.0f - kmEpsilon)) // angle is 0 or 360 so just simply set axis to 0,0,1 with angle 0
+ {
+ *pAngle = 0.0f;
+
+ pAxis->x = 0.0f;
+ pAxis->y = 0.0f;
+ pAxis->z = 1.0f;
+ }
+ else
+ {
+ *pAngle = tempAngle * 2.0; // angle in radians
+
+ pAxis->x = pIn->x / scale;
+ pAxis->y = pIn->y / scale;
+ pAxis->z = pIn->z / scale;
+ kmVec3Normalize(pAxis, pAxis);
+ }
+}
+
+kmQuaternion* kmQuaternionScale(kmQuaternion* pOut,
+ const kmQuaternion* pIn,
+ kmScalar s)
+{
+ pOut->x = pIn->x * s;
+ pOut->y = pIn->y * s;
+ pOut->z = pIn->z * s;
+ pOut->w = pIn->w * s;
+
+ return pOut;
+}
+
+kmQuaternion* kmQuaternionAssign(kmQuaternion* pOut, const kmQuaternion* pIn)
+{
+ memcpy(pOut, pIn, sizeof(float) * 4);
+
+ return pOut;
+}
+
+kmQuaternion* kmQuaternionAdd(kmQuaternion* pOut, const kmQuaternion* pQ1, const kmQuaternion* pQ2)
+{
+ pOut->x = pQ1->x + pQ2->x;
+ pOut->y = pQ1->y + pQ2->y;
+ pOut->z = pQ1->z + pQ2->z;
+ pOut->w = pQ1->w + pQ2->w;
+
+ return pOut;
+}
+
+/** Adapted from the OGRE engine!
+
+ Gets the shortest arc quaternion to rotate this vector to the destination
+ vector.
+@remarks
+ If you call this with a dest vector that is close to the inverse
+ of this vector, we will rotate 180 degrees around the 'fallbackAxis'
+ (if specified, or a generated axis if not) since in this case
+ ANY axis of rotation is valid.
+*/
+
+kmQuaternion* kmQuaternionRotationBetweenVec3(kmQuaternion* pOut, const kmVec3* vec1, const kmVec3* vec2, const kmVec3* fallback) {
+
+ kmVec3 v1, v2;
+ kmVec3Assign(&v1, vec1);
+ kmVec3Assign(&v2, vec2);
+
+ kmVec3Normalize(&v1, &v1);
+ kmVec3Normalize(&v2, &v2);
+
+ kmScalar a = kmVec3Dot(&v1, &v2);
+
+ if (a >= 1.0) {
+ kmQuaternionIdentity(pOut);
+ return pOut;
+ }
+
+ if (a < (1e-6f - 1.0f)) {
+ if (fabs(kmVec3LengthSq(fallback)) < kmEpsilon) {
+ kmQuaternionRotationAxis(pOut, fallback, kmPI);
+ } else {
+ kmVec3 axis;
+ kmVec3 X;
+ X.x = 1.0;
+ X.y = 0.0;
+ X.z = 0.0;
+
+
+ kmVec3Cross(&axis, &X, vec1);
+
+ //If axis is zero
+ if (fabs(kmVec3LengthSq(&axis)) < kmEpsilon) {
+ kmVec3 Y;
+ Y.x = 0.0;
+ Y.y = 1.0;
+ Y.z = 0.0;
+
+ kmVec3Cross(&axis, &Y, vec1);
+ }
+
+ kmVec3Normalize(&axis, &axis);
+
+ kmQuaternionRotationAxis(pOut, &axis, kmPI);
+ }
+ } else {
+ kmScalar s = sqrtf((1+a) * 2);
+ kmScalar invs = 1 / s;
+
+ kmVec3 c;
+ kmVec3Cross(&c, &v1, &v2);
+
+ pOut->x = c.x * invs;
+ pOut->y = c.y * invs;
+ pOut->z = c.z * invs;
+ pOut->w = s * 0.5;
+
+ kmQuaternionNormalize(pOut, pOut);
+ }
+
+ return pOut;
+
+}
+
+kmVec3* kmQuaternionMultiplyVec3(kmVec3* pOut, const kmQuaternion* q, const kmVec3* v) {
+ kmVec3 uv, uuv, qvec;
+
+ qvec.x = q->x;
+ qvec.y = q->y;
+ qvec.z = q->z;
+
+ kmVec3Cross(&uv, &qvec, v);
+ kmVec3Cross(&uuv, &qvec, &uv);
+
+ kmVec3Scale(&uv, &uv, (2.0 * q->w));
+ kmVec3Scale(&uuv, &uuv, 2.0);
+
+ kmVec3Add(pOut, v, &uv);
+ kmVec3Add(pOut, pOut, &uuv);
+
+ return pOut;
+}
+
View
137 src/quaternion.h
@@ -0,0 +1,137 @@
+/*
+Copyright 2007 Luke Benstead
+
+This file is part of KazMath.
+
+KazMath is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser Public License as published by
+the Free Software Foundation; either version 3 of the License, or
+(at your option) any later version.
+
+KazMath is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser Public License for more details.
+
+You should have received a copy of the GNU Lesser Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef QUATERNION_H_INCLUDED
+#define QUATERNION_H_INCLUDED
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#include "utility.h"
+#include "mat4.h"
+
+struct kmVec3;
+struct kmMat4;
+
+typedef struct kmQuaternion {
+ kmScalar x;
+ kmScalar y;
+ kmScalar z;
+ kmScalar w;
+} kmQuaternion;
+
+kmQuaternion* kmQuaternionConjugate(kmQuaternion* pOut,
+ const kmQuaternion* pIn); ///< Returns pOut, sets pOut to the conjugate of pIn
+
+
+
+kmScalar kmQuaternionDot(const kmQuaternion* q1,
+ const kmQuaternion* q2); ///< Returns the dot product of the 2 quaternions
+
+
+
+kmQuaternion* kmQuaternionExp(kmQuaternion* pOut, const kmQuaternion* pIn); ///< Returns the exponential of the quaternion
+
+///< Makes the passed quaternion an identity quaternion
+
+kmQuaternion* kmQuaternionIdentity(kmQuaternion* pOut);
+
+///< Returns the inverse of the passed Quaternion
+
+kmQuaternion* kmQuaternionInverse(kmQuaternion* pOut,
+ const kmQuaternion* pIn);
+
+///< Returns true if the quaternion is an identity quaternion
+
+bool kmQuaternionIsIdentity(const kmQuaternion* pIn);
+
+///< Returns the length of the quaternion
+
+kmScalar kmQuaternionLength(const kmQuaternion* pIn);
+
+///< Returns the length of the quaternion squared (prevents a sqrt)
+
+kmScalar kmQuaternionLengthSq(const kmQuaternion* pIn);
+
+///< Returns the natural logarithm
+
+kmQuaternion* kmQuaternionLn(kmQuaternion* pOut, const kmQuaternion* pIn);
+
+///< Multiplies 2 quaternions together
+
+kmQuaternion* kmQuaternionMultiply(kmQuaternion* pOut,
+ const kmQuaternion* q1,
+ const kmQuaternion* q2);
+
+///< Normalizes a quaternion
+
+kmQuaternion* kmQuaternionNormalize(kmQuaternion* pOut,
+ const kmQuaternion* pIn);
+
+///< Rotates a quaternion around an axis
+
+kmQuaternion* kmQuaternionRotationAxis(kmQuaternion* pOut,
+ const kmVec3* pV,
+ kmScalar angle);
+
+///< Creates a quaternion from a rotation matrix
+
+kmQuaternion* kmQuaternionRotationMatrix(kmQuaternion* pOut,
+ const kmMat4* pIn);
+
+///< Create a quaternion from yaw, pitch and roll
+
+kmQuaternion* kmQuaternionRotationYawPitchRoll(kmQuaternion* pOut,
+ kmScalar yaw,
+ kmScalar pitch,
+ kmScalar roll);
+///< Interpolate between 2 quaternions
+
+kmQuaternion* kmQuaternionSlerp(kmQuaternion* pOut,
+ const kmQuaternion* q1,
+ const kmQuaternion* q2,
+ kmScalar t);
+
+///< Get the axis and angle of rotation from a quaternion
+
+void kmQuaternionToAxisAngle(const kmQuaternion* pIn,
+ kmVec3* pVector,
+ kmScalar* pAngle);
+
+///< Scale a quaternion
+
+kmQuaternion* kmQuaternionScale(kmQuaternion* pOut,
+ const kmQuaternion* pIn,
+ kmScalar s);
+
+
+kmQuaternion* kmQuaternionAssign(kmQuaternion* pOut, const kmQuaternion* pIn);
+kmQuaternion* kmQuaternionAdd(kmQuaternion* pOut, const kmQuaternion* pQ1, const kmQuaternion* pQ2);
+
+kmQuaternion* kmQuaternionRotationBetweenVec3(kmQuaternion* pOut, const kmVec3* vec1, const kmVec3* vec2, const kmVec3* fallback);
+kmVec3* kmQuaternionMultiplyVec3(kmVec3* pOut, const kmQuaternion* q, const kmVec3* v);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
View
14 src/utility.c
@@ -0,0 +1,14 @@
+#include "utility.h"
+
+kmScalar kmSQR(kmScalar s) {
+ return s*s;
+}
+
+kmScalar kmDegreesToRadians(kmScalar degrees) {
+ return degrees * kmPIOver180;
+}
+
+kmScalar kmRadiansToDegrees(kmScalar radians) {
+ return radians * kmPIUnder180;
+}
+
View
50 src/utility.h
@@ -0,0 +1,50 @@
+/*
+Copyright 2007 Luke Benstead
+
+This file is part of KazMath.
+
+KazMath is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser Public License as published by
+the Free Software Foundation; either version 3 of the License, or
+(at your option) any later version.
+
+KazMath is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser Public License for more details.
+
+You should have received a copy of the GNU Lesser Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef UTILITY_H_INCLUDED
+#define UTILITY_H_INCLUDED
+
+#include <math.h>
+#include <stdbool.h>
+
+#define nullptr 0L
+
+#ifndef kmScalar
+#define kmScalar float
+#endif
+
+#define kmPI 3.141592
+#define kmPIOver180 0.017453 // PI / 180
+#define kmPIUnder180 57.295779 // 180 / PI
+#define kmEpsilon 1.0 / 64.0
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern kmScalar kmSQR(kmScalar s);
+extern kmScalar kmDegreesToRadians(kmScalar degrees);
+extern kmScalar kmRadiansToDegrees(kmScalar radians);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* UTILITY_H_INCLUDED */
View
70 src/vec2.c
@@ -0,0 +1,70 @@
+
+#include <assert.h>
+
+#include "mat4.h"
+#include "vec2.h"
+#include "utility.h"
+
+kmScalar kmVec2Length(const kmVec2* pIn)
+{
+ return sqrtf(kmSQR(pIn->x) + kmSQR(pIn->y));
+}
+
+kmScalar kmVec2LengthSq(const kmVec2* pIn)
+{
+ return kmSQR(pIn->x) + kmSQR(pIn->y);
+}
+
+kmVec2* kmVec2Normalize(kmVec2* pOut, const kmVec2* pIn)
+{
+ kmScalar l = 1.0 / kmVec2Length(pIn);
+
+ pOut->x *= l;
+ pOut->y *= l;
+
+ return pOut;
+}
+
+kmVec2* kmVec2Add(kmVec2* pOut, const kmVec2* pV1, const kmVec2* pV2)
+{
+ pOut->x = pV1->x + pV2->x;
+ pOut->y = pV1->y + pV2->y;
+
+ return pOut;
+}
+
+kmScalar kmVec2Dot(const kmVec2* pV1, const kmVec2* pV2)
+{
+ return pV1->x * pV2->x + pV1->y * pV2->y;
+}
+
+kmVec2* kmVec2Subtract(kmVec2* pOut, const kmVec2* pV1, const kmVec2* pV2)
+{
+ pOut->x = pV1->x - pV2->x;
+ pOut->y = pV1->y - pV2->y;
+
+ return pOut;
+}
+
+kmVec2* kmVec2Transform(kmVec2* pOut, const kmVec2* pV1, const kmMat4* pM)
+{
+ assert(0);
+}
+
+kmVec2* kmVec2TransformCoord(kmVec2* pOut, const kmVec2* pV, const kmMat4* pM)
+{
+ assert(0);
+}
+
+kmVec2* kmVec2Scale(kmVec2* pOut, const kmVec2* pIn, const kmScalar s)
+{
+ assert(0);
+}
+
+bool kmVec2AreEqual(const kmVec2* p1, const kmVec2* p2)
+{
+ return (
+ (p1->x < p2->x + kmEpsilon && p1->x > p2->x - kmEpsilon) &&
+ (p1->y < p2->y + kmEpsilon && p1->y > p2->y - kmEpsilon)
+ );
+}
View
38 src/vec2.h
@@ -0,0 +1,38 @@
+#ifndef VEC2_H_INCLUDED
+#define VEC2_H_INCLUDED
+
+struct kmMat4;
+
+#ifndef kmScalar
+#define kmScalar float
+#endif
+
+#pragma pack(push) /* push current alignment to stack */
+#pragma pack(1) /* set alignment to 1 byte boundary */
+typedef struct kmVec2 {
+ kmScalar x;
+ kmScalar y;
+} kmVec2;
+
+#pragma pack(pop)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+kmScalar kmVec2Length(const kmVec2* pIn); ///< Returns the length of the vector
+kmScalar kmVec2LengthSq(const kmVec2* pIn); ///< Returns the square of the length of the vector
+kmVec2* kmVec2Normalize(kmVec2* pOut, const kmVec2* pIn); ///< Returns the vector passed in set to unit length
+kmVec2* kmVec2Add(kmVec2* pOut, const kmVec2* pV1, const kmVec2* pV2); ///< Adds 2 vectors and returns the result
+kmScalar kmVec2Dot(const kmVec2* pV1, const kmVec2* pV2); /** Returns the Dot product which is the cosine of the angle between the two vectors multiplied by their lengths */
+kmVec2* kmVec2Subtract(kmVec2* pOut, const kmVec2* pV1, const kmVec2* pV2); ///< Subtracts 2 vectors and returns the result
+kmVec2* kmVec2Transform(kmVec2* pOut, const kmVec2* pV1, const struct kmMat4* pM); /** Transform the Vector */
+kmVec2* kmVec2TransformCoord(kmVec2* pOut, const kmVec2* pV, const struct kmMat4* pM); ///<Transforms a 3D vector by a given matrix, projecting the result back into w = 1.
+kmVec2* kmVec2Scale(kmVec2* pOut, const kmVec2* pIn, const kmScalar s); ///< Scales a vector to length s
+bool kmVec2AreEqual(const kmVec2* p1, const kmVec2* p2); ///< Returns true if both vectors are equal
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif // VEC2_H_INCLUDED
View
245 src/vec3.c
@@ -0,0 +1,245 @@
+/*
+Copyright 2007 Luke Benstead
+
+This file is part of KazMath.
+
+KazMath is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser Public License as published by
+the Free Software Foundation; either version 3 of the License, or
+(at your option) any later version.
+
+KazMath is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser Public License for more details.
+
+You should have received a copy of the GNU Lesser Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include <assert.h>
+#include <memory.h>
+
+#include "utility.h"
+#include "vec4.h"
+#include "mat4.h"
+#include "vec3.h"
+
+///< Returns the length of the vector
+kmScalar kmVec3Length(const kmVec3* pIn)
+{
+ return sqrtf(kmSQR(pIn->x) + kmSQR(pIn->y) + kmSQR(pIn->z));
+}
+
+///< Returns the square of the length of the vector
+kmScalar kmVec3LengthSq(const kmVec3* pIn)
+{
+ return kmSQR(pIn->x) + kmSQR(pIn->y) + kmSQR(pIn->z);
+}
+
+ ///< Returns the vector passed in set to unit length
+kmVec3* kmVec3Normalize(kmVec3* pOut, const kmVec3* pIn)
+{
+ kmScalar l = 1.0 / kmVec3Length(pIn);
+
+ kmVec3 v;
+ v.x = pIn->x * l;
+ v.y = pIn->y * l;
+ v.z = pIn->z * l;
+
+ pOut->x = v.x;
+ pOut->y = v.y;
+ pOut->z = v.z;
+
+ return pOut;
+}
+
+///< Returns a vector perpendicular to 2 other vectors
+kmVec3* kmVec3Cross(kmVec3* pOut, const kmVec3* pV1, const kmVec3* pV2)
+{
+
+ kmVec3 v;
+
+ v.x = (pV1->y * pV2->z) - (pV1->z * pV2->y);
+ v.y = (pV1->z * pV2->x) - (pV1->x * pV2->z);
+ v.z = (pV1->x * pV2->y) - (pV1->y * pV2->x);
+
+ pOut->x = v.x;
+ pOut->y = v.y;
+ pOut->z = v.z;
+
+ return pOut;
+}
+
+///< Returns the cosine of the angle between 2 vectors
+kmScalar kmVec3Dot(const kmVec3* pV1, const kmVec3* pV2)
+{
+ return ( pV1->x * pV2->x
+ + pV1->y * pV2->y
+ + pV1->z * pV2->z );
+}
+
+///< Adds 2 vectors and returns the result
+kmVec3* kmVec3Add(kmVec3* pOut, const kmVec3* pV1, const kmVec3* pV2)
+{
+ kmVec3 v;
+
+ v.x = pV1->x + pV2->x;
+ v.y = pV1->y + pV2->y;
+ v.z = pV1->z + pV2->z;
+
+ pOut->x = v.x;
+ pOut->y = v.y;
+ pOut->z = v.z;
+
+ return pOut;
+}
+
+ ///< Subtracts 2 vectors and returns the result
+kmVec3* kmVec3Subtract(kmVec3* pOut, const kmVec3* pV1, const kmVec3* pV2)
+{
+ kmVec3 v;
+
+ v.x = pV1->x - pV2->x;
+ v.y = pV1->y - pV2->y;
+ v.z = pV1->z - pV2->z;
+
+ pOut->x = v.x;
+ pOut->y = v.y;
+ pOut->z = v.z;
+
+ return pOut;
+}
+
+ ///< Transforms vector (x, y, z, 1) by a given matrix.
+kmVec3* kmVec3Transform(kmVec3* pOut, const kmVec3* pV, const kmMat4* pM)
+{
+ /*
+ a = (Vx, Vy, Vz, 1)
+ b = (a×M)T
+ Out = (bx, by, bz)
+ */
+
+ kmVec3 v;
+
+ v.x = pV->x * pM->m_Mat[0] + pV->y * pM->m_Mat[4] + pV->z * pM->m_Mat[8] + pM->m_Mat[12];
+ v.y = pV->x * pM->m_Mat[1] + pV->y * pM->m_Mat[5] + pV->z * pM->m_Mat[9] + pM->m_Mat[13];
+ v.z = pV->x * pM->m_Mat[2] + pV->y * pM->m_Mat[6] + pV->z * pM->m_Mat[10] + pM->m_Mat[14];
+
+ pOut->x = v.x;
+ pOut->y = v.y;
+ pOut->z = v.z;
+
+ return pOut;
+}
+
+kmVec3* kmVec3InverseTransform(kmVec3* pOut, const kmVec3* pVect, const kmMat4* pM)
+{
+ kmVec3 v1, v2;
+
+ v1.x = pVect->x - pM->m_Mat[12];
+ v1.y = pVect->y - pM->m_Mat[13];
+ v1.z = pVect->z - pM->m_Mat[14];
+
+ v2.x = v1.x * pM->m_Mat[0] + v1.y * pM->m_Mat[1] + v1.z * pM->m_Mat[2];
+ v2.y = v1.x * pM->m_Mat[4] + v1.y * pM->m_Mat[5] + v1.z * pM->m_Mat[6];
+ v2.z = v1.x * pM->m_Mat[8] + v1.y * pM->m_Mat[9] + v1.z * pM->m_Mat[10];
+
+ pOut->x = v2.x;
+ pOut->y = v2.y;
+ pOut->z = v2.z;
+
+ return pOut;
+}
+
+kmVec3* kmVec3InverseTransformNormal(kmVec3* pOut, const kmVec3* pVect, const kmMat4* pM)
+{
+ kmVec3 v;
+
+ v.x = pVect->x * pM->m_Mat[0] + pVect->y * pM->m_Mat[1] + pVect->z * pM->m_Mat[2];
+ v.y = pVect->x * pM->m_Mat[4] + pVect->y * pM->m_Mat[5] + pVect->z * pM->m_Mat[6];
+ v.z = pVect->x * pM->m_Mat[8] + pVect->y * pM->m_Mat[9] + pVect->z * pM->m_Mat[10];
+
+ pOut->x = v.x;
+ pOut->y = v.y;
+ pOut->z = v.z;
+
+ return pOut;
+}
+
+kmVec3* kmVec3TransformCoord(kmVec3* pOut, const kmVec3* pV, const kmMat4* pM)
+{
+ /*
+ a = (Vx, Vy, Vz, 1)
+ b = (a×M)T
+ Out = 1⁄bw(bx, by, bz)
+ */
+
+ assert(0);
+
+ return pOut;
+}
+
+kmVec3* kmVec3TransformNormal(kmVec3* pOut, const kmVec3* pV, const kmMat4* pM)
+{
+/*
+ a = (Vx, Vy, Vz, 0)
+ b = (a×M)T
+ Out = (bx, by, bz)
+*/
+
+ kmVec3 v;
+
+ v.x = pV->x * pM->m_Mat[0] + pV->y * pM->m_Mat[4] + pV->z * pM->m_Mat[8];
+ v.y = pV->x * pM->m_Mat[1] + pV->y * pM->m_Mat[5] + pV->z * pM->m_Mat[9];
+ v.z = pV->x * pM->m_Mat[2] + pV->y * pM->m_Mat[6] + pV->z * pM->m_Mat[10];
+
+ pOut->x = v.x;
+ pOut->y = v.y;
+ pOut->z = v.z;
+
+ return pOut;
+
+}
+
+///< Scales a vector to length s
+kmVec3* kmVec3Scale(kmVec3* pOut, const kmVec3* pIn, const kmScalar s)
+{
+ pOut->x *= s;
+ pOut->y *= s;
+ pOut->z *= s;
+
+ return pOut;
+}
+
+int kmVec3AreEqual(const kmVec3* p1, const kmVec3* p2)
+{
+ if ((p1->x < (p2->x + kmEpsilon) && p1->x > (p2->x - kmEpsilon)) &&
+ (p1->y < (p2->y + kmEpsilon) && p1->y > (p2->y - kmEpsilon)) &&
+ (p1->z < (p2->z + kmEpsilon) && p1->z > (p2->z - kmEpsilon))) {
+ return 1;
+ }
+
+ return 0;
+}
+
+kmVec3* kmVec3Assign(kmVec3* pOut, const kmVec3* pIn) {
+ if (pOut == pIn) {
+ return pOut;
+ }
+
+ pOut->x = pIn->x;
+ pOut->y = pIn->y;
+ pOut->z = pIn->z;
+
+ return pOut;
+}
+
+kmVec3* kmVec3Zero(kmVec3* pOut) {
+ pOut->x = 0.0f;
+ pOut->y = 0.0f;
+ pOut->z = 0.0f;
+
+ return pOut;
+}
View
62 src/vec3.h
@@ -0,0 +1,62 @@
+/*
+Copyright 2007 Luke Benstead
+
+This file is part of KazMath.
+
+KazMath is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser Public License as published by
+the Free Software Foundation; either version 3 of the License, or
+(at your option) any later version.
+
+KazMath is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser Public License for more details.
+
+You should have received a copy of the GNU Lesser Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef VEC3_H_INCLUDED
+#define VEC3_H_INCLUDED
+
+#include <assert.h>
+
+#ifndef kmScalar
+#define kmScalar float
+#endif
+
+struct kmMat4;
+
+typedef struct kmVec3 {
+ kmScalar x;
+ kmScalar y;
+ kmScalar z;
+} kmVec3;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+kmScalar kmVec3Length(const kmVec3* pIn); /** Returns the length of the vector */
+kmScalar kmVec3LengthSq(const kmVec3* pIn); /** Returns the square of the length of the vector */
+kmVec3* kmVec3Normalize(kmVec3* pOut, const kmVec3* pIn); /** Returns the vector passed in set to unit length */
+kmVec3* kmVec3Cross(kmVec3* pOut, const kmVec3* pV1, const kmVec3* pV2); /** Returns a vector perpendicular to 2 other vectors */
+kmScalar kmVec3Dot(const kmVec3* pV1, const kmVec3* pV2); /** Returns the cosine of the angle between 2 vectors */
+kmVec3* kmVec3Add(kmVec3* pOut, const kmVec3* pV1, const kmVec3* pV2); /** Adds 2 vectors and returns the result */
+kmVec3* kmVec3Subtract(kmVec3* pOut, const kmVec3* pV1, const kmVec3* pV2); /** Subtracts 2 vectors and returns the result */
+kmVec3* kmVec3Transform(kmVec3* pOut, const kmVec3* pV1, const struct kmMat4* pM);
+kmVec3* kmVec3TransformNormal(kmVec3* pOut, const kmVec3* pV, const struct kmMat4* pM);
+kmVec3* kmVec3TransformCoord(kmVec3* pOut, const kmVec3* pV, const struct kmMat4* pM); /**Transforms a 3D vector by a given matrix, projecting the result back into w = 1. */
+kmVec3* kmVec3Scale(kmVec3* pOut, const kmVec3* pIn, const kmScalar s); /** Scales a vector to length s */
+int kmVec3AreEqual(const kmVec3* p1, const kmVec3* p2);
+kmVec3* kmVec3InverseTransform(kmVec3* pOut, const kmVec3* pV, const struct kmMat4* pM);
+kmVec3* kmVec3InverseTransformNormal(kmVec3* pOut, const kmVec3* pVect, const struct kmMat4* pM);
+kmVec3* kmVec3Assign(kmVec3* pOut, const kmVec3* pIn);
+kmVec3* kmVec3Zero(kmVec3* pOut);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* VEC3_H_INCLUDED */
View
154 src/vec4.c
@@ -0,0 +1,154 @@
+/*
+Copyright 2007 Luke Benstead
+
+This file is part of KazMath.
+
+KazMath is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser Public License as published by
+the Free Software Foundation; either version 3 of the License, or
+(at your option) any later version.
+
+KazMath is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser Public License for more details.
+
+You should have received a copy of the GNU Lesser Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include <memory.h>
+#include <assert.h>
+
+#include "utility.h"
+#include "vec4.h"
+#include "mat4.h"
+
+/// Adds 2 4D vectors together. The result is store in pOut, the function returns
+/// pOut so that it can be nested in another function.
+kmVec4* kmVec4Add(kmVec4* pOut, const kmVec4* pV1, const kmVec4* pV2) {
+ pOut->x = pV1->x - pV2->x;
+ pOut->y = pV1->y - pV2->y;
+ pOut->z = pV1->z - pV2->z;
+ pOut->w = pV1->w - pV2->w;
+
+ return pOut;
+}
+
+/*
+kmVec4* kmVec4Cross(kmVec4* pOut, const kmVec4* pV1, const kmVec4* pV2, const kmVec4* pV3)
+{
+ pOut->x = pV1->y * (pV2->z * pV3->w - pV3->z * pV2->w) - pV1->z * (pV2->
+ pOut->y =
+ pOut->z =
+ pOut->w =
+
+
+| i j k l | | ay*(bz*cw - cz*bw) - az*(by*cw - cy*bw) + aw*(by*cz - cy*bz) |
+| ax ay az aw | |-ax*(bz*cw - cz*bw) + az*(bx*cw - cx*bw) - aw*(bx*cz - cx*bz) |
+| bx by bz bw | = | ax*(by*cw - cy*bw) - ay*(bx*cw - cx*bw) + aw*(bx*cy - cx*by) |
+| cx cy cz cw | |-ax*(by*cz - cy*bz) + ay*(bx*cz - cx*bz) - az*(bx*cy - cx*by) |
+
+ return pOut;
+}*/
+
+/// Returns the dot product of 2 4D vectors
+kmScalar kmVec4Dot(const kmVec4* pV1, const kmVec4* pV2) {
+ return ( pV1->x * pV2->x
+ + pV1->y * pV2->y
+ + pV1->z * pV2->z
+ + pV1->w * pV2->w );
+}
+
+/// Returns the length of a 4D vector, this uses a sqrt so if the squared length will do use
+/// kmVec4LengthSq
+kmScalar kmVec4Length(const kmVec4* pIn) {
+ return sqrtf(kmSQR(pIn->x) + kmSQR(pIn->y) + kmSQR(pIn->z) + kmSQR(pIn->w));
+}
+
+/// Returns the length of the 4D vector squared.
+kmScalar kmVec4LengthSq(const kmVec4* pIn) {
+ return kmSQR(pIn->x) + kmSQR(pIn->y) + kmSQR(pIn->z) + kmSQR(pIn->w);
+}
+
+/// Returns the interpolation of 2 4D vectors based on t. Currently not implemented!
+kmVec4* kmVec4Lerp(kmVec4* pOut, const kmVec4* pV1, const kmVec4* pV2, kmScalar t) {
+ assert(0);
+ return pOut;
+}
+
+/// Normalizes a 4D vector. The result is stored in pOut. pOut is returned
+kmVec4* kmVec4Normalize(kmVec4* pOut, const kmVec4* pIn) {
+ kmScalar l = 1.0 / kmVec4Length(pIn);
+
+ pOut->x *= l;
+ pOut->y *= l;
+ pOut->z *= l;
+ pOut->w *= l;
+
+ return pOut;
+}
+
+/// Scales a vector to the required length. This performs a Normalize before multiplying by S.
+kmVec4* kmVec4Scale(kmVec4* pOut, const kmVec4* pIn, const kmScalar s) {
+ kmVec4Normalize(pOut, pIn);
+
+ pOut->x *= s;
+ pOut->y *= s;
+ pOut->z *= s;
+ pOut->w *= s;
+ return pOut;
+}
+
+/// Subtracts one 4D pV2 from pV1. The result is stored in pOut. pOut is returned
+kmVec4* kmVec4Subtract(kmVec4* pOut, const kmVec4* pV1, const kmVec4* pV2) {
+ pOut->x = pV1->x - pV2->x;
+ pOut->y = pV1->y - pV2->y;
+ pOut->z = pV1->z - pV2->z;
+ pOut->w = pV1->w - pV2->w;
+
+ return pOut;
+}
+
+/// Transforms a 4D vector by a matrix, the result is stored in pOut, and pOut is returned.
+kmVec4* kmVec4Transform(kmVec4* pOut, const kmVec4* pV, const kmMat4* pM) {
+ pOut->x = pV->x * pM->m_Mat[0] + pV->y * pM->m_Mat[4] + pV->z * pM->m_Mat[8] + pV->w * pM->m_Mat[12];
+ pOut->y = pV->x * pM->m_Mat[1] + pV->y * pM->m_Mat[5] + pV->z * pM->m_Mat[9] + pV->w * pM->m_Mat[13];
+ pOut->z = pV->x * pM->m_Mat[2] + pV->y * pM->m_Mat[6] + pV->z * pM->m_Mat[10] + pV->w * pM->m_Mat[14];
+ pOut->w = pV->x * pM->m_Mat[3] + pV->y * pM->m_Mat[7] + pV->z * pM->m_Mat[11] + pV->w * pM->m_Mat[15];
+ return pOut;
+}
+
+/// Loops through an input array transforming each vec4 by the matrix.
+kmVec4* kmVec4TransformArray(kmVec4* pOut, unsigned int outStride,
+ const kmVec4* pV, unsigned int vStride, const kmMat4* pM, unsigned int count) {
+ unsigned int i = 0;
+ //Go through all of the vectors
+ while (i < count) {
+ const kmVec4* in = pV + (i * vStride); //Get a pointer to the current input
+ kmVec4* out = pOut + (i * outStride); //and the current output
+ kmVec4Transform(out, in, pM); //Perform transform on it
+ ++i;
+ }
+
+ return pOut;
+}
+
+bool kmVec4AreEqual(const kmVec4* p1, const kmVec4* p2) {
+ return (
+ (p1->x < p2->x + kmEpsilon && p1->x > p2->x - kmEpsilon) &&
+ (p1->y < p2->y + kmEpsilon && p1->y > p2->y - kmEpsilon) &&
+ (p1->z < p2->z + kmEpsilon && p1->z > p2->z - kmEpsilon) &&
+ (p1->w < p2->w + kmEpsilon && p1->w > p2->w - kmEpsilon)
+ );
+}
+
+kmVec4* kmVec4Assign(kmVec4* pOut, const kmVec4* pIn) {
+ assert(pOut != pIn);
+
+ memcpy(pOut, pIn, sizeof(float) * 4);
+
+ return pOut;
+}
+
View
62 src/vec4.h
@@ -0,0 +1,62 @@
+/*
+Copyright 2007 Luke Benstead
+
+This file is part of KazMath.
+
+KazMath is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser Public License as published by
+the Free Software Foundation; either version 3 of the License, or
+(at your option) any later version.
+
+KazMath is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser Public License for more details.
+
+You should have received a copy of the GNU Lesser Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef VEC4_H_INCLUDED
+#define VEC4_H_INCLUDED
+
+#include "utility.h"
+
+struct kmMat4;
+
+#pragma pack(push) /* push current alignment to stack */
+#pragma pack(1) /* set alignment to 1 byte boundary */
+
+typedef struct kmVec4 {
+ kmScalar x;
+ kmScalar y;
+ kmScalar z;
+ kmScalar w;
+} kmVec4;
+
+#pragma pack(pop)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+kmVec4* kmVec4Add(kmVec4* pOut, const kmVec4* pV1, const kmVec4* pV2);
+kmScalar kmVec4Dot(const kmVec4* pV1, const kmVec4* pV2);
+kmScalar kmVec4Length(const kmVec4* pIn);
+kmScalar kmVec4LengthSq(const kmVec4* pIn);
+kmVec4* kmVec4Lerp(kmVec4* pOut, const kmVec4* pV1, const kmVec4* pV2, kmScalar t);
+kmVec4* kmVec4Normalize(kmVec4* pOut, const kmVec4* pIn);
+kmVec4* kmVec4Scale(kmVec4* pOut, const kmVec4* pIn, const kmScalar s); ///< Scales a vector to length s
+kmVec4* kmVec4Subtract(kmVec4* pOut, const kmVec4* pV1, const kmVec4* pV2);
+kmVec4* kmVec4Transform(kmVec4* pOut, const kmVec4* pV, const struct kmMat4* pM);
+kmVec4* kmVec4TransformArray(kmVec4* pOut, unsigned int outStride,
+ const kmVec4* pV, unsigned int vStride, const struct kmMat4* pM, unsigned int count);
+bool kmVec4AreEqual(const kmVec4* p1, const kmVec4* p2);
+kmVec4* kmVec4Assign(kmVec4* pOut, const kmVec4* pIn);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // VEC4_H_INCLUDED
Please sign in to comment.
Something went wrong with that request. Please try again.