Updates to latest version of kazmath

This commit is contained in:
Ricardo Quesada 2014-03-04 16:33:00 -08:00
parent bf1413e71f
commit 4fe3b16287
48 changed files with 3910 additions and 3894 deletions

View File

@ -1 +1 @@
8fad051dc33d390c01df304fee2a78e22785136f
e8eaf27db3b5c75d371db6c73f434cea5c0f970d

View File

@ -1 +1 @@
9da17496043155938cbd8973b01514f220e7192b
d70aa2f168a737e7a152028e2156e3099e01c3aa

View File

@ -191,7 +191,7 @@ void Frustum::setupProjectionOrthogonal(const cocos2d::ViewTransform &view, floa
normal = cDir;
kmVec3Scale(&point, &cDir, nearPlane);
kmVec3Add(&point, &point, &cc);
kmPlaneFromPointNormal(&_frustumPlanes[FrustumPlane::FRUSTUM_NEAR], &point, &normal);
kmPlaneFromPointAndNormal(&_frustumPlanes[FrustumPlane::FRUSTUM_NEAR], &point, &normal);
}
//far
@ -201,7 +201,7 @@ void Frustum::setupProjectionOrthogonal(const cocos2d::ViewTransform &view, floa
kmVec3Scale(&normal, &cDir, -1);
kmVec3Scale(&point, &cDir, farPlane);
kmVec3Add(&point, &point, &cc);
kmPlaneFromPointNormal(&_frustumPlanes[FrustumPlane::FRUSTUM_FAR], &point, &normal);
kmPlaneFromPointAndNormal(&_frustumPlanes[FrustumPlane::FRUSTUM_FAR], &point, &normal);
}
//left
@ -211,7 +211,7 @@ void Frustum::setupProjectionOrthogonal(const cocos2d::ViewTransform &view, floa
normal = cRight;
kmVec3Scale(&point, &cRight, -width * 0.5);
kmVec3Add(&point, &point, &cc);
kmPlaneFromPointNormal(&_frustumPlanes[FrustumPlane::FRUSTUM_LEFT], &point, &normal);
kmPlaneFromPointAndNormal(&_frustumPlanes[FrustumPlane::FRUSTUM_LEFT], &point, &normal);
}
//right
@ -221,7 +221,7 @@ void Frustum::setupProjectionOrthogonal(const cocos2d::ViewTransform &view, floa
kmVec3Scale(&normal, &cRight, -1);
kmVec3Scale(&point, &cRight, width * 0.5);
kmVec3Add(&point, &point, &cc);
kmPlaneFromPointNormal(&_frustumPlanes[FrustumPlane::FRUSTUM_RIGHT], &point, &normal);
kmPlaneFromPointAndNormal(&_frustumPlanes[FrustumPlane::FRUSTUM_RIGHT], &point, &normal);
}
//bottom
@ -231,7 +231,7 @@ void Frustum::setupProjectionOrthogonal(const cocos2d::ViewTransform &view, floa
normal = cUp;
kmVec3Scale(&point, &cUp, -height * 0.5);
kmVec3Add(&point, &point, &cc);
kmPlaneFromPointNormal(&_frustumPlanes[FrustumPlane::FRUSTUM_BOTTOM], &point, &normal);
kmPlaneFromPointAndNormal(&_frustumPlanes[FrustumPlane::FRUSTUM_BOTTOM], &point, &normal);
}
//top
@ -241,7 +241,7 @@ void Frustum::setupProjectionOrthogonal(const cocos2d::ViewTransform &view, floa
kmVec3Scale(&normal, &cUp, -1);
kmVec3Scale(&point, &cUp, height * 0.5);
kmVec3Add(&point, &point, &cc);
kmPlaneFromPointNormal(&_frustumPlanes[FrustumPlane::FRUSTUM_TOP], &point, &normal);
kmPlaneFromPointAndNormal(&_frustumPlanes[FrustumPlane::FRUSTUM_TOP], &point, &normal);
}
}
@ -267,14 +267,14 @@ void Frustum::setupProjectionPerspective(const ViewTransform& view, float left,
//near
{
kmPlaneFromPointNormal(&_frustumPlanes[FrustumPlane::FRUSTUM_NEAR], &nearCenter, &cDir);
kmPlaneFromPointAndNormal(&_frustumPlanes[FrustumPlane::FRUSTUM_NEAR], &nearCenter, &cDir);
}
//far
{
kmVec3 normal;
kmVec3Scale(&normal, &cDir, -1);
kmPlaneFromPointNormal(&_frustumPlanes[FrustumPlane::FRUSTUM_FAR], &farCenter, &normal);
kmPlaneFromPointAndNormal(&_frustumPlanes[FrustumPlane::FRUSTUM_FAR], &farCenter, &normal);
}
//left
@ -288,7 +288,7 @@ void Frustum::setupProjectionPerspective(const ViewTransform& view, float left,
kmVec3Cross(&normal, &normal, &cUp);
kmVec3Normalize(&normal, &normal);
kmPlaneFromPointNormal(&_frustumPlanes[FrustumPlane::FRUSTUM_LEFT], &point, &normal);
kmPlaneFromPointAndNormal(&_frustumPlanes[FrustumPlane::FRUSTUM_LEFT], &point, &normal);
}
//right
@ -302,7 +302,7 @@ void Frustum::setupProjectionPerspective(const ViewTransform& view, float left,
kmVec3Cross(&normal, &cUp, &normal);
kmVec3Normalize(&normal, &normal);
kmPlaneFromPointNormal(&_frustumPlanes[FrustumPlane::FRUSTUM_RIGHT], &point, &normal);
kmPlaneFromPointAndNormal(&_frustumPlanes[FrustumPlane::FRUSTUM_RIGHT], &point, &normal);
}
//bottom
@ -316,7 +316,7 @@ void Frustum::setupProjectionPerspective(const ViewTransform& view, float left,
kmVec3Cross(&normal, &cRight, &normal);
kmVec3Normalize(&normal, &normal);
kmPlaneFromPointNormal(&_frustumPlanes[FrustumPlane::FRUSTUM_BOTTOM], &point, &normal);
kmPlaneFromPointAndNormal(&_frustumPlanes[FrustumPlane::FRUSTUM_BOTTOM], &point, &normal);
}
//top
@ -330,7 +330,7 @@ void Frustum::setupProjectionPerspective(const ViewTransform& view, float left,
kmVec3Cross(&normal, &normal, &cRight);
kmVec3Normalize(&normal, &normal);
kmPlaneFromPointNormal(&_frustumPlanes[FrustumPlane::FRUSTUM_TOP], &point, &normal);
kmPlaneFromPointAndNormal(&_frustumPlanes[FrustumPlane::FRUSTUM_TOP], &point, &normal);
}
}

View File

@ -1,76 +0,0 @@
/*
Copyright (c) 2008, Luke Benstead.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef MAT3_H_INCLUDED
#define MAT3_H_INCLUDED
#include "CCPlatformMacros.h"
#include "utility.h"
struct kmVec3;
struct kmQuaternion;
typedef struct kmMat3{
kmScalar mat[9];
} kmMat3;
#ifdef __cplusplus
extern "C" {
#endif
CC_DLL kmMat3* const kmMat3Fill(kmMat3* pOut, const kmScalar* pMat);
CC_DLL kmMat3* const kmMat3Adjugate(kmMat3* pOut, const kmMat3* pIn);
CC_DLL kmMat3* const kmMat3Identity(kmMat3* pOut);
CC_DLL kmMat3* const kmMat3Inverse(kmMat3* pOut, const kmScalar pDeterminate, const kmMat3* pM);
CC_DLL const int kmMat3IsIdentity(const kmMat3* pIn);
CC_DLL kmMat3* const kmMat3Transpose(kmMat3* pOut, const kmMat3* pIn);
CC_DLL const kmScalar kmMat3Determinant(const kmMat3* pIn);
CC_DLL kmMat3* const kmMat3Multiply(kmMat3* pOut, const kmMat3* pM1, const kmMat3* pM2);
CC_DLL kmMat3* const kmMat3ScalarMultiply(kmMat3* pOut, const kmMat3* pM, const kmScalar pFactor);
CC_DLL kmMat3* const kmMat3RotationAxisAngle(kmMat3* pOut, const struct kmVec3* axis, kmScalar radians);
CC_DLL struct kmVec3* const kmMat3RotationToAxisAngle(struct kmVec3* pAxis, kmScalar* radians, const kmMat3* pIn);
CC_DLL kmMat3* const kmMat3Assign(kmMat3* pOut, const kmMat3* pIn);
CC_DLL const int kmMat3AreEqual(const kmMat3* pM1, const kmMat3* pM2);
CC_DLL kmMat3* const kmMat3RotationX(kmMat3* pOut, const kmScalar radians);
CC_DLL kmMat3* const kmMat3RotationY(kmMat3* pOut, const kmScalar radians);
CC_DLL kmMat3* const kmMat3RotationZ(kmMat3* pOut, const kmScalar radians);
CC_DLL kmMat3* const kmMat3Rotation(kmMat3* pOut, const kmScalar radians);
CC_DLL kmMat3* const kmMat3Scaling(kmMat3* pOut, const kmScalar x, const kmScalar y);
CC_DLL kmMat3* const kmMat3Translation(kmMat3* pOut, const kmScalar x, const kmScalar y);
CC_DLL kmMat3* const kmMat3RotationQuaternion(kmMat3* pOut, const struct kmQuaternion* pIn);
CC_DLL kmMat3* const kmMat3RotationAxisAngle(kmMat3* pOut, const struct kmVec3* axis, kmScalar radians);
CC_DLL struct kmVec3* const kmMat3RotationToAxisAngle(struct kmVec3* pAxis, kmScalar* radians, const kmMat3* pIn);
#ifdef __cplusplus
}
#endif
#endif // MAT3_H_INCLUDED

View File

@ -1,94 +0,0 @@
/*
Copyright (c) 2008, Luke Benstead.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef MAT4_H_INCLUDED
#define MAT4_H_INCLUDED
#include "CCPlatformMacros.h"
#include "utility.h"
struct kmVec3;
struct kmMat3;
struct kmQuaternion;
struct kmPlane;
/*
A 4x4 matrix
| 0 4 8 12 |
mat = | 1 5 9 13 |
| 2 6 10 14 |
| 3 7 11 15 |
*/
#ifdef __cplusplus
extern "C" {
#endif
typedef struct kmMat4 {
kmScalar mat[16];
} kmMat4;
CC_DLL kmMat4* const kmMat4Fill(kmMat4* pOut, const kmScalar* pMat);
CC_DLL kmMat4* const kmMat4Identity(kmMat4* pOut);
CC_DLL kmMat4* const kmMat4Inverse(kmMat4* pOut, const kmMat4* pM);
CC_DLL const int kmMat4IsIdentity(const kmMat4* pIn);
CC_DLL kmMat4* const kmMat4Transpose(kmMat4* pOut, const kmMat4* pIn);
CC_DLL kmMat4* const kmMat4Multiply(kmMat4* pOut, const kmMat4* pM1, const kmMat4* pM2);
CC_DLL kmMat4* const kmMat4Assign(kmMat4* pOut, const kmMat4* pIn);
CC_DLL const int kmMat4AreEqual(const kmMat4* pM1, const kmMat4* pM2);
CC_DLL kmMat4* const kmMat4RotationX(kmMat4* pOut, const kmScalar radians);
CC_DLL kmMat4* const kmMat4RotationY(kmMat4* pOut, const kmScalar radians);
CC_DLL kmMat4* const kmMat4RotationZ(kmMat4* pOut, const kmScalar radians);
CC_DLL kmMat4* const kmMat4RotationPitchYawRoll(kmMat4* pOut, const kmScalar pitch, const kmScalar yaw, const kmScalar roll);
CC_DLL kmMat4* const kmMat4RotationQuaternion(kmMat4* pOut, const struct kmQuaternion* pQ);
CC_DLL kmMat4* const kmMat4RotationTranslation(kmMat4* pOut, const struct kmMat3* rotation, const struct kmVec3* translation);
CC_DLL kmMat4* const kmMat4Scaling(kmMat4* pOut, const kmScalar x, const kmScalar y, const kmScalar z);
CC_DLL kmMat4* const kmMat4Translation(kmMat4* pOut, const kmScalar x, const kmScalar y, const kmScalar z);
CC_DLL struct kmVec3* const kmMat4GetUpVec3(struct kmVec3* pOut, const kmMat4* pIn);
CC_DLL struct kmVec3* const kmMat4GetRightVec3(struct kmVec3* pOut, const kmMat4* pIn);
CC_DLL struct kmVec3* const kmMat4GetForwardVec3(struct kmVec3* pOut, const kmMat4* pIn);
CC_DLL kmMat4* const kmMat4PerspectiveProjection(kmMat4* pOut, kmScalar fovY, kmScalar aspect, kmScalar zNear, kmScalar zFar);
CC_DLL kmMat4* const kmMat4OrthographicProjection(kmMat4* pOut, kmScalar left, kmScalar right, kmScalar bottom, kmScalar top, kmScalar nearVal, kmScalar farVal);
CC_DLL kmMat4* const kmMat4LookAt(kmMat4* pOut, const struct kmVec3* pEye, const struct kmVec3* pCenter, const struct kmVec3* pUp);
CC_DLL kmMat4* const kmMat4RotationAxisAngle(kmMat4* pOut, const struct kmVec3* axis, kmScalar radians);
CC_DLL struct kmMat3* const kmMat4ExtractRotation(struct kmMat3* pOut, const kmMat4* pIn);
CC_DLL struct kmPlane* const kmMat4ExtractPlane(struct kmPlane* pOut, const kmMat4* pIn, const kmEnum plane);
CC_DLL struct kmVec3* const kmMat4RotationToAxisAngle(struct kmVec3* pAxis, kmScalar* radians, const kmMat4* pIn);
#ifdef __cplusplus
}
#endif
#endif /* MAT4_H_INCLUDED */

View File

@ -1,114 +0,0 @@
/*
Copyright (c) 2008, Luke Benstead.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef QUATERNION_H_INCLUDED
#define QUATERNION_H_INCLUDED
#ifdef __cplusplus
extern "C" {
#endif
#include "CCPlatformMacros.h"
#include "utility.h"
struct kmMat4;
struct kmMat3;
struct kmVec3;
typedef struct kmQuaternion {
kmScalar x;
kmScalar y;
kmScalar z;
kmScalar w;
} kmQuaternion;
CC_DLL kmQuaternion* const kmQuaternionConjugate(kmQuaternion* pOut, const kmQuaternion* pIn); ///< Returns pOut, sets pOut to the conjugate of pIn
CC_DLL const kmScalar kmQuaternionDot(const kmQuaternion* q1, const kmQuaternion* q2); ///< Returns the dot product of the 2 quaternions
CC_DLL kmQuaternion* kmQuaternionExp(kmQuaternion* pOut, const kmQuaternion* pIn); ///< Returns the exponential of the quaternion
///< Makes the passed quaternion an identity quaternion
CC_DLL kmQuaternion* kmQuaternionIdentity(kmQuaternion* pOut);
///< Returns the inverse of the passed Quaternion
CC_DLL kmQuaternion* kmQuaternionInverse(kmQuaternion* pOut,
const kmQuaternion* pIn);
///< Returns true if the quaternion is an identity quaternion
CC_DLL int kmQuaternionIsIdentity(const kmQuaternion* pIn);
///< Returns the length of the quaternion
CC_DLL kmScalar kmQuaternionLength(const kmQuaternion* pIn);
///< Returns the length of the quaternion squared (prevents a sqrt)
CC_DLL kmScalar kmQuaternionLengthSq(const kmQuaternion* pIn);
///< Returns the natural logarithm
CC_DLL kmQuaternion* kmQuaternionLn(kmQuaternion* pOut, const kmQuaternion* pIn);
///< Multiplies 2 quaternions together
CC_DLL kmQuaternion* kmQuaternionMultiply(kmQuaternion* pOut, const kmQuaternion* q1, const kmQuaternion* q2);
///< Normalizes a quaternion
CC_DLL kmQuaternion* kmQuaternionNormalize(kmQuaternion* pOut, const kmQuaternion* pIn);
///< Rotates a quaternion around an axis
CC_DLL kmQuaternion* kmQuaternionRotationAxis(kmQuaternion* pOut, const struct kmVec3* pV, kmScalar angle);
///< Creates a quaternion from a rotation matrix
CC_DLL kmQuaternion* kmQuaternionRotationMatrix(kmQuaternion* pOut, const struct kmMat3* pIn);
///< Create a quaternion from yaw, pitch and roll
CC_DLL kmQuaternion* kmQuaternionRotationYawPitchRoll(kmQuaternion* pOut, kmScalar yaw, kmScalar pitch, kmScalar roll);
///< Interpolate between 2 quaternions
CC_DLL kmQuaternion* kmQuaternionSlerp(kmQuaternion* pOut, const kmQuaternion* q1, const kmQuaternion* q2, kmScalar t);
///< Get the axis and angle of rotation from a quaternion
CC_DLL void kmQuaternionToAxisAngle(const kmQuaternion* pIn, struct kmVec3* pVector, kmScalar* pAngle);
///< Scale a quaternion
CC_DLL kmQuaternion* kmQuaternionScale(kmQuaternion* pOut, const kmQuaternion* pIn, kmScalar s);
CC_DLL kmQuaternion* kmQuaternionAssign(kmQuaternion* pOut, const kmQuaternion* pIn);
CC_DLL kmQuaternion* kmQuaternionAdd(kmQuaternion* pOut, const kmQuaternion* pQ1, const kmQuaternion* pQ2);
CC_DLL kmQuaternion* kmQuaternionRotationBetweenVec3(kmQuaternion* pOut, const struct kmVec3* vec1, const struct kmVec3* vec2, const struct kmVec3* fallback);
CC_DLL struct kmVec3* kmQuaternionMultiplyVec3(struct kmVec3* pOut, const kmQuaternion* q, const struct kmVec3* v);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,66 +0,0 @@
/*
Copyright (c) 2008, Luke Benstead.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef VEC2_H_INCLUDED
#define VEC2_H_INCLUDED
#include "CCPlatformMacros.h"
struct kmMat3;
#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
CC_DLL kmVec2* kmVec2Fill(kmVec2* pOut, kmScalar x, kmScalar y);
CC_DLL kmScalar kmVec2Length(const kmVec2* pIn); ///< Returns the length of the vector
CC_DLL kmScalar kmVec2LengthSq(const kmVec2* pIn); ///< Returns the square of the length of the vector
CC_DLL kmVec2* kmVec2Normalize(kmVec2* pOut, const kmVec2* pIn); ///< Returns the vector passed in set to unit length
CC_DLL kmVec2* kmVec2Add(kmVec2* pOut, const kmVec2* pV1, const kmVec2* pV2); ///< Adds 2 vectors and returns the result
CC_DLL 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 */
CC_DLL kmVec2* kmVec2Subtract(kmVec2* pOut, const kmVec2* pV1, const kmVec2* pV2); ///< Subtracts 2 vectors and returns the result
CC_DLL kmVec2* kmVec2Transform(kmVec2* pOut, const kmVec2* pV1, const struct kmMat3* pM); /** Transform the Vector */
CC_DLL kmVec2* kmVec2TransformCoord(kmVec2* pOut, const kmVec2* pV, const struct kmMat3* pM); ///<Transforms a 2D vector by a given matrix, projecting the result back into w = 1.
CC_DLL kmVec2* kmVec2Scale(kmVec2* pOut, const kmVec2* pIn, const kmScalar s); ///< Scales a vector to length s
CC_DLL int kmVec2AreEqual(const kmVec2* p1, const kmVec2* p2); ///< Returns 1 if both vectors are equal
#ifdef __cplusplus
}
#endif
#endif // VEC2_H_INCLUDED

View File

@ -1,69 +0,0 @@
/*
Copyright (c) 2008, Luke Benstead.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef VEC3_H_INCLUDED
#define VEC3_H_INCLUDED
#include "CCPlatformMacros.h"
#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
CC_DLL kmVec3* kmVec3Fill(kmVec3* pOut, kmScalar x, kmScalar y, kmScalar z);
CC_DLL kmScalar kmVec3Length(const kmVec3* pIn); /** Returns the length of the vector */
CC_DLL kmScalar kmVec3LengthSq(const kmVec3* pIn); /** Returns the square of the length of the vector */
CC_DLL kmVec3* kmVec3Normalize(kmVec3* pOut, const kmVec3* pIn); /** Returns the vector passed in set to unit length */
CC_DLL kmVec3* kmVec3Cross(kmVec3* pOut, const kmVec3* pV1, const kmVec3* pV2); /** Returns a vector perpendicular to 2 other vectors */
CC_DLL kmScalar kmVec3Dot(const kmVec3* pV1, const kmVec3* pV2); /** Returns the cosine of the angle between 2 vectors */
CC_DLL kmVec3* kmVec3Add(kmVec3* pOut, const kmVec3* pV1, const kmVec3* pV2); /** Adds 2 vectors and returns the result */
CC_DLL kmVec3* kmVec3Subtract(kmVec3* pOut, const kmVec3* pV1, const kmVec3* pV2); /** Subtracts 2 vectors and returns the result */
CC_DLL kmVec3* kmVec3Transform(kmVec3* pOut, const kmVec3* pV1, const struct kmMat4* pM); /** Transforms a vector (assuming w=1) by a given matrix */
CC_DLL kmVec3* kmVec3TransformNormal(kmVec3* pOut, const kmVec3* pV, const struct kmMat4* pM);/**Transforms a 3D normal by a given matrix */
CC_DLL 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. */
CC_DLL kmVec3* kmVec3Scale(kmVec3* pOut, const kmVec3* pIn, const kmScalar s); /** Scales a vector to length s */
CC_DLL int kmVec3AreEqual(const kmVec3* p1, const kmVec3* p2);
CC_DLL kmVec3* kmVec3InverseTransform(kmVec3* pOut, const kmVec3* pV, const struct kmMat4* pM);
CC_DLL kmVec3* kmVec3InverseTransformNormal(kmVec3* pOut, const kmVec3* pVect, const struct kmMat4* pM);
CC_DLL kmVec3* kmVec3Assign(kmVec3* pOut, const kmVec3* pIn);
CC_DLL kmVec3* kmVec3Zero(kmVec3* pOut);
#ifdef __cplusplus
}
#endif
#endif /* VEC3_H_INCLUDED */

View File

@ -0,0 +1,18 @@
#ADD_LIBRARY(Kazmath STATIC ${KAZMATH_SRCS})
#INSTALL(TARGETS Kazmath ARCHIVE DESTINATION lib)
FIND_PACKAGE(Threads REQUIRED)
ADD_LIBRARY(kazmath SHARED ${KAZMATH_SOURCES})
TARGET_LINK_LIBRARIES(kazmath ${CMAKE_THREAD_LIBS_INIT})
SET_TARGET_PROPERTIES(kazmath
PROPERTIES
VERSION 0.0.1
SOVERSION 1)
INSTALL(TARGETS kazmath DESTINATION lib)
#ADD_LIBRARY(KazmathGL STATIC ${GL_UTILS_SRCS})
#INSTALL(TARGETS KazmathGL ARCHIVE DESTINATION lib)
INSTALL(FILES ${KAZMATH_HEADERS} DESTINATION include/kazmath)
INSTALL(FILES ${GL_UTILS_HEADERS} DESTINATION include/kazmath/GL)
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/../cmake_modules/KAZMATHConfig.cmake DESTINATION ${CMAKE_INSTALL_PREFIX}/share/kazmath)

View File

@ -0,0 +1,141 @@
/*
Copyright (c) 2008, Luke Benstead.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "aabb.h"
/**
Initializes the AABB around a central point. If centre is NULL then the origin
is used. Returns pBox.
*/
kmAABB* kmAABBInitialize(kmAABB* pBox, const kmVec3* centre, const kmScalar width, const kmScalar height, const kmScalar depth) {
if(!pBox) return 0;
kmVec3 origin;
kmVec3* point = centre ? (kmVec3*) centre : &origin;
kmVec3Zero(&origin);
pBox->min.x = point->x - (width / 2);
pBox->min.y = point->y - (height / 2);
pBox->min.z = point->z - (depth / 2);
pBox->max.x = point->x + (width / 2);
pBox->max.y = point->y + (height / 2);
pBox->max.z = point->z + (depth / 2);
return pBox;
}
/**
* Returns KM_TRUE if point is in the specified AABB, returns
* KM_FALSE otherwise.
*/
int kmAABBContainsPoint(const kmAABB* pBox, const kmVec3* pPoint)
{
if(pPoint->x >= pBox->min.x && pPoint->x <= pBox->max.x &&
pPoint->y >= pBox->min.y && pPoint->y <= pBox->max.y &&
pPoint->z >= pBox->min.z && pPoint->z <= pBox->max.z) {
return KM_TRUE;
}
return KM_FALSE;
}
/**
* Assigns pIn to pOut, returns pOut.
*/
kmAABB* kmAABBAssign(kmAABB* pOut, const kmAABB* pIn)
{
kmVec3Assign(&pOut->min, &pIn->min);
kmVec3Assign(&pOut->max, &pIn->max);
return pOut;
}
/**
* Scales pIn by s, stores the resulting AABB in pOut. Returns pOut
*/
kmAABB* kmAABBScale(kmAABB* pOut, const kmAABB* pIn, kmScalar s)
{
assert(0 && "Not implemented");
return pOut;
}
kmBool kmAABBIntersectsTriangle(kmAABB* box, const kmVec3* p1, const kmVec3* p2, const kmVec3* p3) {
assert(0 && "Not implemented");
return KM_TRUE;
}
kmEnum kmAABBContainsAABB(const kmAABB* container, const kmAABB* to_check) {
kmVec3 corners[8];
kmEnum result = KM_CONTAINS_ALL;
kmBool found = KM_FALSE;
kmVec3Fill(&corners[0], to_check->min.x, to_check->min.y, to_check->min.z);
kmVec3Fill(&corners[1], to_check->max.x, to_check->min.y, to_check->min.z);
kmVec3Fill(&corners[2], to_check->max.x, to_check->max.y, to_check->min.z);
kmVec3Fill(&corners[3], to_check->min.x, to_check->max.y, to_check->min.z);
kmVec3Fill(&corners[4], to_check->min.x, to_check->min.y, to_check->max.z);
kmVec3Fill(&corners[5], to_check->max.x, to_check->min.y, to_check->max.z);
kmVec3Fill(&corners[6], to_check->max.x, to_check->max.y, to_check->max.z);
kmVec3Fill(&corners[7], to_check->min.x, to_check->max.y, to_check->max.z);
for(kmUchar i = 0; i < 8; ++i) {
if(!kmAABBContainsPoint(container, &corners[i])) {
result = KM_CONTAINS_PARTIAL;
if(found) {
//If we previously found a corner that was within the container
//We know that partial is the final result
return result;
}
} else {
found = KM_TRUE;
}
}
if(!found) {
result = KM_CONTAINS_NONE;
}
return result;
}
kmScalar kmAABBDiameterX(const kmAABB* aabb) {
return fabs(aabb->max.x - aabb->min.x);
}
kmScalar kmAABBDiameterY(const kmAABB* aabb) {
return fabs(aabb->max.y - aabb->min.y);
}
kmScalar kmAABBDiameterZ(const kmAABB* aabb) {
return fabs(aabb->max.z - aabb->min.z);
}
kmVec3* kmAABBCentre(const kmAABB* aabb, kmVec3* pOut) {
kmVec3Add(pOut, &aabb->min, &aabb->max);
kmVec3Scale(pOut, pOut, 0.5);
return pOut;
}

View File

