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; } }}
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 xd e f yg h i z
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];}
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] [?]
[a b c]
[ax by cz]
[ax+by+cz][ ? ][ ? ]
[a b c] [x] [ax+by+cz][d e f] * [y] = [dx+ey+fz][g h i] [z] [gx+hy+iz]
So for example, with a matrix like this...[1 0 0][1 0 0][1 0 0]
[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]
Now, here's a related one:[1 0 0][0 1 0][0 0 1]
[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]
Ok. How about if we wanted to rearrange the components of a vector? (don't ask me why...)
[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]
[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]
So, two pages later, we finally get to see why the scaling code works. Half-Life supplies me with a matrix, I multiply each entry by the scale factor, and as a result, when the model gets drawn, each bit is scaled up! (note that the scaling will be relative to its origin - which for most monsters is at its feet, but not for all).You must log in to post a comment. You can login or register a new account.