This commit is contained in:
2025-11-24 14:19:51 +05:30
commit f5c1412b28
6734 changed files with 1527575 additions and 0 deletions

View File

@ -0,0 +1,76 @@
/*
Copyright (c) 2009 Christopher A. Taylor. 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.
* Neither the name of LibCat nor the names of its contributors may be used
to endorse or promote products derived from this software without
specific prior written permission.
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 HOLDER 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 LOAD_BITMAP_HPP
#define LOAD_BITMAP_HPP
#include <cat/Platform.hpp>
namespace cat {
/*
LoadBitmap() loads a memory-mapped bitmap or a file from disk into RGBA format,
meaning the first byte of every pixel is Red, then Green, Blue, and Alpha.
The output data is useful for creating an OpenGL texture using GL_RGBA format.
The output width and height will be powers of two.
Parameters:
file, bytes : Memory-mapped file pointer and number of bytes in the file
path : Alternatively, the path to the file to load
width, height : The dimensions of the loaded file, in pixels
Returns: Zero on error, or a pointer to the rasterized RGBA pixels.
Free the allocated memory using Aligned::Delete(a);
*/
void *LoadBitmap(void *file, u32 bytes, u32 &width, u32 &height);
void *LoadBitmap(const char *path, u32 &width, u32 &height);
class BMPTokenizer
{
u8 trans_red, trans_green, trans_blue;
bool requirePOTS; // Require Power-of-Two Size
void rasterizeImage(u8 *image);
void onImage(u32 *image, u32 newWidth, u32 newHeight);
public:
BMPTokenizer();
~BMPTokenizer();
public:
bool LoadFile(const char *path);
};
} // namespace cat
#endif // LOAD_BITMAP_HPP

View File

