Some definitions:
#define _count(total) for (int count = 0; count < total; count++)
#define _xyCount(x,y) \
for (int xCount = 0; xCount < x; xCount++) \
{for (int yCount = 0; yCount < y; yCount++){
#define _xy }}
I just use these to save time. The _xy
is used cause if I don't, VS will act weird. Now for the vector and matrix. I've created a number of different kinds of vectors and matrices and I post these as the general form.
struct vector3
{
double e[3];
///////////////////////////
vector3 operator/(double d)
{
vector3 out;
_count(3)
{
out.e[count] = e[count] / d;
}
return out;
}
vector3 operator*(double d)
{
vector3 out;
_count(3)
{
out.e[count] = e[count] * d;
}
return out;
}
vector3 operator-(vector3 vec)
{
vector3 out;
_count(3)
{
out.e[count] = e[count] - vec.e[count];
}
return out;
}
vector3 operator+(vector3 vec)
{
vector3 out;
_count(3)
{
out.e[count] = e[count] + vec.e[count];
}
return out;
}
double operator*(vector3 vec)
{
double out;
_count(3)
{
out += e[count] * vec.e[count];
}
return out;
}
vector3 operator%(vector3 vec)///-cross product
{
vector3 out;
out.e[0] = e[1] * vec.e[2] - e[2] * vec.e[1];
out.e[1] = e[0] * vec.e[2] - e[2] * vec.e[0];
out.e[2] = e[0] * vec.e[1] - e[1] * vec.e[0];
return out;
}
////////////////////////////
vector3()
{
e[0] = e[1] = e[2] = 0;
}
~vector3(){}
}; typedef vector3 v3_;
This is the 3 by 3 matrix:
struct matrix_3x3
{
double e[3][3];
///----------------
matrix_3x3 operator/(double d)
{
_xyCount(3,3)
e[xCount][yCount] /= d;
_xy
}
///----------------
matrix_3x3 operator*(double d)
{
_xyCount(3,3)
e[xCount][yCount] *= d;
_xy
}
///----------------
///-?
vector3 operator*(vector3 v)
{
vector3 out;
_xyCount(3,3)
out.e[xCount] += v.e[yCount] * e[xCount][yCount];
_xy
return out;
}
///----------------
matrix_2x2 minorAltB(int column, int row)
{
matrix_2x2 out;
///----------------------------
int x, y;
x = y = 0;
_xCount(2)
{
y = 0;
if (xCount == column)
{
x = 1;
}
_yCount(2)
{
if (yCount == row)
{
y = 1;
}
out.e[xCount][yCount] = (int)(e[xCount + x][yCount + y]);
}
}
///----------------------------
return out;
}
matrix_2x2 minorAlt(int column, int row)
{
matrix_2x2 m;
int x, y;
x = y = 0;
_xyCount(3,3)
if (xCount != column)
{
y = 0;
if (yCount != row)
{
m.e[x][y] = (int)(e[xCount][yCount]);
y = 1;
}
x = 1;
}
_xy
}
matrix_2x2 minor(int column, int row)
{
matrix_2x2 out;
double temp[4];
int count;
_xyCount(3,3)
if (xCount != column)
{
if (yCount != row)
{
temp[count] = e[xCount][yCount];
count++;
}
}
_xy
out.e[0][0] = (int)temp[0]; out.e[0][1] = (int)temp[1];
out.e[1][1] = (int)temp[2]; out.e[1][1] = (int)temp[3];
}
double det()
{
return minor(0,0).value() - minor(1,0).value() + minor(2,0).value();
}
matrix_3x3 transpose()
{
matrix_3x3 out;
_xyCount(3,3)
out.e[xCount][yCount] = e[yCount][xCount];
_xy
return out;
}
bool invert()
{
double d = det();
if (d == 0)
{
return false;
}
else
{
matrix_3x3 m, t, i;
double sign = 1;
_xyCount(3,3)
m.e[xCount][yCount] = minor(xCount,yCount).value() * sign;
sign *= -1;
_xy
t = m.transpose();
i = t / d;
*this = i;
return true;
}
}
///-------------------
matrix_3x3( double ax, double ay, double az,
double bx, double by, double bz,
double cx, double cy, double cz)
{
e[0][0] = ax; e[1][0] = ay; e[2][0] = az;
e[0][1] = bx; e[1][1] = by; e[2][1] = bz;
e[0][2] = cx; e[1][2] = cy; e[2][2] = cz;
}
matrix_3x3()
{
_xyCount(3,3)
e[xCount][yCount] = 0;
_xy
}
~matrix_3x3()
{
}
}; typedef matrix_3x3 m33_;
I've created 3 functions to get minors but haven't decided which one to go with.
Here is the 3D point, ray and triangle:
///+++++++++++++++++++++++++++++++++\
/// point3 }
///+++++++++++++++++++++++++++++++++/
struct point3 : public v3_
{
///-nothing yet
double x()
{
return e[0];
}
double y()
{
return e[1];
}
double z()
{
return e[2];
}
///------------------------------
void x(double n)
{
e[0] = n;
}
void y(double n)
{
e[1] = n;
}
void z(double n)
{
e[2] = n;
}
///------------------------------
void xyz(double X, double Y, double Z)
{
e[0] = X; e[1] = Y; e[2] = Z;
}
///------------------------------
double abs()
{
return cSqrt(_sq(e[0]) + _sq(e[1]) + _sq(e[2]));
}
double getDistance(point3 from)
{
point3 diff;
diff.x(x() - from.x());
diff.y(y() - from.y());
diff.z(z() - from.z());
return diff.abs();
}
///------------------------------
void operator=(vector3 v)
{
x(v.e[0]); y(v.e[1]); z(v.e[2]);
}
point3 operator+(point3 p)
{
point3 out;
out.e[0] = e[0] + p.e[0];
out.e[1] = e[1] + p.e[1];
out.e[2] = e[2] + p.e[2];
return out;
}
point3 operator-(point3 p)
{
point3 out;
out.e[0] = e[0] - p.e[0];
out.e[1] = e[1] - p.e[1];
out.e[2] = e[2] - p.e[2];
return out;
}
point3 operator/(double d)
{
point3 out;
out.e[0] = e[0] / d;
out.e[1] = e[1] / d;
out.e[2] = e[2] / d;
return out;
}
point3 operator*(double d)
{
point3 out;
out.e[0] = e[0] * d;
out.e[1] = e[1] * d;
out.e[2] = e[2] * d;
return out;
}
double operator*(point3 p)
{
double out;
_count(3)
{
out += e[count] * p.e[count];
}
return out;
}
point3 operator%(point3 p)
{
point3 out;
out.e[0] = e[1] * p.e[2] - e[2] * p.e[1];
out.e[1] = e[0] * p.e[2] - e[2] * p.e[0];
out.e[2] = e[0] * p.e[1] - e[1] * p.e[0];
return out;
}
///------------------------------
point3(double a, double b, double c)
{
e[0] = a; e[1] = b; e[2] = c;
}
point3(){}
~point3(){}
};
typedef point3 p3_;
point3 origin3(0,0,0);
///||||||||||||||||||||||||||||||||||
///+++++++++++++++++++++++++++++++++\
/// ray }
///+++++++++++++++++++++++++++++++++/
struct ray : public m32_
{
///-----------------------------
p3_ A()
{
p3_ out;
out.x(e[0][0]); out.y(e[1][0]); out.z(e[2][0]);
return out;
}
p3_ B()
{
p3_ out;
out.x(e[1][0]); out.y(e[1][0]); out.z(e[2][1]);
return out;
}
void A(p3_ a)
{
e[0][0] = a.x(); e[1][0] = a.y(); e[2][0] = a.z();
}
void B(p3_ a)
{
e[0][1] = a.x(); e[1][1] = a.y(); e[2][1] = a.z();
}
void AB(p3_ a, p3_ b)
{
A(a); B(b);
}
///-----------------------------
p3_ B_A()
{
p3_ out;
out = B() - A();
return out;
}
double length()
{
return B_A().abs();
}
ray getUnit()
{
ray out;
out.B(A() + (B_A() / length()));
return out;
}
p3_ getUV()
{
return getUnit().B_A();
}
///-----------------------------
ray(p3_ a, p3_ b)
{
A(a); B(b);
}
ray(){}
~ray(){}
};
///||||||||||||||||||||||||||||||||||
///+++++++++++++++++++++++++++++++++\
/// triangle3 }
///+++++++++++++++++++++++++++++++++/
struct triangle3 : public m33_
{
Uint32 color;
///-------------------------------
p3_ A()
{
p3_ out;
_count(3)
{
out.e[count] = e[count][0];
}
return out;
}
p3_ B()
{
p3_ out;
_count(3)
{
out.e[count] = e[count][1];
}
return out;
}
p3_ C()
{
p3_ out;
_count(3)
{
out.e[count] = e[count][2];
}
return out;
}
///-------------------------------
void A(p3_ in)
{
_count(3)
{
e[count][0] = in.e[count];
}
}
void B(p3_ in)
{
_count(3)
{
e[count][1] = in.e[count];
}
}
void C(p3_ in)
{
_count(3)
{
e[count][2] = in.e[count];
}
}
///-------------------------------
p3_ P(int p)
{
p3_ out;
_count(3)
{
out.e[count] = e[count][p];
}
return out;
}
void P(int p, p3_ in)
{
if (p >= 3)
{
///-do nothing
}
else
{
_count(3)
{
e[count][p] = in.e[count];
}
}
}
///-------------------------------
///-find the angle at vertex A
double ang()
{
///-two vectors 'lines' on either side of vertex A
p3_ b, c;
///-subtract A from each vertex to get required vectors
c = B() - A();
b = C() - A();
///-get the dot product 'dp'
double dp = b * c;
///-get the lengths of each line
double bAbs = b.abs();
double cAbs = c.abs();
///-out set at 1000 for error check
double out = 1000;
///-dbz check
if (bAbs != 0 && cAbs != 0)
{
///- b * c = bc(Cos(A))
out = acos(dp / (bAbs * cAbs));
}
return out;
}
///-find the angle at any vertex
double ang(int p)
{
int i;
double out = 1000;
p3_ temp[2];
_count(3)
{
if (count != p)
{
temp[i] = P(count);
i++;
}
}
_count(2)
{
temp[count] = temp[count] - P(p);
}
double dp = temp[0] * temp[1];
double absB = temp[0].abs();
double absC = temp[0].abs();
if (absB != 0 && absC != 0)
{
out = acos(dp / (absB * absC));
}
return out;
}
///-------------------------------
///-find the center of the triangle
p3_ center()
{
p3_ out;
double X, Y, Z;
_count(3)
{
X += e[0][count];
Y += e[1][count];
Z += e[2][count];
}
out = out / 3;
return out;
}
p3_ normalAlt(int v = 0, bool added = false)
{
p3_ out;
p3_ *others;
_count(3)
{
if (count != v)
{
*others = P(count);
others++;
}
}
if (added)
{
out = P(v) + ((others[0] - P(v)) % (others[1] - P(v)));
}
else
{
out = (others[0] - P(v)) % (others[1] - P(v));
}
return out;
}
p3_ normal()
{
return (B() - A()) % (C() - A());
}
p3_ bounce(p3_ in, int vertex = 0)
{
p3_ out;
out = in;
p3_ left, forward;
p3_ n = normal();
p3_ diff;
if (vertex > 2 || vertex < 0)
{
return in;
}
diff = in - P(vertex);
left = diff % n;
forward = left % n;
ray u(in, in + forward);
u = u.getUnit();
p3_ in_A = in - A();
double den = in_A.abs() * n.abs();
if (den == 0)
{
return in;
}
out = in + in_A * 2 * (cSqrt(1 - (_sq((in_A % n) / den))));
return out;
}
triangle3 reflect(p3_ pov)
{
triangle3 out;
_count(3)
{
out.P(count,bounce(pov,count));
}
return out;
}
///-------------------------------
double getDistance(p3_ p)
{
double out;
ray r;
r.AB(p, A());
out = r.length();
r.B(B());
if(out > r.length())
out = r.length();
r.B(C());
if(out > r.length())
out = r.length();
return out;
}
///-------------------------------
triangle3(p3_ a, p3_ b, p3_ c)
{
A(a); B(b); C(c);
}
triangle3()
{
color = WHITE;
}
~triangle3(){}
};
typedef triangle3 t3_;
///||||||||||||||||||||||||||||||||||
I've actually used this to raytrace successfully and render a reflected circular light onto a polygon. Unfortunately, it took almost ten seconds to render so I must be doing something wrong. If there's a good matrix/vector library out there I might use someone else's code. If this is the best I can get, I want to figure out how to make a matrix of varying dimensions.