@ -26,7 +26,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef KAZMATH_AABB_H_INCLUDED
#define KAZMATH_AABB_H_INCLUDED
#include "CCPlatformMacros.h"
#include "vec3.h"
#include "utility.h"
@ -35,7 +34,7 @@ extern "C" {
#endif
/**
* A structure that represents an axis-aligned
* A struture that represents an axis-aligned
* bounding box.
*/
typedef struct kmAABB {
@ -43,9 +42,17 @@ typedef struct kmAABB {
kmVec3 max; /** The min corner of the box */
} kmAABB;
CC_DLL const int kmAABBContainsPoint(const kmVec3* pPoint, const kmAABB* pBox);
CC_DLL kmAABB* const kmAABBAssign(kmAABB* pOut, const kmAABB* pIn);
CC_DLL kmAABB* const kmAABBScale(kmAABB* pOut, const kmAABB* pIn, kmScalar s);
kmAABB* kmAABBInitialize(kmAABB* pBox, const kmVec3* centre, const kmScalar width, const kmScalar height, const kmScalar depth);
int kmAABBContainsPoint(const kmAABB* pBox, const kmVec3* pPoint);
kmAABB* kmAABBAssign(kmAABB* pOut, const kmAABB* pIn);
kmAABB* kmAABBScale(kmAABB* pOut, const kmAABB* pIn, kmScalar s);
kmBool kmAABBIntersectsTriangle(kmAABB* box, const kmVec3* p1, const kmVec3* p2, const kmVec3* p3);
kmEnum kmAABBContainsAABB(const kmAABB* container, const kmAABB* to_check);
kmScalar kmAABBDiameterX(const kmAABB* aabb);
kmScalar kmAABBDiameterY(const kmAABB* aabb);
kmScalar kmAABBDiameterZ(const kmAABB* aabb);
kmVec3* kmAABBCentre(const kmAABB* aabb, kmVec3* pOut);
#ifdef __cplusplus
}

View File

@ -28,7 +28,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "vec2.h"
#include "vec3.h"
#include "vec4.h"
#include "mat3.h"
#include "mat4.h"
#include "utility.h"
@ -36,5 +35,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "plane.h"
#include "aabb.h"
#include "ray2.h"
#include "ray3.h"
#endif // KAZMATH_H_INCLUDED

View File

@ -0,0 +1,458 @@
/*
Copyright (c) 2008, Luke Benstead.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdlib.h>
#include <memory.h>
#include <assert.h>
#include "utility.h"
#include "vec3.h"
#include "mat3.h"
#include "mat4.h"
#include "quaternion.h"
kmMat3* kmMat3Fill(kmMat3* pOut, const kmScalar* pMat)
{
memcpy(pOut->mat, pMat, sizeof(kmScalar) * 9);
return pOut;
}
/** Sets pOut to an identity matrix returns pOut*/
kmMat3* kmMat3Identity(kmMat3* pOut)
{
memset(pOut->mat, 0, sizeof(kmScalar) * 9);
pOut->mat[0] = pOut->mat[4] = pOut->mat[8] = 1.0f;
return pOut;
}
kmScalar kmMat3Determinant(const kmMat3* pIn)
{
kmScalar output;
/*
calculating the determinant following the rule of sarus,
| 0 3 6 | 0 3 |
m = | 1 4 7 | 1 4 |
| 2 5 8 | 2 5 |
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->mat[0] * pIn->mat[4] * pIn->mat[8] + pIn->mat[1] * pIn->mat[5] * pIn->mat[6] + pIn->mat[2] * pIn->mat[3] * pIn->mat[7];
output -= pIn->mat[2] * pIn->mat[4] * pIn->mat[6] + pIn->mat[0] * pIn->mat[5] * pIn->mat[7] + pIn->mat[1] * pIn->mat[3] * pIn->mat[8];
return output;
}
kmMat3* kmMat3Adjugate(kmMat3* pOut, const kmMat3* pIn)
{
pOut->mat[0] = pIn->mat[4] * pIn->mat[8] - pIn->mat[5] * pIn->mat[7];
pOut->mat[1] = pIn->mat[2] * pIn->mat[7] - pIn->mat[1] * pIn->mat[8];
pOut->mat[2] = pIn->mat[1] * pIn->mat[5] - pIn->mat[2] * pIn->mat[4];
pOut->mat[3] = pIn->mat[5] * pIn->mat[6] - pIn->mat[3] * pIn->mat[8];
pOut->mat[4] = pIn->mat[0] * pIn->mat[8] - pIn->mat[2] * pIn->mat[6];
pOut->mat[5] = pIn->mat[2] * pIn->mat[3] - pIn->mat[0] * pIn->mat[5];
pOut->mat[6] = pIn->mat[3] * pIn->mat[7] - pIn->mat[4] * pIn->mat[6];
pOut->mat[7] = pIn->mat[1] * pIn->mat[6] - pIn->mat[0] * pIn->mat[7];
pOut->mat[8] = pIn->mat[0] * pIn->mat[4] - pIn->mat[1] * pIn->mat[3];
return pOut;
}
kmMat3* kmMat3Inverse(kmMat3* pOut, const kmMat3* pM)
{
kmScalar determinate = kmMat3Determinant(pM);
kmScalar detInv;
kmMat3 adjugate;
if(determinate == 0.0)
{
return NULL;
}
detInv = 1.0 / determinate;
kmMat3Adjugate(&adjugate, pM);
kmMat3ScalarMultiply(pOut, &adjugate, detInv);
return pOut;
}
/** Returns true if pIn is an identity matrix */
int kmMat3IsIdentity(const kmMat3* pIn)
{
static kmScalar identity [] = { 1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f};
return (memcmp(identity, pIn->mat, sizeof(kmScalar) * 9) == 0);
}
/** Sets pOut to the transpose of pIn, returns pOut */
kmMat3* kmMat3Transpose(kmMat3* pOut, const kmMat3* pIn)
{
kmScalar temp[9];
temp[0] = pIn->mat[0];
temp[1] = pIn->mat[3];
temp[2] = pIn->mat[6];
temp[3] = pIn->mat[1];
temp[4] = pIn->mat[4];
temp[5] = pIn->mat[7];
temp[6] = pIn->mat[2];
temp[7] = pIn->mat[5];
temp[8] = pIn->mat[8];
memcpy(&pOut->mat, temp, sizeof(kmScalar)*9);
return pOut;
}
/* Multiplies pM1 with pM2, stores the result in pOut, returns pOut */
kmMat3* kmMat3Multiply(kmMat3* pOut, const kmMat3* pM1, const kmMat3* pM2)
{
kmScalar mat[9];
const kmScalar *m1 = pM1->mat, *m2 = pM2->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->mat, mat, sizeof(kmScalar)*9);
return pOut;
}
kmMat3* kmMat3ScalarMultiply(kmMat3* pOut, const kmMat3* pM, const kmScalar pFactor)
{
kmScalar mat[9];
int i;
for(i = 0; i < 9; i++)
{
mat[i] = pM->mat[i] * pFactor;
}
memcpy(pOut->mat, mat, sizeof(kmScalar)*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->mat, pIn->mat, sizeof(kmScalar)*9);
return pOut;
}
kmMat3* kmMat3AssignMat4(kmMat3* pOut, const kmMat4* pIn) {
pOut->mat[0] = pIn->mat[0];
pOut->mat[1] = pIn->mat[1];
pOut->mat[2] = pIn->mat[2];
pOut->mat[3] = pIn->mat[4];
pOut->mat[4] = pIn->mat[5];
pOut->mat[5] = pIn->mat[6];
pOut->mat[6] = pIn->mat[8];
pOut->mat[7] = pIn->mat[9];
pOut->mat[8] = pIn->mat[10];
return pOut;
}
/** Returns true if the 2 matrices are equal (approximately) */
int kmMat3AreEqual(const kmMat3* pMat1, const kmMat3* pMat2)
{
int i;
if (pMat1 == pMat2) {
return KM_TRUE;
}
for (i = 0; i < 9; ++i) {
if (!(pMat1->mat[i] + kmEpsilon > pMat2->mat[i] &&
pMat1->mat[i] - kmEpsilon < pMat2->mat[i])) {
return KM_FALSE;
}
}
return KM_TRUE;
}
/* Rotation around the z axis so everything stays planar in XY */
kmMat3* kmMat3Rotation(kmMat3* pOut, const kmScalar radians)
{
/*
| cos(A) -sin(A) 0 |
M = | sin(A) cos(A) 0 |
| 0 0 1 |
*/
pOut->mat[0] = cosf(radians);
pOut->mat[1] = sinf(radians);
pOut->mat[2] = 0.0f;
pOut->mat[3] = -sinf(radians);
pOut->mat[4] = cosf(radians);
pOut->mat[5] = 0.0f;
pOut->mat[6] = 0.0f;
pOut->mat[7] = 0.0f;
pOut->mat[8] = 1.0f;
return pOut;
}
/** Builds a scaling matrix */
kmMat3* kmMat3Scaling(kmMat3* pOut, const kmScalar x, const kmScalar y)
{
// memset(pOut->mat, 0, sizeof(kmScalar) * 9);
kmMat3Identity(pOut);
pOut->mat[0] = x;
pOut->mat[4] = y;
return pOut;
}
kmMat3* kmMat3Translation(kmMat3* pOut, const kmScalar x, const kmScalar y)
{
// memset(pOut->mat, 0, sizeof(kmScalar) * 9);
kmMat3Identity(pOut);
pOut->mat[6] = x;
pOut->mat[7] = y;
// pOut->mat[8] = 1.0;
return pOut;
}
kmMat3* kmMat3RotationQuaternion(kmMat3* pOut, const kmQuaternion* pIn)
{
if (!pIn || !pOut) {
return NULL;
}
// First row
pOut->mat[0] = 1.0f - 2.0f * (pIn->y * pIn->y + pIn->z * pIn->z);
pOut->mat[1] = 2.0f * (pIn->x * pIn->y - pIn->w * pIn->z);
pOut->mat[2] = 2.0f * (pIn->x * pIn->z + pIn->w * pIn->y);
// Second row
pOut->mat[3] = 2.0f * (pIn->x * pIn->y + pIn->w * pIn->z);
pOut->mat[4] = 1.0f - 2.0f * (pIn->x * pIn->x + pIn->z * pIn->z);
pOut->mat[5] = 2.0f * (pIn->y * pIn->z - pIn->w * pIn->x);
// Third row
pOut->mat[6] = 2.0f * (pIn->x * pIn->z - pIn->w * pIn->y);
pOut->mat[7] = 2.0f * (pIn->y * pIn->z + pIn->w * pIn->x);
pOut->mat[8] = 1.0f - 2.0f * (pIn->x * pIn->x + pIn->y * pIn->y);
return pOut;
}
kmMat3* kmMat3RotationAxisAngle(kmMat3* pOut, const struct kmVec3* axis, kmScalar radians)
{
kmScalar rcos = cosf(radians);
kmScalar rsin = sinf(radians);
pOut->mat[0] = rcos + axis->x * axis->x * (1 - rcos);
pOut->mat[1] = axis->z * rsin + axis->y * axis->x * (1 - rcos);
pOut->mat[2] = -axis->y * rsin + axis->z * axis->x * (1 - rcos);
pOut->mat[3] = -axis->z * rsin + axis->x * axis->y * (1 - rcos);
pOut->mat[4] = rcos + axis->y * axis->y * (1 - rcos);
pOut->mat[5] = axis->x * rsin + axis->z * axis->y * (1 - rcos);
pOut->mat[6] = axis->y * rsin + axis->x * axis->z * (1 - rcos);
pOut->mat[7] = -axis->x * rsin + axis->y * axis->z * (1 - rcos);
pOut->mat[8] = rcos + axis->z * axis->z * (1 - rcos);
return pOut;
}
kmVec3* kmMat3RotationToAxisAngle(kmVec3* pAxis, kmScalar* radians, const kmMat3* pIn)
{
/*Surely not this easy?*/
kmQuaternion temp;
kmQuaternionRotationMatrix(&temp, pIn);
kmQuaternionToAxisAngle(&temp, pAxis, radians);
return pAxis;
}
/**
* Builds an X-axis rotation matrix and stores it in pOut, returns pOut
*/
kmMat3* kmMat3RotationX(kmMat3* pOut, const kmScalar radians)
{
/*
| 1 0 0 |
M = | 0 cos(A) -sin(A) |
| 0 sin(A) cos(A) |
*/
pOut->mat[0] = 1.0f;
pOut->mat[1] = 0.0f;
pOut->mat[2] = 0.0f;
pOut->mat[3] = 0.0f;
pOut->mat[4] = cosf(radians);
pOut->mat[5] = sinf(radians);
pOut->mat[6] = 0.0f;
pOut->mat[7] = -sinf(radians);
pOut->mat[8] = cosf(radians);
return pOut;
}
/**
* Builds a rotation matrix using the rotation around the Y-axis
* The result is stored in pOut, pOut is returned.
*/
kmMat3* kmMat3RotationY(kmMat3* pOut, const kmScalar radians)
{
/*
| cos(A) 0 sin(A) |
M = | 0 1 0 |
| -sin(A) 0 cos(A) |
*/
pOut->mat[0] = cosf(radians);
pOut->mat[1] = 0.0f;
pOut->mat[2] = -sinf(radians);
pOut->mat[3] = 0.0f;
pOut->mat[4] = 1.0f;
pOut->mat[5] = 0.0f;
pOut->mat[6] = sinf(radians);
pOut->mat[7] = 0.0f;
pOut->mat[8] = cosf(radians);
return pOut;
}
/**
* Builds a rotation matrix around the Z-axis. The resulting
* matrix is stored in pOut. pOut is returned.
*/
kmMat3* kmMat3RotationZ(kmMat3* pOut, const kmScalar radians)
{
/*
| cos(A) -sin(A) 0 |
M = | sin(A) cos(A) 0 |
| 0 0 1 |
*/
pOut->mat[0] = cosf(radians);
pOut->mat[1] =-sinf(radians);
pOut->mat[2] = 0.0f;
pOut->mat[3] = sinf(radians);
pOut->mat[4] = cosf(radians);
pOut->mat[5] = 0.0f;
pOut->mat[6] = 0.0f;
pOut->mat[7] = 0.0f;
pOut->mat[8] = 1.0f;
return pOut;
}
kmVec3* kmMat3GetUpVec3(kmVec3* pOut, const kmMat3* pIn) {
pOut->x = pIn->mat[3];
pOut->y = pIn->mat[4];
pOut->z = pIn->mat[5];
kmVec3Normalize(pOut, pOut);
return pOut;
}
kmVec3* kmMat3GetRightVec3(kmVec3* pOut, const kmMat3* pIn) {
pOut->x = pIn->mat[0];
pOut->y = pIn->mat[1];
pOut->z = pIn->mat[2];
kmVec3Normalize(pOut, pOut);
return pOut;
}
kmVec3* kmMat3GetForwardVec3(kmVec3* pOut, const kmMat3* pIn) {
pOut->x = pIn->mat[6];
pOut->y = pIn->mat[7];
pOut->z = pIn->mat[8];
kmVec3Normalize(pOut, pOut);
return pOut;
}
kmMat3* kmMat3LookAt(kmMat3* pOut, const kmVec3* pEye,
const kmVec3* pCenter, const kmVec3* pUp)
{
kmVec3 f, up, s, u;
kmVec3Subtract(&f, pCenter, pEye);
kmVec3Normalize(&f, &f);
kmVec3Assign(&up, pUp);
kmVec3Normalize(&up, &up);
kmVec3Cross(&s, &f, &up);
kmVec3Normalize(&s, &s);
kmVec3Cross(&u, &s, &f);
kmVec3Normalize(&s, &s);
pOut->mat[0] = s.x;
pOut->mat[3] = s.y;
pOut->mat[6] = s.z;
pOut->mat[1] = u.x;
pOut->mat[4] = u.y;
pOut->mat[7] = u.z;
pOut->mat[2] = -f.x;
pOut->mat[5] = -f.y;
pOut->mat[8] = -f.z;
return pOut;
}

View File

@ -0,0 +1,85 @@
#ifndef HEADER_8E9D0ABA3C76B989
#define HEADER_8E9D0ABA3C76B989
/*
Copyright (c) 2008, Luke Benstead.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef MAT3_H_INCLUDED
#define MAT3_H_INCLUDED
#include "utility.h"
struct kmVec3;
struct kmQuaternion;
struct kmMat4;
typedef struct kmMat3{
kmScalar mat[9];
} kmMat3;
#ifdef __cplusplus
extern "C" {
#endif
kmMat3* kmMat3Fill(kmMat3* pOut, const kmScalar* pMat);
kmMat3* kmMat3Adjugate(kmMat3* pOut, const kmMat3* pIn);
kmMat3* kmMat3Identity(kmMat3* pOut);
kmMat3* kmMat3Inverse(kmMat3* pOut, const kmMat3* pM);
int 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, const kmScalar pFactor);
kmMat3* kmMat3Assign(kmMat3* pOut, const kmMat3* pIn);
kmMat3* kmMat3AssignMat4(kmMat3* pOut, const struct kmMat4* pIn);
int kmMat3AreEqual(const kmMat3* pM1, const kmMat3* pM2);
struct kmVec3* kmMat3GetUpVec3(struct kmVec3* pOut, const kmMat3* pIn);
struct kmVec3* kmMat3GetRightVec3(struct kmVec3* pOut, const kmMat3* pIn);
struct kmVec3* kmMat3GetForwardVec3(struct kmVec3* pOut, const kmMat3* pIn);
kmMat3* kmMat3RotationX(kmMat3* pOut, const kmScalar radians);
kmMat3* kmMat3RotationY(kmMat3* pOut, const kmScalar radians);
kmMat3* kmMat3RotationZ(kmMat3* pOut, const kmScalar radians);
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);
kmMat3* kmMat3RotationQuaternion(kmMat3* pOut, const struct kmQuaternion* pIn);
kmMat3* kmMat3RotationAxisAngle(kmMat3* pOut, const struct kmVec3* axis, kmScalar radians);
struct kmVec3* kmMat3RotationToAxisAngle(struct kmVec3* pAxis, kmScalar* radians, const kmMat3* pIn);
kmMat3* kmMat3LookAt(kmMat3* pOut, const struct kmVec3* pEye, const struct kmVec3* pCenter, const struct kmVec3* pUp);
#ifdef __cplusplus
}
#endif
#endif // MAT3_H_INCLUDED
#endif // header guard

View File

@ -0,0 +1,805 @@
/*
Copyright (c) 2008, Luke Benstead.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file mat4.c
*/
#include <memory.h>
#include <assert.h>
#include <stdlib.h>
#include "utility.h"
#include "vec3.h"
#include "mat4.h"
#include "mat3.h"
#include "quaternion.h"
#include "plane.h"
#include "neon_matrix_impl.h"
/**
* Fills a kmMat4 structure with the values from a 16
* element array of kmScalars
* @Params pOut - A pointer to the destination matrix
* pMat - A 16 element array of kmScalars
* @Return Returns pOut so that the call can be nested
*/
kmMat4* kmMat4Fill(kmMat4* pOut, const kmScalar* pMat)
{
memcpy(pOut->mat, pMat, sizeof(kmScalar) * 16);
return pOut;
}
/**
* Sets pOut to an identity matrix returns pOut
* @Params pOut - A pointer to the matrix to set to identity
* @Return Returns pOut so that the call can be nested
*/
kmMat4* kmMat4Identity(kmMat4* pOut)
{
memset(pOut->mat, 0, sizeof(kmScalar) * 16);
pOut->mat[0] = pOut->mat[5] = pOut->mat[10] = pOut->mat[15] = 1.0f;
return pOut;
}
/**
* Calculates the inverse of pM and stores the result in
* pOut.
* @Return Returns NULL if there is no inverse, else pOut
*/
kmMat4* kmMat4Inverse(kmMat4* pOut, const kmMat4* pM) {
kmMat4 tmp;
double det;
int i;
tmp.mat[0] = pM->mat[5] * pM->mat[10] * pM->mat[15] -
pM->mat[5] * pM->mat[11] * pM->mat[14] -
pM->mat[9] * pM->mat[6] * pM->mat[15] +
pM->mat[9] * pM->mat[7] * pM->mat[14] +
pM->mat[13] * pM->mat[6] * pM->mat[11] -
pM->mat[13] * pM->mat[7] * pM->mat[10];
tmp.mat[4] = -pM->mat[4] * pM->mat[10] * pM->mat[15] +
pM->mat[4] * pM->mat[11] * pM->mat[14] +
pM->mat[8] * pM->mat[6] * pM->mat[15] -
pM->mat[8] * pM->mat[7] * pM->mat[14] -
pM->mat[12] * pM->mat[6] * pM->mat[11] +
pM->mat[12] * pM->mat[7] * pM->mat[10];
tmp.mat[8] = pM->mat[4] * pM->mat[9] * pM->mat[15] -
pM->mat[4] * pM->mat[11] * pM->mat[13] -
pM->mat[8] * pM->mat[5] * pM->mat[15] +
pM->mat[8] * pM->mat[7] * pM->mat[13] +
pM->mat[12] * pM->mat[5] * pM->mat[11] -
pM->mat[12] * pM->mat[7] * pM->mat[9];
tmp.mat[12] = -pM->mat[4] * pM->mat[9] * pM->mat[14] +
pM->mat[4] * pM->mat[10] * pM->mat[13] +
pM->mat[8] * pM->mat[5] * pM->mat[14] -
pM->mat[8] * pM->mat[6] * pM->mat[13] -
pM->mat[12] * pM->mat[5] * pM->mat[10] +
pM->mat[12] * pM->mat[6] * pM->mat[9];
tmp.mat[1] = -pM->mat[1] * pM->mat[10] * pM->mat[15] +
pM->mat[1] * pM->mat[11] * pM->mat[14] +
pM->mat[9] * pM->mat[2] * pM->mat[15] -
pM->mat[9] * pM->mat[3] * pM->mat[14] -
pM->mat[13] * pM->mat[2] * pM->mat[11] +
pM->mat[13] * pM->mat[3] * pM->mat[10];
tmp.mat[5] = pM->mat[0] * pM->mat[10] * pM->mat[15] -
pM->mat[0] * pM->mat[11] * pM->mat[14] -
pM->mat[8] * pM->mat[2] * pM->mat[15] +
pM->mat[8] * pM->mat[3] * pM->mat[14] +
pM->mat[12] * pM->mat[2] * pM->mat[11] -
pM->mat[12] * pM->mat[3] * pM->mat[10];
tmp.mat[9] = -pM->mat[0] * pM->mat[9] * pM->mat[15] +
pM->mat[0] * pM->mat[11] * pM->mat[13] +
pM->mat[8] * pM->mat[1] * pM->mat[15] -
pM->mat[8] * pM->mat[3] * pM->mat[13] -
pM->mat[12] * pM->mat[1] * pM->mat[11] +
pM->mat[12] * pM->mat[3] * pM->mat[9];
tmp.mat[13] = pM->mat[0] * pM->mat[9] * pM->mat[14] -
pM->mat[0] * pM->mat[10] * pM->mat[13] -
pM->mat[8] * pM->mat[1] * pM->mat[14] +
pM->mat[8] * pM->mat[2] * pM->mat[13] +
pM->mat[12] * pM->mat[1] * pM->mat[10] -
pM->mat[12] * pM->mat[2] * pM->mat[9];
tmp.mat[2] = pM->mat[1] * pM->mat[6] * pM->mat[15] -
pM->mat[1] * pM->mat[7] * pM->mat[14] -
pM->mat[5] * pM->mat[2] * pM->mat[15] +
pM->mat[5] * pM->mat[3] * pM->mat[14] +
pM->mat[13] * pM->mat[2] * pM->mat[7] -
pM->mat[13] * pM->mat[3] * pM->mat[6];
tmp.mat[6] = -pM->mat[0] * pM->mat[6] * pM->mat[15] +
pM->mat[0] * pM->mat[7] * pM->mat[14] +
pM->mat[4] * pM->mat[2] * pM->mat[15] -
pM->mat[4] * pM->mat[3] * pM->mat[14] -
pM->mat[12] * pM->mat[2] * pM->mat[7] +
pM->mat[12] * pM->mat[3] * pM->mat[6];
tmp.mat[10] = pM->mat[0] * pM->mat[5] * pM->mat[15] -
pM->mat[0] * pM->mat[7] * pM->mat[13] -
pM->mat[4] * pM->mat[1] * pM->mat[15] +
pM->mat[4] * pM->mat[3] * pM->mat[13] +
pM->mat[12] * pM->mat[1] * pM->mat[7] -
pM->mat[12] * pM->mat[3] * pM->mat[5];
tmp.mat[14] = -pM->mat[0] * pM->mat[5] * pM->mat[14] +
pM->mat[0] * pM->mat[6] * pM->mat[13] +
pM->mat[4] * pM->mat[1] * pM->mat[14] -
pM->mat[4] * pM->mat[2] * pM->mat[13] -
pM->mat[12] * pM->mat[1] * pM->mat[6] +
pM->mat[12] * pM->mat[2] * pM->mat[5];
tmp.mat[3] = -pM->mat[1] * pM->mat[6] * pM->mat[11] +
pM->mat[1] * pM->mat[7] * pM->mat[10] +
pM->mat[5] * pM->mat[2] * pM->mat[11] -
pM->mat[5] * pM->mat[3] * pM->mat[10] -
pM->mat[9] * pM->mat[2] * pM->mat[7] +
pM->mat[9] * pM->mat[3] * pM->mat[6];
tmp.mat[7] = pM->mat[0] * pM->mat[6] * pM->mat[11] -
pM->mat[0] * pM->mat[7] * pM->mat[10] -
pM->mat[4] * pM->mat[2] * pM->mat[11] +
pM->mat[4] * pM->mat[3] * pM->mat[10] +
pM->mat[8] * pM->mat[2] * pM->mat[7] -
pM->mat[8] * pM->mat[3] * pM->mat[6];
tmp.mat[11] = -pM->mat[0] * pM->mat[5] * pM->mat[11] +
pM->mat[0] * pM->mat[7] * pM->mat[9] +
pM->mat[4] * pM->mat[1] * pM->mat[11] -
pM->mat[4] * pM->mat[3] * pM->mat[9] -
pM->mat[8] * pM->mat[1] * pM->mat[7] +
pM->mat[8] * pM->mat[3] * pM->mat[5];
tmp.mat[15] = pM->mat[0] * pM->mat[5] * pM->mat[10] -
pM->mat[0] * pM->mat[6] * pM->mat[9] -
pM->mat[4] * pM->mat[1] * pM->mat[10] +
pM->mat[4] * pM->mat[2] * pM->mat[9] +
pM->mat[8] * pM->mat[1] * pM->mat[6] -
pM->mat[8] * pM->mat[2] * pM->mat[5];
det = pM->mat[0] * tmp.mat[0] + pM->mat[1] * tmp.mat[4] + pM->mat[2] * tmp.mat[8] + pM->mat[3] * tmp.mat[12];
if (det == 0) {
return NULL;
}
det = 1.0 / det;
for (i = 0; i < 16; i++) {
pOut->mat[i] = tmp.mat[i] * det;
}
return pOut;
}
/**
* Returns KM_TRUE if pIn is an identity matrix
* KM_FALSE otherwise
*/
int kmMat4IsIdentity(const kmMat4* pIn)
{
static kmScalar 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->mat, sizeof(kmScalar) * 16) == 0);
}
/**
* Sets pOut to the transpose of pIn, returns pOut
*/
kmMat4* kmMat4Transpose(kmMat4* pOut, const kmMat4* pIn)
{
int x, z;
for (z = 0; z < 4; ++z) {
for (x = 0; x < 4; ++x) {
pOut->mat[(z * 4) + x] = pIn->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)
{
#if defined(__ARM_NEON__) && !defined(__arm64__)
// It is possible to skip the memcpy() since "out" does not overwrite p1 or p2.
// otherwise a temp must be needed.
float *mat = pOut->mat;
// Invert column-order with row-order
NEON_Matrix4Mul( &pM2->mat[0], &pM1->mat[0], &mat[0] );
#else
kmScalar mat[16];
const kmScalar *m1 = pM1->mat, *m2 = pM2->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->mat, mat, sizeof(kmScalar)*16);
#endif
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->mat, pIn->mat, sizeof(kmScalar)*16);
return pOut;
}
kmMat4* kmMat4AssignMat3(kmMat4* pOut, const kmMat3* pIn) {
kmMat4Identity(pOut);
pOut->mat[0] = pIn->mat[0];
pOut->mat[1] = pIn->mat[1];
pOut->mat[2] = pIn->mat[2];
pOut->mat[3] = 0.0;
pOut->mat[4] = pIn->mat[3];
pOut->mat[5] = pIn->mat[4];
pOut->mat[6] = pIn->mat[5];
pOut->mat[7] = 0.0;
pOut->mat[8] = pIn->mat[6];
pOut->mat[9] = pIn->mat[7];
pOut->mat[10] = pIn->mat[8];
pOut->mat[11] = 0.0;
return pOut;
}
/**
* Returns KM_TRUE if the 2 matrices are equal (approximately)
*/
int kmMat4AreEqual(const kmMat4* pMat1, const kmMat4* pMat2)
{
int i = 0;
assert(pMat1 != pMat2 && "You are comparing the same thing!");
for (i = 0; i < 16; ++i)
{
if (!(pMat1->mat[i] + kmEpsilon > pMat2->mat[i] &&
pMat1->mat[i] - kmEpsilon < pMat2->mat[i])) {
return KM_FALSE;
}
}
return KM_TRUE;
}
/**
* Build a rotation matrix from an axis and an angle. Result is stored in pOut.
* pOut is returned.
*/
kmMat4* kmMat4RotationAxisAngle(kmMat4* pOut, const kmVec3* axis, kmScalar radians)
{
kmQuaternion quat;
kmQuaternionRotationAxisAngle(&quat, axis, radians);
kmMat4RotationQuaternion(pOut, &quat);
return pOut;
}
/**
* Builds an X-axis rotation matrix and stores it in pOut, returns pOut
*/
kmMat4* kmMat4RotationX(kmMat4* pOut, const kmScalar radians)
{
/*
| 1 0 0 0 |
M = | 0 cos(A) -sin(A) 0 |
| 0 sin(A) cos(A) 0 |
| 0 0 0 1 |
*/
pOut->mat[0] = 1.0f;
pOut->mat[1] = 0.0f;
pOut->mat[2] = 0.0f;
pOut->mat[3] = 0.0f;
pOut->mat[4] = 0.0f;
pOut->mat[5] = cosf(radians);
pOut->mat[6] = sinf(radians);
pOut->mat[7] = 0.0f;
pOut->mat[8] = 0.0f;
pOut->mat[9] = -sinf(radians);
pOut->mat[10] = cosf(radians);
pOut->mat[11] = 0.0f;
pOut->mat[12] = 0.0f;
pOut->mat[13] = 0.0f;
pOut->mat[14] = 0.0f;
pOut->mat[15] = 1.0f;
return pOut;
}
/**
* Builds a rotation matrix using the rotation around the Y-axis
* The result is stored in pOut, pOut is returned.
*/
kmMat4* kmMat4RotationY(kmMat4* pOut, const kmScalar radians)
{
/*
| cos(A) 0 sin(A) 0 |
M = | 0 1 0 0 |
| -sin(A) 0 cos(A) 0 |
| 0 0 0 1 |
*/
pOut->mat[0] = cosf(radians);
pOut->mat[1] = 0.0f;
pOut->mat[2] = -sinf(radians);
pOut->mat[3] = 0.0f;
pOut->mat[4] = 0.0f;
pOut->mat[5] = 1.0f;
pOut->mat[6] = 0.0f;
pOut->mat[7] = 0.0f;
pOut->mat[8] = sinf(radians);
pOut->mat[9] = 0.0f;
pOut->mat[10] = cosf(radians);
pOut->mat[11] = 0.0f;
pOut->mat[12] = 0.0f;
pOut->mat[13] = 0.0f;
pOut->mat[14] = 0.0f;
pOut->mat[15] = 1.0f;
return pOut;
}
/**
* Builds a rotation matrix around the Z-axis. The resulting
* matrix is stored in pOut. pOut is returned.
*/
kmMat4* kmMat4RotationZ(kmMat4* pOut, const kmScalar radians)
{
/*
| cos(A) -sin(A) 0 0 |
M = | sin(A) cos(A) 0 0 |
| 0 0 1 0 |
| 0 0 0 1 |
*/
pOut->mat[0] = cosf(radians);
pOut->mat[1] = sinf(radians);
pOut->mat[2] = 0.0f;
pOut->mat[3] = 0.0f;
pOut->mat[4] = -sinf(radians);
pOut->mat[5] = cosf(radians);
pOut->mat[6] = 0.0f;
pOut->mat[7] = 0.0f;
pOut->mat[8] = 0.0f;
pOut->mat[9] = 0.0f;
pOut->mat[10] = 1.0f;
pOut->mat[11] = 0.0f;
pOut->mat[12] = 0.0f;
pOut->mat[13] = 0.0f;
pOut->mat[14] = 0.0f;
pOut->mat[15] = 1.0f;
return pOut;
}
/**
* Builds a rotation matrix from pitch, yaw and roll. The resulting
* matrix is stored in pOut and pOut is returned
*/
kmMat4* kmMat4RotationYawPitchRoll(kmMat4* pOut, const kmScalar pitch, const kmScalar yaw, const kmScalar roll)
{
kmMat4 yaw_matrix;
kmMat4RotationY(&yaw_matrix, yaw);
kmMat4 pitch_matrix;
kmMat4RotationX(&pitch_matrix, pitch);
kmMat4 roll_matrix;
kmMat4RotationZ(&roll_matrix, roll);
kmMat4Multiply(pOut, &pitch_matrix, &roll_matrix);
kmMat4Multiply(pOut, &yaw_matrix, pOut);
return pOut;
}
/** Converts a quaternion to a rotation matrix,
* the result is stored in pOut, returns pOut
*/
kmMat4* kmMat4RotationQuaternion(kmMat4* pOut, const kmQuaternion* pQ)
{
double xx = pQ->x * pQ->x;
double xy = pQ->x * pQ->y;
double xz = pQ->x * pQ->z;
double xw = pQ->x * pQ->w;
double yy = pQ->y * pQ->y;
double yz = pQ->y * pQ->z;
double yw = pQ->y * pQ->w;
double zz = pQ->z * pQ->z;
double zw = pQ->z * pQ->w;
pOut->mat[0] = 1 - 2 * (yy + zz);
pOut->mat[1] = 2 * (xy + zw);
pOut->mat[2] = 2 * (xz - yw);
pOut->mat[3] = 0;
pOut->mat[4] = 2 * (xy - zw);
pOut->mat[5] = 1 - 2 * (xx + zz);
pOut->mat[6] = 2 * (yz + xw);
pOut->mat[7] = 0.0;
pOut->mat[8] = 2 * (xz + yw);
pOut->mat[9] = 2 * (yz - xw);
pOut->mat[10] = 1 - 2 * (xx + yy);
pOut->mat[11] = 0.0;
pOut->mat[12] = 0.0;
pOut->mat[13] = 0.0;
pOut->mat[14] = 0.0;
pOut->mat[15] = 1.0;
return pOut;
}
/** Builds a scaling matrix */
kmMat4* kmMat4Scaling(kmMat4* pOut, const kmScalar x, const kmScalar y,
kmScalar z)
{
memset(pOut->mat, 0, sizeof(kmScalar) * 16);
pOut->mat[0] = x;
pOut->mat[5] = y;
pOut->mat[10] = z;
pOut->mat[15] = 1.0f;
return pOut;
}
/**
* Builds a translation matrix. All other elements in the matrix
* will be set to zero except for the diagonal which is set to 1.0
*/
kmMat4* kmMat4Translation(kmMat4* pOut, const kmScalar x,
kmScalar y, const kmScalar z)
{
//FIXME: Write a test for this
memset(pOut->mat, 0, sizeof(kmScalar) * 16);
pOut->mat[0] = 1.0f;
pOut->mat[5] = 1.0f;
pOut->mat[10] = 1.0f;
pOut->mat[12] = x;
pOut->mat[13] = y;
pOut->mat[14] = z;
pOut->mat[15] = 1.0f;
return pOut;
}
/**
* Get the up vector from a matrix. pIn is the matrix you
* wish to extract the vector from. pOut is a pointer to the
* kmVec3 structure that should hold the resulting vector
*/
kmVec3* kmMat4GetUpVec3(kmVec3* pOut, const kmMat4* pIn)
{
kmVec3MultiplyMat4(pOut, &KM_VEC3_POS_Y, pIn);
kmVec3Normalize(pOut, pOut);
return pOut;
}
/** Extract the right vector from a 4x4 matrix. The result is
* stored in pOut. Returns pOut.
*/
kmVec3* kmMat4GetRightVec3(kmVec3* pOut, const kmMat4* pIn)
{
kmVec3MultiplyMat4(pOut, &KM_VEC3_POS_X, pIn);
kmVec3Normalize(pOut, pOut);
return pOut;
}
/**
* Extract the forward vector from a 4x4 matrix. The result is
* stored in pOut. Returns pOut.
*/
kmVec3* kmMat4GetForwardVec3RH(kmVec3* pOut, const kmMat4* pIn)
{
kmVec3MultiplyMat4(pOut, &KM_VEC3_NEG_Z, pIn);
kmVec3Normalize(pOut, pOut);
return pOut;
}
kmVec3* kmMat4GetForwardVec3LH(kmVec3* pOut, const kmMat4* pIn)
{
kmVec3MultiplyMat4(pOut, &KM_VEC3_POS_Z, pIn);
kmVec3Normalize(pOut, pOut);
return pOut;
}
/**
* Creates a perspective projection matrix in the
* same way as gluPerspective
*/
kmMat4* kmMat4PerspectiveProjection(kmMat4* pOut, kmScalar fovY,
kmScalar aspect, kmScalar zNear,
kmScalar zFar)
{
kmScalar r = kmDegreesToRadians(fovY / 2);
kmScalar deltaZ = zFar - zNear;
kmScalar s = sin(r);
kmScalar cotangent = 0;
if (deltaZ == 0 || s == 0 || aspect == 0) {
return NULL;
}
//cos(r) / sin(r) = cot(r)
cotangent = cos(r) / s;
kmMat4Identity(pOut);
pOut->mat[0] = cotangent / aspect;
pOut->mat[5] = cotangent;
pOut->mat[10] = -(zFar + zNear) / deltaZ;
pOut->mat[11] = -1;
pOut->mat[14] = -2 * zNear * zFar / deltaZ;
pOut->mat[15] = 0;
return pOut;
}
/** Creates an orthographic projection matrix like glOrtho */
kmMat4* kmMat4OrthographicProjection(kmMat4* pOut, kmScalar left,
kmScalar right, kmScalar bottom,
kmScalar top, kmScalar nearVal,
kmScalar farVal)
{
kmScalar tx = -((right + left) / (right - left));
kmScalar ty = -((top + bottom) / (top - bottom));
kmScalar tz = -((farVal + nearVal) / (farVal - nearVal));
kmMat4Identity(pOut);
pOut->mat[0] = 2 / (right - left);
pOut->mat[5] = 2 / (top - bottom);
pOut->mat[10] = -2 / (farVal - nearVal);
pOut->mat[12] = tx;
pOut->mat[13] = ty;
pOut->mat[14] = tz;
return pOut;
}
/**
* Builds a translation matrix in the same way as gluLookAt()
* the resulting matrix is stored in pOut. pOut is returned.
*/
kmMat4* kmMat4LookAt(kmMat4* pOut, const kmVec3* pEye,
const kmVec3* pCenter, const kmVec3* pUp)
{
kmVec3 f, up, s, u;
kmMat4 translate;
kmVec3Subtract(&f, pCenter, pEye);
kmVec3Normalize(&f, &f);
kmVec3Assign(&up, pUp);
kmVec3Normalize(&up, &up);
kmVec3Cross(&s, &f, &up);
kmVec3Normalize(&s, &s);
kmVec3Cross(&u, &s, &f);
kmVec3Normalize(&s, &s);
kmMat4Identity(pOut);
pOut->mat[0] = s.x;
pOut->mat[4] = s.y;
pOut->mat[8] = s.z;
pOut->mat[1] = u.x;
pOut->mat[5] = u.y;
pOut->mat[9] = u.z;
pOut->mat[2] = -f.x;
pOut->mat[6] = -f.y;
pOut->mat[10] = -f.z;
kmMat4Translation(&translate, -pEye->x, -pEye->y, -pEye->z);
kmMat4Multiply(pOut, pOut, &translate);
return pOut;
}
/**
* Extract a 3x3 rotation matrix from the input 4x4 transformation.
* Stores the result in pOut, returns pOut
*/
kmMat3* kmMat4ExtractRotation(kmMat3* pOut, const kmMat4* pIn)
{
pOut->mat[0] = pIn->mat[0];
pOut->mat[1] = pIn->mat[1];
pOut->mat[2] = pIn->mat[2];
pOut->mat[3] = pIn->mat[4];
pOut->mat[4] = pIn->mat[5];
pOut->mat[5] = pIn->mat[6];
pOut->mat[6] = pIn->mat[8];
pOut->mat[7] = pIn->mat[9];
pOut->mat[8] = pIn->mat[10];
return pOut;
}
/**
* Take the rotation from a 4x4 transformation matrix, and return it as an axis and an angle (in radians)
* returns the output axis.
*/
kmVec3* kmMat4RotationToAxisAngle(kmVec3* pAxis, kmScalar* radians, const kmMat4* pIn)
{
/*Surely not this easy?*/
kmQuaternion temp;
kmMat3 rotation;
kmMat4ExtractRotation(&rotation, pIn);
kmQuaternionRotationMatrix(&temp, &rotation);
kmQuaternionToAxisAngle(&temp, pAxis, radians);
return pAxis;
}
/** Build a 4x4 OpenGL transformation matrix using a 3x3 rotation matrix,
* and a 3d vector representing a translation. Assign the result to pOut,
* pOut is also returned.
*/
kmMat4* kmMat4RotationTranslation(kmMat4* pOut, const kmMat3* rotation, const kmVec3* translation)
{
pOut->mat[0] = rotation->mat[0];
pOut->mat[1] = rotation->mat[1];
pOut->mat[2] = rotation->mat[2];
pOut->mat[3] = 0.0f;
pOut->mat[4] = rotation->mat[3];
pOut->mat[5] = rotation->mat[4];
pOut->mat[6] = rotation->mat[5];
pOut->mat[7] = 0.0f;
pOut->mat[8] = rotation->mat[6];
pOut->mat[9] = rotation->mat[7];
pOut->mat[10] = rotation->mat[8];
pOut->mat[11] = 0.0f;
pOut->mat[12] = translation->x;
pOut->mat[13] = translation->y;
pOut->mat[14] = translation->z;
pOut->mat[15] = 1.0f;
return pOut;
}
kmPlane* kmMat4ExtractPlane(kmPlane* pOut, const kmMat4* pIn, const kmEnum plane)
{
kmScalar t = 1.0f;
switch(plane) {
case KM_PLANE_RIGHT:
pOut->a = pIn->mat[3] - pIn->mat[0];
pOut->b = pIn->mat[7] - pIn->mat[4];
pOut->c = pIn->mat[11] - pIn->mat[8];
pOut->d = pIn->mat[15] - pIn->mat[12];
break;
case KM_PLANE_LEFT:
pOut->a = pIn->mat[3] + pIn->mat[0];
pOut->b = pIn->mat[7] + pIn->mat[4];
pOut->c = pIn->mat[11] + pIn->mat[8];
pOut->d = pIn->mat[15] + pIn->mat[12];
break;
case KM_PLANE_BOTTOM:
pOut->a = pIn->mat[3] + pIn->mat[1];
pOut->b = pIn->mat[7] + pIn->mat[5];
pOut->c = pIn->mat[11] + pIn->mat[9];
pOut->d = pIn->mat[15] + pIn->mat[13];
break;
case KM_PLANE_TOP:
pOut->a = pIn->mat[3] - pIn->mat[1];
pOut->b = pIn->mat[7] - pIn->mat[5];
pOut->c = pIn->mat[11] - pIn->mat[9];
pOut->d = pIn->mat[15] - pIn->mat[13];
break;
case KM_PLANE_FAR:
pOut->a = pIn->mat[3] - pIn->mat[2];
pOut->b = pIn->mat[7] - pIn->mat[6];
pOut->c = pIn->mat[11] - pIn->mat[10];
pOut->d = pIn->mat[15] - pIn->mat[14];
break;
case KM_PLANE_NEAR:
pOut->a = pIn->mat[3] + pIn->mat[2];
pOut->b = pIn->mat[7] + pIn->mat[6];
pOut->c = pIn->mat[11] + pIn->mat[10];
pOut->d = pIn->mat[15] + pIn->mat[14];
break;
default:
assert(0 && "Invalid plane index");
}
t = sqrtf(pOut->a * pOut->a +
pOut->b * pOut->b +
pOut->c * pOut->c);
pOut->a /= t;
pOut->b /= t;
pOut->c /= t;
pOut->d /= t;
return pOut;
}

