// Math3d.c
// Implementation of non-inlined functions in the Math3D Library
// Richard S. Wright Jr.
// These are pretty portable
#include <math.h>
#include "math3d.h"
////////////////////////////////////////////////////////////
// LoadIdentity
// For 3x3 and 4x4 float and double matricies.
// 3x3 float
void m3dLoadIdentity33(M3DMatrix33f m)
{
// Don't be fooled, this is still column major
static M3DMatrix33f identity = { 1.0f, 0.0f, 0.0f ,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f };
memcpy(m, identity, sizeof(M3DMatrix33f));
}
// 3x3 double
void m3dLoadIdentity33(M3DMatrix33d m)
{
// Don't be fooled, this is still column major
static M3DMatrix33d identity = { 1.0, 0.0, 0.0 ,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0 };
memcpy(m, identity, sizeof(M3DMatrix33d));
}
// 4x4 float
void m3dLoadIdentity44(M3DMatrix44f m)
{
// Don't be fooled, this is still column major
static M3DMatrix44f 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 };
memcpy(m, identity, sizeof(M3DMatrix44f));
}
// 4x4 double
void m3dLoadIdentity44(M3DMatrix44d m)
{
static M3DMatrix44d identity = { 1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0 };
memcpy(m, identity, sizeof(M3DMatrix44d));
}
////////////////////////////////////////////////////////////////////////
// Return the square of the distance between two points
// Should these be inlined...?
float m3dGetDistanceSquared(const M3DVector3f u, const M3DVector3f v)
{
float x = u[0] - v[0];
x = x*x;
float y = u[1] - v[1];
y = y*y;
float z = u[2] - v[2];
z = z*z;
return (x + y + z);
}
// Ditto above, but for doubles
double m3dGetDistanceSquared(const M3DVector3d u, const M3DVector3d v)
{
double x = u[0] - v[0];
x = x*x;
double y = u[1] - v[1];
y = y*y;
double z = u[2] - v[2];
z = z*z;
return (x + y + z);
}
#define A(row,col) a[(col<<2)+row]
#define B(row,col) b[(col<<2)+row]
#define P(row,col) product[(col<<2)+row]
///////////////////////////////////////////////////////////////////////////////
// Multiply two 4x4 matricies
void m3dMatrixMultiply44(M3DMatrix44f product, const M3DMatrix44f a, const M3DMatrix44f b )
{
for (int i = 0; i < 4; i++) {
float ai0=A(i,0), ai1=A(i,1), ai2=A(i,2), ai3=A(i,3);
P(i,0) = ai0 * B(0,0) + ai1 * B(1,0) + ai2 * B(2,0) + ai3 * B(3,0);
P(i,1) = ai0 * B(0,1) + ai1 * B(1,1) + ai2 * B(2,1) + ai3 * B(3,1);
P(i,2) = ai0 * B(0,2) + ai1 * B(1,2) + ai2 * B(2,2) + ai3 * B(3,2);
P(i,3) = ai0 * B(0,3) + ai1 * B(1,3) + ai2 * B(2,3) + ai3 * B(3,3);
}
}
// Ditto above, but for doubles
void m3dMatrixMultiply(M3DMatrix44d product, const M3DMatrix44d a, const M3DMatrix44d b )
{
for (int i = 0; i < 4; i++) {
double ai0=A(i,0), ai1=A(i,1), ai2=A(i,2), ai3=A(i,3);
P(i,0) = ai0 * B(0,0) + ai1 * B(1,0) + ai2 * B(2,0) + ai3 * B(3,0);
P(i,1) = ai0 * B(0,1) + ai1 * B(1,1) + ai2 * B(2,1) + ai3 * B(3,1);
P(i,2) = ai0 * B(0,2) + ai1 * B(1,2) + ai2 * B(2,2) + ai3 * B(3,2);
P(i,3) = ai0 * B(0,3) + ai1 * B(1,3) + ai2 * B(2,3) + ai3 * B(3,3);
}
}
#undef A
#undef B
#undef P
#define A33(row,col) a[(col*3)+row]
#define B33(row,col) b[(col*3)+row]
#define P33(row,col) product[(col*3)+row]
///////////////////////////////////////////////////////////////////////////////
// Multiply two 3x3 matricies
void m3dMatrixMultiply33(M3DMatrix33f product, const M3DMatrix33f a, const M3DMatrix33f b )
{
for (int i = 0; i < 3; i++) {
float ai0=A33(i,0), ai1=A33(i,1), ai2=A33(i,2);
P33(i,0) = ai0 * B33(0,0) + ai1 * B33(1,0) + ai2 * B33(2,0);
P33(i,1) = ai0 * B33(0,1) + ai1 * B33(1,1) + ai2 * B33(2,1);
P33(i,2) = ai0 * B33(0,2) + ai1 * B33(1,2) + ai2 * B33(2,2);
}
}
// Ditto above, but for doubles
void m3dMatrixMultiply44(M3DMatrix33d product, const M3DMatrix33d a, const M3DMatrix33d b )
{
for (int i = 0; i < 3; i++) {
double ai0=A33(i,0), ai1=A33(i,1), ai2=A33(i,2);
P33(i,0) = ai0 * B33(0,0) + ai1 * B33(1,0) + ai2 * B33(2,0);
P33(i,1) = ai0 * B33(0,1) + ai1 * B33(1,1) + ai2 * B33(2,1);
P33(i,2) = ai0 * B33(0,2) + ai1 * B33(1,2) + ai2 * B33(2,2);
}
}
#undef A33
#undef B33
#undef P33
#define M33(row,col) m[col*3+row]
///////////////////////////////////////////////////////////////////////////////
// Creates a 3x3 rotation matrix, takes radians NOT degrees
void m3dRotationMatrix33(M3DMatrix33f m, float angle, float x, float y, float z)
{
float mag, s, c;
float xx, yy, zz, xy, yz, zx, xs, ys, zs, one_c;
s = float(sin(angle));
c = float(cos(angle));
mag = float(sqrt( x*x + y*y + z*z ));
// Identity matrix
if (mag == 0.0f) {
m3dLoadIdentity33(m);
return;
}
// Rotation matrix is normalized
x /= mag;
y /= mag;
z /= mag;
xx = x * x;
yy = y * y;
zz = z * z;
xy = x * y;
yz = y * z;
zx = z * x;
xs = x * s;
ys = y * s;
zs = z * s;
one_c = 1.0f - c;
M33(0,0) = (one_c * xx) + c;
M33(0,1) = (one_c * xy) - zs;
M33(0,2) = (one_c * zx) + ys;
M33(1,0) = (one_c * xy) + zs;
M33(1,1) = (one_c * yy) + c;
M33(1,2) = (one_c * yz) - xs;
M33(2,0) = (one_c * zx) - ys;
M33(2,1) = (one_c * yz) + xs;
M33(2,2) = (one_c * zz) + c;
}
#undef M33
///////////////////////////////////////////////////////////////////////////////
// Creates a 4x4 rotation matrix, takes radians NOT degrees
void m3dRotationMatrix44(M3DMatrix44f m, float angle, float x, float y, float z)
{
float mag, s, c;
float xx, yy, zz, xy, yz, zx, xs, ys, zs, one_c;
s = float(sin(angle));
c = float(cos(angle));
mag = float(sqrt( x*x + y*y + z*z ));
// Identity matrix
if (mag == 0.0f) {
m3dLoadIdentity44(m);
return;
}
// Rotation matrix is normalized
x /= mag;
y /= mag;
z /= mag;
#define M(row,col) m[col*4+row]
xx = x * x;
yy = y * y;
zz = z * z;
xy = x * y;
yz = y * z;
zx = z * x;
xs = x * s;
ys = y * s;
zs = z * s;
one_c = 1.0f - c;
M(0,0) = (one_c * xx) + c;
M(0,1) = (one_c * xy) - zs;
M(0,2) = (one_c * zx) + ys;
M(0,3) = 0.0f;
M(1,0) = (one_c * xy) + zs;
M(1,1) = (one_c * yy) + c;
M(1,2) = (one_c * yz) - xs;
M(1,3) = 0.0f;
M(2,0) = (one_c * zx) - ys;
M(2,1) = (one_c * yz) + xs;
M(2,2) = (one_c * zz) + c;
M(2,3) = 0.0f;
M(3,0) = 0.0f;
M(3,1) = 0.0f;
M(3,2) = 0.0f;
M(3,3) = 1.0f;
#undef M
}
///////////////////////////////////////////////////////////////////////////////
// Ditto above, but for doubles
void m3dRotationMatrix33(M3DMatrix33d m, double angle, double x, double y, double z)
{
double mag, s, c;
double xx, yy, zz, xy, yz, zx, xs, ys, zs, one_c;
s = sin(angle);
c = cos(angle);
mag = sqrt( x*x + y*y + z*z );
// Identity matrix
if (mag == 0.0) {
m3dLoadIdentity33(m);
return;
}
// Rotation matrix is normalized
x /= mag;
y /= mag;
z /= mag;
#define M(row,col) m[col*3+row]
xx = x * x;
yy = y * y;
zz = z * z;
xy = x * y;
yz = y * z;
zx = z * x;
xs = x * s;
ys = y * s;
zs = z * s;
one_c = 1.0 - c;
M(0,0) = (one_c * xx) + c;
M(0,1) = (one_c * xy) - zs;
M(0,2) = (one_c * zx) + ys;
M(1,0) = (one_c * xy) + zs;
M(1,1) = (one_c * yy) + c;
M(1,2) = (one_c * yz) - xs;
M(2,0) = (one_c * zx) - ys;
M(2,1) = (one_c * yz) + xs;
M(2,2) = (one_c * zz) + c;
#undef M
}
///////////////////////////////////////////////////////////////////////////////
// Creates a 4x4 rotation matrix, takes radians NOT degrees
void m3dRotationMatrix44(M3DMatrix44d m, double angle, double x, double y, double z)
{
double mag, s, c;
double xx, yy, zz, xy, yz, zx, xs, ys, zs, one_c;
s = sin(angle);
c = cos(angle);
mag = sqrt( x*x + y*y + z*z );
// Identity matrix
if (mag == 0.0) {
m3dLoadIdentity44(m);
return;
}
// Rotation matrix is normalized
x /= mag;
y /= mag;
z /= mag;
#define M(row,col) m[col*4+row]
xx = x * x;
yy = y * y;
zz = z * z;
xy = x * y;
yz = y * z;
zx = z * x;
xs = x * s;
ys = y * s;
zs = z * s;
one_c = 1.0f - c;
M(0,0) = (one_c * xx) + c;
M(0,