ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[ Rage Technologies, Inc. ]ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ ³
³ - Members - ³
³ ] Myth: Ideas / Coder [ ³
³ ] Night Stalker: Coder [ ³
³ ] SKoRPiON: Musician [ ³
³ ³
³ - Support Board - ³
³ ] Shadow Lands: (407) 851-2313, run by Night Stalker [ ³
³ ³
ÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄ
How to use Fixed Point (16.16) Math (Part 2 of 2) - by Night Stalker
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
[1] Introduction
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Welcome to part 2 of the 'How to use Fixed Point Math' series. We will be
delving into the world of verticies and matricies and other miscellaneous
functions that can be used to assist in 3D rendering.
This code is straight C. It capitalizes on part 1's code to be able to do
fixed point multiplication and other operations. If you haven't read part 1,
you might want to look it over before you continue.
[2] Vectors
ÄÄÄÄÄÄÄÄÄÄÄ
Alright, let's start off with vectors. We need a good definition of a
vector, especially if we expect to do 3D math. Since the only type that
seems to fit good with this restriction is your standard vector,
I think the following definition would work fine:
ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
typedef Fixed32 Vector[3]; // Vector
ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
Now, how would we access the specific values inside this vector?
Easy. You need to make 'macros' to access each value:
ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
// Macros for Vector access
#define VECT_X 0
#define VECT_Y 1
#define VECT_Z 2
ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
So if you want the Y component of vector 'A', you would use 'A[VECT_Y]'.
[3] Basic vector math and stuff
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Ok, the vector access macros work great, but we need a faster way to 'make'
a vector. Quite simply done, actually:
ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
void make_vector(Vector v, Fixed32 x, Fixed32 y, Fixed32 z)
{
*v++ = x;
*v++ = y;
*v = z;
}
ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
See how easy that is? :) Just make a pointer to your vector, and
increment it along the way.
Let's get into some basic math and other basic functions with vectors:
ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
void VectCopy(Vector sv, Vector dv)
{
memcpy(dv, sv, 12);
}
void VectAdd(Vector v1, Vector v2, Vector dv)
{
*dv++ = v1[VECT_X] + v2[VECT_X];
*dv++ = v1[VECT_Y] + v2[VECT_Y];
*dv = v1[VECT_Z] + v2[VECT_Z];
}
void VectSub(Vector v1, Vector v2, Vector dv)
{
*dv++ = v1[VECT_X] - v2[VECT_X];
*dv++ = v1[VECT_Y] - v2[VECT_Y];
*dv = v1[VECT_Z] - v2[VECT_Z];
}
Fixed32 VectLen(Vector v)
{
// We use the High Precision Square Root here.
return FixedSqrtHP(FixedSquare(*v) + FixedSquare(v[1]) + FixedSquare(v[2]));
}
ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
VectCopy() does just what it says. It copies a vector to another one.
Could be useful, could be useless, but very easy to implement.
VectAdd() and VectSub() also are pretty self-explanatory.
But, what does VectLen() do? It returns the length of a vector. How do
you find the length of a standard vector? You don't actually find
the LENGTH of the vector, you find the distance between the vector and the
center of your world at <0, 0, 0>. Now, if for some reason, you need the
length of the vector squared, you'll find this function is much faster than
VectLen():
ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
Fixed32 VectLen_2(Vector v)
{
return (FixedSquare(*v) + FixedSquare(v[1]) + FixedSquare(v[2]));
}
ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
As you can see, it doesn't use the square root. So why square a square
root when you could just chop it off?
If you're still confused about the length, think back to trigonometry
class in high school. (Sorry if you're there now.. ) The Pythagorean
Equation was:
aý = bý + cý
But this is two dimensions, not three! That's why our formula works:
aý = xý + yý + zý
Knowing this, you should understand why this next function works:
ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
Fixed32 VectDist(Vector v1, Vector v2)
{
return FixedSqrtHP(FixedSquare((*v1) - (*v2)) +
FixedSquare(v1[1] - v2[1]) +
FixedSquare(v1[2] - v2[2]));
}
Fixed32 VectDist_2(Vector v1, Vector v2)
{
return (FixedSquare((*v1) - (*v2)) + FixedSquare(v1[1] - v2[1]) +
FixedSquare(v1[2] - v2[2]));
}
ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
Same set of rules, except instead of finding the length, you're finding
the distance between two vectors. And again, if you need your distance value
squared, use VectDist_2().
[4] Even more vector math
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Allright, let's get into some stuff you either learned in Calculus 3, or
are getting ready to. (Myself being the latter of the two... )
ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
void ScaleVect(Vector v, Fixed32 factor)
{
*v++ = FixedMul(*v, factor);
*v++ = FixedMul(*v, factor);
*v = FixedMul(*v, factor);
}
void NormalizeVect(Vector v)
{
Fixed32 factor;
factor = OneOver(VectLen(v));
*v++ = FixedMul(*v, factor);
*v++ = FixedMul(*v, factor);
*v = FixedMul(*v, factor);
}
Fixed32 DotProduct(Vector v1, Vector v2)
{
return (FixedMul(v1[VECT_X], v2[VECT_X]) +
FixedMul(v1[VECT_Y], v2[VECT_Y]) +
FixedMul(v1[VECT_Z], v2[VECT_Z]));
}
void CrossProduct(Vector v1, Vector v2, Vector dv)
{
*dv++ = FixedMul(v1[VECT_Y], v2[VECT_Z]) - FixedMul(v1[VECT_Z], v2[VECT_Y]);
*dv++ = FixedMul(v1[VECT_Z], v2[VECT_X]) - FixedMul(v1[VECT_X], v2[VECT_Z]);
*dv = FixedMul(v1[VECT_X], v2[VECT_Y]) - FixedMul(v1[VECT_Y], v2[VECT_X]);
}
Fixed32 CrossZProduct(Vector v1, Vector v2)
{
return FixedMul(*v1, v2[VECT_Y]) - FixedMul(v1[VECT_Y], *v2);
}
ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
ScaleVect() is pretty self-explanatory. You pass in a factor, and it
multiplies the entire vector by that factor.
NormalizeVect() normalizes a vector (hence it's name). If you don't really
understand what it does, picture this: You have a polygon (make it 3 sided,
for ease) floating in space. If you take a normal to this polygon, you will
have a vector standing straight out (perpendicular) in the middle of the
polygon. Just picture the same thing happening for a vector.
DotProduct() and CrossProduct() do just what they say. They take the dot
product and the cross product of two vectors, respectively. These are quite
useful in calculating light sources.
CrossZProduct() simply returns the Z component of the cross product, just
in case you might need it for something. :)
[5] Matricies
ÄÄÄÄÄÄÄÄÄÄÄÄÄ
Okay, you know everything about vectors now. Let's hit matricies. Again,
we need a good definition. Well, since most 3D operations can be done with a
3-by-4 matrix (allowing transformational, rotational, and scalar matrix
multiplication), the following definition suits our needs perfectly:
ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
typedef Fixed32 Matrix[12]; // Matrix[3][4]
ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
And we might as well define an identity matrix so we can create one
easily:
ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
Fixed32 identity_matrix[12] =
{
ONE, 0, 0, 0,
0, ONE, 0, 0,
0, 0, ONE, 0,
};
void make_identity_matrix(Matrix m)
{
memcpy(m, identity_matrix, 48);
}
ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
What about scaling matricies and rotational matricies, you ask? Allright,
here they are:
ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
void make_scale_matrix(Matrix m, Vector sv)
{
*m++ = *sv++; *m++ = 0; *m++ = 0; *m++ = 0;
*m++ = 0; *m++ = *sv++; *m++ = 0; *m++ = 0;
*m++ = 0; *m++ = 0; *m++ = *sv; *m = 0;
}
void make_trans_matrix(Matrix m, Vector tv)
{
*m++ = ONE; *m++ = 0; *m++ = 0; *m++ = *tv++;
*m++ = 0; *m++ = ONE; *m++ = 0; *m++ = *tv++;
*m++ = 0; *m++ = 0; *m++ = ONE; *m = *tv;
}
void make_xrot_matrix(Matrix m, Iangle theta)
{
Fixed32 trig_sin, trig_cos;
CosSin(theta, &trig_cos, &trig_sin);
*m++ = ONE; *m++ = 0; *m++ = 0; *m++ = 0;
*m++ = 0; *m++ = trig_cos; *m++ = trig_sin; *m++ = 0;
*m++ = 0; *m++ = -trig_sin; *m++ = -trig_cos; *m = 0;
}
void make_yrot_matrix(Matrix m, Iangle theta)
{
Fixed32 trig_sin, trig_cos;
CosSin(theta, &trig_cos, &trig_sin);
*m++ = trig_cos; *m++ = 0; *m++ = -trig_sin; *m++ = 0;
*m++ = 0; *m++ = ONE; *m++ = 0; *m++ = 0;
*m++ = -trig_sin; *m++ = 0; *m++ = trig_cos; *m = 0;
}
void make_zrot_matrix(Matrix m, Iangle theta)
{
Fixed32 trig_sin, trig_cos;
CosSin(theta, &trig_cos, &trig_sin);
*m++ = trig_cos; *m++ = trig_sin; *m++ = 0; *m++ = 0;
*m++ = -trig_sin; *m++ = trig_cos; *m++ = 0; *m++ = 0;
*m++ = 0; *m++ = 0; *m++ = ONE; *m = 0;
}
ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
And a simple copy function to copy one matrix to another:
ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
void MatrixCopy(Matrix sm, Matrix dm)
{
memcpy(dm, sm, 48);
}
ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
Allright, which ones of you are totally lost about this matrix ordeal and
who isn't? Those of you that understand, you can skip the next paragraph...
Having matricies is an ideal way to transform verticies. The basic idea
is to create a matrix and multiply it by a vector. So if you had an identity
matrix and multiplied it by all the vectors in your object, nothing would
happen. However, if you started with an x-rotational matrix of 20 Iangles,
and multiplied each vector by this matrix, your object would rotate on the
X axis by 20 Iangles. You can also concatenate matricies together to say,
rotate and scale at the same time with just a single matrix! Hopefully you
understand now. :)
Allright, now you need to concatenate two matricies together. Here's how
you do it:
ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
void ConcatMatrices(Matrix m1, Matrix m2, Matrix dm)
{
int i, temp;
temp = 0;
i = 3;
while (i--)
{
*dm++ = FixedMul(m1[temp ], m2[0]) +
FixedMul(m1[temp+1], m2[4]) +
FixedMul(m1[temp+2], m2[8]);
*dm++ = FixedMul(m1[temp ], m2[1]) +
FixedMul(m1[temp+1], m2[5]) +
FixedMul(m1[temp+2], m2[9]);
*dm++ = FixedMul(m1[temp ], m2[2]) +
FixedMul(m1[temp+1], m2[6]) +
FixedMul(m1[temp+2], m2[10]);
*dm++ = FixedMul(m1[temp ], m2[3]) +
FixedMul(m1[temp+1], m2[7]) +
FixedMul(m1[temp+2], m2[11]) + m1[temp+3];
temp += 4;
}
}
ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
Yep, that's it. If you forgot matrix multiplication, go open your Algebra
book and look it up. :)
There's also a couple of other "quicker" methods of adding translation and
rotational matricies together instead of concatenating them together. You
might find these functions a bit useful to pull out that little bit of extra
performance:
ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
void trans_matrix(Matrix m, Vector dv)
{
m[ 3] += *dv++;
m[ 7] += *dv++;
m[11] += *dv;
}
void append_xrot_matrix(Matrix m, Iangle theta)
{
Fixed32 trig_sin, trig_cos;
Fixed32 temp0, temp1, temp2;
CosSin(theta, &trig_cos, &trig_sin);
temp0 = FixedMul(trig_cos, m[4]) + FixedMul(-trig_sin, m[8]);
temp1 = FixedMul(trig_cos, m[5]) + FixedMul(-trig_sin, m[9]);
temp2 = FixedMul(trig_cos, m[6]) + FixedMul(-trig_sin, m[10]);
m[8] = FixedMul(trig_sin, m[4]) + FixedMul(trig_cos, m[8]);
m[9] = FixedMul(trig_sin, m[5]) + FixedMul(trig_cos, m[9]);
m[10] = FixedMul(trig_sin, m[6]) + FixedMul(trig_cos, m[10]);
m[4] = temp0;
m[5] = temp1;
m[6] = temp2;
}
void append_yrot_matrix(Matrix m, Iangle theta)
{
Fixed32 trig_cos, trig_sin;
Fixed32 temp0, temp1, temp2;
CosSin(theta, &trig_cos, &trig_sin);
temp0 = FixedMul(trig_cos, m[0]) + FixedMul(trig_sin, m[8]);
temp1 = FixedMul(trig_cos, m[1]) + FixedMul(trig_sin, m[9]);
temp2 = FixedMul(trig_cos, m[2]) + FixedMul(trig_sin, m[10]);
m[8] = FixedMul(-trig_sin, m[0]) + FixedMul(trig_cos, m[8]);
m[9] = FixedMul(-trig_sin, m[1]) + FixedMul(trig_cos, m[9]);
m[10] = FixedMul(-trig_sin, m[2]) + FixedMul(trig_cos, m[10]);
m[0] = temp0;
m[1] = temp1;
m[2] = temp2;
}
void append_zrot_matrix(Matrix m, Iangle theta)
{
Fixed32 trig_cos, trig_sin;
Fixed32 temp0, temp1, temp2;
CosSin(theta, &trig_cos, &trig_sin);
temp0 = FixedMul(trig_cos, m[0]) + FixedMul(-trig_sin, m[4]);
temp1 = FixedMul(trig_cos, m[1]) + FixedMul(-trig_sin, m[5]);
temp2 = FixedMul(trig_cos, m[2]) + FixedMul(-trig_sin, m[6]);
m[4] = FixedMul(trig_sin, m[0]) + FixedMul(trig_cos, m[4]);
m[5] = FixedMul(trig_sin, m[1]) + FixedMul(trig_cos, m[5]);
m[6] = FixedMul(trig_sin, m[2]) + FixedMul(trig_cos, m[6]);
m[0] = temp0;
m[1] = temp1;
m[2] = temp2;
}
ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
There's one important function I haven't given to you yet, and it's VITAL
to being able to do these transformations in the first place. The following
function will take a vector and a matrix and multiply them together to give
you your new vector:
ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
void XformVector(Matrix m, Vector sv, Vector dv)
{
Fixed32 sv0, sv1, sv2;
sv0 = *sv++;
sv1 = *sv++;
sv2 = *sv;
*dv++ = FixedMul(*m++, sv0) + FixedMul(*m++, sv1) +
FixedMul(*m++, sv2) + *m++;
*dv++ = FixedMul(*m++, sv0) + FixedMul(*m++, sv1) +
FixedMul(*m++, sv2) + *m++;
*dv = FixedMul(*m++, sv0) + FixedMul(*m++, sv1) +
FixedMul(*m++, sv2) + *m;
}
ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
[6] Conclusion
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Well, congradulations! If you made it this far, then you understand just
about everything there is to know about fixed point math, vector and matrix
multiplication.
Again, and as always, if you run into any problems, we'll be happy to help
you out.
- Night Stalker
-------------------------------------------------------------------------------
Look for other Rage Technologies, Inc. stuff coming soon:
- Our first major demo, "Transvectoring". The theme is to
show off our new 3-D engine with lightsourcing and texture
mapping... REALLY fast. Also to show what objects beyond
3D really look like. For example, a 4D or a 5D cube. Maybe
more. Expected release date: Mid '95 (?)
- Night Hawk 0.2à BBS. The first BBS software to show that
ANSI is dead, and RIP is a thing of the past. Features
include: True multitasking, full video and audio routines,
and more. Expected release date: Early/Mid '96.
-------------------------------------------------------------------------------
Other news:
- Shadow Lands is still not up. Blame Night Stalker. He's too
lazy to sell his old 486/33 to run the board on a DX4-100.
We'll let you know when he gets off his duff and has Shadow
Lands online.
- Rage Technologies, Inc. has a mailing list. If you'd like to
get ahold of any one of us, send E-mail to:
ragetech@trappen.vsl.ist.ucf.edu
- Rage Technologies, Inc. also has an experimental FTP server
running. If you would like to get any Rage products, simply
anonymous FTP to: trappen.vsl.ist.ucf.edu. All Rage files
are located in /pub/ragetech.