View File

@ -0,0 +1,96 @@
/*
Copyright (c) 2008, Luke Benstead.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef MAT4_H_INCLUDED
#define MAT4_H_INCLUDED
#include "utility.h"
struct kmVec3;
struct kmMat3;
struct kmQuaternion;
struct kmPlane;
/*
A 4x4 matrix
| 0 4 8 12 |
mat = | 1 5 9 13 |
| 2 6 10 14 |
| 3 7 11 15 |
*/
#ifdef __cplusplus
extern "C" {
#endif
typedef struct kmMat4 {
kmScalar mat[16];
} kmMat4;
kmMat4* kmMat4Fill(kmMat4* pOut, const kmScalar* pMat);
kmMat4* kmMat4Identity(kmMat4* pOut);
kmMat4* kmMat4Inverse(kmMat4* pOut, const kmMat4* pM);
int kmMat4IsIdentity(const kmMat4* pIn);
kmMat4* kmMat4Transpose(kmMat4* pOut, const kmMat4* pIn);
kmMat4* kmMat4Multiply(kmMat4* pOut, const kmMat4* pM1, const kmMat4* pM2);
kmMat4* kmMat4Assign(kmMat4* pOut, const kmMat4* pIn);
kmMat4* kmMat4AssignMat3(kmMat4* pOut, const struct kmMat3* pIn);
int kmMat4AreEqual(const kmMat4* pM1, const kmMat4* pM2);
kmMat4* kmMat4RotationX(kmMat4* pOut, const kmScalar radians);
kmMat4* kmMat4RotationY(kmMat4* pOut, const kmScalar radians);
kmMat4* kmMat4RotationZ(kmMat4* pOut, const kmScalar radians);
kmMat4* kmMat4RotationYawPitchRoll(kmMat4* pOut, const kmScalar pitch, const kmScalar yaw, const kmScalar roll);
kmMat4* kmMat4RotationQuaternion(kmMat4* pOut, const struct kmQuaternion* pQ);
kmMat4* kmMat4RotationTranslation(kmMat4* pOut, const struct kmMat3* rotation, const struct kmVec3* translation);
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* kmMat4GetForwardVec3RH(struct kmVec3* pOut, const kmMat4* pIn);
struct kmVec3* kmMat4GetForwardVec3LH(struct kmVec3* pOut, const kmMat4* pIn);
kmMat4* kmMat4PerspectiveProjection(kmMat4* pOut, kmScalar fovY, kmScalar aspect, kmScalar zNear, kmScalar zFar);
kmMat4* kmMat4OrthographicProjection(kmMat4* pOut, kmScalar left, kmScalar right, kmScalar bottom, kmScalar top, kmScalar nearVal, kmScalar farVal);
kmMat4* kmMat4LookAt(kmMat4* pOut, const struct kmVec3* pEye, const struct kmVec3* pCenter, const struct kmVec3* pUp);
kmMat4* kmMat4RotationAxisAngle(kmMat4* pOut, const struct kmVec3* axis, kmScalar radians);
struct kmMat3* kmMat4ExtractRotation(struct kmMat3* pOut, const kmMat4* pIn);
struct kmPlane* kmMat4ExtractPlane(struct kmPlane* pOut, const kmMat4* pIn, const kmEnum plane);
struct kmVec3* kmMat4RotationToAxisAngle(struct kmVec3* pAxis, kmScalar* radians, const kmMat4* pIn);
#ifdef __cplusplus
}
#endif
#endif /* MAT4_H_INCLUDED */

View File

@ -0,0 +1,254 @@
/*
Copyright (c) 2008, Luke Benstead.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <assert.h>
#include <stdlib.h>
#include "vec3.h"
#include "vec4.h"
#include "plane.h"
#include "mat4.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* kmPlaneFromNormalAndDistance(kmPlane* plane, const struct kmVec3* normal, const kmScalar dist) {
plane->a = normal->x;
plane->b = normal->y;
plane->c = normal->z;
plane->d = dist;
return plane;
}
kmPlane* kmPlaneFromPointAndNormal(kmPlane* pOut, const kmVec3* pPoint, const kmVec3* pNormal)
{
/*
Planea = Nx
Planeb = Ny
Planec = Nz
Planed = NP
*/
pOut->a = pNormal->x;
pOut->b = pNormal->y;
pOut->c = pNormal->z;
pOut->d = -kmVec3Dot(pNormal, pPoint);
return pOut;
}
/**
* Creates a plane from 3 points. The result is stored in pOut.
* pOut is returned.
*/
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 = nA
*/
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;
}
// Added by tlensing (http://icedcoffee-framework.org)
kmVec3* kmPlaneIntersectLine(kmVec3* pOut, const kmPlane* pP, const kmVec3* pV1, const kmVec3* pV2)
{
/*
n = (Planea, Planeb, Planec)
d = V U
Out = U d(Pd + nU)(dn) [iff dn 0]
*/
kmVec3 d; // direction from V1 to V2
kmVec3Subtract(&d, pV2, pV1); // Get the direction vector
kmVec3 n; // plane normal
n.x = pP->a;
n.y = pP->b;
n.z = pP->c;
kmVec3Normalize(&n, &n);
kmScalar nt = -(n.x * pV1->x + n.y * pV1->y + n.z * pV1->z + pP->d);
kmScalar dt = (n.x * d.x + n.y * d.y + n.z * d.z);
if (fabs(dt) < kmEpsilon) {
pOut = NULL;
return pOut; // line parallel or contained
}
kmScalar t = nt/dt;
pOut->x = pV1->x + d.x * t;
pOut->y = pV1->y + d.y * t;
pOut->z = pV1->z + d.z * t;
return pOut;
}
kmPlane* kmPlaneNormalize(kmPlane* pOut, const kmPlane* pP)
{
kmVec3 n;
kmScalar l = 0;
if (!pP->a && !pP->b && !pP->c) {
pOut->a = pP->a;
pOut->b = pP->b;
pOut->c = pP->c;
pOut->d = pP->d;
return pOut;
}
n.x = pP->a;
n.y = pP->b;
n.z = pP->c;
l = 1.0f / 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 && "Not implemented");
return NULL;
}
/**
* Returns POINT_INFRONT_OF_PLANE if pP is infront of pIn. Returns
* POINT_BEHIND_PLANE if it is behind. Returns POINT_ON_PLANE otherwise
*/
KM_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.
kmScalar 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 > kmEpsilon) return POINT_INFRONT_OF_PLANE;
if(distance < -kmEpsilon) return POINT_BEHIND_PLANE;
return POINT_ON_PLANE;
}
kmPlane* kmPlaneExtractFromMat4(kmPlane* pOut, const struct kmMat4* pIn, kmInt row) {
int scale = (row < 0) ? -1 : 1;
row = abs(row) - 1;
pOut->a = pIn->mat[3] + scale * pIn->mat[row];
pOut->b = pIn->mat[7] + scale * pIn->mat[row + 4];
pOut->c = pIn->mat[11] + scale * pIn->mat[row + 8];
pOut->d = pIn->mat[15] + scale * pIn->mat[row + 12];
return kmPlaneNormalize(pOut, pOut);
}
kmVec3* kmPlaneGetIntersection(kmVec3* pOut, const kmPlane* p1, const kmPlane* p2, const kmPlane* p3) {
kmVec3 n1, n2, n3, cross;
kmVec3 r1, r2, r3;
double denom = 0;
kmVec3Fill(&n1, p1->a, p1->b, p1->c);
kmVec3Fill(&n2, p2->a, p2->b, p2->c);
kmVec3Fill(&n3, p3->a, p3->b, p3->c);
kmVec3Cross(&cross, &n2, &n3);
denom = kmVec3Dot(&n1, &cross);
if (kmAlmostEqual(denom, 0.0)) {
return NULL;
}
kmVec3Cross(&r1, &n2, &n3);
kmVec3Cross(&r2, &n3, &n1);
kmVec3Cross(&r3, &n1, &n2);
kmVec3Scale(&r1, &r1, -p1->d);
kmVec3Scale(&r2, &r2, p2->d);
kmVec3Scale(&r3, &r3, p3->d);
kmVec3Subtract(pOut, &r1, &r2);
kmVec3Subtract(pOut, pOut, &r3);
kmVec3Scale(pOut, pOut, 1.0 / denom);
//p = -d1 * ( n2.Cross ( n3 ) ) d2 * ( n3.Cross ( n1 ) ) d3 * ( n1.Cross ( n2 ) ) / denom;
return pOut;
}
kmPlane* kmPlaneFill(kmPlane* plane, kmScalar a, kmScalar b, kmScalar c, kmScalar d) {
plane->a = a;
plane->b = b;
plane->c = c;
plane->d = d;
return plane;
}

View File

@ -33,7 +33,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define KM_PLANE_NEAR 4
#define KM_PLANE_FAR 5
#include "CCPlatformMacros.h"
#include "utility.h"
struct kmVec3;
@ -41,28 +40,33 @@ struct kmVec4;
struct kmMat4;
typedef struct kmPlane {
kmScalar a, b, c, d;
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;
typedef enum KM_POINT_CLASSIFICATION {
POINT_BEHIND_PLANE = -1,
POINT_ON_PLANE = 0,
POINT_INFRONT_OF_PLANE = 1
} KM_POINT_CLASSIFICATION;
CC_DLL const kmScalar kmPlaneDot(const kmPlane* pP, const struct kmVec4* pV);
CC_DLL const kmScalar kmPlaneDotCoord(const kmPlane* pP, const struct kmVec3* pV);
CC_DLL const kmScalar kmPlaneDotNormal(const kmPlane* pP, const struct kmVec3* pV);
CC_DLL kmPlane* const kmPlaneFromPointNormal(kmPlane* pOut, const struct kmVec3* pPoint, const struct kmVec3* pNormal);
CC_DLL kmPlane* const kmPlaneFromPoints(kmPlane* pOut, const struct kmVec3* p1, const struct kmVec3* p2, const struct kmVec3* p3);
CC_DLL kmVec3* const kmPlaneIntersectLine(struct kmVec3* pOut, const kmPlane* pP, const struct kmVec3* pV1, const struct kmVec3* pV2);
CC_DLL kmPlane* const kmPlaneNormalize(kmPlane* pOut, const kmPlane* pP);
CC_DLL kmPlane* const kmPlaneScale(kmPlane* pOut, const kmPlane* pP, kmScalar s);
CC_DLL const POINT_CLASSIFICATION kmPlaneClassifyPoint(const kmPlane* pIn, const kmVec3* pP); /** Classifies a point against a plane */
kmPlane* kmPlaneFill(kmPlane* plane, float a, float b, float c, float d);
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* kmPlaneFromNormalAndDistance(kmPlane* plane, const struct kmVec3* normal, const kmScalar dist);
kmPlane* kmPlaneFromPointAndNormal(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);
struct 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);
KM_POINT_CLASSIFICATION kmPlaneClassifyPoint(const kmPlane* pIn, const struct kmVec3* pP); /** Classifys a point against a plane */
kmPlane* kmPlaneExtractFromMat4(kmPlane* pOut, const struct kmMat4* pIn, kmInt row);
struct kmVec3* kmPlaneGetIntersection(struct kmVec3* pOut, const kmPlane* p1, const kmPlane* p2, const kmPlane* p3);
#ifdef __cplusplus
}