@ -0,0 +1,162 @@
/*
Copyright (c) 2009 Christopher A. Taylor. 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.
* Neither the name of LibCat nor the names of its contributors may be used
to endorse or promote products derived from this software without
specific prior written permission.
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 HOLDER 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 LOAD_PNG_HPP
#define LOAD_PNG_HPP
#include <cat/AllFramework.hpp>
#include <string>
using namespace std;
#include "zlib-1.2.4/zlib.h"
namespace cat {
#include "CRC32.hpp"
#ifdef CAT_PRAGMA_PACK
#pragma pack(push)
#pragma pack(1)
#endif
typedef struct
{
u32 length;
char type[4];
} CAT_PACKED SectionHeader;
typedef struct
{
u32 length;
char type[4];
u32 crc;
} CAT_PACKED EmptySection;
typedef struct
{
u32 width, height;
u8 bitDepth, colorType, compressionMethod, filterMethod, interlaceMethod;
} CAT_PACKED PNG_IHDR;
typedef struct
{
u8 r, g, b;
} CAT_PACKED PLTE_Entry8;
typedef struct
{
PLTE_Entry8 table[256];
} CAT_PACKED PNG_PLTE;
#ifdef CAT_PRAGMA_PACK
#pragma pack(pop)
#endif
class PNGSkeletonTokenizer
{
protected:
MMapFile mmf;
CRC32Calculator calculator;
string path;
// Split this from the ctor, so virtual overloads are in place by the time we start reading
bool read(const u8 signature[8]); // Returns false on failure
public:
PNGSkeletonTokenizer(const string &path, u32 CRC32polynomial);
virtual ~PNGSkeletonTokenizer() {}
protected:
// return true only if section is valid (no exceptions please)
virtual bool onSection(char type[4], u8 data[], u32 len) = 0;
};
class PNGTokenizer : public PNGSkeletonTokenizer
{
protected:
z_stream zstream;
u8 *obuf;
u32 olen;
int lastZlibResult;
bool requirePOTS;
PNG_IHDR header;
u16 bpp;
u32 palette[256];
u8 trans_red, trans_green, trans_blue;
void rasterizeImage(u8 *image);
public:
PNGTokenizer(const string &path, bool requirePOTS);
virtual ~PNGTokenizer();
protected:
bool onSection(char type[4], u8 data[], u32 len);
protected:
// Rasterized image in R8G8B8A8 format, new dimensions are powers of two
virtual void onImage(u32 *image, u32 newWidth, u32 newHeight);
protected:
// Important sections
void onIHDR(PNG_IHDR *infohdr);
void onPLTE(PNG_PLTE *c_palette);
void onIDAT(u8 *data, u32 len);
void onIEND();
// Transparency info
void onTRNS_Color2(u16 red, u16 green, u16 blue);
void onTRNS_Color3(u8 trans[256], u16 len);
// Color space information (all unimplemented)
void onGAMA();
void onCHRM();
void onSRGB();
void onICCP();
// Textual information (all unimplemented)
void onTEXT();
void onZTXT();
void onITXT();
// Other non-essential info (all unimplemented)
void onBKGD();
void onPHYS();
void onSBIT();
void onSPLT();
void onHIST();
void onTIME();
};
} // namespace cat
#endif // LOAD_PNG_HPP

View File

@ -0,0 +1,186 @@
/*
Copyright (c) 2009 Christopher A. Taylor. 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.
* Neither the name of LibCat nor the names of its contributors may be used
to endorse or promote products derived from this software without
specific prior written permission.
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 HOLDER 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 CAT_MATRIX_HPP
#define CAT_MATRIX_HPP
#include <cat/gfx/Vector.hpp>
namespace cat {
#define FOR_EACH_ELEMENT(index) for (int index = 0; index < ELEMENTS; ++index)
/*
4x4 matrix elements arranged column major (row, column):
m[0] m[4] m[8] m[12]
m[1] m[5] m[9] m[13]
m[2] m[6] m[10] m[14]
m[3] m[7] m[11] m[15]
Matrix element order corresponds to OpenGL matrix ordering s.t. in a
4x4 matrix the elements define the following new coordinate system:
new x-axis vector: { m[0] m[1] m[2] }
new y-axis vector: { m[4] m[5] m[6] }
new z-axis vector: { m[7] m[9] m[10] }
new origin: { m[12] m[13] m[14] }
*/
template<int ROWS, int COLS, class Scalar> class Matrix
{
protected:
static const int ELEMENTS = ROWS * COLS;
Scalar _elements[ROWS * COLS];
public:
// Short-hand for the current matrix type
typedef Matrix<ROWS, COLS, Scalar> mytype;
// Default constructor does not initialize elements
Matrix()
{
}
// Copy constructor
Matrix(const mytype &u)
{
memcpy(_elements, u._elements, sizeof(_elements));
}
// Assignment operator
mytype &operator=(const mytype &u)
{
memcpy(_elements, u._elements, sizeof(_elements));
}
// Load zero matrix
void loadZero()
{
OBJCLR(_elements);
}
// Load identity matrix
void loadIdentity()
{
OBJCLR(_elements);
// Write a 1 along the diagonal
for (int ii = 0; ii < ROWS && ii < COLS; ++ii)
{
_elements[ii * ROWS + ii] = static_cast<Scalar>( 1 );
}
}
// Addition in-place
mytype &operator+=(const mytype &u)
{
FOR_EACH_ELEMENT(ii) _elements[ii] += u._elements[ii];
}
// Subtraction in-place
mytype &operator-=(const mytype &u)
{
FOR_EACH_ELEMENT(ii) _elements[ii] -= u._elements[ii];
}
// Multiplication by scalar in-place
mytype &operator*=(Scalar u)
{
FOR_EACH_ELEMENT(ii) _elements[ii] *= u;
}
// Division by scalar in-place
mytype &operator/=(Scalar u)
{
FOR_EACH_ELEMENT(ii) _elements[ii] /= u;
}
// Matrix multiplication
template<int OTHER_COLS>
Matrix<ROWS, OTHER_COLS, Scalar> operator*(const Matrix<COLS, OTHER_COLS, Scalar> &u)
{
Matrix<ROWS, OTHER_COLS, Scalar> result;
// For each row of the matrix product,
for (int r = 0; r < ROWS; ++r)
{
// For each column of the matrix product,
for (int c = 0; c < OTHER_COLS; ++c)
{
Scalar x = static_cast<Scalar>( 0 );
// For each row of the right operand (u),
for (int ii = 0; ii < COLS; ++ii)
{
// Accumulate sum of products
x += (*this)(r, ii) * u(ii, c);
}
// Write the sum
result(r, c) = x;
}
}
return result;
}
// Accessors
inline Scalar &operator()(int ii) { return _elements[ii]; }
inline const Scalar &operator()(int ii) const { return _elements[ii]; }
inline Scalar &operator()(int row, int col) { return _elements[col * ROWS + row]; }
inline const Scalar &operator()(int row, int col) const { return _elements[col * ROWS + row]; }
};
// Short-hand for common usages:
typedef Matrix<2, 2, u32> Matrix2x2u;
typedef Matrix<3, 3, u32> Matrix3x3u;
typedef Matrix<4, 4, u32> Matrix4x4u;
typedef Matrix<2, 2, s32> Matrix2x2i;
typedef Matrix<3, 3, s32> Matrix3x3i;
typedef Matrix<4, 4, s32> Matrix4x4i;
typedef Matrix<2, 2, f32> Matrix2x2f;
typedef Matrix<3, 3, f32> Matrix3x3f;
typedef Matrix<4, 4, f32> Matrix4x4f;
typedef Matrix<2, 2, f64> Matrix2x2d;
typedef Matrix<3, 3, f64> Matrix3x3d;
typedef Matrix<4, 4, f64> Matrix4x4d;
#undef FOR_EACH_ELEMENT
} // namespace cat
#endif // CAT_MATRIX_HPP

