client.dll
source code, there's a file called StudoModelRenderer.cpp
. It handles the drawing of all the .mdl
models in the game.StudioDrawModel
. This function then works out where the model is, where all the bones of its skeleton should go, whether there are any special effects that need applying, and finally draws it.StudioSetupTransform
(a function in StudioModelRenderer.cpp
which decides where the model will be drawn on the screen):
if (m_pCurrentEntity->curstate.scale != 0)
{
int j;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
(*m_protationmatrix)[i][j] *= m_pCurrentEntity->curstate.scale;
}
}
}
That's it. Add this code, compile, and you've finished! To test it, you just need to make a monster in Worldcraft, turn off Smartedit and give it a "scale" setting of 2.0 (double size) or 0.5 (half size), or whatever.
m_pCurrentEntity->curstate
is the current state of the entity we're supposed to be drawing. The "scale" variable is one of the properties that make up that state. (I didn't create it - it's been there all along, although previously it was only used by sprites. I'm using it here because having a pre-existing variable makes the example nice and simple. And it seems sensible to reuse it for such a similar purpose.)m_protationmatrix
.m_protationmatrix
is a matrix with 4 columns and 3 rows, and its 12 numbers are used to define exactly where a model will appear on the screen. Don't let the name fool you: it can express all sorts of transformations, not just a rotation. It comes in two parts:
a b c x
d e f y
g h i z
Numbers in the first three columns are used to scale, rotate and/or skew the model. (I'll explain how in a minute.) Numbers in the right-hand column simply define where the model is in 3d space.StudioSetupTransform
function, there's a good example of how the last column can be used - the very first and very last things it does.
void CStudioModelRenderer::StudioSetUpTransform (int trivial_accept)
{
//...some variables...
vec3_t modelpos;
VectorCopy( m_pCurrentEntity->origin, modelpos );
//...the rest of the function...
(*m_protationmatrix)[0][3] = modelpos[0];
(*m_protationmatrix)[1][3] = modelpos[1];
(*m_protationmatrix)[2][3] = modelpos[2];
}
As I hope you can see, this code first saves the entity's origin into the modelpos
vector, and at the end, copies that vector directly into the last column of the matrix. Yes, it really is that simple to use.[a b c] [x] [?]
[d e f] * [y] = [?]
[g h i] [z] [?]
1) Take the top line of the first matrix:
[a b c]
2) Multiply the first number in that line by the first number in the vector, multiply the second by the second, and so on.
[ax by cz]
3) Add up the results, and write the answer as the first entry in the result vector.
[ax+by+cz]
[ ? ]
[ ? ]
Then, repeat this process for the second row of the matrix, and put the result in as the second entry in the result vector. And then do the same for the third.
[a b c] [x] [ax+by+cz]
[d e f] * [y] = [dx+ey+fz]
[g h i] [z] [gx+hy+iz]
With me still? Once you get your head around it, you'll hopefully realise that the idea of a matrix is actually quite simple: it's like a recipe. Our ingredients are x, y and z from the vector; the matrix is telling us how much of each ingredient we need to stir into a given part of the result.[1 0 0]
[1 0 0]
[1 0 0]
...each line says "stir in 100% of the vector's x value, and 0% of the other two values". Let's see how that works on a vector containing a bunch of random numbers:
[1 0 0] [453] [1*453 + 0*7 + 0*99] [453]
[1 0 0] * [ 7] = [1*453 + 0*7 + 0*99] = [453]
[1 0 0] [ 99] [1*453 + 0*7 + 0*99] [453]
Since the three lines in the matrix were the same, we got the same answer for each entry in the result.[1 0 0]
[0 1 0]
[0 0 1]
Here, the first line says "use 100% of x, and nothing else". The second line says "use 100% of y, and nothing else". The third line says "use 100% of z, and nothing else".[1 0 0] [453] [1*453 + 0*7 + 0*99] [453]
[0 1 0] * [ 7] = [0*453 + 1*7 + 0*99] = [ 7]
[0 0 1] [ 99] [0*453 + 0*7 + 1*99] [ 99]
No change at all! This "no change" matrix is known as the "identity" matrix.[0 1 0] [453] [0*453 + 1*7 + 0*99] [ 7]
[0 0 1] * [ 7] = [0*453 + 0*7 + 1*99] = [ 99]
[1 0 0] [ 99] [1*453 + 0*7 + 0*99] [453]
Or making a vector longer, without changing its direction?
[2 0 0] [453] [2*453 + 0*7 + 0*99] [906]
[0 2 0] * [ 7] = [0*453 + 2*7 + 0*99] = [ 14]
[0 0 2] [ 99] [0*453 + 0*7 + 2*99] [198]
If you've been paying attention, that last one should have made you remember the beginning. By scaling up each of the components in a matrix, we scale up each value in the result.You must log in to post a comment. You can login or register a new account.