View File

@ -0,0 +1,609 @@
/*
Copyright (c) 2008, Luke Benstead.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <assert.h>
#include <memory.h>
#include <string.h>
#include "mat4.h"
#include "utility.h"
#include "mat3.h"
#include "vec3.h"
#include "quaternion.h"
int kmQuaternionAreEqual(const kmQuaternion* p1, const kmQuaternion* 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)) &&
(p1->w < (p2->w + kmEpsilon) && p1->w > (p2->w - kmEpsilon))) {
return 1;
}
return 0;
}
kmQuaternion* kmQuaternionFill(kmQuaternion* pOut, kmScalar x, kmScalar y, kmScalar z, kmScalar w) {
pOut->x = x;
pOut->y = y;
pOut->z = z;
pOut->w = 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;
}
pOut->x = -pIn->x;
pOut->y = -pIn->y;
pOut->z = -pIn->z;
pOut->w = pIn->w;
return pOut;
}
///< Returns true if the quaternion is an identity quaternion
int 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 sqrt(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* qu1,
const kmQuaternion* qu2)
{
kmQuaternion tmp1, tmp2;
kmQuaternionAssign(&tmp1, qu1);
kmQuaternionAssign(&tmp2, qu2);
//Just aliasing
kmQuaternion* q1 = &tmp1;
kmQuaternion* q2 = &tmp2;
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;
pOut->w = q1->w * q2->w - q1->x * q2->x - q1->y * q2->y - q1->z * q2->z;
return pOut;
}
///< Normalizes a quaternion
kmQuaternion* kmQuaternionNormalize(kmQuaternion* pOut,
const kmQuaternion* pIn)
{
kmScalar length = kmQuaternionLength(pIn);
if (fabs(length) < kmEpsilon)
{
pOut->x = 0.0;
pOut->y = 0.0;
pOut->z = 0.0;
pOut->w = 0.0;
return pOut;
}
kmQuaternionFill(pOut,
pOut->x / length,
pOut->y / length,
pOut->z / length,
pOut->w / length
);
return pOut;
}
///< Rotates a quaternion around an axis
kmQuaternion* kmQuaternionRotationAxisAngle(kmQuaternion* pOut,
const kmVec3* pV,
kmScalar angle)
{
kmScalar rad = angle * 0.5f;
kmScalar scale = sinf(rad);
pOut->x = pV->x * scale;
pOut->y = pV->y * scale;
pOut->z = pV->z * scale;
pOut->w = cosf(rad);
kmQuaternionNormalize(pOut, pOut);
return pOut;
}
///< Creates a quaternion from a rotation matrix
kmQuaternion* kmQuaternionRotationMatrix(kmQuaternion* pOut,
const kmMat3* 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 x, y, z, w;
kmScalar *pMatrix = NULL;
kmScalar m4x4[16] = {0};
kmScalar scale = 0.0f;
kmScalar diagonal = 0.0f;
if(!pIn) {
return NULL;
}
/* 0 3 6
1 4 7
2 5 8
0 1 2 3
4 5 6 7
8 9 10 11
12 13 14 15*/
m4x4[0] = pIn->mat[0];
m4x4[1] = pIn->mat[3];
m4x4[2] = pIn->mat[6];
m4x4[4] = pIn->mat[1];
m4x4[5] = pIn->mat[4];
m4x4[6] = pIn->mat[7];
m4x4[8] = pIn->mat[2];
m4x4[9] = pIn->mat[5];
m4x4[10] = pIn->mat[8];
m4x4[15] = 1;
pMatrix = &m4x4[0];
diagonal = pMatrix[0] + pMatrix[5] + pMatrix[10] + 1;
if(diagonal > kmEpsilon) {
// Calculate the scale of the diagonal
scale = (kmScalar)sqrt(diagonal ) * 2;
// Calculate the x, y, x and w of the quaternion through the respective equation
x = ( pMatrix[9] - pMatrix[6] ) / scale;
y = ( pMatrix[2] - pMatrix[8] ) / scale;
z = ( pMatrix[4] - pMatrix[1] ) / scale;
w = 0.25f * scale;
}
else
{
// If the first element of the diagonal is the greatest value
if ( pMatrix[0] > pMatrix[5] && pMatrix[0] > pMatrix[10] )
{
// Find the scale according to the first element, and double that value
scale = (kmScalar)sqrt( 1.0f + pMatrix[0] - pMatrix[5] - pMatrix[10] ) * 2.0f;
// Calculate the x, y, x and w of the quaternion through the respective equation
x = 0.25f * scale;
y = (pMatrix[4] + pMatrix[1] ) / scale;
z = (pMatrix[2] + pMatrix[8] ) / scale;
w = (pMatrix[9] - pMatrix[6] ) / scale;
}
// Else if the second element of the diagonal is the greatest value
else if (pMatrix[5] > pMatrix[10])
{
// Find the scale according to the second element, and double that value
scale = (kmScalar)sqrt( 1.0f + pMatrix[5] - pMatrix[0] - pMatrix[10] ) * 2.0f;
// Calculate the x, y, x and w of the quaternion through the respective equation
x = (pMatrix[4] + pMatrix[1] ) / scale;
y = 0.25f * scale;
z = (pMatrix[9] + pMatrix[6] ) / scale;
w = (pMatrix[2] - pMatrix[8] ) / scale;
}
// Else the third element of the diagonal is the greatest value
else
{
// Find the scale according to the third element, and double that value
scale = (kmScalar)sqrt( 1.0f + pMatrix[10] - pMatrix[0] - pMatrix[5] ) * 2.0f;
// Calculate the x, y, x and w of the quaternion through the respective equation
x = (pMatrix[2] + pMatrix[8] ) / scale;
y = (pMatrix[9] + pMatrix[6] ) / scale;
z = 0.25f * scale;
w = (pMatrix[4] - pMatrix[1] ) / scale;
}
}
pOut->x = x;
pOut->y = y;
pOut->z = z;
pOut->w = w;
return pOut;
}
///< Create a quaternion from yaw, pitch and roll
kmQuaternion* kmQuaternionRotationPitchYawRoll(kmQuaternion* pOut,
kmScalar pitch,
kmScalar yaw,
kmScalar roll)
{
assert(pitch <= 2*kmPI);
assert(yaw <= 2*kmPI);
assert(roll <= 2*kmPI);
// Finds the Sin and Cosin for each half angles.
float sY = sinf(yaw * 0.5);
float cY = cosf(yaw * 0.5);
float sZ = sinf(roll * 0.5);
float cZ = cosf(roll * 0.5);
float sX = sinf(pitch * 0.5);
float cX = cosf(pitch * 0.5);
// Formula to construct a new Quaternion based on Euler Angles.
pOut->w = cY * cZ * cX - sY * sZ * sX;
pOut->x = sY * sZ * cX + cY * cZ * sX;
pOut->y = sY * cZ * cX + cY * sZ * sX;
pOut->z = cY * sZ * cX - sY * cZ * sX;
return pOut;
}
///< Interpolate between 2 quaternions
kmQuaternion* kmQuaternionSlerp(kmQuaternion* pOut,
const kmQuaternion* q1,
const kmQuaternion* q2,
kmScalar t)
{
kmScalar dot = kmQuaternionDot(q1, q2);
const double DOT_THRESHOLD = 0.9995;
if (dot > DOT_THRESHOLD) {
kmQuaternion diff;
kmQuaternionSubtract(&diff, q2, q1);
kmQuaternionScale(&diff, &diff, t);
kmQuaternionAdd(pOut, q1, &diff);
kmQuaternionNormalize(pOut, pOut);
return pOut;
}
dot = kmClamp(dot, -1, 1);
kmScalar theta_0 = acos(dot);
kmScalar theta = theta_0 * t;
kmQuaternion tmp;
kmQuaternionScale(&tmp, q1, dot);
kmQuaternionSubtract(&tmp, q2, &tmp);
kmQuaternionNormalize(&tmp, &tmp);
kmQuaternion t1, t2;
kmQuaternionScale(&t1, q1, cos(theta));
kmQuaternionScale(&t2, &tmp, sin(theta));
kmQuaternionAdd(pOut, &t1, &t2);
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 < 2*kmPI + kmEpsilon && scale > 2*kmPI - 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.0f; // 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(kmScalar) * 4);
return pOut;
}
kmQuaternion* kmQuaternionSubtract(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;
}
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;
kmScalar a;
kmVec3Assign(&v1, vec1);
kmVec3Assign(&v2, vec2);
kmVec3Normalize(&v1, &v1);
kmVec3Normalize(&v2, &v2);
a = kmVec3Dot(&v1, &v2);
if (a >= 1.0) {
kmQuaternionIdentity(pOut);
return pOut;
}
if (a < (1e-6f - 1.0f)) {
if (fabs(kmVec3LengthSq(fallback)) < kmEpsilon) {
kmQuaternionRotationAxisAngle(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);
kmQuaternionRotationAxisAngle(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.5f;
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.0f * q->w));
kmVec3Scale(&uuv, &uuv, 2.0f);
kmVec3Add(pOut, v, &uv);
kmVec3Add(pOut, pOut, &uuv);
return pOut;
}
kmVec3* kmQuaternionGetUpVec3(kmVec3* pOut, const kmQuaternion* pIn) {
return kmQuaternionMultiplyVec3(pOut, pIn, &KM_VEC3_POS_Y);
}
kmVec3* kmQuaternionGetRightVec3(kmVec3* pOut, const kmQuaternion* pIn) {
return kmQuaternionMultiplyVec3(pOut, pIn, &KM_VEC3_POS_X);
}
kmVec3* kmQuaternionGetForwardVec3RH(kmVec3* pOut, const kmQuaternion* pIn) {
return kmQuaternionMultiplyVec3(pOut, pIn, &KM_VEC3_NEG_Z);
}
kmVec3* kmQuaternionGetForwardVec3LH(kmVec3* pOut, const kmQuaternion* pIn) {
return kmQuaternionMultiplyVec3(pOut, pIn, &KM_VEC3_POS_Z);
}
kmScalar kmQuaternionGetPitch(const kmQuaternion* q) {
float result = atan2(2 * (q->y * q->z + q->w * q->x), q->w * q->w - q->x * q->x - q->y * q->y + q->z * q->z);
return result;
}
kmScalar kmQuaternionGetYaw(const kmQuaternion* q) {
float result = asin(-2 * (q->x * q->z - q->w * q->y));
return result;
}
kmScalar kmQuaternionGetRoll(const kmQuaternion* q) {
float result = atan2(2 * (q->x * q->y + q->w * q->z), q->w * q->w + q->x * q->x - q->y * q->y - q->z * q->z);
return result;
}
kmQuaternion* kmQuaternionLookRotation(kmQuaternion* pOut, const kmVec3* direction, const kmVec3* up) {
kmMat3 tmp;
kmMat3LookAt(&tmp, &KM_VEC3_ZERO, direction, up);
return kmQuaternionNormalize(pOut, kmQuaternionRotationMatrix(pOut, &tmp));
/*
if(!direction->x && !direction->y && !direction->z) {
return kmQuaternionIdentity(pOut);
}
kmVec3 right;
kmVec3Cross(&right, up, direction);
pOut->w = sqrtf(1.0f + right.x + up->y + direction->z) * 0.5f;
float w4_recip = 1.0f / (4.0f * pOut->w);
pOut->x = (up->z - direction->y) * w4_recip;
pOut->y = (direction->x - right.z) * w4_recip;
pOut->z = (right.y - up->x) * w4_recip;
return kmQuaternionNormalize(pOut, pOut);*/
}

View File

@ -0,0 +1,125 @@
/*
Copyright (c) 2008, Luke Benstead.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef QUATERNION_H_INCLUDED
#define QUATERNION_H_INCLUDED
#ifdef __cplusplus
extern "C" {
#endif
#include "utility.h"
struct kmMat4;
struct kmMat3;
struct kmVec3;
typedef struct kmQuaternion {
kmScalar x;
kmScalar y;
kmScalar z;
kmScalar w;
} kmQuaternion;
int kmQuaternionAreEqual(const kmQuaternion* p1, const kmQuaternion* p2);
kmQuaternion* kmQuaternionFill(kmQuaternion* pOut, kmScalar x, kmScalar y, kmScalar z, kmScalar w);
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
int 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* kmQuaternionRotationAxisAngle(kmQuaternion* pOut, const struct kmVec3* pV, kmScalar angle);
///< Creates a quaternion from a rotation matrix
kmQuaternion* kmQuaternionRotationMatrix(kmQuaternion* pOut, const struct kmMat3* pIn);
///< Create a quaternion from yaw, pitch and roll
kmQuaternion* kmQuaternionRotationPitchYawRoll(kmQuaternion* pOut, kmScalar pitch, kmScalar yaw, 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, struct 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* kmQuaternionSubtract(kmQuaternion* pOut, const kmQuaternion* pQ1, const kmQuaternion* pQ2);
kmQuaternion* kmQuaternionRotationBetweenVec3(kmQuaternion* pOut, const struct kmVec3* vec1, const struct kmVec3* vec2, const struct kmVec3* fallback);
struct kmVec3* kmQuaternionMultiplyVec3(struct kmVec3* pOut, const kmQuaternion* q, const struct kmVec3* v);
kmVec3* kmQuaternionGetUpVec3(kmVec3* pOut, const kmQuaternion* pIn);
kmVec3* kmQuaternionGetRightVec3(kmVec3* pOut, const kmQuaternion* pIn);
kmVec3* kmQuaternionGetForwardVec3RH(kmVec3* pOut, const kmQuaternion* pIn);
kmVec3* kmQuaternionGetForwardVec3LH(kmVec3* pOut, const kmQuaternion* pIn);
kmScalar kmQuaternionGetPitch(const kmQuaternion* q);
kmScalar kmQuaternionGetYaw(const kmQuaternion* q);
kmScalar kmQuaternionGetRoll(const kmQuaternion* q);
kmQuaternion* kmQuaternionLookRotation(kmQuaternion* pOut, const kmVec3* direction, const kmVec3* up);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,200 @@
#include <assert.h>
#include <stdio.h>
#include "ray2.h"
void kmRay2Fill(kmRay2* ray, kmScalar px, kmScalar py, kmScalar vx, kmScalar vy) {
ray->start.x = px;
ray->start.y = py;
ray->dir.x = vx;
ray->dir.y = vy;
}
kmBool kmRay2IntersectLineSegment(const kmRay2* ray, const kmVec2* p1, const kmVec2* p2, kmVec2* intersection) {
kmScalar x1 = ray->start.x;
kmScalar y1 = ray->start.y;
kmScalar x2 = ray->start.x + ray->dir.x;
kmScalar y2 = ray->start.y + ray->dir.y;
kmScalar x3 = p1->x;
kmScalar y3 = p1->y;
kmScalar x4 = p2->x;
kmScalar y4 = p2->y;
kmScalar denom = (y4 -y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);
//If denom is zero, the lines are parallel
if(denom > -kmEpsilon && denom < kmEpsilon) {
return KM_FALSE;
}
kmScalar ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / denom;
kmScalar ub = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) / denom;
kmScalar x = x1 + ua * (x2 - x1);
kmScalar y = y1 + ua * (y2 - y1);
if((0.0 <= ua) && (ua <= 1.0) && (0.0 <= ub) && (ub <= 1.0)) {
intersection->x = x;
intersection->y = y;
return KM_TRUE;
}
return KM_FALSE;
}
void calculate_line_normal(kmVec2 p1, kmVec2 p2, kmVec2 other_point, kmVec2* normal_out) {
/*
A = (3,4)
B = (2,1)
C = (1,3)
AB = (2,1) - (3,4) = (-1,-3)
AC = (1,3) - (3,4) = (-2,-1)
N = n(AB) = (-3,1)
D = dot(N,AC) = 6 + -1 = 5
since D > 0:
N = -N = (3,-1)
*/
kmVec2 edge, other_edge;
kmVec2Subtract(&edge, &p2, &p1);
kmVec2Subtract(&other_edge, &other_point, &p1);
kmVec2Normalize(&edge, &edge);
kmVec2Normalize(&other_edge, &other_edge);
kmVec2 n;
n.x = edge.y;
n.y = -edge.x;
kmScalar d = kmVec2Dot(&n, &other_edge);
if(d > 0.0f) {
n.x = -n.x;
n.y = -n.y;
}
normal_out->x = n.x;
normal_out->y = n.y;
kmVec2Normalize(normal_out, normal_out);
}
kmBool kmRay2IntersectTriangle(const kmRay2* ray, const kmVec2* p1, const kmVec2* p2, const kmVec2* p3, kmVec2* intersection, kmVec2* normal_out, kmScalar* distance_out) {
kmVec2 intersect;
kmVec2 final_intersect;
kmVec2 normal;
kmScalar distance = 10000.0f;
kmBool intersected = KM_FALSE;
if(kmRay2IntersectLineSegment(ray, p1, p2, &intersect)) {
kmVec2 tmp;
kmScalar this_distance = kmVec2Length(kmVec2Subtract(&tmp, &intersect, &ray->start));
kmVec2 this_normal;
calculate_line_normal(*p1, *p2, *p3, &this_normal);
if(this_distance < distance && kmVec2Dot(&this_normal, &ray->dir) < 0.0f) {
final_intersect.x = intersect.x;
final_intersect.y = intersect.y;
distance = this_distance;
kmVec2Assign(&normal, &this_normal);
intersected = KM_TRUE;
}
}
if(kmRay2IntersectLineSegment(ray, p2, p3, &intersect)) {
kmVec2 tmp;
kmScalar this_distance = kmVec2Length(kmVec2Subtract(&tmp, &intersect, &ray->start));
kmVec2 this_normal;
calculate_line_normal(*p2, *p3, *p1, &this_normal);
if(this_distance < distance && kmVec2Dot(&this_normal, &ray->dir) < 0.0f) {
final_intersect.x = intersect.x;
final_intersect.y = intersect.y;
distance = this_distance;
kmVec2Assign(&normal, &this_normal);
intersected = KM_TRUE;
}
}
if(kmRay2IntersectLineSegment(ray, p3, p1, &intersect)) {
kmVec2 tmp;
kmScalar this_distance = kmVec2Length(kmVec2Subtract(&tmp, &intersect, &ray->start));
kmVec2 this_normal;
calculate_line_normal(*p3, *p1, *p2, &this_normal);
if(this_distance < distance && kmVec2Dot(&this_normal, &ray->dir) < 0.0f) {
final_intersect.x = intersect.x;
final_intersect.y = intersect.y;
distance = this_distance;
kmVec2Assign(&normal, &this_normal);
intersected = KM_TRUE;
}
}
if(intersected) {
intersection->x = final_intersect.x;
intersection->y = final_intersect.y;
if(normal_out) {
normal_out->x = normal.x;
normal_out->y = normal.y;
}
if(distance) {
*distance_out = distance;
}
}
return intersected;
}
kmBool kmRay2IntersectBox(const kmRay2* ray, const kmVec2* p1, const kmVec2* p2, const kmVec2* p3, const kmVec2* p4,
kmVec2* intersection, kmVec2* normal_out) {
kmBool intersected = KM_FALSE;
kmVec2 intersect, final_intersect, normal;
kmScalar distance = 10000.0f;
const kmVec2* points[4];
points[0] = p1;
points[1] = p2;
points[2] = p3;
points[3] = p4;
unsigned int i = 0;
for(; i < 4; ++i) {
const kmVec2* this_point = points[i];
const kmVec2* next_point = (i == 3) ? points[0] : points[i+1];
const kmVec2* other_point = (i == 3 || i == 0) ? points[1] : points[0];
if(kmRay2IntersectLineSegment(ray, this_point, next_point, &intersect)) {
kmVec2 tmp;
kmScalar this_distance = kmVec2Length(kmVec2Subtract(&tmp, &intersect, &ray->start));
kmVec2 this_normal;
calculate_line_normal(*this_point, *next_point, *other_point, &this_normal);
if(this_distance < distance && kmVec2Dot(&this_normal, &ray->dir) < 0.0f) {
kmVec2Assign(&final_intersect, &intersect);
distance = this_distance;
intersected = KM_TRUE;
kmVec2Assign(&normal, &this_normal);
}
}
}
if(intersected) {
intersection->x = final_intersect.x;
intersection->y = final_intersect.y;
if(normal_out) {
normal_out->x = normal.x;
normal_out->y = normal.y;
}
}
return intersected;
}
kmBool kmRay2IntersectCircle(const kmRay2* ray, const kmVec2 centre, const kmScalar radius, kmVec2* intersection) {
assert(0 && "Not implemented");
return KM_TRUE;
}

View File

@ -26,7 +26,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef RAY_2_H
#define RAY_2_H
#include "CCPlatformMacros.h"
#include "utility.h"
#include "vec2.h"
@ -39,10 +38,14 @@ typedef struct kmRay2 {
kmVec2 dir;
} kmRay2;
CC_DLL void kmRay2Fill(kmRay2* ray, kmScalar px, kmScalar py, kmScalar vx, kmScalar vy);
CC_DLL kmBool kmRay2IntersectLineSegment(const kmRay2* ray, const kmVec2* p1, const kmVec2* p2, kmVec2* intersection);
CC_DLL kmBool kmRay2IntersectTriangle(const kmRay2* ray, const kmVec2* p1, const kmVec2* p2, const kmVec2* p3, kmVec2* intersection, kmVec2* normal_out);
CC_DLL kmBool kmRay2IntersectCircle(const kmRay2* ray, const kmVec2 centre, const kmScalar radius, kmVec2* intersection);
void kmRay2Fill(kmRay2* ray, kmScalar px, kmScalar py, kmScalar vx, kmScalar vy);
kmBool kmRay2IntersectLineSegment(const kmRay2* ray, const kmVec2* p1, const kmVec2* p2, kmVec2* intersection);
kmBool kmRay2IntersectTriangle(const kmRay2* ray, const kmVec2* p1, const kmVec2* p2, const kmVec2* p3, kmVec2* intersection, kmVec2* normal_out, kmScalar* distance);
kmBool kmRay2IntersectBox(const kmRay2* ray, const kmVec2* p1, const kmVec2* p2, const kmVec2* p3, const kmVec2* p4,
kmVec2* intersection, kmVec2* normal_out);
kmBool kmRay2IntersectCircle(const kmRay2* ray, const kmVec2 centre, const kmScalar radius, kmVec2* intersection);
#ifdef __cplusplus
}

View File

@ -0,0 +1,47 @@
#include "plane.h"
#include "ray3.h"
kmRay3* kmRay3Fill(kmRay3* ray, kmScalar px, kmScalar py, kmScalar pz, kmScalar vx, kmScalar vy, kmScalar vz) {
ray->start.x = px;
ray->start.y = py;
ray->start.z = pz;
ray->dir.x = vx;
ray->dir.y = vy;
ray->dir.z = vz;
return ray;
}
kmRay3* kmRay3FromPointAndDirection(kmRay3* ray, const kmVec3* point, const kmVec3* direction) {
kmVec3Assign(&ray->start, point);
kmVec3Assign(&ray->dir, direction);
return ray;
}
kmBool kmRay3IntersectPlane(kmVec3* pOut, const kmRay3* ray, const kmPlane* plane) {
//t = - (A*org.x + B*org.y + C*org.z + D) / (A*dir.x + B*dir.y + C*dir.z )
kmScalar d = (plane->a * ray->dir.x +
plane->b * ray->dir.y +
plane->c * ray->dir.z);
if(d == 0)
{
return KM_FALSE;
}
kmScalar t = -(plane->a * ray->start.x +
plane->b * ray->start.y +
plane->c * ray->start.z + plane->d) / d;
if(t < 0)
{
return KM_FALSE;
}
kmVec3 scaled_dir;
kmVec3Scale(&scaled_dir, &ray->dir, t);
kmVec3Add(pOut, &ray->start, &scaled_dir);
return KM_TRUE;
}

View File

@ -0,0 +1,26 @@
#ifndef RAY3_H
#define RAY3_H
#include "utility.h"
#include "vec3.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct kmRay3 {
kmVec3 start;
kmVec3 dir;
} kmRay3;
struct kmPlane;
kmRay3* kmRay3Fill(kmRay3* ray, kmScalar px, kmScalar py, kmScalar pz, kmScalar vx, kmScalar vy, kmScalar vz);
kmRay3* kmRay3FromPointAndDirection(kmRay3* ray, const kmVec3* point, const kmVec3* direction);
kmBool kmRay3IntersectPlane(kmVec3* pOut, const kmRay3* ray, const struct kmPlane* plane);
#ifdef __cplusplus
}
#endif
#endif // RAY3_H

View File