View File

@ -0,0 +1,401 @@
/*
Copyright (c) 2009 Christopher A. Taylor. 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.
* Neither the name of LibCat nor the names of its contributors may be used
to endorse or promote products derived from this software without
specific prior written permission.
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 HOLDER 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.
*/
/*
Based on code from "Physics for Game Developers", David M. Bourg
slerp() code adapted from this website:
http://www.number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/index.html
*/
#ifndef CAT_QUATERNION_HPP
#define CAT_QUATERNION_HPP
#include <cat/gfx/Vector.hpp>
#include <cat/gfx/Matrix.hpp>
namespace cat {
// Generic quaternion class for linear algebra
template <typename Scalar, typename Double>
class Quaternion
{
protected:
// Backed by a 4D vector with elements arranged as <x,y,z,w>
Vector<4, Scalar, Double> _v;
public:
// Short-hand for the current quaternion type
typedef Quaternion<Scalar, Double> mytype;
// Short-hand for the vector type
typedef Vector<3, Scalar, Double> vectype;
// Uninitialized quaternion is not cleared
Quaternion() { }
// Copy constructor
Quaternion(const mytype &u)
: _v(u._v)
{
}
// Initialization constructor
Quaternion(const vectype &v, Scalar w)
: _v(v)
{
}
// Initialization constructor
Quaternion(Scalar x, Scalar y, Scalar z, Scalar w)
: _v(x, y, z, w)
{
}
// Assignment operator
mytype &operator=(const mytype &u)
{
_v.copy(u._v);
return *this;
}
// Convert from Euler angle representation
// Pre-condition: angles in radians (see Deg2Rad in Scalar.hpp)
void setFromEulerAngles(f32 xroll, f32 ypitch, f32 zyaw)
{
f64 croll = cos(0.5f * xroll);
f64 cpitch = cos(0.5f * ypitch);
f64 cyaw = cos(0.5f * zyaw);
f64 sroll = sin(0.5f * xroll);
f64 spitch = sin(0.5f * ypitch);
f64 syaw = sin(0.5f * zyaw);
f64 cyawcpitch = cyaw * cpitch;
f64 syawspitch = syaw * spitch;
f64 cyawspitch = cyaw * spitch;
f64 syawcpitch = syaw * cpitch;
_v(0) = static_cast<Scalar>( cyawcpitch * sroll - syawspitch * croll );
_v(1) = static_cast<Scalar>( cyawspitch * croll + syawcpitch * sroll );
_v(2) = static_cast<Scalar>( syawcpitch * croll - cyawspitch * sroll );
_v(3) = static_cast<Scalar>( cyawcpitch * croll + syawspitch * sroll );
_v.normalize();
}
// Convert from axis-angle representation
// Pre-condition: axis must be unit-length
void setFromAxisAngle(const vectype &axis, f32 angle)
{
angle *= 0.5f;
Scalar theta = static_cast<Scalar>( sin(angle) );
_v(0) = theta * axis(0);
_v(1) = theta * axis(1);
_v(2) = theta * axis(2);
_v(3) = static_cast<Scalar>( cos(angle) );
}
// Conjugate
mytype operator~() const
{
return mytype(-_v(0), -_v(1), -_v(2), _v(3));
}
// Conjugate in-place
mytype &conjugate() const
{
_v(0) = -_v(0);
_v(1) = -_v(1);
_v(2) = -_v(2);
return *this;
}
// Multiply by quaternion
mytype operator*(const mytype &u)
{
// Cache each of the elements since each is used 4 times
Double x1 = _v(0), x2 = u._v(0);
Double y1 = _v(1), y2 = u._v(1);
Double z1 = _v(2), z2 = u._v(2);
Double w1 = _v(3), w2 = u._v(3);
// Quaternion multiplication formula:
Scalar x3 = static_cast<Scalar>( w1*x2 + x1*w2 + y1*z2 - z1*y2 );
Scalar y3 = static_cast<Scalar>( w1*y2 - x1*z2 + y1*w2 + z1*x2 );
Scalar z3 = static_cast<Scalar>( w1*z2 + x1*y2 - y1*x2 + z1*w2 );
Scalar w3 = static_cast<Scalar>( w1*w2 - x1*x2 - y1*y2 - z1*z2 );
return mytype(x3, y3, z3, w3);
}
// Multiply by quaternion in-place: this = this * u
mytype &operator*=(const mytype &u)
{
// Cache each of the elements since each is used 4 times
Double x1 = _v(0), x2 = u._v(0);
Double y1 = _v(1), y2 = u._v(1);
Double z1 = _v(2), z2 = u._v(2);
Double w1 = _v(3), w2 = u._v(3);
// Quaternion multiplication formula:
_v(0) = static_cast<Scalar>( w1*x2 + x1*w2 + y1*z2 - z1*y2 );
_v(1) = static_cast<Scalar>( w1*y2 - x1*z2 + y1*w2 + z1*x2 );
_v(2) = static_cast<Scalar>( w1*z2 + x1*y2 - y1*x2 + z1*w2 );
_v(3) = static_cast<Scalar>( w1*w2 - x1*x2 - y1*y2 - z1*z2 );
return *this;
}
// Multiply by quaternion in-place: this = u * this
mytype &postMultiply(const mytype &u)
{
// Cache each of the elements since each is used 4 times
Double x2 = _v(0), x1 = u._v(0);
Double y2 = _v(1), y1 = u._v(1);
Double z2 = _v(2), z1 = u._v(2);
Double w2 = _v(3), w1 = u._v(3);
// Quaternion multiplication formula:
_v(0) = static_cast<Scalar>( w1*x2 + x1*w2 + y1*z2 - z1*y2 );
_v(1) = static_cast<Scalar>( w1*y2 - x1*z2 + y1*w2 + z1*x2 );
_v(2) = static_cast<Scalar>( w1*z2 + x1*y2 - y1*x2 + z1*w2 );
_v(3) = static_cast<Scalar>( w1*w2 - x1*x2 - y1*y2 - z1*z2 );
return *this;
}
// Rotate given vector in-place
void rotate(vectype &u)
{
// Implements the simple formula: (q1 * u2 * ~q1).getVector()
// Cache each of the elements since each is used 4 times
Double x1 = _v(0), x2 = u(0);
Double y1 = _v(1), y2 = u(1);
Double z1 = _v(2), z2 = u(2);
Double w1 = _v(3);
// Quaternion-vector multiplication formula (q3 = q1 * u2):
Double x3 = w1*x2 + y1*z2 - z1*y2;
Double y3 = w1*y2 - x1*z2 + z1*x2;
Double z3 = w1*z2 + x1*y2 - y1*x2;
Double w3 = -(x1*x2 + y1*y2 + z1*z2);
// Quaternion multiplication formula (q2' = q3 * ~q1):
u(0) = static_cast<Scalar>( w1*x3 - x1*w3 + y1*z3 - z1*y3 );
u(1) = static_cast<Scalar>( w1*y3 - x1*z3 - y1*w3 + z1*x3 );
u(2) = static_cast<Scalar>( w1*z3 + x1*y3 - y1*x3 - z1*w3 );
}
// NLERP: Very fast, non-constant velocity and torque-minimal
// Precondition: q1, q2 are unit length
friend void nlerp(const mytype &q1, const mytype &q2, Scalar t, mytype &result)
{
// Linearly interpolate and normalize result
// This formula is a little more work than "q1 + (q2 - q1) * t"
// but less likely to lose precision when it matters
// Cosine of phi, the angle between the two vectors
Double cos_phi = q1._v.dotProduct(q2._v);
// I have read this may try to rotate around the "long way" sometimes and to
// fix that we check if cos(phi) is negative and invert one of the inputs.
if (cos_phi < 0.0)
{
result._v = -q1._v;
}
else
{
result._v = q1._v;
}
// Simple linear interpolation
Scalar scale0 = static_cast<Scalar>(1) - t;
Scalar scale1 = t;
result._v *= scale0;
result._v += q2._v * scale1;
result._v.normalize();
}
// SLERP: Slower, constant velocity and torque-minimal
// Precondition: q1, q2 are unit length
friend void slerp(const mytype &q1, const mytype &q2, Scalar t, mytype &result)
{
// Cosine of phi, the angle between the two vectors
Double cos_phi = q1._v.dotProduct(q2._v);
// I have read this may try to rotate around the "long way" sometimes and to
// fix that we check if cos(phi) is negative and invert one of the inputs.
if (cos_phi < 0.0)
{
cos_phi = -cos_phi;
result._v = -q1._v;
}
else
{
result._v = q1._v;
}
// Default to simple linear interpolation
Scalar scale0 = static_cast<Scalar>(1) - t;
Scalar scale1 = t;
// If the distance is not small we need to do full slerp:
if (cos_phi < 0.9995)
{
// cos_phi is guaranteed to be within the domain of acos(), 0..1
Double phi = static_cast<Double>( acos(cos_phi) );
Double inv_sin_phi = static_cast<Double>(1) / sin(phi);
scale0 = static_cast<Scalar>( sin(scale0 * phi) * inv_sin_phi );
scale1 = static_cast<Scalar>( sin(scale1 * phi) * inv_sin_phi );
}
result._v *= scale0;
result._v += q2._v * scale1;
result._v.normalize();
}
// Get angle of rotation
Scalar getAngle()
{
return static_cast<Scalar>( 2 ) * static_cast<Scalar>( acos(_v(3)) );
}
// Get axis of rotation
vectype getAxis()
{
return vectype(_v(0), _v(1), _v(2)).normalize();
}
// Get matrix form of the rotation represented by this quaternion
void getMatrix4x4(Matrix<4, 4, Scalar> &result)
{
Double dx = _v(0);
Double dy = _v(1);
Double dz = _v(2);
Double dw = _v(3);
Double x2 = dx * dx;
Double y2 = dy * dy;
Double z2 = dz * dz;
Double xy = dx * dy;
Double yz = dy * dz;
Double zx = dz * dx;
Double xw = dx * dw;
Double yw = dy * dw;
Double zw = dz * dw;
const Double ONE = static_cast<Double>( 1 );
const Double TWO = static_cast<Double>( 2 );
// Result is written in OpenGL column-major matrix order:
result( 0) = static_cast<Scalar>( ONE - TWO * (y2 + z2) );
result( 1) = static_cast<Scalar>( TWO * (xy - zw) );
result( 2) = static_cast<Scalar>( TWO * (zx + yw) );
result( 3) = static_cast<Scalar>( 0 );
result( 4) = static_cast<Scalar>( TWO * (xy + zw) );
result( 5) = static_cast<Scalar>( ONE - TWO * (x2 + z2) );
result( 6) = static_cast<Scalar>( TWO * (yz - xw) );
result( 7) = static_cast<Scalar>( 0 );
result( 8) = static_cast<Scalar>( TWO * (zx - yw) );
result( 9) = static_cast<Scalar>( TWO * (yz + xw) );
result(10) = static_cast<Scalar>( ONE - TWO * (x2 + y2) );
result(11) = static_cast<Scalar>( 0 );
result(12) = static_cast<Scalar>( 0 );
result(13) = static_cast<Scalar>( 0 );
result(14) = static_cast<Scalar>( 0 );
result(15) = static_cast<Scalar>( ONE );
}
// Get Euler angles
vectype Quaternion::getEulerAngles()
{
Double dx = _v(0);
Double dy = _v(1);
Double dz = _v(2);
Double dw = _v(3);
Double x2 = dx * dx;
Double y2 = dy * dy;
Double z2 = dz * dz;
Double w2 = dw * dw;
Double xy = dx * dy;
Double yz = dy * dz;
Double xw = dx * dw;
Double yw = dy * dw;
Double zw = dz * dw;
const Double TWO = static_cast<Double>( 2 );
Double r11 = w2 + x2 - y2 - z2;
Double r21 = TWO * (xy + zw);
Double r31 = TWO * (xy - yw);
Double r32 = TWO * (yz + xw);
Double r33 = w2 - x2 - y2 + z2;
Double tmp = fabs(r31);
const Double LIMIT = static_cast<Double>( 0.999999 );
if (tmp > LIMIT)
{
Double xz = dx * dz;
Double r12 = TWO * (yz - zw);
Double r13 = TWO * (xz + yw);
return vectype(static_cast<Scalar>( 0 ),
static_cast<Scalar>( -CAT_HALF_PI_64 * r31 / tmp ),
static_cast<Scalar>( atan2(-r12, -r31 * r13) ));
}
return vectype(static_cast<Scalar>( atan2(r32, r33) ),
static_cast<Scalar>( asin(-r31) ),
static_cast<Scalar>( atan2(r21, r11) ));
}
};
// Short-hand for common usages:
typedef Quaternion<f32, f64> Quaternion4f;
typedef Quaternion<f64, f64> Quaternion4d;
} // namespace cat
#endif // CAT_QUATERNION_HPP