@ -23,27 +23,27 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "kazmath/utility.h"
#include "utility.h"
/**
* Returns the square of s (e.g. s*s)
*/
kmScalar kmSQR(kmScalar s) {
return s*s;
return s*s;
}
/**
* Returns degrees as radians.
*/
kmScalar kmDegreesToRadians(kmScalar degrees) {
return degrees * kmPIOver180;
return degrees * kmPIOver180;
}
/**
* Returns radians as degrees
*/
kmScalar kmRadiansToDegrees(kmScalar radians) {
return radians * kmPIUnder180;
return radians * kmPIUnder180;
}
kmScalar kmMin(kmScalar lhs, kmScalar rhs) {
@ -57,3 +57,13 @@ kmScalar kmMax(kmScalar lhs, kmScalar rhs) {
kmBool kmAlmostEqual(kmScalar lhs, kmScalar rhs) {
return (lhs + kmEpsilon > rhs && lhs - kmEpsilon < rhs);
}
kmScalar kmClamp(kmScalar x, kmScalar min, kmScalar max)
{
return x < min ? min : (x > max ? max : x);
}
kmScalar kmLerp(kmScalar x, kmScalar y, kmScalar t )
{
return x + t * ( y - x );
}

View File

@ -26,21 +26,37 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef UTILITY_H_INCLUDED
#define UTILITY_H_INCLUDED
#include "CCPlatformMacros.h"
#include <math.h>
#ifndef kmScalar
#ifdef USE_DOUBLE_PRECISION
#define kmScalar double
#else
#define kmScalar float
#endif
#endif
#ifndef kmBool
#define kmBool unsigned char
#endif
#ifndef kmUchar
#define kmUchar unsigned char
#endif
#ifndef kmEnum
#define kmEnum unsigned int
#endif
#ifndef kmUint
#define kmUint unsigned int
#endif
#ifndef kmInt
#define kmInt int
#endif
#ifndef KM_FALSE
#define KM_FALSE 0
#endif
@ -49,24 +65,29 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define KM_TRUE 1
#endif
#define kmPI 3.141592f
#define kmPIOver180 0.017453f // PI / 180
#define kmPIUnder180 57.295779f // 180 / PI
#define kmEpsilon 1.0 / 64.0
#define kmPI 3.14159265358979323846f
#define kmPIOver180 (kmPI / 180.0f)
#define kmPIUnder180 (180.0 / kmPI)
#define kmEpsilon 0.0001
#define KM_CONTAINS_NONE 0
#define KM_CONTAINS_PARTIAL 1
#define KM_CONTAINS_ALL 2
#ifdef __cplusplus
extern "C" {
#endif
CC_DLL kmScalar kmSQR(kmScalar s);
CC_DLL kmScalar kmDegreesToRadians(kmScalar degrees);
CC_DLL kmScalar kmRadiansToDegrees(kmScalar radians);
extern kmScalar kmSQR(kmScalar s);
extern kmScalar kmDegreesToRadians(kmScalar degrees);
extern kmScalar kmRadiansToDegrees(kmScalar radians);
CC_DLL kmScalar kmMin(kmScalar lhs, kmScalar rhs);
CC_DLL kmScalar kmMax(kmScalar lhs, kmScalar rhs);
CC_DLL kmBool kmAlmostEqual(kmScalar lhs, kmScalar rhs);
extern kmScalar kmMin(kmScalar lhs, kmScalar rhs);
extern kmScalar kmMax(kmScalar lhs, kmScalar rhs);
extern kmBool kmAlmostEqual(kmScalar lhs, kmScalar rhs);
extern kmScalar kmClamp(kmScalar x, kmScalar min, kmScalar max);
extern kmScalar kmLerp(kmScalar x, kmScalar y, kmScalar factor);
#ifdef __cplusplus
}

View File

@ -0,0 +1,239 @@
/*
Copyright (c) 2008, Luke Benstead.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <assert.h>
#include <stdlib.h>
#include "mat3.h"
#include "vec2.h"
#include "utility.h"
const kmVec2 KM_VEC2_POS_Y = { 0, 1 };
const kmVec2 KM_VEC2_NEG_Y = { 0, -1 };
const kmVec2 KM_VEC2_NEG_X = { -1, 0 };
const kmVec2 KM_VEC2_POS_X = { 1, 0 };
const kmVec2 KM_VEC2_ZERO = { 0, 0 };
kmVec2* kmVec2Fill(kmVec2* pOut, kmScalar x, kmScalar y)
{
pOut->x = x;
pOut->y = y;
return pOut;
}
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* kmVec2Lerp(kmVec2* pOut, const kmVec2* pV1, const kmVec2* pV2, kmScalar t) {
pOut->x = pV1->x + t * ( pV2->x - pV1->x );
pOut->y = pV1->y + t * ( pV2->y - pV1->y );
return pOut;
}
kmVec2* kmVec2Normalize(kmVec2* pOut, const kmVec2* pIn)
{
if (!pIn->x && !pIn->y)
return kmVec2Assign(pOut, pIn);
kmScalar l = 1.0f / kmVec2Length(pIn);
kmVec2 v;
v.x = pIn->x * l;
v.y = pIn->y * l;
pOut->x = v.x;
pOut->y = v.y;
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;
}
kmScalar kmVec2Cross(const kmVec2* pV1, const kmVec2* pV2)
{
return pV1->x * pV2->y - pV1->y * pV2->x;
}
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* kmVec2Mul( kmVec2* pOut,const kmVec2* pV1, const kmVec2* pV2 ) {
pOut->x = pV1->x * pV2->x;
pOut->y = pV1->y * pV2->y;
return pOut;
}
kmVec2* kmVec2Div( kmVec2* pOut,const kmVec2* pV1, const kmVec2* pV2 ) {
if ( pV2->x && pV2->y ){
pOut->x = pV1->x / pV2->x;
pOut->y = pV1->y / pV2->y;
}
return pOut;
}
kmVec2* kmVec2Transform(kmVec2* pOut, const kmVec2* pV, const kmMat3* pM)
{
kmVec2 v;
v.x = pV->x * pM->mat[0] + pV->y * pM->mat[3] + pM->mat[6];
v.y = pV->x * pM->mat[1] + pV->y * pM->mat[4] + pM->mat[7];
pOut->x = v.x;
pOut->y = v.y;
return pOut;
}
kmVec2* kmVec2TransformCoord(kmVec2* pOut, const kmVec2* pV, const kmMat3* pM)
{
assert(0);
return NULL;
}
kmVec2* kmVec2Scale(kmVec2* pOut, const kmVec2* pIn, const kmScalar s)
{
pOut->x = pIn->x * s;
pOut->y = pIn->y * s;
return pOut;
}
int 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)
);
}
/**
* Assigns pIn to pOut. Returns pOut. If pIn and pOut are the same
* then nothing happens but pOut is still returned
*/
kmVec2* kmVec2Assign(kmVec2* pOut, const kmVec2* pIn) {
if (pOut == pIn) {
return pOut;
}
pOut->x = pIn->x;
pOut->y = pIn->y;
return pOut;
}
/**
* Rotates the point anticlockwise around a center
* by an amount of degrees.
*
* Code ported from Irrlicht: http://irrlicht.sourceforge.net/
*/
kmVec2* kmVec2RotateBy(kmVec2* pOut, const kmVec2* pIn,
const kmScalar degrees, const kmVec2* center)
{
kmScalar x, y;
const kmScalar radians = kmDegreesToRadians(degrees);
const kmScalar cs = cosf(radians), sn = sinf(radians);
pOut->x = pIn->x - center->x;
pOut->y = pIn->y - center->y;
x = pOut->x * cs - pOut->y * sn;
y = pOut->x * sn + pOut->y * cs;
pOut->x = x + center->x;
pOut->y = y + center->y;
return pOut;
}
/**
* Returns the angle in degrees between the two vectors
*/
kmScalar kmVec2DegreesBetween(const kmVec2* v1, const kmVec2* v2) {
if(kmVec2AreEqual(v1, v2)) {
return 0.0;
}
kmVec2 t1, t2;
kmVec2Normalize(&t1, v1);
kmVec2Normalize(&t2, v2);
kmScalar cross = kmVec2Cross(&t1, &t2);
kmScalar dot = kmVec2Dot(&t1, &t2);
/*
* acos is only defined for -1 to 1. Outside the range we
* get NaN even if that's just because of a floating point error
* so we clamp to the -1 - 1 range
*/
if(dot > 1.0) dot = 1.0;
if(dot < -1.0) dot = -1.0;
return kmRadiansToDegrees(atan2(cross, dot));
}
/**
* Returns the distance between the two points
*/
kmScalar kmVec2DistanceBetween(const kmVec2* v1, const kmVec2* v2) {
kmVec2 diff;
kmVec2Subtract(&diff, v2, v1);
return fabs(kmVec2Length(&diff));
}
/**
* Returns the point mid-way between two others
*/
kmVec2* kmVec2MidPointBetween(kmVec2* pOut, const kmVec2* v1, const kmVec2* v2) {
kmVec2 sum;
kmVec2Add(&sum, v1, v2);
pOut->x = sum.x / 2.0f;
pOut->y = sum.y / 2.0f;
return pOut;
}

View File

@ -0,0 +1,78 @@
/*
Copyright (c) 2008, Luke Benstead.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef VEC2_H_INCLUDED
#define VEC2_H_INCLUDED
#include "utility.h"
struct kmMat3;
#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
kmVec2* kmVec2Fill(kmVec2* pOut, kmScalar x, kmScalar y);
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* kmVec2Lerp(kmVec2* pOut, const kmVec2* pV1, const kmVec2* pV2, kmScalar t);
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 */
kmScalar kmVec2Cross(const kmVec2* pV1, const kmVec2* pV2);
kmVec2* kmVec2Subtract(kmVec2* pOut, const kmVec2* pV1, const kmVec2* pV2); ///< Subtracts 2 vectors and returns the result
kmVec2* kmVec2Mul( kmVec2* pOut,const kmVec2* pV1, const kmVec2* pV2 ); ///< Component-wise multiplication
kmVec2* kmVec2Div( kmVec2* pOut,const kmVec2* pV1, const kmVec2* pV2 ); ///< Component-wise division
kmVec2* kmVec2Transform(kmVec2* pOut, const kmVec2* pV1, const struct kmMat3* pM); /** Transform the Vector */
kmVec2* kmVec2TransformCoord(kmVec2* pOut, const kmVec2* pV, const struct kmMat3* pM); ///<Transforms a 2D 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
int kmVec2AreEqual(const kmVec2* p1, const kmVec2* p2); ///< Returns 1 if both vectors are equal
kmVec2* kmVec2Assign(kmVec2* pOut, const kmVec2* pIn);
kmVec2* kmVec2RotateBy(kmVec2* pOut, const kmVec2* pIn, const kmScalar degrees, const kmVec2* center); ///<Rotates the point anticlockwise around a center by an amount of degrees.
kmScalar kmVec2DegreesBetween(const kmVec2* v1, const kmVec2* v2);
kmScalar kmVec2DistanceBetween(const kmVec2* v1, const kmVec2* v2);
kmVec2* kmVec2MidPointBetween(kmVec2* pOut, const kmVec2* v1, const kmVec2* v2);
extern const kmVec2 KM_VEC2_POS_Y;
extern const kmVec2 KM_VEC2_NEG_Y;
extern const kmVec2 KM_VEC2_NEG_X;
extern const kmVec2 KM_VEC2_POS_X;
extern const kmVec2 KM_VEC2_ZERO;
#ifdef __cplusplus
}
#endif
#endif // VEC2_H_INCLUDED

View File

@ -0,0 +1,444 @@
/*
Copyright (c) 2008, Luke Benstead.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file vec3.c
*/
#include <assert.h>
#include <memory.h>
#include "utility.h"
#include "vec4.h"
#include "mat4.h"
#include "mat3.h"
#include "vec3.h"
#include "plane.h"
#include "ray3.h"
const kmVec3 KM_VEC3_POS_Z = { 0, 0, 1 };
const kmVec3 KM_VEC3_NEG_Z = { 0, 0, -1 };
const kmVec3 KM_VEC3_POS_Y = { 0, 1, 0 };
const kmVec3 KM_VEC3_NEG_Y = { 0, -1, 0 };
const kmVec3 KM_VEC3_NEG_X = { -1, 0, 0 };
const kmVec3 KM_VEC3_POS_X = { 1, 0, 0 };
const kmVec3 KM_VEC3_ZERO = { 0, 0, 0 };
/**
* Fill a kmVec3 structure using 3 floating point values
* The result is store in pOut, returns pOut
*/
kmVec3* kmVec3Fill(kmVec3* pOut, kmScalar x, kmScalar y, kmScalar z)
{
pOut->x = x;
pOut->y = y;
pOut->z = z;
return pOut;
}
/**
* 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 interpolation of 2 4D vectors based on t.
kmVec3* kmVec3Lerp(kmVec3* pOut, const kmVec3* pV1, const kmVec3* pV2, kmScalar t) {
pOut->x = pV1->x + t * ( pV2->x - pV1->x );
pOut->y = pV1->y + t * ( pV2->y - pV1->y );
pOut->z = pV1->z + t * ( pV2->z - pV1->z );
return pOut;
}
/**
* Returns the vector passed in set to unit length
* the result is stored in pOut.
*/
kmVec3* kmVec3Normalize(kmVec3* pOut, const kmVec3* pIn)
{
if (!pIn->x && !pIn->y && !pIn->z)
return kmVec3Assign(pOut, pIn);
kmScalar l = 1.0f / 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.
* The result is stored in pOut.
*/
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. The resulting
* vector is stored in pOut.
*/
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. The result is stored in
* pOut.
*/
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;
}
kmVec3* kmVec3Mul( kmVec3* pOut,const kmVec3* pV1, const kmVec3* pV2 ) {
pOut->x = pV1->x * pV2->x;
pOut->y = pV1->y * pV2->y;
pOut->z = pV1->z * pV2->z;
return pOut;
}
kmVec3* kmVec3Div( kmVec3* pOut,const kmVec3* pV1, const kmVec3* pV2 ) {
if ( pV2->x && pV2->y && pV2->z ){
pOut->x = pV1->x / pV2->x;
pOut->y = pV1->y / pV2->y;
pOut->z = pV1->z / pV2->z;
}
return pOut;
}
kmVec3* kmVec3MultiplyMat3(kmVec3* pOut, const kmVec3* pV, const kmMat3* pM) {
kmVec3 v;
v.x = pV->x * pM->mat[0] + pV->y * pM->mat[3] + pV->z * pM->mat[6];
v.y = pV->x * pM->mat[1] + pV->y * pM->mat[4] + pV->z * pM->mat[7];
v.z = pV->x * pM->mat[2] + pV->y * pM->mat[5] + pV->z * pM->mat[8];
pOut->x = v.x;
pOut->y = v.y;
pOut->z = v.z;
return pOut;
}
/**
* Multiplies vector (x, y, z, 1) by a given matrix. The result
* is stored in pOut. pOut is returned.
*/
kmVec3* kmVec3MultiplyMat4(kmVec3* pOut, const kmVec3* pV, const kmMat4* pM) {
kmVec3 v;
v.x = pV->x * pM->mat[0] + pV->y * pM->mat[4] + pV->z * pM->mat[8] + pM->mat[12];
v.y = pV->x * pM->mat[1] + pV->y * pM->mat[5] + pV->z * pM->mat[9] + pM->mat[13];
v.z = pV->x * pM->mat[2] + pV->y * pM->mat[6] + pV->z * pM->mat[10] + pM->mat[14];
pOut->x = v.x;
pOut->y = v.y;
pOut->z = v.z;
return pOut;
}
kmVec3* kmVec3Transform(kmVec3* pOut, const kmVec3* pV, const kmMat4* pM)
{
/*
@deprecated Should intead use kmVec3MultiplyMat4
*/
return kmVec3MultiplyMat4(pOut, pV, pM);
}
kmVec3* kmVec3InverseTransform(kmVec3* pOut, const kmVec3* pVect, const kmMat4* pM)
{
kmVec3 v1, v2;
v1.x = pVect->x - pM->mat[12];
v1.y = pVect->y - pM->mat[13];
v1.z = pVect->z - pM->mat[14];
v2.x = v1.x * pM->mat[0] + v1.y * pM->mat[1] + v1.z * pM->mat[2];
v2.y = v1.x * pM->mat[4] + v1.y * pM->mat[5] + v1.z * pM->mat[6];
v2.z = v1.x * pM->mat[8] + v1.y * pM->mat[9] + v1.z * pM->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->mat[0] + pVect->y * pM->mat[1] + pVect->z * pM->mat[2];
v.y = pVect->x * pM->mat[4] + pVect->y * pM->mat[5] + pVect->z * pM->mat[6];
v.z = pVect->x * pM->mat[8] + pVect->y * pM->mat[9] + pVect->z * pM->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 = 1bw(bx, by, bz)
*/
kmVec4 v;
kmVec4 inV;
kmVec4Fill(&inV, pV->x, pV->y, pV->z, 1.0);
kmVec4Transform(&v, &inV,pM);
pOut->x = v.x / v.w;
pOut->y = v.y / v.w;
pOut->z = v.z / v.w;
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)
*/
//Omits the translation, only scaling + rotating
kmVec3 v;
v.x = pV->x * pM->mat[0] + pV->y * pM->mat[4] + pV->z * pM->mat[8];
v.y = pV->x * pM->mat[1] + pV->y * pM->mat[5] + pV->z * pM->mat[9];
v.z = pV->x * pM->mat[2] + pV->y * pM->mat[6] + pV->z * pM->mat[10];
pOut->x = v.x;
pOut->y = v.y;
pOut->z = v.z;
return pOut;
}
/**
* Scales a vector to length s. Does not normalize first,
* you should do that!
*/
kmVec3* kmVec3Scale(kmVec3* pOut, const kmVec3* pIn, const kmScalar s)
{
pOut->x = pIn->x * s;
pOut->y = pIn->y * s;
pOut->z = pIn->z * s;
return pOut;
}
/**
* Returns KM_TRUE if the 2 vectors are approximately equal
*/
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;
}
/**
* Assigns pIn to pOut. Returns pOut. If pIn and pOut are the same
* then nothing happens but pOut is still returned
*/
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;
}
/**
* Sets all the elements of pOut to zero. Returns pOut.
*/
kmVec3* kmVec3Zero(kmVec3* pOut) {
pOut->x = 0.0f;
pOut->y = 0.0f;
pOut->z = 0.0f;
return pOut;
}
/**
* Get the rotations that would make a (0,0,1) direction vector point in the same direction as this direction vector.
* Useful for orienting vector towards a point.
*
* Returns a rotation vector containing the X (pitch) and Y (raw) rotations (in degrees) that when applied to a
* +Z (e.g. 0, 0, 1) direction vector would make it point in the same direction as this vector. The Z (roll) rotation
* is always 0, since two Euler rotations are sufficient to point in any given direction.
*
* Code ported from Irrlicht: http://irrlicht.sourceforge.net/
*/
kmVec3* kmVec3GetHorizontalAngle(kmVec3* pOut, const kmVec3 *pIn) {
const kmScalar z1 = sqrt(pIn->x * pIn->x + pIn->z * pIn->z);
pOut->y = kmRadiansToDegrees(atan2(pIn->x, pIn->z));
if (pOut->y < 0)
pOut->y += 360;
if (pOut->y >= 360)
pOut->y -= 360;
pOut->x = kmRadiansToDegrees(atan2(z1, pIn->y)) - 90.0;
if (pOut->x < 0)
pOut->x += 360;
if (pOut->x >= 360)
pOut->x -= 360;
return pOut;
}
/**
* Builds a direction vector from input vector.
* Input vector is assumed to be rotation vector composed from 3 Euler angle rotations, in degrees.
* The forwards vector will be rotated by the input vector
*
* Code ported from Irrlicht: http://irrlicht.sourceforge.net/
*/
kmVec3* kmVec3RotationToDirection(kmVec3* pOut, const kmVec3* pIn, const kmVec3* forwards)
{
const kmScalar xr = kmDegreesToRadians(pIn->x);
const kmScalar yr = kmDegreesToRadians(pIn->y);
const kmScalar zr = kmDegreesToRadians(pIn->z);
const kmScalar cr = cos(xr), sr = sin(xr);
const kmScalar cp = cos(yr), sp = sin(yr);
const kmScalar cy = cos(zr), sy = sin(zr);
const kmScalar srsp = sr*sp;
const kmScalar crsp = cr*sp;
const kmScalar pseudoMatrix[] = {
(cp*cy), (cp*sy), (-sp),
(srsp*cy-cr*sy), (srsp*sy+cr*cy), (sr*cp),
(crsp*cy+sr*sy), (crsp*sy-sr*cy), (cr*cp)
};
pOut->x = forwards->x * pseudoMatrix[0] +
forwards->y * pseudoMatrix[3] +
forwards->z * pseudoMatrix[6];
pOut->y = forwards->x * pseudoMatrix[1] +
forwards->y * pseudoMatrix[4] +
forwards->z * pseudoMatrix[7];
pOut->z = forwards->x * pseudoMatrix[2] +
forwards->y * pseudoMatrix[5] +
forwards->z * pseudoMatrix[8];
return pOut;
}
kmVec3* kmVec3ProjectOnToPlane(kmVec3* pOut, const kmVec3* point, const struct kmPlane* plane) {
kmRay3 ray;
kmVec3Assign(&ray.start, point);
ray.dir.x = -plane->a;
ray.dir.y = -plane->b;
ray.dir.z = -plane->c;
kmRay3IntersectPlane(pOut, &ray, plane);
return pOut;
}

View File

@ -0,0 +1,87 @@
/*
Copyright (c) 2008, Luke Benstead.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef VEC3_H_INCLUDED
#define VEC3_H_INCLUDED
#include <assert.h>
#include "utility.h"
struct kmMat4;
struct kmMat3;
struct kmPlane;
typedef struct kmVec3 {
kmScalar x;
kmScalar y;
kmScalar z;
} kmVec3;
#ifdef __cplusplus
extern "C" {
#endif
kmVec3* kmVec3Fill(kmVec3* pOut, kmScalar x, kmScalar y, kmScalar z);
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* kmVec3Lerp(kmVec3* pOut, const kmVec3* pV1, const kmVec3* pV2, kmScalar t);
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* kmVec3Mul( kmVec3* pOut,const kmVec3* pV1, const kmVec3* pV2 );
kmVec3* kmVec3Div( kmVec3* pOut,const kmVec3* pV1, const kmVec3* pV2 );
kmVec3* kmVec3MultiplyMat3(kmVec3 *pOut, const kmVec3 *pV, const struct kmMat3* pM);
kmVec3* kmVec3MultiplyMat4(kmVec3* pOut, const kmVec3* pV, const struct kmMat4* pM);
kmVec3* kmVec3Transform(kmVec3* pOut, const kmVec3* pV1, const struct kmMat4* pM); /** Transforms a vector (assuming w=1) by a given matrix */
kmVec3* kmVec3TransformNormal(kmVec3* pOut, const kmVec3* pV, const struct kmMat4* pM);/**Transforms a 3D normal by a given matrix */
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);
kmVec3* kmVec3GetHorizontalAngle(kmVec3* pOut, const kmVec3 *pIn); /** Get the rotations that would make a (0,0,1) direction vector point in the same direction as this direction vector. */
kmVec3* kmVec3RotationToDirection(kmVec3* pOut, const kmVec3* pIn, const kmVec3* forwards); /** Builds a direction vector from input vector. */
kmVec3* kmVec3ProjectOnToPlane(kmVec3* pOut, const kmVec3* point, const struct kmPlane* plane);
extern const kmVec3 KM_VEC3_NEG_Z;
extern const kmVec3 KM_VEC3_POS_Z;
extern const kmVec3 KM_VEC3_POS_Y;
extern const kmVec3 KM_VEC3_NEG_Y;
extern const kmVec3 KM_VEC3_NEG_X;
extern const kmVec3 KM_VEC3_POS_X;
extern const kmVec3 KM_VEC3_ZERO;
#ifdef __cplusplus
}
#endif
#endif /* VEC3_H_INCLUDED */

View File

@ -27,9 +27,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <memory.h>
#include <assert.h>
#include "kazmath/utility.h"
#include "kazmath/vec4.h"
#include "kazmath/mat4.h"
#include "utility.h"
#include "vec4.h"
#include "mat4.h"
kmVec4* kmVec4Fill(kmVec4* pOut, kmScalar x, kmScalar y, kmScalar z, kmScalar w)
@ -45,74 +45,98 @@ kmVec4* kmVec4Fill(kmVec4* pOut, kmScalar x, kmScalar y, kmScalar z, kmScalar w)
/// 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;
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;
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 );
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));
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);
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!
/// Returns the interpolation of 2 4D vectors based on t.
kmVec4* kmVec4Lerp(kmVec4* pOut, const kmVec4* pV1, const kmVec4* pV2, kmScalar t) {
assert(0);
pOut->x = pV1->x + t * ( pV2->x - pV1->x );
pOut->y = pV1->y + t * ( pV2->y - pV1->y );
pOut->z = pV1->z + t * ( pV2->z - pV1->z );
pOut->w = pV1->w + t * ( pV2->w - pV1->w );
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.0f / kmVec4Length(pIn);
if (!pIn->x && !pIn->y && !pIn->z && !pIn->w){
return kmVec4Assign(pOut, pIn);
}
pOut->x *= l;
pOut->y *= l;
pOut->z *= l;
pOut->w *= l;
kmScalar l = 1.0f / kmVec4Length(pIn);
pOut->x = pIn->x * l;
pOut->y = pIn->y * l;
pOut->z = pIn->z * l;
pOut->w = pIn->w * l;
return pOut;
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);
kmVec4Normalize(pOut, pIn);
pOut->x *= s;
pOut->y *= s;
pOut->z *= s;
pOut->w *= s;
return pOut;
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;
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* kmVec4Mul( 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) {
kmVec4* kmVec4Div( kmVec4* pOut,const kmVec4* pV1, const kmVec4* pV2 ) {
if ( pV2->x && pV2->y && pV2->z && pV2->w){
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;
}
/// Multiplies a 4D vector by a matrix, the result is stored in pOut, and pOut is returned.
kmVec4* kmVec4MultiplyMat4(kmVec4* pOut, const kmVec4* pV, const struct kmMat4* pM) {
pOut->x = pV->x * pM->mat[0] + pV->y * pM->mat[4] + pV->z * pM->mat[8] + pV->w * pM->mat[12];
pOut->y = pV->x * pM->mat[1] + pV->y * pM->mat[5] + pV->z * pM->mat[9] + pV->w * pM->mat[13];
pOut->z = pV->x * pM->mat[2] + pV->y * pM->mat[6] + pV->z * pM->mat[10] + pV->w * pM->mat[14];
@ -120,9 +144,13 @@ kmVec4* kmVec4Transform(kmVec4* pOut, const kmVec4* pV, const kmMat4* pM) {
return pOut;
}
kmVec4* kmVec4Transform(kmVec4* pOut, const kmVec4* pV, const kmMat4* pM) {
return kmVec4MultiplyMat4(pOut, pV, pM);
}
/// 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) {
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) {
@ -136,19 +164,19 @@ kmVec4* kmVec4TransformArray(kmVec4* pOut, unsigned int outStride,
}
int 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)
);
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);
assert(pOut != pIn);
memcpy(pOut, pIn, sizeof(float) * 4);
memcpy(pOut, pIn, sizeof(kmScalar) * 4);
return pOut;
return pOut;
}

View File

@ -26,7 +26,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef VEC4_H_INCLUDED
#define VEC4_H_INCLUDED
#include "CCPlatformMacros.h"
#include "utility.h"
struct kmMat4;
@ -34,11 +33,12 @@ 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;
typedef struct kmVec4
{
kmScalar x;
kmScalar y;
kmScalar z;
kmScalar w;
} kmVec4;
#pragma pack(pop)
@ -47,20 +47,24 @@ typedef struct kmVec4 {
extern "C" {
#endif
CC_DLL kmVec4* kmVec4Fill(kmVec4* pOut, kmScalar x, kmScalar y, kmScalar z, kmScalar w);
CC_DLL kmVec4* kmVec4Add(kmVec4* pOut, const kmVec4* pV1, const kmVec4* pV2);
CC_DLL kmScalar kmVec4Dot(const kmVec4* pV1, const kmVec4* pV2);
CC_DLL kmScalar kmVec4Length(const kmVec4* pIn);
CC_DLL kmScalar kmVec4LengthSq(const kmVec4* pIn);
CC_DLL kmVec4* kmVec4Lerp(kmVec4* pOut, const kmVec4* pV1, const kmVec4* pV2, kmScalar t);
CC_DLL kmVec4* kmVec4Normalize(kmVec4* pOut, const kmVec4* pIn);
CC_DLL kmVec4* kmVec4Scale(kmVec4* pOut, const kmVec4* pIn, const kmScalar s); ///< Scales a vector to length s
CC_DLL kmVec4* kmVec4Subtract(kmVec4* pOut, const kmVec4* pV1, const kmVec4* pV2);
CC_DLL kmVec4* kmVec4Transform(kmVec4* pOut, const kmVec4* pV, const struct kmMat4* pM);
CC_DLL kmVec4* kmVec4TransformArray(kmVec4* pOut, unsigned int outStride,
const kmVec4* pV, unsigned int vStride, const struct kmMat4* pM, unsigned int count);
CC_DLL int kmVec4AreEqual(const kmVec4* p1, const kmVec4* p2);
CC_DLL kmVec4* kmVec4Assign(kmVec4* pOut, const kmVec4* pIn);
kmVec4* kmVec4Fill(kmVec4* pOut, kmScalar x, kmScalar y, kmScalar z, kmScalar w);
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* kmVec4Mul( kmVec4* pOut,const kmVec4* pV1, const kmVec4* pV2 );
kmVec4* kmVec4Div( kmVec4* pOut,const kmVec4* pV1, const kmVec4* pV2 );
kmVec4* kmVec4MultiplyMat4(kmVec4* pOut, const kmVec4* pV, const struct kmMat4* pM);
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);
int kmVec4AreEqual(const kmVec4* p1, const kmVec4* p2);
kmVec4* kmVec4Assign(kmVec4* pOut, const kmVec4* pIn);
#ifdef __cplusplus
}

View File

@ -1,14 +0,0 @@
#ADD_LIBRARY(Kazmath STATIC ${KAZMATH_SRCS})
#INSTALL(TARGETS Kazmath ARCHIVE DESTINATION lib)
INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR}/include )
ADD_LIBRARY(kazmath STATIC ${KAZMATH_SOURCES})
INSTALL(TARGETS kazmath ARCHIVE DESTINATION lib)
#ADD_LIBRARY(KazmathGL STATIC ${GL_UTILS_SRCS})
#INSTALL(TARGETS KazmathGL ARCHIVE DESTINATION lib)
INSTALL(FILES ${KAZMATH_HEADERS} DESTINATION include/kazmath)
INSTALL(FILES ${GL_UTILS_HEADERS} DESTINATION include/kazmath/GL)

View File

@ -1,738 +0,0 @@
------------------------------------------------------------
revno: 111
committer: Kazade <kazade@gmail.com>
branch nick: kazmath
timestamp: Thu 2010-08-19 12:07:29 +0100
message:
Fix #620352. Fix a reference to kmMat4RotationAxisAngle
------------------------------------------------------------
revno: 110
committer: Carsten Haubld <carstenhaubold@googlemail.com>
branch nick: kazmath
timestamp: Wed 2010-04-21 12:55:39 +0200
message:
applied the change to the header files as well
------------------------------------------------------------
revno: 109
committer: Carsten Haubld <carstenhaubold@googlemail.com>
branch nick: kazmath
timestamp: Wed 2010-04-21 12:54:06 +0200
message:
fixed kmMat4RotationAxis
------------------------------------------------------------
revno: 108 [merge]
committer: Carsten Haubld <carstenhaubold@googlemail.com>
branch nick: kazmath
timestamp: Wed 2010-04-21 12:27:53 +0200
message:
fixed CMake in kazmathxx due to missing utility.h
------------------------------------------------------------
revno: 107
committer: Carsten Haubld <carstenhaubold@googlemail.com>
branch nick: kazmath
timestamp: Wed 2010-04-21 12:22:40 +0200
message:
fixed mat4 rotation axis by normalizing the axis first
------------------------------------------------------------
revno: 106
committer: Luke Benstead <kazade@gmail.com>
branch nick: kazmath
timestamp: Sat 2010-01-09 16:56:04 +0000
message:
Add cmake module
------------------------------------------------------------
revno: 105
committer: Luke Benstead <luke@Hydrogen>
branch nick: kazmath
timestamp: Sat 2010-01-09 16:23:31 +0000
message:
Remove kazmodel - it really should belong in its own repo
------------------------------------------------------------
revno: 104
committer: Luke Benstead <luke@Hydrogen>
branch nick: kazmath
timestamp: Fri 2010-01-08 23:03:13 +0000
message:
Reorganize the headers so that the tests can compile in place
------------------------------------------------------------
revno: 103
committer: Carsten Haubld <carstenhaubold@googlemail.com>
branch nick: kazmath
timestamp: Mon 2009-08-31 11:21:42 +0200
message:
Operators now inline, constructors fixed
------------------------------------------------------------
revno: 102
committer: Carsten Haubld <carstenhaubold@googlemail.com>
branch nick: kazmath
timestamp: Sat 2009-08-29 11:42:59 +0200
message:
fixed some compilation errors - still how do we define operators in headers correctly??
------------------------------------------------------------
revno: 101
committer: Luke Benstead <kazade@gmail.com>
branch nick: kazmath
timestamp: Wed 2009-08-26 10:37:52 +0100
message:
Added the header defines
------------------------------------------------------------
revno: 100
committer: Luke Benstead <luke@sidney>
branch nick: kazmath
timestamp: Wed 2009-08-26 09:38:47 +0100
message:
Added a V2 for kazmathxx
------------------------------------------------------------
revno: 99
committer: Luke Benstead <kazade@gmail.com>
branch nick: kazmath
timestamp: Sun 2009-08-02 08:08:26 +0100
message:
Added missing header file to one of the tests
------------------------------------------------------------
revno: 98
committer: Carsten Haubld <carstenhaubold@googlemail.com>
branch nick: kazmath
timestamp: Sat 2009-08-01 12:05:25 +0200
message:
No longer doing self assignment in kmMat4Inverse
------------------------------------------------------------
revno: 97
committer: Carsten Haubld <carstenhaubold@googlemail.com>
branch nick: kazmath
timestamp: Sat 2009-08-01 11:15:36 +0200
message:
Fixed kmMat4Inverse
------------------------------------------------------------
revno: 96
committer: Luke Benstead <kazade@gmail.com>
branch nick: kazmath
timestamp: Sat 2009-08-01 09:20:33 +0100
message:
Fixed some whitespace issues in plane.c
------------------------------------------------------------
revno: 95
committer: Luke Benstead <kazade@gmail.com>
branch nick: kazmath
timestamp: Sat 2009-08-01 09:17:01 +0100
message:
Rename kmAABBPointInBox to kmAABBContainsPoint
------------------------------------------------------------
revno: 94
committer: Luke Benstead <kazade@gmail.com>
branch nick: kazmath
timestamp: Sat 2009-08-01 09:16:28 +0100
message:
Implement kmAABBPointInBox
------------------------------------------------------------
revno: 93
committer: Luke Benstead <kazade@gmail.com>
branch nick: kazmath
timestamp: Sat 2009-08-01 09:14:00 +0100
message:
Implement kmAABBAssign
------------------------------------------------------------
revno: 92
committer: Luke Benstead <kazade@gmail.com>
branch nick: kazmath
timestamp: Sat 2009-08-01 09:10:36 +0100
message:
Fixed some whitespace and added some comments
------------------------------------------------------------
revno: 91
committer: Luke Benstead <kazade@gmail.com>
branch nick: kazmath
timestamp: Sat 2009-08-01 08:56:13 +0100
message:
Implemented (untested) kmMat4RotationTranslation to construct a 4x4 matrix from a 3x3 + vec3
------------------------------------------------------------
revno: 90
committer: Luke Benstead <luke@hydrogen>
branch nick: kazmath
timestamp: Sun 2009-07-05 07:55:45 +0100
message:
Added kmMat3RotationX, kmMat3RotationY and kmMat3RotationZ
------------------------------------------------------------
revno: 89
committer: Carsten Haubld <carstenhaubold@googlemail.com>
branch nick: kazmath
timestamp: Sat 2009-06-27 09:38:20 +0200
message:
Fixed a crash?
------------------------------------------------------------
revno: 88
committer: Luke Benstead <kazade@gmail.com>
branch nick: kazmath
timestamp: Tue 2009-04-28 09:52:57 +0100
message:
Added a test for kmMat4Transpose
------------------------------------------------------------
revno: 87
committer: Luke Benstead <kazade@gmail.com>
branch nick: kazmath
timestamp: Tue 2009-04-28 08:49:59 +0100
message:
Added a commented test for kmMat4Inverse, however kmMat4Adjugate and kmMat4Determinate need implementing
------------------------------------------------------------
revno: 86
committer: Luke Benstead <kazade@gmail.com>
branch nick: kazmath
timestamp: Tue 2009-04-28 08:46:03 +0100
message:
Fixed bug in kmQuaternionRotationMatrix
------------------------------------------------------------
revno: 85
committer: Luke Benstead <kazade@gmail.com>
branch nick: kazmath
timestamp: Tue 2009-04-28 08:41:27 +0100
message:
Added missing include to test_mat3.cpp
------------------------------------------------------------
revno: 84
committer: Carsten Haubld <carstenhaubold@googlemail.com>
branch nick: kazmath
timestamp: Mon 2009-04-27 22:59:08 +0200
message:
fixed CMakeLists.txt for the tests
------------------------------------------------------------
revno: 83
committer: Luke Benstead <kazade@gmail.com>
branch nick: kazmath
timestamp: Mon 2009-04-27 21:34:20 +0100
message:
Added a test for kmMat3Translation
------------------------------------------------------------
revno: 82
committer: Luke Benstead <kazade@gmail.com>
branch nick: kazmath
timestamp: Mon 2009-04-27 21:32:19 +0100
message:
Fixed bugs in kmMat3Scaling and kmMat3Translation, added test for kmMat3Scaling
------------------------------------------------------------
revno: 81 [merge]
committer: Luke Benstead <kazade@gmail.com>
branch nick: kazmath
timestamp: Mon 2009-04-27 19:04:56 +0100
message:
Merge from upstream. Fixed mismatching prototype in quaternion.c
------------------------------------------------------------
revno: 80
committer: Luke Benstead <kazade@gmail.com>
branch nick: kazmath
timestamp: Mon 2009-04-27 19:01:35 +0100
message:
Added a test for kmMat3AreEqual. Fixed a bug in kmMat3AreEqual
------------------------------------------------------------
revno: 79
committer: Luke Benstead <kazade@gmail.com>
branch nick: kazmath
timestamp: Mon 2009-04-27 18:57:28 +0100
message:
Added a test for kmMat3IsIdentity
------------------------------------------------------------
revno: 78
committer: Luke Benstead <kazade@gmail.com>
branch nick: kazmath
timestamp: Mon 2009-04-27 18:54:48 +0100
message:
Added a test for kmMat3Identity
------------------------------------------------------------
revno: 77
committer: Luke Benstead <kazade@gmail.com>
branch nick: kazmath
timestamp: Mon 2009-04-27 18:52:14 +0100
message:
Added a test for kmMat3Fill
------------------------------------------------------------
revno: 76
committer: Luke Benstead <kazade@gmail.com>
branch nick: kazmath
timestamp: Mon 2009-04-27 18:46:30 +0100
message:
Added some mat3 unit tests. Fixed a bug in kmMat3AreEqual
------------------------------------------------------------
revno: 75
committer: Luke Benstead <kazade@gmail.com>
branch nick: kazmath
timestamp: Mon 2009-04-27 11:08:43 +0100
message:
Added mat4 test stub
------------------------------------------------------------
revno: 74
committer: Luke Benstead <kazade@gmail.com>
branch nick: kazmath
timestamp: Mon 2009-04-27 11:06:12 +0100
message:
Enabled unit testing in cmake
------------------------------------------------------------
revno: 73
committer: Luke Benstead <kazade@gmail.com>
branch nick: kazmath
timestamp: Mon 2009-04-27 10:44:37 +0100
message:
Added cmakelists.txt to the tests subfolder
------------------------------------------------------------
revno: 72
committer: Luke Benstead <kazade@gmail.com>
branch nick: kazmath
timestamp: Mon 2009-04-27 10:37:34 +0100
message:
Added stub mat3 test file
------------------------------------------------------------
revno: 71
committer: Luke Benstead <kazade@gmail.com>
branch nick: kazmath
timestamp: Mon 2009-04-27 10:35:48 +0100
message:
Added tests folder for new boost::unit based tests
------------------------------------------------------------
revno: 70
committer: Carsten Haubld <carstenhaubold@googlemail.com>
branch nick: kazmath
timestamp: Sun 2009-04-26 14:25:48 +0200
message:
Fixed the new quaternion -> Matrix -> AngleAxis methods and added them to mat4
------------------------------------------------------------
revno: 69
committer: Luke Benstead <kazade@gmail.com>
branch nick: kazmath
timestamp: Sun 2009-04-26 12:40:08 +0100
message:
Added kazmodel to the kazlibs repo
------------------------------------------------------------
revno: 68 [merge]
committer: Luke Benstead <kazade@gmail.com>
branch nick: kazmath
timestamp: Sun 2009-04-26 12:34:27 +0100
message:
Merge from upstream
------------------------------------------------------------
revno: 67
committer: Luke Benstead <kazade@gmail.com>
branch nick: kazmath
timestamp: Sun 2009-04-26 12:33:43 +0100
message:
Reorganized bzr
------------------------------------------------------------
revno: 66
committer: Luke Benstead <kazade@gmail.com>
branch nick: kazmath
timestamp: Sun 2009-04-26 10:00:18 +0100
message:
Renamed kmMat3RotationAxis to kmMat3RotationAxisAngle to be more accurate
------------------------------------------------------------
revno: 65
committer: Luke Benstead <kazade@gmail.com>
branch nick: kazmath
timestamp: Sun 2009-04-26 09:57:19 +0100
message:
Fixed some compilation errors
------------------------------------------------------------
revno: 64
committer: Luke Benstead <kazade@gmail.com>
branch nick: kazmath
timestamp: Sun 2009-04-26 09:54:12 +0100
message:
Added untested implementation of kmMat3RotationToAxisAngle
------------------------------------------------------------
revno: 63
committer: Luke Benstead <kazade@gmail.com>
branch nick: kazmath
timestamp: Sun 2009-04-26 09:49:17 +0100
message:
Added stub for kmMat3RotationToAxisAngle()
------------------------------------------------------------
revno: 62
committer: Luke Benstead <kazade@gmail.com>
branch nick: kazmath
timestamp: Sun 2009-04-26 09:45:58 +0100
message:
Corrected a typo
------------------------------------------------------------
revno: 61
committer: Luke Benstead <kazade@gmail.com>
branch nick: kazmath
timestamp: Sun 2009-04-26 09:44:39 +0100
message:
Fixed broken Quaternion functions
Added (untested) kmMat3RotationAxis()
------------------------------------------------------------
revno: 60
committer: Luke Benstead <kazade@gmail.com>
branch nick: kazmath
timestamp: Sat 2009-04-18 08:55:29 +0100
message:
Fixed some errors in the quaternion header.
Changed kmQuaternionRotationMatrix to accept a kmMat3 instead of kmMat4
------------------------------------------------------------
revno: 59
committer: Luke Benstead <kazade@gmail.com>
branch nick: kazmath
timestamp: Sat 2009-04-18 08:42:38 +0100
message:
Added kmMat3RotationQuaternion
------------------------------------------------------------
revno: 58
committer: Carsten Haubld <carstenhaubold@googlemail.com>
branch nick: kazmath
timestamp: Sun 2009-04-05 11:58:29 +0200
message:
Added mat3
------------------------------------------------------------
revno: 57 [merge]
committer: Carsten Haubld <carstenhaubold@googlemail.com>
branch nick: kazmath
timestamp: Sun 2009-04-05 11:54:15 +0200
message:
Implemented mat4 and vec4 for kazmathxx
------------------------------------------------------------
revno: 56
committer: Carsten Haubld <carstenhaubold@googlemail.com>
branch nick: kazmath
timestamp: Sun 2009-04-05 11:53:07 +0200
message:
Implemented mat4 and vec4 for kazmathxx
------------------------------------------------------------
revno: 55
committer: Carsten Haubld <carstenhaubold@googlemail.com>
branch nick: kazmath
timestamp: Fri 2009-03-13 16:46:26 +0100
message:
added km::vec3 to kazmathxx
------------------------------------------------------------
revno: 54
committer: Carsten Haubld <carstenhaubold@googlemail.com>
branch nick: kazmath
timestamp: Fri 2009-03-13 16:14:51 +0100
message:
Fixed: kmVec2 is no longer transformed by kmMat4\nAdded km::vec2
------------------------------------------------------------
revno: 53
committer: Carsten Haubld <carstenhaubold@googlemail.com>
branch nick: kazmath
timestamp: Fri 2009-03-13 15:38:53 +0100
message:
Added folder for kazmathxx
------------------------------------------------------------
revno: 52 [merge]
committer: Luke Benstead <kazade@gmail.com>
branch nick: trunk
timestamp: Fri 2009-03-13 14:04:32 +0000
message:
Merge from upstream
------------------------------------------------------------
revno: 51
committer: Luke Benstead <kazade@gmail.com>
branch nick: trunk
timestamp: Fri 2009-03-13 14:00:14 +0000
message:
Fixed for C89
------------------------------------------------------------
revno: 50
committer: Carsten Haubold <CarstenHaubold@googlemail.com>
timestamp: Tue 2008-12-30 12:45:23 +0100
message:
fixed kmGLTranslate
------------------------------------------------------------
revno: 49
committer: Carsten Haubold <CarstenHaubold@googlemail.com>
timestamp: Tue 2008-12-30 12:15:27 +0100
message:
fixed some stack memory leaks
------------------------------------------------------------
revno: 48
committer: Carsten Haubold <CarstenHaubold@googlemail.com>
timestamp: Tue 2008-12-30 11:01:35 +0100
message:
The GL matrix stacks now work as expected - matrix multiplication was the wrong way round
------------------------------------------------------------
revno: 47
committer: Carsten Haubold <CarstenHaubold@googlemail.com>
timestamp: Tue 2008-12-30 10:52:28 +0100
message:
Debug output
------------------------------------------------------------
revno: 46
committer: Carsten Haubold <CarstenHaubold@googlemail.com>
timestamp: Mon 2008-12-29 18:32:13 +0100
message:
Fixed some compiler errors
------------------------------------------------------------
revno: 45
committer: Luke <kazade@gmail.com>
timestamp: Wed 2008-11-19 08:36:47 +0000
message:
Added kmGLTranslatef, kmGLScalef and kmGLRotatef
------------------------------------------------------------
revno: 44
committer: Luke <kazade@gmail.com>
timestamp: Tue 2008-11-04 20:57:30 +0000
message:
Fixed up kazmathxx
------------------------------------------------------------
revno: 43
committer: Luke <kazade@gmail.com>
timestamp: Wed 2008-10-29 09:24:32 +0000
message:
Started implementing C++ operators in kazmathxx.h
------------------------------------------------------------
revno: 42
committer: Luke <kazade@gmail.com>
timestamp: Tue 2008-10-28 18:21:16 +0000
message:
Added kazmathxx.h for C++ usage
------------------------------------------------------------
revno: 41
committer: Luke <kazade@gmail.com>
timestamp: Tue 2008-10-28 11:00:41 +0000
message:
Added Doxygen documentation
------------------------------------------------------------
revno: 40
committer: Luke <kazade@gmail.com>
timestamp: Tue 2008-10-28 08:46:19 +0000
message:
Began documenting the kmPlane functions.
Changed some assert(0)s to include a not implemented message
------------------------------------------------------------
revno: 39
committer: Luke <kazade@gmail.com>
timestamp: Tue 2008-10-28 08:42:24 +0000
message:
- Wrote stubs for the AABB functions which raise assertions if used.
- Documented the AABB functions
- Changed the definition of kmAABBPointInBox so that it actually makes sense
------------------------------------------------------------
revno: 38
committer: Luke <kazade@gmail.com>
timestamp: Tue 2008-10-28 08:38:48 +0000
message:
- Documented utility.c
------------------------------------------------------------
revno: 37
committer: Luke <kazade@gmail.com>
timestamp: Tue 2008-10-28 08:36:30 +0000
message:
- Documented vec3.c in detail.
- Fixed up a not-implemented assertion.
- Changed existing doc strings to C style - /** */
------------------------------------------------------------
revno: 36
committer: Luke <kazade@gmail.com>
timestamp: Tue 2008-10-28 08:30:00 +0000
message:
Removed uneccessary files from git
------------------------------------------------------------
revno: 35
committer: Luke <kazade@gmail.com>
timestamp: Tue 2008-10-28 08:28:49 +0000
message:
- Documented all the functions in mat4.c
- Fixed up all asserts in mat4.c to include a message
- Tidied up the code. Mat4.c is now done.
------------------------------------------------------------
revno: 34
committer: Luke <kazade@gmail.com>
timestamp: Mon 2008-10-27 21:52:33 +0000
message:
Added potential 0.1 release binary
------------------------------------------------------------
revno: 33
committer: Luke Benstead <kazade@gmail.com>
timestamp: Mon 2008-10-27 21:46:55 +0000
message:
Changed the README to include the BSD license
------------------------------------------------------------
revno: 32
committer: Luke Benstead <kazade@gmail.com>
timestamp: Mon 2008-10-27 21:45:51 +0000
message:
Added the modified BSD license to all source files
------------------------------------------------------------
revno: 31
committer: Luke Benstead <kazade@gmail.com>
timestamp: Mon 2008-10-27 21:11:51 +0000
message:
Fixed the installation of header files in CMake
------------------------------------------------------------
revno: 30
committer: Luke <kazade@gmail.com>
timestamp: Mon 2008-10-27 21:05:51 +0000
message:
Added kazmath project files
------------------------------------------------------------
revno: 29 [merge]
committer: Luke <kazade@gmail.com>
timestamp: Mon 2008-10-27 21:03:22 +0000
message:
Merge branch 'master' of git@github.com:Kazade/kazmath
------------------------------------------------------------
revno: 28
committer: Luke <kazade@gmail.com>
timestamp: Mon 2008-10-27 21:02:04 +0000
message:
Finally got kazmath compiling on VC++, man that compiler sucks! Have MS not heard of C99?
------------------------------------------------------------
revno: 27
committer: Luke Benstead <kazade@gmail.com>
timestamp: Sun 2008-10-26 21:35:24 +0000
message:
Changed the readme slightly, we need to change the license everywhere
------------------------------------------------------------
revno: 26
committer: Luke Benstead <kazade@gmail.com>
timestamp: Sun 2008-10-26 21:21:47 +0000
message:
Implemented the stacks test, fixed the undefined references I was getting
------------------------------------------------------------
revno: 25
committer: Luke Benstead <kazade@gmail.com>
timestamp: Sun 2008-10-26 20:59:34 +0000
message:
Removed the old matrix stack stuff
------------------------------------------------------------
revno: 24
committer: Luke Benstead <kazade@gmail.com>
timestamp: Sun 2008-10-26 20:11:58 +0000
message:
Started implementing the matrix stack tests
------------------------------------------------------------
revno: 23
committer: Luke Benstead <kazade@gmail.com>
timestamp: Sun 2008-10-26 10:56:51 +0000
message:
Started new implementation of the GL matrix stack
------------------------------------------------------------
revno: 22
committer: Carsten Haubold <CarstenHaubold@googlemail.com>
timestamp: Thu 2008-08-28 12:37:41 +0200
message:
Added kmGLRotation
------------------------------------------------------------
revno: 21
committer: Luke Benstead <luke@helium.(none)>
timestamp: Thu 2008-08-28 09:24:00 +0100
message:
We now have a working matrix stack
------------------------------------------------------------
revno: 20
committer: Luke Benstead <luke@helium.(none)>
timestamp: Wed 2008-08-27 13:34:49 +0100
message:
Fixed the stack memory constants
------------------------------------------------------------
revno: 19
committer: Luke Benstead <luke@helium.(none)>
timestamp: Wed 2008-08-27 13:33:12 +0100
message:
Added the initial gl_utils implementation for replacing the matrix functionality deprecated in OpenGL 3.0
------------------------------------------------------------
revno: 18
committer: Carsten Haubold <dumbo@dumbo-laptop.(none)>
timestamp: Mon 2008-08-25 12:46:16 +0200
message:
Fixed a bug in kmMat4LookAt
------------------------------------------------------------
revno: 17 [merge]
committer: Carsten Haubold <dumbo@dumbo-laptop.(none)>
timestamp: Sun 2008-08-24 22:07:49 +0200
message:
Merge branch 'master' of git@github.com:Kazade/kazmath
------------------------------------------------------------
revno: 16
committer: Carsten Haubold <dumbo@dumbo-laptop.(none)>
timestamp: Sun 2008-08-24 22:06:45 +0200
message:
Added kmMat4LookAt
------------------------------------------------------------
revno: 15
committer: Carsten Haubold <dumbo@dumbo-laptop.(none)>
timestamp: Wed 2008-08-20 11:18:10 +0200
message:
Added Fill methods for all Vec and Mat structs
------------------------------------------------------------
revno: 14
committer: Carsten Haubold <dumbo@dumbo-laptop.(none)>
timestamp: Tue 2008-08-19 22:31:55 +0200
message:
Added UnitTests, changed bool to int and fixed some minor bugs
------------------------------------------------------------
revno: 13
committer: Carsten Haubold <dumbo@dumbo-laptop.(none)>
timestamp: Sun 2008-08-17 23:19:21 +0200
message:
removed .svn entries which did not belong here
------------------------------------------------------------
revno: 12
committer: Carsten Haubold <dumbo@dumbo-laptop.(none)>
timestamp: Sun 2008-08-17 23:17:07 +0200
message:
some tweaks on matrices and first test-app, PerspectiveProjection is correct !
------------------------------------------------------------
revno: 11
committer: Carsten Haubold <dumbo@dumbo-laptop.(none)>
timestamp: Sun 2008-08-17 16:04:09 +0200
message:
Renamed cotangent to cotangens
------------------------------------------------------------
revno: 10
committer: Luke Benstead <kazade@gmail.com>
timestamp: Sat 2008-08-16 21:51:22 +0100
message:
Added kmMat4PerspectiveProjection and kmMat4OrthographicProjection
------------------------------------------------------------
revno: 9
committer: Luke Benstead <kazade@gmail.com>
timestamp: Thu 2008-08-14 21:15:45 +0100
message:
Added the aabb struct
------------------------------------------------------------
revno: 8
committer: Luke Benstead <kazade@gmail.com>
timestamp: Thu 2008-08-14 17:57:43 +0100
message:
Added the kmAABB structure
------------------------------------------------------------
revno: 7
committer: Luke Benstead <kazade@gmail.com>
timestamp: Thu 2008-08-14 14:32:24 +0100
message:
Fixed broken kmMat3Transpose
------------------------------------------------------------
revno: 6
committer: Luke Benstead <kazade@gmail.com>
timestamp: Thu 2008-08-14 14:21:04 +0100
message:
Fixed broken kmMat4Translation, w component was not set
------------------------------------------------------------
revno: 5
committer: Luke Benstead <kazade@gmail.com>
timestamp: Thu 2008-08-14 14:01:47 +0100
message:
Added mat3.c and mat3.h to the cmake file
------------------------------------------------------------
revno: 4
committer: Luke Benstead <kazade@gmail.com>
timestamp: Thu 2008-08-14 13:56:26 +0100
message:
Added the authors section to the readme
------------------------------------------------------------
revno: 3
committer: Luke Benstead <kazade@gmail.com>
timestamp: Thu 2008-08-14 13:55:41 +0100
message:
Updated the readme file
------------------------------------------------------------
revno: 2
committer: Luke Benstead <kazade@gmail.com>
timestamp: Thu 2008-08-14 13:53:26 +0100
message:
Added kazmath to git
------------------------------------------------------------
revno: 1
committer: Luke Benstead <kazade@gmail.com>
timestamp: Thu 2008-08-14 13:47:51 +0100
message:
First commit
------------------------------------------------------------
Use --include-merges or -n0 to see merged revisions.

View File

@ -1,63 +0,0 @@
/*
Copyright (c) 2008, Luke Benstead.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "kazmath/aabb.h"
/**
* Returns KM_TRUE if point is in the specified AABB, returns
* KM_FALSE otherwise.
*/
const int kmAABBContainsPoint(const kmVec3* pPoint, const kmAABB* pBox)
{
if(pPoint->x >= pBox->min.x && pPoint->x <= pBox->max.x &&
pPoint->y >= pBox->min.y && pPoint->y <= pBox->max.y &&
pPoint->z >= pBox->min.z && pPoint->z <= pBox->max.z) {
return KM_TRUE;
}
return KM_FALSE;
}
/**
* Assigns pIn to pOut, returns pOut.
*/
kmAABB* const kmAABBAssign(kmAABB* pOut, const kmAABB* pIn)
{
kmVec3Assign(&pOut->min, &pIn->min);
kmVec3Assign(&pOut->max, &pIn->max);
return pOut;
}
/**
* Scales pIn by s, stores the resulting AABB in pOut. Returns pOut
*/
kmAABB* const kmAABBScale(kmAABB* pOut, const kmAABB* pIn, kmScalar s)
{
assert(0 && "Not implemented");
return 0;
}