View File

@ -0,0 +1,85 @@
/*
Copyright (c) 2009 Christopher A. Taylor. 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.
* Neither the name of LibCat nor the names of its contributors may be used
to endorse or promote products derived from this software without
specific prior written permission.
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 HOLDER 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 CAT_SCALAR_HPP
#define CAT_SCALAR_HPP
#include <cat/Platform.hpp>
#include <cmath>
namespace cat {
// PI
#define CAT_TWO_PI_64 6.283185307179586476925286766559
#define CAT_TWO_PI_32 6.28318531f
#define CAT_PI_64 3.1415926535897932384626433832795
#define CAT_PI_32 3.14159265f
#define CAT_HALF_PI_64 1.5707963267948966192313216916398
#define CAT_HALF_PI_32 1.5707963268f
#define CAT_QUARTER_PI_64 0.78539816339744830961566084581988
#define CAT_QUARTER_PI_32 0.7853981634f
#define CAT_INV_PI_64 0.31830988618379067153776752674503
#define CAT_INV_PI_32 0.3183098862f
// Angle conversion
inline f64 Deg2Rad(f64 angle)
{
return angle * CAT_TWO_PI_64 / 360.0;
}
inline f32 Deg2Rad(f32 angle)
{
return angle * CAT_TWO_PI_32 / 360.0f;
}
inline f64 Rad2Deg(f64 angle)
{
return angle * 360.0 / CAT_TWO_PI_64;
}
inline f32 Rad2Deg(f32 angle)
{
return angle * 360.0f / CAT_TWO_PI_32;
}
// Generic clamp() function
template<class Scalar>
void Clamp(Scalar &x, Scalar low, Scalar high)
{
if (x < low) x = low;
else if (x > high) x = high;
}
// Fast inverse square root
f32 InvSqrt(f32 x);
} // namespace cat
#endif // CAT_SCALAR_HPP

View File

@ -0,0 +1,389 @@
/*
Copyright (c) 2009 Christopher A. Taylor. 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.
* Neither the name of LibCat nor the names of its contributors may be used
to endorse or promote products derived from this software without
specific prior written permission.
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 HOLDER 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 CAT_VECTOR_HPP
#define CAT_VECTOR_HPP
#include <cat/gfx/Scalar.hpp>
namespace cat {
#define FOR_EACH_DIMENSION(index) for (int index = 0; index < DIM; ++index)
// Generic vector class for linear algebra
template<int DIM, typename Scalar, typename Double> class Vector
{
protected:
// Protected internal storage of vector components
Scalar _elements[DIM];
public:
// Short-hand for the current vector type
typedef Vector<DIM, Scalar, Double> mytype;
// Uninitialized vector is not cleared
Vector() {}
// Component-wise initializing constructors
Vector(Scalar x, Scalar y)
{
_elements[0] = x;
_elements[1] = y;
}
Vector(Scalar x, Scalar y, Scalar z)
{
_elements[0] = x;
_elements[1] = y;
_elements[2] = z;
}
Vector(Scalar x, Scalar y, Scalar z, Scalar w)
{
_elements[0] = x;
_elements[1] = y;
_elements[2] = z;
_elements[3] = w;
}
// Make the vector a copy of a given vector
mytype &copy(const mytype &u)
{
memcpy(_elements, u._elements, sizeof(_elements));
return *this;
}
// Copy constructor
Vector(const mytype &u)
{
copy(u);
}
// Assignment operator
mytype &operator=(const mytype &u)
{
return copy(u);
}
// Magnitude calculation
Double magnitude() const
{
Double element, sum = 0;
FOR_EACH_DIMENSION(ii)
{
element = _elements[ii];
sum += element * element;
}
return static_cast<Double>( sqrt(sum) );
}
// Fast normalization for 32-bit floating point elements in-place
mytype &normalize_fast_f32()
{
f32 element = _elements[0];
f32 sum = element * element;
for (int ii = 1; ii < DIM; ++ii)
{
element = _elements[ii];
sum += element * element;
}
// If sum is not close to 1, then perform normalization:
if (sum > 1.005f || sum < 0.995f)
{
f32 inv = InvSqrt(sum);
FOR_EACH_DIMENSION(ii) _elements[ii] *= inv;
}
return *this;
}
// Normalization in-place
mytype &normalize()
{
Double m = magnitude();
Double inv = static_cast<Double>( 1 ) / m;
FOR_EACH_DIMENSION(ii) _elements[ii] *= inv;
return *this;
}
// Zero elements
void zero()
{
OBJCLR(_elements);
}
// Is zero?
bool isZero()
{
FOR_EACH_DIMENSION(ii)
if (_elements[ii] != static_cast<Scalar>( 0 ))
return false;
return true;
}
// For consistency with Matrix class, use the () operator instead of [] to index it
inline Scalar &operator()(int ii) { return _elements[ii]; }
inline Scalar &x() { return _elements[0]; }
inline Scalar &y() { return _elements[1]; }
inline Scalar &z() { return _elements[2]; }
inline Scalar &w() { return _elements[3]; }
// Const version for accessors
inline const Scalar &operator()(int ii) const { return _elements[ii]; }
inline const Scalar &x() const { return _elements[0]; }
inline const Scalar &y() const { return _elements[1]; }
inline const Scalar &z() const { return _elements[2]; }
inline const Scalar &w() const { return _elements[3]; }
// Negation
mytype operator-() const
{
mytype x;
FOR_EACH_DIMENSION(ii) x._elements[ii] = -_elements[ii];
return x;
}
// Negation in-place
mytype &negate()
{
FOR_EACH_DIMENSION(ii) _elements[ii] = -_elements[ii];
return *this;
}
// Addition
mytype operator+(const mytype &u) const
{
mytype x;
FOR_EACH_DIMENSION(ii) x._elements[ii] = _elements[ii] + u._elements[ii];
return x;
}
// Addition in-place
mytype &operator+=(const mytype &u)
{
FOR_EACH_DIMENSION(ii) _elements[ii] += u._elements[ii];
return *this;
}
// Add a scalar to each element in-place
mytype &addToEachElement(Scalar u)
{
FOR_EACH_DIMENSION(ii) _elements[ii] += u;
return *this;
}
// Subtraction
mytype operator-(const mytype &u) const
{
mytype x;
FOR_EACH_DIMENSION(ii) x._elements[ii] = _elements[ii] - u._elements[ii];
return x;
}
// Subtraction in-place
mytype &operator-=(const mytype &u)
{
FOR_EACH_DIMENSION(ii) _elements[ii] -= u._elements[ii];
return *this;
}
// Subtract a scalar from each element in-place
mytype &subtractFromEachElement(Scalar u)
{
FOR_EACH_DIMENSION(ii) _elements[ii] -= u;
return *this;
}
// Scalar multiplication
mytype operator*(Scalar u) const
{
mytype x;
FOR_EACH_DIMENSION(ii) x._elements[ii] = u * _elements[ii];
return x;
}
// Scalar multiplication in-place
mytype &operator*=(Scalar u)
{
FOR_EACH_DIMENSION(ii) _elements[ii] *= u;
return *this;
}
// Component-wise multiply in-place
mytype &componentMultiply(const mytype &u)
{
FOR_EACH_DIMENSION(ii) _elements[ii] *= u._elements[ii];
return *this;
}
// Scalar division
mytype operator/(Scalar u) const
{
mytype x;
Scalar inv_u = static_cast<Scalar>( 1 ) / static_cast<Scalar>( u );
FOR_EACH_DIMENSION(ii) x._elements[ii] = _elements[ii] * inv_u;
return x;
}
// Scalar division in-place
mytype &operator/=(Scalar u)
{
Scalar inv_u = static_cast<Scalar>( 1 ) / static_cast<Scalar>( u );
FOR_EACH_DIMENSION(ii) _elements[ii] *= inv_u;
return *this;
}
// Component-wise divide in-place
mytype &componentDivide(const mytype &u)
{
FOR_EACH_DIMENSION(ii) _elements[ii] /= u._elements[ii];
return *this;
}
// Dot product
Double dotProduct(const mytype &u) const
{
Double sum = 0;
FOR_EACH_DIMENSION(ii)
sum += static_cast<Double>( _elements[ii] )
* static_cast<Double>( u._elements[ii] );
return sum;
}
public:
// Only for 2-element vectors:
// Generate a 2D rotation vector in-place
void generateRotation2D(f32 angle)
{
x() = cos(angle);
y() = sin(angle);
}
// Add rotation vector in-place
mytype &addRotation2D(const mytype &r)
{
Double ax = x(), ay = y();
Double rx = r.x(), ry = r.y();
x() = static_cast<Scalar>( ax*rx - ay*ry ); // cos(a+r) = cos(a)*cos(r) - sin(a)*sin(r)
y() = static_cast<Scalar>( ay*rx + ax*ry ); // sin(a+r) = sin(a)*cos(r) + cos(a)*sin(r)
return *this;
}
// Subtract rotation vector in-place
mytype &subtractRotation2D(const mytype &r)
{
Double ax = x(), ay = y();
Double rx = r.x(), ry = r.y();
x() = static_cast<Scalar>( ax*rx + ay*ry ); // cos(a-r) = cos(a)*cos(r) + sin(a)*sin(r)
y() = static_cast<Scalar>( ay*rx - ax*ry ); // sin(a-r) = sin(a)*cos(r) - cos(a)*sin(r)
return *this;
}
// Cross product: Result is a scalar
f32 crossProduct2D(const mytype &u)
{
return x() * u.y() - y() * u.x();
}
public:
// Only for 3-element vectors:
// Cross product: Result is a 3D vector
mytype crossProduct3D(const mytype &u)
{
mytype result;
result.x() = y() * u.z() - z() * u.y();
result.y() = z() * u.x() - x() * u.z();
result.z() = x() * u.y() - y() * u.x();
return result;
}
};
// Short-hand for common usages:
typedef Vector<2, u32, u32> Vector2u;
typedef Vector<3, u32, u32> Vector3u;
typedef Vector<4, u32, u32> Vector4u;
typedef Vector<2, s32, s32> Vector2s;
typedef Vector<3, s32, s32> Vector3s;
typedef Vector<4, s32, s32> Vector4s;
typedef Vector<2, f32, f64> Vector2f;
typedef Vector<3, f32, f64> Vector3f;
typedef Vector<4, f32, f64> Vector4f;
typedef Vector<2, f64, f64> Vector2d;
typedef Vector<3, f64, f64> Vector3d;
typedef Vector<4, f64, f64> Vector4d;
#undef FOR_EACH_DIMENSION
} // namespace cat
#endif // CAT_VECTOR_HPP