View File

@ -1,372 +0,0 @@
/*
Copyright (c) 2008, Luke Benstead.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdlib.h>
#include <memory.h>
#include <assert.h>
#include "kazmath/utility.h"
#include "kazmath/vec3.h"
#include "kazmath/mat3.h"
#include "kazmath/quaternion.h"
kmMat3* const kmMat3Fill(kmMat3* pOut, const kmScalar* pMat)
{
memcpy(pOut->mat, pMat, sizeof(kmScalar) * 9);
return pOut;
}
/** Sets pOut to an identity matrix returns pOut*/
kmMat3* const kmMat3Identity(kmMat3* pOut)
{
memset(pOut->mat, 0, sizeof(float) * 9);
pOut->mat[0] = pOut->mat[4] = pOut->mat[8] = 1.0f;
return pOut;
}
const kmScalar kmMat3Determinant(const kmMat3* pIn)
{
kmScalar output;
/*
calculating the determinant following the rule of sarus,
| 0 3 6 | 0 3 |
m = | 1 4 7 | 1 4 |
| 2 5 8 | 2 5 |
now sum up the products of the diagonals going to the right (i.e. 0,4,8)
and subtract the products of the other diagonals (i.e. 2,4,6)
*/
output = pIn->mat[0] * pIn->mat[4] * pIn->mat[8] + pIn->mat[1] * pIn->mat[5] * pIn->mat[6] + pIn->mat[2] * pIn->mat[3] * pIn->mat[7];
output -= pIn->mat[2] * pIn->mat[4] * pIn->mat[6] + pIn->mat[0] * pIn->mat[5] * pIn->mat[7] + pIn->mat[1] * pIn->mat[3] * pIn->mat[8];
return output;
}
kmMat3* const kmMat3Adjugate(kmMat3* pOut, const kmMat3* pIn)
{
pOut->mat[0] = pIn->mat[4] * pIn->mat[8] - pIn->mat[5] * pIn->mat[7];
pOut->mat[1] = pIn->mat[2] * pIn->mat[7] - pIn->mat[1] * pIn->mat[8];
pOut->mat[2] = pIn->mat[1] * pIn->mat[5] - pIn->mat[2] * pIn->mat[4];
pOut->mat[3] = pIn->mat[5] * pIn->mat[6] - pIn->mat[3] * pIn->mat[8];
pOut->mat[4] = pIn->mat[0] * pIn->mat[8] - pIn->mat[2] * pIn->mat[6];
pOut->mat[5] = pIn->mat[2] * pIn->mat[3] - pIn->mat[0] * pIn->mat[5];
pOut->mat[6] = pIn->mat[3] * pIn->mat[7] - pIn->mat[4] * pIn->mat[6];
// XXX: pIn->mat[9] is invalid!
// pOut->mat[7] = pIn->mat[1] * pIn->mat[6] - pIn->mat[9] * pIn->mat[7];
pOut->mat[8] = pIn->mat[0] * pIn->mat[4] - pIn->mat[1] * pIn->mat[3];
return pOut;
}
kmMat3* const kmMat3Inverse(kmMat3* pOut, const kmScalar pDeterminate, const kmMat3* pM)
{
kmScalar detInv;
kmMat3 adjugate;
if(pDeterminate == 0.0)
{
return NULL;
}
detInv = 1.0f / pDeterminate;
kmMat3Adjugate(&adjugate, pM);
kmMat3ScalarMultiply(pOut, &adjugate, detInv);
return pOut;
}
/** Returns true if pIn is an identity matrix */
const int 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->mat, sizeof(float) * 9) == 0);
}
/** Sets pOut to the transpose of pIn, returns pOut */
kmMat3* const kmMat3Transpose(kmMat3* pOut, const kmMat3* pIn)
{
int z, x;
for (z = 0; z < 3; ++z) {
for (x = 0; x < 3; ++x) {
pOut->mat[(z * 3) + x] = pIn->mat[(x * 3) + z];
}
}
return pOut;
}
/* Multiplies pM1 with pM2, stores the result in pOut, returns pOut */
kmMat3* const kmMat3Multiply(kmMat3* pOut, const kmMat3* pM1, const kmMat3* pM2)
{
float mat[9];
const float *m1 = pM1->mat, *m2 = pM2->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->mat, mat, sizeof(float)*9);
return pOut;
}
kmMat3* const kmMat3ScalarMultiply(kmMat3* pOut, const kmMat3* pM, const kmScalar pFactor)
{
float mat[9];
int i;
for(i = 0; i < 9; i++)
{
mat[i] = pM->mat[i] * pFactor;
}
memcpy(pOut->mat, mat, sizeof(float)*9);
return pOut;
}
/** Assigns the value of pIn to pOut */
kmMat3* const kmMat3Assign(kmMat3* pOut, const kmMat3* pIn)
{
assert(pOut != pIn); //You have tried to self-assign!!
memcpy(pOut->mat, pIn->mat, sizeof(float)*9);
return pOut;
}
/** Returns true if the 2 matrices are equal (approximately) */
const int kmMat3AreEqual(const kmMat3* pMat1, const kmMat3* pMat2)
{
int i;
if (pMat1 == pMat2) {
return KM_TRUE;
}
for (i = 0; i < 9; ++i) {
if (!(pMat1->mat[i] + kmEpsilon > pMat2->mat[i] &&
pMat1->mat[i] - kmEpsilon < pMat2->mat[i])) {
return KM_FALSE;
}
}
return KM_TRUE;
}
/* Rotation around the z axis so everything stays planar in XY */
kmMat3* const kmMat3Rotation(kmMat3* pOut, const float radians)
{
/*
| cos(A) -sin(A) 0 |
M = | sin(A) cos(A) 0 |
| 0 0 1 |
*/
pOut->mat[0] = cosf(radians);
pOut->mat[1] = sinf(radians);
pOut->mat[2] = 0.0f;
pOut->mat[3] = -sinf(radians);;
pOut->mat[4] = cosf(radians);
pOut->mat[5] = 0.0f;
pOut->mat[6] = 0.0f;
pOut->mat[7] = 0.0f;
pOut->mat[8] = 1.0f;
return pOut;
}
/** Builds a scaling matrix */
kmMat3* const kmMat3Scaling(kmMat3* pOut, const kmScalar x, const kmScalar y)
{
// memset(pOut->mat, 0, sizeof(float) * 9);
kmMat3Identity(pOut);
pOut->mat[0] = x;
pOut->mat[4] = y;
return pOut;
}
kmMat3* const kmMat3Translation(kmMat3* pOut, const kmScalar x, const kmScalar y)
{
// memset(pOut->mat, 0, sizeof(float) * 9);
kmMat3Identity(pOut);
pOut->mat[6] = x;
pOut->mat[7] = y;
// pOut->mat[8] = 1.0;
return pOut;
}
kmMat3* const kmMat3RotationQuaternion(kmMat3* pOut, const kmQuaternion* pIn)
{
if (!pIn || !pOut) {
return NULL;
}
// First row
pOut->mat[0] = 1.0f - 2.0f * (pIn->y * pIn->y + pIn->z * pIn->z);
pOut->mat[1] = 2.0f * (pIn->x * pIn->y - pIn->w * pIn->z);
pOut->mat[2] = 2.0f * (pIn->x * pIn->z + pIn->w * pIn->y);
// Second row
pOut->mat[3] = 2.0f * (pIn->x * pIn->y + pIn->w * pIn->z);
pOut->mat[4] = 1.0f - 2.0f * (pIn->x * pIn->x + pIn->z * pIn->z);
pOut->mat[5] = 2.0f * (pIn->y * pIn->z - pIn->w * pIn->x);
// Third row
pOut->mat[6] = 2.0f * (pIn->x * pIn->z - pIn->w * pIn->y);
pOut->mat[7] = 2.0f * (pIn->y * pIn->z + pIn->w * pIn->x);
pOut->mat[8] = 1.0f - 2.0f * (pIn->x * pIn->x + pIn->y * pIn->y);
return pOut;
}
kmMat3* const kmMat3RotationAxisAngle(kmMat3* pOut, const struct kmVec3* axis, kmScalar radians)
{
float rcos = cosf(radians);
float rsin = sinf(radians);
pOut->mat[0] = rcos + axis->x * axis->x * (1 - rcos);
pOut->mat[1] = axis->z * rsin + axis->y * axis->x * (1 - rcos);
pOut->mat[2] = -axis->y * rsin + axis->z * axis->x * (1 - rcos);
pOut->mat[3] = -axis->z * rsin + axis->x * axis->y * (1 - rcos);
pOut->mat[4] = rcos + axis->y * axis->y * (1 - rcos);
pOut->mat[5] = axis->x * rsin + axis->z * axis->y * (1 - rcos);
pOut->mat[6] = axis->y * rsin + axis->x * axis->z * (1 - rcos);
pOut->mat[7] = -axis->x * rsin + axis->y * axis->z * (1 - rcos);
pOut->mat[8] = rcos + axis->z * axis->z * (1 - rcos);
return pOut;
}
kmVec3* const kmMat3RotationToAxisAngle(kmVec3* pAxis, kmScalar* radians, const kmMat3* pIn)
{
/*Surely not this easy?*/
kmQuaternion temp;
kmQuaternionRotationMatrix(&temp, pIn);
kmQuaternionToAxisAngle(&temp, pAxis, radians);
return pAxis;
}
/**
* Builds an X-axis rotation matrix and stores it in pOut, returns pOut
*/
kmMat3* const kmMat3RotationX(kmMat3* pOut, const float radians)
{
/*
| 1 0 0 |
M = | 0 cos(A) -sin(A) |
| 0 sin(A) cos(A) |
*/
pOut->mat[0] = 1.0f;
pOut->mat[1] = 0.0f;
pOut->mat[2] = 0.0f;
pOut->mat[3] = 0.0f;
pOut->mat[4] = cosf(radians);
pOut->mat[5] = sinf(radians);
pOut->mat[6] = 0.0f;
pOut->mat[7] = -sinf(radians);
pOut->mat[8] = cosf(radians);
return pOut;
}
/**
* Builds a rotation matrix using the rotation around the Y-axis
* The result is stored in pOut, pOut is returned.
*/
kmMat3* const kmMat3RotationY(kmMat3* pOut, const float radians)
{
/*
| cos(A) 0 sin(A) |
M = | 0 1 0 |
| -sin(A) 0 cos(A) |
*/
pOut->mat[0] = cosf(radians);
pOut->mat[1] = 0.0f;
pOut->mat[2] = -sinf(radians);
pOut->mat[3] = 0.0f;
pOut->mat[4] = 1.0f;
pOut->mat[5] = 0.0f;
pOut->mat[6] = sinf(radians);
pOut->mat[7] = 0.0f;
pOut->mat[8] = cosf(radians);
return pOut;
}
/**
* Builds a rotation matrix around the Z-axis. The resulting
* matrix is stored in pOut. pOut is returned.
*/
kmMat3* const kmMat3RotationZ(kmMat3* pOut, const float radians)
{
/*
| cos(A) -sin(A) 0 |
M = | sin(A) cos(A) 0 |
| 0 0 1 |
*/
pOut->mat[0] = cosf(radians);
pOut->mat[1] =-sinf(radians);
pOut->mat[2] = 0.0f;
pOut->mat[3] = sinf(radians);;
pOut->mat[4] = cosf(radians);
pOut->mat[5] = 0.0f;
pOut->mat[6] = 0.0f;
pOut->mat[7] = 0.0f;
pOut->mat[8] = 1.0f;
return pOut;
}

View File

@ -1,792 +0,0 @@
/*
Copyright (c) 2008, Luke Benstead.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file mat4.c
*/
#include <memory.h>
#include <assert.h>
#include <stdlib.h>
#include "kazmath/utility.h"
#include "kazmath/vec3.h"
#include "kazmath/mat4.h"
#include "kazmath/mat3.h"
#include "kazmath/quaternion.h"
#include "kazmath/plane.h"
#include "kazmath/neon_matrix_impl.h"
/**
* Fills a kmMat4 structure with the values from a 16
* element array of floats
* @Params pOut - A pointer to the destination matrix
* pMat - A 16 element array of floats
* @Return Returns pOut so that the call can be nested
*/
kmMat4* const kmMat4Fill(kmMat4* pOut, const kmScalar* pMat)
{
memcpy(pOut->mat, pMat, sizeof(kmScalar) * 16);
return pOut;
}
/**
* Sets pOut to an identity matrix returns pOut
* @Params pOut - A pointer to the matrix to set to identity
* @Return Returns pOut so that the call can be nested
*/
kmMat4* const kmMat4Identity(kmMat4* pOut)
{
memset(pOut->mat, 0, sizeof(float) * 16);
pOut->mat[0] = pOut->mat[5] = pOut->mat[10] = pOut->mat[15] = 1.0f;
return pOut;
}
float get(const kmMat4 * pIn, int row, int col)
{
return pIn->mat[row + 4*col];
}
void set(kmMat4 * pIn, int row, int col, float value)
{
pIn->mat[row + 4*col] = value;
}
void swap(kmMat4 * pIn, int r1, int c1, int r2, int c2)
{
float tmp = get(pIn,r1,c1);
set(pIn,r1,c1,get(pIn,r2,c2));
set(pIn,r2,c2, tmp);
}
//Returns an upper and a lower triangular matrix which are L and R in the Gauss algorithm
int gaussj(kmMat4 *a, kmMat4 *b)
{
int i, icol = 0, irow = 0, j, k, l, ll, n = 4, m = 4;
float big, dum, pivinv;
int indxc[4] = {0};
int indxr[4] = {0};
int ipiv[4] = {0};
for (j = 0; j < n; j++) {
ipiv[j] = 0;
}
for (i = 0; i < n; i++) {
big = 0.0f;
for (j = 0; j < n; j++) {
if (ipiv[j] != 1) {
for (k = 0; k < n; k++) {
if (ipiv[k] == 0) {
if (abs(get(a,j, k)) >= big) {
big = abs(get(a,j, k));
irow = j;
icol = k;
}
}
}
}
}
++(ipiv[icol]);
if (irow != icol) {
for (l = 0; l < n; l++) {
swap(a,irow, l, icol, l);
}
for (l = 0; l < m; l++) {
swap(b,irow, l, icol, l);
}
}
indxr[i] = irow;
indxc[i] = icol;
if (get(a,icol, icol) == 0.0) {
return KM_FALSE;
}
pivinv = 1.0f / get(a,icol, icol);
set(a,icol, icol, 1.0f);
for (l = 0; l < n; l++) {
set(a,icol, l, get(a,icol, l) * pivinv);
}
for (l = 0; l < m; l++) {
set(b,icol, l, get(b,icol, l) * pivinv);
}
for (ll = 0; ll < n; ll++) {
if (ll != icol) {
dum = get(a,ll, icol);
set(a,ll, icol, 0.0f);
for (l = 0; l < n; l++) {
set(a,ll, l, get(a,ll, l) - get(a,icol, l) * dum);
}
for (l = 0; l < m; l++) {
set(b,ll, l, get(a,ll, l) - get(b,icol, l) * dum);
}
}
}
}
// This is the end of the main loop over columns of the reduction. It only remains to unscram-
// ble the solution in view of the column interchanges. We do this by interchanging pairs of
// columns in the reverse order that the permutation was built up.
for (l = n - 1; l >= 0; l--) {
if (indxr[l] != indxc[l]) {
for (k = 0; k < n; k++) {
swap(a,k, indxr[l], k, indxc[l]);
}
}
}
return KM_TRUE;
}
/**
* Calculates the inverse of pM and stores the result in
* pOut.
* @Return Returns NULL if there is no inverse, else pOut
*/
kmMat4* const kmMat4Inverse(kmMat4* pOut, const kmMat4* pM)
{
kmMat4 inv;
kmMat4 tmp;
kmMat4Assign(&inv, pM);
kmMat4Identity(&tmp);
if(gaussj(&inv, &tmp) == KM_FALSE) {
return NULL;
}
kmMat4Assign(pOut, &inv);
return pOut;
}
/**
* Returns KM_TRUE if pIn is an identity matrix
* KM_FALSE otherwise
*/
const int 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->mat, sizeof(float) * 16) == 0);
}
/**
* Sets pOut to the transpose of pIn, returns pOut
*/
kmMat4* const kmMat4Transpose(kmMat4* pOut, const kmMat4* pIn)
{
int x, z;
for (z = 0; z < 4; ++z) {
for (x = 0; x < 4; ++x) {
pOut->mat[(z * 4) + x] = pIn->mat[(x * 4) + z];
}
}
return pOut;
}
/**
* Multiplies pM1 with pM2, stores the result in pOut, returns pOut
*/
kmMat4* const kmMat4Multiply(kmMat4* pOut, const kmMat4* pM1, const kmMat4* pM2)
{
#if defined(__ARM_NEON__) && !defined(__arm64__)
// It is possible to skip the memcpy() since "out" does not overwrite p1 or p2.
// otherwise a temp must be needed.
float *mat = pOut->mat;
// Invert column-order with row-order
NEON_Matrix4Mul( &pM2->mat[0], &pM1->mat[0], &mat[0] );
#else
float mat[16];
const float *m1 = pM1->mat, *m2 = pM2->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->mat, mat, sizeof(pOut->mat));
#endif
return pOut;
}
/**
* Assigns the value of pIn to pOut
*/
kmMat4* const kmMat4Assign(kmMat4* pOut, const kmMat4* pIn)
{
assert(pOut != pIn && "You have tried to self-assign!!");
memcpy(pOut->mat, pIn->mat, sizeof(float)*16);
return pOut;
}
/**
* Returns KM_TRUE if the 2 matrices are equal (approximately)
*/
const int kmMat4AreEqual(const kmMat4* pMat1, const kmMat4* pMat2)
{
int i = 0;
assert(pMat1 != pMat2 && "You are comparing the same thing!");
for (i = 0; i < 16; ++i)
{
if (!(pMat1->mat[i] + kmEpsilon > pMat2->mat[i] &&
pMat1->mat[i] - kmEpsilon < pMat2->mat[i])) {
return KM_FALSE;
}
}
return KM_TRUE;
}
/**
* Build a rotation matrix from an axis and an angle. Result is stored in pOut.
* pOut is returned.
*/
kmMat4* const kmMat4RotationAxisAngle(kmMat4* pOut, const kmVec3* axis, kmScalar radians)
{
float rcos = cosf(radians);
float rsin = sinf(radians);
kmVec3 normalizedAxis;
kmVec3Normalize(&normalizedAxis, axis);
pOut->mat[0] = rcos + normalizedAxis.x * normalizedAxis.x * (1 - rcos);
pOut->mat[1] = normalizedAxis.z * rsin + normalizedAxis.y * normalizedAxis.x * (1 - rcos);
pOut->mat[2] = -normalizedAxis.y * rsin + normalizedAxis.z * normalizedAxis.x * (1 - rcos);
pOut->mat[3] = 0.0f;
pOut->mat[4] = -normalizedAxis.z * rsin + normalizedAxis.x * normalizedAxis.y * (1 - rcos);
pOut->mat[5] = rcos + normalizedAxis.y * normalizedAxis.y * (1 - rcos);
pOut->mat[6] = normalizedAxis.x * rsin + normalizedAxis.z * normalizedAxis.y * (1 - rcos);
pOut->mat[7] = 0.0f;
pOut->mat[8] = normalizedAxis.y * rsin + normalizedAxis.x * normalizedAxis.z * (1 - rcos);
pOut->mat[9] = -normalizedAxis.x * rsin + normalizedAxis.y * normalizedAxis.z * (1 - rcos);
pOut->mat[10] = rcos + normalizedAxis.z * normalizedAxis.z * (1 - rcos);
pOut->mat[11] = 0.0f;
pOut->mat[12] = 0.0f;
pOut->mat[13] = 0.0f;
pOut->mat[14] = 0.0f;
pOut->mat[15] = 1.0f;
return pOut;
}
/**
* Builds an X-axis rotation matrix and stores it in pOut, returns pOut
*/
kmMat4* const 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->mat[0] = 1.0f;
pOut->mat[1] = 0.0f;
pOut->mat[2] = 0.0f;
pOut->mat[3] = 0.0f;
pOut->mat[4] = 0.0f;
pOut->mat[5] = cosf(radians);
pOut->mat[6] = sinf(radians);
pOut->mat[7] = 0.0f;
pOut->mat[8] = 0.0f;
pOut->mat[9] = -sinf(radians);
pOut->mat[10] = cosf(radians);
pOut->mat[11] = 0.0f;
pOut->mat[12] = 0.0f;
pOut->mat[13] = 0.0f;
pOut->mat[14] = 0.0f;
pOut->mat[15] = 1.0f;
return pOut;
}
/**
* Builds a rotation matrix using the rotation around the Y-axis
* The result is stored in pOut, pOut is returned.
*/
kmMat4* const 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->mat[0] = cosf(radians);
pOut->mat[1] = 0.0f;
pOut->mat[2] = -sinf(radians);
pOut->mat[3] = 0.0f;
pOut->mat[4] = 0.0f;
pOut->mat[5] = 1.0f;
pOut->mat[6] = 0.0f;
pOut->mat[7] = 0.0f;
pOut->mat[8] = sinf(radians);
pOut->mat[9] = 0.0f;
pOut->mat[10] = cosf(radians);
pOut->mat[11] = 0.0f;
pOut->mat[12] = 0.0f;
pOut->mat[13] = 0.0f;
pOut->mat[14] = 0.0f;
pOut->mat[15] = 1.0f;
return pOut;
}
/**
* Builds a rotation matrix around the Z-axis. The resulting
* matrix is stored in pOut. pOut is returned.
*/
kmMat4* const 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->mat[0] = cosf(radians);
pOut->mat[1] = sinf(radians);
pOut->mat[2] = 0.0f;
pOut->mat[3] = 0.0f;
pOut->mat[4] = -sinf(radians);;
pOut->mat[5] = cosf(radians);
pOut->mat[6] = 0.0f;
pOut->mat[7] = 0.0f;
pOut->mat[8] = 0.0f;
pOut->mat[9] = 0.0f;
pOut->mat[10] = 1.0f;
pOut->mat[11] = 0.0f;
pOut->mat[12] = 0.0f;
pOut->mat[13] = 0.0f;
pOut->mat[14] = 0.0f;
pOut->mat[15] = 1.0f;
return pOut;
}
/**
* Builds a rotation matrix from pitch, yaw and roll. The resulting
* matrix is stored in pOut and pOut is returned
*/
kmMat4* const 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);
double srsp = sr * sp;
double crsp = cr * sp;
pOut->mat[0] = (kmScalar) cp * cy;
pOut->mat[4] = (kmScalar) cp * sy;
pOut->mat[8] = (kmScalar) - sp;
pOut->mat[1] = (kmScalar) srsp * cy - cr * sy;
pOut->mat[5] = (kmScalar) srsp * sy + cr * cy;
pOut->mat[9] = (kmScalar) sr * cp;
pOut->mat[2] = (kmScalar) crsp * cy + sr * sy;
pOut->mat[6] = (kmScalar) crsp * sy - sr * cy;
pOut->mat[10] = (kmScalar) cr * cp;
pOut->mat[3] = pOut->mat[7] = pOut->mat[11] = 0.0;
pOut->mat[15] = 1.0;
return pOut;
}
/** Converts a quaternion to a rotation matrix,
* the result is stored in pOut, returns pOut
*/
kmMat4* const kmMat4RotationQuaternion(kmMat4* pOut, const kmQuaternion* pQ)
{
pOut->mat[0] = 1.0f - 2.0f * (pQ->y * pQ->y + pQ->z * pQ->z );
pOut->mat[1] = 2.0f * (pQ->x * pQ->y + pQ->z * pQ->w);
pOut->mat[2] = 2.0f * (pQ->x * pQ->z - pQ->y * pQ->w);
pOut->mat[3] = 0.0f;
// Second row
pOut->mat[4] = 2.0f * ( pQ->x * pQ->y - pQ->z * pQ->w );
pOut->mat[5] = 1.0f - 2.0f * ( pQ->x * pQ->x + pQ->z * pQ->z );
pOut->mat[6] = 2.0f * (pQ->z * pQ->y + pQ->x * pQ->w );
pOut->mat[7] = 0.0f;
// Third row
pOut->mat[8] = 2.0f * ( pQ->x * pQ->z + pQ->y * pQ->w );
pOut->mat[9] = 2.0f * ( pQ->y * pQ->z - pQ->x * pQ->w );
pOut->mat[10] = 1.0f - 2.0f * ( pQ->x * pQ->x + pQ->y * pQ->y );
pOut->mat[11] = 0.0f;
// Fourth row
pOut->mat[12] = 0;
pOut->mat[13] = 0;
pOut->mat[14] = 0;
pOut->mat[15] = 1.0f;
return pOut;
}
/** Builds a scaling matrix */
kmMat4* const kmMat4Scaling(kmMat4* pOut, const kmScalar x, const kmScalar y,
const kmScalar z)
{
memset(pOut->mat, 0, sizeof(float) * 16);
pOut->mat[0] = x;
pOut->mat[5] = y;
pOut->mat[10] = z;
pOut->mat[15] = 1.0f;
return pOut;
}
/**
* Builds a translation matrix. All other elements in the matrix
* will be set to zero except for the diagonal which is set to 1.0
*/
kmMat4* const kmMat4Translation(kmMat4* pOut, const kmScalar x,
const kmScalar y, const kmScalar z)
{
//FIXME: Write a test for this
memset(pOut->mat, 0, sizeof(float) * 16);
pOut->mat[0] = 1.0f;
pOut->mat[5] = 1.0f;
pOut->mat[10] = 1.0f;
pOut->mat[12] = x;
pOut->mat[13] = y;
pOut->mat[14] = z;
pOut->mat[15] = 1.0f;
return pOut;
}
/**
* Get the up vector from a matrix. pIn is the matrix you
* wish to extract the vector from. pOut is a pointer to the
* kmVec3 structure that should hold the resulting vector
*/
kmVec3* const kmMat4GetUpVec3(kmVec3* pOut, const kmMat4* pIn)
{
pOut->x = pIn->mat[4];
pOut->y = pIn->mat[5];
pOut->z = pIn->mat[6];
kmVec3Normalize(pOut, pOut);
return pOut;
}
/** Extract the right vector from a 4x4 matrix. The result is
* stored in pOut. Returns pOut.
*/
kmVec3* const kmMat4GetRightVec3(kmVec3* pOut, const kmMat4* pIn)
{
pOut->x = pIn->mat[0];
pOut->y = pIn->mat[1];
pOut->z = pIn->mat[2];
kmVec3Normalize(pOut, pOut);
return pOut;
}
/**
* Extract the forward vector from a 4x4 matrix. The result is
* stored in pOut. Returns pOut.
*/
kmVec3* const kmMat4GetForwardVec3(kmVec3* pOut, const kmMat4* pIn)
{
pOut->x = pIn->mat[8];
pOut->y = pIn->mat[9];
pOut->z = pIn->mat[10];
kmVec3Normalize(pOut, pOut);
return pOut;
}
/**
* Creates a perspective projection matrix in the
* same way as gluPerspective
*/
kmMat4* const kmMat4PerspectiveProjection(kmMat4* pOut, kmScalar fovY,
kmScalar aspect, kmScalar zNear,
kmScalar zFar)
{
kmScalar r = kmDegreesToRadians(fovY / 2);
kmScalar deltaZ = zFar - zNear;
kmScalar s = sin(r);
kmScalar cotangent = 0;
if (deltaZ == 0 || s == 0 || aspect == 0) {
return NULL;
}
//cos(r) / sin(r) = cot(r)
cotangent = cos(r) / s;
kmMat4Identity(pOut);
pOut->mat[0] = cotangent / aspect;
pOut->mat[5] = cotangent;
pOut->mat[10] = -(zFar + zNear) / deltaZ;
pOut->mat[11] = -1;
pOut->mat[14] = -2 * zNear * zFar / deltaZ;
pOut->mat[15] = 0;
return pOut;
}
/** Creates an orthographic projection matrix like glOrtho */
kmMat4* const kmMat4OrthographicProjection(kmMat4* pOut, kmScalar left,
kmScalar right, kmScalar bottom,
kmScalar top, kmScalar nearVal,
kmScalar farVal)
{
kmScalar tx = -((right + left) / (right - left));
kmScalar ty = -((top + bottom) / (top - bottom));
kmScalar tz = -((farVal + nearVal) / (farVal - nearVal));
kmMat4Identity(pOut);
pOut->mat[0] = 2 / (right - left);
pOut->mat[5] = 2 / (top - bottom);
pOut->mat[10] = -2 / (farVal - nearVal);
pOut->mat[12] = tx;
pOut->mat[13] = ty;
pOut->mat[14] = tz;
return pOut;
}
/**
* Builds a translation matrix in the same way as gluLookAt()
* the resulting matrix is stored in pOut. pOut is returned.
*/
kmMat4* const kmMat4LookAt(kmMat4* pOut, const kmVec3* pEye,
const kmVec3* pCenter, const kmVec3* pUp)
{
kmVec3 f, up, s, u;
kmMat4 translate;
kmVec3Subtract(&f, pCenter, pEye);
kmVec3Normalize(&f, &f);
kmVec3Assign(&up, pUp);
kmVec3Normalize(&up, &up);
kmVec3Cross(&s, &f, &up);
kmVec3Normalize(&s, &s);
kmVec3Cross(&u, &s, &f);
kmVec3Normalize(&s, &s);
kmMat4Identity(pOut);
pOut->mat[0] = s.x;
pOut->mat[4] = s.y;
pOut->mat[8] = s.z;
pOut->mat[1] = u.x;
pOut->mat[5] = u.y;
pOut->mat[9] = u.z;
pOut->mat[2] = -f.x;
pOut->mat[6] = -f.y;
pOut->mat[10] = -f.z;
kmMat4Translation(&translate, -pEye->x, -pEye->y, -pEye->z);
kmMat4Multiply(pOut, pOut, &translate);
return pOut;
}
/**
* Extract a 3x3 rotation matrix from the input 4x4 transformation.
* Stores the result in pOut, returns pOut
*/
kmMat3* const kmMat4ExtractRotation(kmMat3* pOut, const kmMat4* pIn)
{
pOut->mat[0] = pIn->mat[0];
pOut->mat[1] = pIn->mat[1];
pOut->mat[2] = pIn->mat[2];
pOut->mat[3] = pIn->mat[4];
pOut->mat[4] = pIn->mat[5];
pOut->mat[5] = pIn->mat[6];
pOut->mat[6] = pIn->mat[8];
pOut->mat[7] = pIn->mat[9];
pOut->mat[8] = pIn->mat[10];
return pOut;
}
/**
* Take the rotation from a 4x4 transformation matrix, and return it as an axis and an angle (in radians)
* returns the output axis.
*/
kmVec3* const kmMat4RotationToAxisAngle(kmVec3* pAxis, kmScalar* radians, const kmMat4* pIn)
{
/*Surely not this easy?*/
kmQuaternion temp;
kmMat3 rotation;
kmMat4ExtractRotation(&rotation, pIn);
kmQuaternionRotationMatrix(&temp, &rotation);
kmQuaternionToAxisAngle(&temp, pAxis, radians);
return pAxis;
}
/** Build a 4x4 OpenGL transformation matrix using a 3x3 rotation matrix,
* and a 3d vector representing a translation. Assign the result to pOut,
* pOut is also returned.
*/
kmMat4* const kmMat4RotationTranslation(kmMat4* pOut, const kmMat3* rotation, const kmVec3* translation)
{
pOut->mat[0] = rotation->mat[0];
pOut->mat[1] = rotation->mat[1];
pOut->mat[2] = rotation->mat[2];
pOut->mat[3] = 0.0f;
pOut->mat[4] = rotation->mat[3];
pOut->mat[5] = rotation->mat[4];
pOut->mat[6] = rotation->mat[5];
pOut->mat[7] = 0.0f;
pOut->mat[8] = rotation->mat[6];
pOut->mat[9] = rotation->mat[7];
pOut->mat[10] = rotation->mat[8];
pOut->mat[11] = 0.0f;
pOut->mat[12] = translation->x;
pOut->mat[13] = translation->y;
pOut->mat[14] = translation->z;
pOut->mat[15] = 1.0f;
return pOut;
}
kmPlane* const kmMat4ExtractPlane(kmPlane* pOut, const kmMat4* pIn, const kmEnum plane)
{
float t = 1.0f;
switch(plane) {
case KM_PLANE_RIGHT:
pOut->a = pIn->mat[3] - pIn->mat[0];
pOut->b = pIn->mat[7] - pIn->mat[4];
pOut->c = pIn->mat[11] - pIn->mat[8];
pOut->d = pIn->mat[15] - pIn->mat[12];
break;
case KM_PLANE_LEFT:
pOut->a = pIn->mat[3] + pIn->mat[0];
pOut->b = pIn->mat[7] + pIn->mat[4];
pOut->c = pIn->mat[11] + pIn->mat[8];
pOut->d = pIn->mat[15] + pIn->mat[12];
break;
case KM_PLANE_BOTTOM:
pOut->a = pIn->mat[3] + pIn->mat[1];
pOut->b = pIn->mat[7] + pIn->mat[5];
pOut->c = pIn->mat[11] + pIn->mat[9];
pOut->d = pIn->mat[15] + pIn->mat[13];
break;
case KM_PLANE_TOP:
pOut->a = pIn->mat[3] - pIn->mat[1];
pOut->b = pIn->mat[7] - pIn->mat[5];
pOut->c = pIn->mat[11] - pIn->mat[9];
pOut->d = pIn->mat[15] - pIn->mat[13];
break;
case KM_PLANE_FAR:
pOut->a = pIn->mat[3] - pIn->mat[2];
pOut->b = pIn->mat[7] - pIn->mat[6];
pOut->c = pIn->mat[11] - pIn->mat[10];
pOut->d = pIn->mat[15] - pIn->mat[14];
break;
case KM_PLANE_NEAR:
pOut->a = pIn->mat[3] + pIn->mat[2];
pOut->b = pIn->mat[7] + pIn->mat[6];
pOut->c = pIn->mat[11] + pIn->mat[10];
pOut->d = pIn->mat[15] + pIn->mat[14];
break;
default:
assert(0 && "Invalid plane index");
}
t = sqrtf(pOut->a * pOut->a +
pOut->b * pOut->b +
pOut->c * pOut->c);
pOut->a /= t;
pOut->b /= t;
pOut->c /= t;
pOut->d /= t;
return pOut;
}

View File

@ -1,175 +0,0 @@
/*
Copyright (c) 2008, Luke Benstead.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <assert.h>
#include <stdlib.h>
#include "kazmath/vec3.h"
#include "kazmath/vec4.h"
#include "kazmath/plane.h"
const 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);
}
const kmScalar kmPlaneDotCoord(const kmPlane* pP, const kmVec3* pV)
{
return (pP->a * pV->x +
pP->b * pV->y +
pP->c * pV->z + pP->d);
}
const kmScalar kmPlaneDotNormal(const kmPlane* pP, const kmVec3* pV)
{
return (pP->a * pV->x +
pP->b * pV->y +
pP->c * pV->z);
}
kmPlane* const kmPlaneFromPointNormal(kmPlane* pOut, const kmVec3* pPoint, const kmVec3* pNormal)
{
/*
Planea = Nx
Planeb = Ny
Planec = Nz
Planed = NP
*/
pOut->a = pNormal->x;
pOut->b = pNormal->y;
pOut->c = pNormal->z;
pOut->d = -kmVec3Dot(pNormal, pPoint);
return pOut;
}
/**
* Creates a plane from 3 points. The result is stored in pOut.
* pOut is returned.
*/
kmPlane* const 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 = nA
*/
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* const kmPlaneIntersectLine(kmVec3* pOut, const kmPlane* pP, const kmVec3* pV1, const kmVec3* pV2)
{
/*
n = (Planea, Planeb, Planec)
d = V U
Out = U d(Pd + nU)(dn) [iff dn 0]
*/
kmVec3 d;
assert(0 && "Not implemented");
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;
} */
return NULL;
}
kmPlane* const kmPlaneNormalize(kmPlane* pOut, const kmPlane* pP)
{
kmVec3 n;
kmScalar l = 0;
n.x = pP->a;
n.y = pP->b;
n.z = pP->c;
l = 1.0f / 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* const kmPlaneScale(kmPlane* pOut, const kmPlane* pP, kmScalar s)
{
assert(0 && "Not implemented");
return NULL;
}
/**
* Returns POINT_INFRONT_OF_PLANE if pP is infront of pIn. Returns
* POINT_BEHIND_PLANE if it is behind. Returns POINT_ON_PLANE otherwise
*/
const 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 File

@ -1,586 +0,0 @@
/*
Copyright (c) 2008, Luke Benstead.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <assert.h>
#include <memory.h>
#include "kazmath/utility.h"
#include "kazmath/mat3.h"
#include "kazmath/vec3.h"
#include "kazmath/quaternion.h"
#ifndef NULL
#define NULL ((void *)0)
#endif
///< Returns pOut, sets pOut to the conjugate of pIn
kmQuaternion* const 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
const 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);
kmQuaternion tmp;
if (fabs(l) > kmEpsilon)
{
pOut->x = 0.0;
pOut->y = 0.0;
pOut->z = 0.0;
pOut->w = 0.0;
return pOut;
}
///Get the conjugute and divide by the length
kmQuaternionScale(pOut,
kmQuaternionConjugate(&tmp, pIn), 1.0f / l);
return pOut;
}
///< Returns true if the quaternion is an identity quaternion
int 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 kmMat3* 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;
}
*/
float x, y, z, w;
float *pMatrix = NULL;
float m4x4[16] = {0};
float scale = 0.0f;
float diagonal = 0.0f;
if(!pIn) {
return NULL;
}
/* 0 3 6
1 4 7
2 5 8
0 1 2 3
4 5 6 7
8 9 10 11
12 13 14 15*/
m4x4[0] = pIn->mat[0];
m4x4[1] = pIn->mat[3];
m4x4[2] = pIn->mat[6];
m4x4[4] = pIn->mat[1];
m4x4[5] = pIn->mat[4];
m4x4[6] = pIn->mat[7];
m4x4[8] = pIn->mat[2];
m4x4[9] = pIn->mat[5];
m4x4[10] = pIn->mat[8];
m4x4[15] = 1;
pMatrix = &m4x4[0];
diagonal = pMatrix[0] + pMatrix[5] + pMatrix[10] + 1;
if(diagonal > kmEpsilon) {
// Calculate the scale of the diagonal
scale = (float)sqrt(diagonal ) * 2;
// Calculate the x, y, x and w of the quaternion through the respective equation
x = ( pMatrix[9] - pMatrix[6] ) / scale;
y = ( pMatrix[2] - pMatrix[8] ) / scale;
z = ( pMatrix[4] - pMatrix[1] ) / scale;
w = 0.25f * scale;
}
else
{
// If the first element of the diagonal is the greatest value
if ( pMatrix[0] > pMatrix[5] && pMatrix[0] > pMatrix[10] )
{
// Find the scale according to the first element, and double that value
scale = (float)sqrt( 1.0f + pMatrix[0] - pMatrix[5] - pMatrix[10] ) * 2.0f;
// Calculate the x, y, x and w of the quaternion through the respective equation
x = 0.25f * scale;
y = (pMatrix[4] + pMatrix[1] ) / scale;
z = (pMatrix[2] + pMatrix[8] ) / scale;
w = (pMatrix[9] - pMatrix[6] ) / scale;
}
// Else if the second element of the diagonal is the greatest value
else if (pMatrix[5] > pMatrix[10])
{
// Find the scale according to the second element, and double that value
scale = (float)sqrt( 1.0f + pMatrix[5] - pMatrix[0] - pMatrix[10] ) * 2.0f;
// Calculate the x, y, x and w of the quaternion through the respective equation
x = (pMatrix[4] + pMatrix[1] ) / scale;
y = 0.25f * scale;
z = (pMatrix[9] + pMatrix[6] ) / scale;
w = (pMatrix[2] - pMatrix[8] ) / scale;
}
// Else the third element of the diagonal is the greatest value
else
{
// Find the scale according to the third element, and double that value
scale = (float)sqrt( 1.0f + pMatrix[10] - pMatrix[0] - pMatrix[5] ) * 2.0f;
// Calculate the x, y, x and w of the quaternion through the respective equation
x = (pMatrix[2] + pMatrix[8] ) / scale;
y = (pMatrix[9] + pMatrix[6] ) / scale;
z = 0.25f * scale;
w = (pMatrix[4] - pMatrix[1] ) / scale;
}
}
pOut->x = x;
pOut->y = y;
pOut->z = z;
pOut->w = w;
return pOut;
#if 0
kmScalar T = pIn->mat[0] + pIn->mat[5] + pIn->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->mat[9] - pIn->mat[6]) / s;
pOut->y = (pIn->mat[8] - pIn->mat[2]) / s;
pOut->z = (pIn->mat[1] - pIn->mat[4]) / s;
pOut->w = 0.25f * s;
kmQuaternionNormalize(pOut, pOut);
return pOut;
}
//Otherwise the calculation depends on which major diagonal element has the greatest value.
if (pIn->mat[0] > pIn->mat[5] && pIn->mat[0] > pIn->mat[10]) {
kmScalar s = sqrtf(1 + pIn->mat[0] - pIn->mat[5] - pIn->mat[10]) * 2;
pOut->x = 0.25f * s;
pOut->y = (pIn->mat[1] + pIn->mat[4]) / s;
pOut->z = (pIn->mat[8] + pIn->mat[2]) / s;
pOut->w = (pIn->mat[9] - pIn->mat[6]) / s;
}
else if (pIn->mat[5] > pIn->mat[10]) {
kmScalar s = sqrtf(1 + pIn->mat[5] - pIn->mat[0] - pIn->mat[10]) * 2;
pOut->x = (pIn->mat[1] + pIn->mat[4]) / s;
pOut->y = 0.25f * s;
pOut->z = (pIn->mat[9] + pIn->mat[6]) / s;
pOut->w = (pIn->mat[8] - pIn->mat[2]) / s;
}
else {
kmScalar s = sqrt(1.0f + pIn->mat[10] - pIn->mat[0] - pIn->mat[5]) * 2.0f;
pOut->x = (pIn->mat[8] + pIn->mat[2] ) / s;
pOut->y = (pIn->mat[6] + pIn->mat[9] ) / s;
pOut->z = 0.25f * s;
pOut->w = (pIn->mat[1] - pIn->mat[4] ) / s;
}
kmQuaternionNormalize(pOut, pOut);
return pOut;*/
#endif // 0
}
///< 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.0f; // convert to rads and half them
ey = kmDegreesToRadians(yaw) / 2.0f;
ez = kmDegreesToRadians(roll) / 2.0f;
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;*/
if (q1->x == q2->x &&
q1->y == q2->y &&
q1->z == q2->z &&
q1->w == q2->w) {
pOut->x = q1->x;
pOut->y = q1->y;
pOut->z = q1->z;
pOut->w = q1->w;
return pOut;
}
{
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 < 2*kmPI + kmEpsilon && scale > 2*kmPI - 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.0f; // 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;
kmScalar a;
kmVec3Assign(&v1, vec1);
kmVec3Assign(&v2, vec2);
kmVec3Normalize(&v1, &v1);
kmVec3Normalize(&v2, &v2);
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.5f;
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.0f * q->w));
kmVec3Scale(&uuv, &uuv, 2.0f);
kmVec3Add(pOut, v, &uv);
kmVec3Add(pOut, pOut, &uuv);
return pOut;
}

View File

@ -1,186 +0,0 @@
#include <assert.h>
#include <stdio.h>
#include "kazmath/ray2.h"
void kmRay2Fill(kmRay2* ray, kmScalar px, kmScalar py, kmScalar vx, kmScalar vy) {
ray->start.x = px;
ray->start.y = py;
ray->dir.x = vx;
ray->dir.y = vy;
}
kmBool kmRay2IntersectLineSegment(const kmRay2* ray, const kmVec2* p1, const kmVec2* p2, kmVec2* intersection) {
float x1 = ray->start.x;
float y1 = ray->start.y;
float x2 = ray->start.x + ray->dir.x;
float y2 = ray->start.y + ray->dir.y;
float x3 = p1->x;
float y3 = p1->y;
float x4 = p2->x;
float y4 = p2->y;
float denom = (y4 -y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);
float ua, x, y;
//If denom is zero, the lines are parallel
if(denom > -kmEpsilon && denom < kmEpsilon) {
return KM_FALSE;
}
ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / denom;
// float ub = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) / denom;
x = x1 + ua * (x2 - x1);
y = y1 + ua * (y2 - y1);
if(x < kmMin(p1->x, p2->x) - kmEpsilon ||
x > kmMax(p1->x, p2->x) + kmEpsilon ||
y < kmMin(p1->y, p2->y) - kmEpsilon ||
y > kmMax(p1->y, p2->y) + kmEpsilon) {
//Outside of line
//printf("Outside of line, %f %f (%f %f)(%f, %f)\n", x, y, p1->x, p1->y, p2->x, p2->y);
return KM_FALSE;
}
if(x < kmMin(x1, x2) - kmEpsilon ||
x > kmMax(x1, x2) + kmEpsilon ||
y < kmMin(y1, y2) - kmEpsilon ||
y > kmMax(y1, y2) + kmEpsilon) {
//printf("Outside of ray, %f %f (%f %f)(%f, %f)\n", x, y, x1, y1, x2, y2);
return KM_FALSE;
}
intersection->x = x;
intersection->y = y;
return KM_TRUE;
/*
kmScalar A1, B1, C1;
kmScalar A2, B2, C2;
A1 = ray->dir.y;
B1 = ray->dir.x;
C1 = A1 * ray->start.x + B1 * ray->start.y;
A2 = p2->y - p1->y;
B2 = p2->x - p1->x;
C2 = A2 * p1->x + B2 * p1->y;
double det = (A1 * B2) - (A2 * B1);
if(det == 0) {
printf("Parallel\n");
return KM_FALSE;
}
double x = (B2*C1 - B1*C2) / det;
double y = (A1*C2 - A2*C1) / det;
if(x < min(p1->x, p2->x) - kmEpsilon ||
x > max(p1->x, p2->x) + kmEpsilon ||
y < min(p1->y, p2->y) - kmEpsilon ||
y > max(p1->y, p2->y) + kmEpsilon) {
//Outside of line
printf("Outside of line, %f %f (%f %f)(%f, %f)\n", x, y, p1->x, p1->y, p2->x, p2->y);
return KM_FALSE;
}
kmScalar x1 = ray->start.x;
kmScalar x2 = ray->start.x + ray->dir.x;
kmScalar y1 = ray->start.y;
kmScalar y2 = ray->start.y + ray->dir.y;
if(x < min(x1, x2) - kmEpsilon ||
x > max(x1, x2) + kmEpsilon ||
y < min(y1, y2) - kmEpsilon ||
y > max(y1, y2) + kmEpsilon) {
printf("Outside of ray, %f %f (%f %f)(%f, %f)\n", x, y, x1, y1, x2, y2);
return KM_FALSE;
}
intersection->x = x;
intersection->y = y;
return KM_TRUE;*/
}
void calculate_line_normal(kmVec2 p1, kmVec2 p2, kmVec2* normal_out) {
kmVec2 tmp;
kmVec2Subtract(&tmp, &p2, &p1); //Get direction vector
normal_out->x = -tmp.y;
normal_out->y = tmp.x;
kmVec2Normalize(normal_out, normal_out);
//TODO: should check that the normal is pointing out of the triangle
}
kmBool kmRay2IntersectTriangle(const kmRay2* ray, const kmVec2* p1, const kmVec2* p2, const kmVec2* p3, kmVec2* intersection, kmVec2* normal_out) {
kmVec2 intersect;
kmVec2 final_intersect = {0., 0.}, normal = {0., 0.}; // Silencing LLVM SA.
kmScalar distance = 10000.0f;
kmBool intersected = KM_FALSE;
if(kmRay2IntersectLineSegment(ray, p1, p2, &intersect)) {
kmVec2 tmp;
kmScalar this_distance;
intersected = KM_TRUE;
this_distance = kmVec2Length(kmVec2Subtract(&tmp, &intersect, &ray->start));
if(this_distance < distance) {
final_intersect.x = intersect.x;
final_intersect.y = intersect.y;
distance = this_distance;
calculate_line_normal(*p1, *p2, &normal);
}
}
if(kmRay2IntersectLineSegment(ray, p2, p3, &intersect)) {
kmVec2 tmp;
kmScalar this_distance;
intersected = KM_TRUE;
this_distance = kmVec2Length(kmVec2Subtract(&tmp, &intersect, &ray->start));
if(this_distance < distance) {
final_intersect.x = intersect.x;
final_intersect.y = intersect.y;
distance = this_distance;
calculate_line_normal(*p2, *p3, &normal);
}
}
if(kmRay2IntersectLineSegment(ray, p3, p1, &intersect)) {
kmVec2 tmp;
kmScalar this_distance;
intersected = KM_TRUE;
this_distance = kmVec2Length(kmVec2Subtract(&tmp, &intersect, &ray->start));
if(this_distance < distance) {
final_intersect.x = intersect.x;
final_intersect.y = intersect.y;
//distance = this_distance;
calculate_line_normal(*p3, *p1, &normal);
}
}
if(intersected) {
intersection->x = final_intersect.x;
intersection->y = final_intersect.y;
if(normal_out) {
normal_out->x = normal.x;
normal_out->y = normal.y;
}
}
return intersected;
}
kmBool kmRay2IntersectCircle(const kmRay2* ray, const kmVec2 centre, const kmScalar radius, kmVec2* intersection) {
assert(0 && "Not implemented");
return 0;
}

View File

@ -1,118 +0,0 @@
/*
Copyright (c) 2008, Luke Benstead.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <assert.h>
#include <stdlib.h>
#include "kazmath/mat3.h"
#include "kazmath/vec2.h"
#include "kazmath/utility.h"
kmVec2* kmVec2Fill(kmVec2* pOut, kmScalar x, kmScalar y)
{
pOut->x = x;
pOut->y = y;
return pOut;
}
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.0f / kmVec2Length(pIn);
kmVec2 v;
v.x = pIn->x * l;
v.y = pIn->y * l;
pOut->x = v.x;
pOut->y = v.y;
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* pV, const kmMat3* pM)
{
kmVec2 v;
v.x = pV->x * pM->mat[0] + pV->y * pM->mat[3] + pM->mat[6];
v.y = pV->x * pM->mat[1] + pV->y * pM->mat[4] + pM->mat[7];
pOut->x = v.x;
pOut->y = v.y;
return pOut;
}
kmVec2* kmVec2TransformCoord(kmVec2* pOut, const kmVec2* pV, const kmMat3* pM)
{
assert(0);
return NULL;
}
kmVec2* kmVec2Scale(kmVec2* pOut, const kmVec2* pIn, const kmScalar s)
{
pOut->x = pIn->x * s;
pOut->y = pIn->y * s;
return pOut;
}
int 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 File

@ -1,310 +0,0 @@
/*
Copyright (c) 2008, Luke Benstead.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file vec3.c
*/
#include <assert.h>
#include <memory.h>
#include "kazmath/utility.h"
#include "kazmath/vec4.h"
#include "kazmath/mat4.h"
#include "kazmath/vec3.h"
/**
* Fill a kmVec3 structure using 3 floating point values
* The result is store in pOut, returns pOut
*/
kmVec3* kmVec3Fill(kmVec3* pOut, kmScalar x, kmScalar y, kmScalar z)
{
pOut->x = x;
pOut->y = y;
pOut->z = z;
return pOut;
}
/**
* 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
* the result is stored in pOut.
*/
kmVec3* kmVec3Normalize(kmVec3* pOut, const kmVec3* pIn)
{
kmScalar l = 1.0f / 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.
* The result is stored in pOut.
*/
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. The resulting
* vector is stored in pOut.
*/
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. The result is stored in
* pOut.
*/
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. The result
* is stored in pOut. pOut is returned.
*/
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->mat[0] + pV->y * pM->mat[4] + pV->z * pM->mat[8] + pM->mat[12];
v.y = pV->x * pM->mat[1] + pV->y * pM->mat[5] + pV->z * pM->mat[9] + pM->mat[13];
v.z = pV->x * pM->mat[2] + pV->y * pM->mat[6] + pV->z * pM->mat[10] + pM->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->mat[12];
v1.y = pVect->y - pM->mat[13];
v1.z = pVect->z - pM->mat[14];
v2.x = v1.x * pM->mat[0] + v1.y * pM->mat[1] + v1.z * pM->mat[2];
v2.y = v1.x * pM->mat[4] + v1.y * pM->mat[5] + v1.z * pM->mat[6];
v2.z = v1.x * pM->mat[8] + v1.y * pM->mat[9] + v1.z * pM->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->mat[0] + pVect->y * pM->mat[1] + pVect->z * pM->mat[2];
v.y = pVect->x * pM->mat[4] + pVect->y * pM->mat[5] + pVect->z * pM->mat[6];
v.z = pVect->x * pM->mat[8] + pVect->y * pM->mat[9] + pVect->z * pM->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 = 1bw(bx, by, bz)
*/
kmVec4 v;
kmVec4 inV;
kmVec4Fill(&inV, pV->x, pV->y, pV->z, 1.0);
kmVec4Transform(&v, &inV,pM);
pOut->x = v.x / v.w;
pOut->y = v.y / v.w;
pOut->z = v.z / v.w;
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)
*/
//Omits the translation, only scaling + rotating
kmVec3 v;
v.x = pV->x * pM->mat[0] + pV->y * pM->mat[4] + pV->z * pM->mat[8];
v.y = pV->x * pM->mat[1] + pV->y * pM->mat[5] + pV->z * pM->mat[9];
v.z = pV->x * pM->mat[2] + pV->y * pM->mat[6] + pV->z * pM->mat[10];
pOut->x = v.x;
pOut->y = v.y;
pOut->z = v.z;
return pOut;
}
/**
* Scales a vector to length s. Does not normalize first,
* you should do that!
*/
kmVec3* kmVec3Scale(kmVec3* pOut, const kmVec3* pIn, const kmScalar s)
{
pOut->x = pIn->x * s;
pOut->y = pIn->y * s;
pOut->z = pIn->z * s;
return pOut;
}
/**
* Returns KM_TRUE if the 2 vectors are approximately equal
*/
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;
}
/**
* Assigns pIn to pOut. Returns pOut. If pIn and pOut are the same
* then nothing happens but pOut is still returned
*/
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;
}
/**
* Sets all the elements of pOut to zero. Returns pOut.
*/
kmVec3* kmVec3Zero(kmVec3* pOut) {
pOut->x = 0.0f;
pOut->y = 0.0f;
pOut->z = 0.0f;
return pOut;
}