/** ** This is pseudo code that demonstrates spawning particles from ** an arbitrary node of your hierarchical model. This problem is more ** difficult than it sounds because of the way the OpenGL MODELVIEW ** matrix stack works. The following pseudo code should get you started ** on this problem. ** ** Brief explanation of the MODELVIEW matrix: ** The MODELVIEW matrix is applied to all points that you send to OpenGL. ** At a high level, the purpose of the MODELVIEW matrix is to convert ** points from the current local coordinate system into the coordinate ** system of your camera. **/ /********************************************* ** ** FIRST, SOME FUNCTION HEADERS ** ** The following two functions are defined at the bottom ** of this page. These headers are to give you an idea of ** what the functions are used for. ** *******************************/ // getModelViewMatrix will return a copy of the // current OpenGL MODELVIEW matrix. Mat4f getModelViewMatrix() // The SpawnParticles function is responsible for generating new // particles in your world. You will call this function as you // you traverse your model's hierarchy. When you reach a point // in the hierarchy from where particles should be emitted, // call this function! // // SpawnParticles takes the camera transformation matrix as a // parameter. More on this later. void SpawnParticles( Mat4f cameraTransform ) /****************************************************** ** ** YOUR MODEL'S DRAW FUNCTION ** ** This draw method is called every frame of the animation ** ***********************************************/ void YourModel::draw() { /************************************************* ** ** BEFORE WE DRAW, PUSH THE CAMERA TRANSFORMS ONTO THE MODELVIEW MATRIX STACK ** ** In Animator, this is done by ModelView::draw(). ** **************************************************/ ... ... ApplyCameraTransforms ... /************************************************* ** ** NOW SAVE THE CURRENT MODELVIEW MATRIX ** ** At this point in execution, the MODELVIEW matrix contains ** ONLY the camera transformation. We need to save this camera ** transformation so that we can use it later (for reasons ** explained below). ** *****************************************************/ ... ... Get the current MODELVIEW Matrix ... Save it into a local variable "CameraMatrix" ... /*********************************************** ** ** NOW WE WILL ACTUALLY BEGIN DRAWING THE MODEL ** ** Draw your model up to the node where you would like ** particles to spawn from. ** ** FYI: As you call glRotate, glScale, or glTranslate, ** OpenGL is multiplying new transformations into the ** MODELVIEW matrix. ** ********************************************/ ... ... Do the model drawing up to the particle spawn point. ... /************************************************* ** ** SPAWN A PARTICLE AT (0,0,0) OF THE LOCAL COORDINATE SYSTEM ** ** This is all done inside the function ** SpawnParticles() which is defined below. ** ************************************************/ ... ... SpawnParticles( CameraMatrix ) ... /************************************************* ** ** NOW DRAW THE REST OF YOUR MODEL ** ************************************************/ ... ... Draw any parts of your model that come after the ... particle spawn point. ... /************************************************* ** ** NOW DO ANY CLOSING CODE ** ** Don't forget that animator requires you to call ** endDraw(). ** **************************************************/ ... ... Call any closing code here ... return } Mat4f getModelViewMatrix() { /************************** ** ** GET THE OPENGL MODELVIEW MATRIX ** ** Since OpenGL stores it's matricies in ** column major order and our library ** use row major order, we will need to ** transpose what OpenGL gives us before returning. ** ** Hint: Use look up glGetFloatv or glGetDoublev ** for how to get these values from OpenGL. ** *******************************/ GLfloat m[16]; glGetFloatv(GL_MODELVIEW_MATRIX, m); Mat4f matMV(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8], m[9], m[10], m[11], m[12], m[13], m[14], m[15] ); return matMV.transpose(); // convert to row major } void SpawnParticles( Mat4f CameraTransforms ) { /**************************************************************** ** ** THIS FUNCTION WILL ADD A NEW PARTICLE TO OUR WORLD ** ** Suppose we want particles to spawn from a the model's arm. ** We need to find the location of the model's arm in world ** coordinates so that we can set the initial position of new ** particles. As discussed on the Animator project page, ** all particle positions should be in world coordinates. ** ** At this point in execution, the MODELVIEW matrix contains the ** camera transforms multiplied by some model transforms. In other words, ** ** MODELVIEW = CameraTransforms * ModelTransforms ** ** We are interested only in ModelTransforms, which is the ** transformation that will convert a point from the current, local ** coordinate system to the world coordinate system. ** ** To do this, we're going to "undo" the camera transforms from the ** current MODELVIEW matrix. The camera transform is passed in as ** a parameter to this function (remember when we saved it ** near the top of the model's draw method?). We can "undo" the ** camera transforms by pre-multiplying the current MODELVIEW matrix ** with the inverse of the camera matrix. In other words, ** ** ModelTransforms = InverseCameraTransforms * MODELVIEW ** ********************************************************************/ ... ... Get the current MODELVIEW matrix. ... "Undo" the camera transforms from the MODELVIEW matrix ... by multiplying Inverse( CameraTransforms ) * CurrentModelViewMatrix. ... Store the result of this in a local variable called WorldMatrix. ... /***************************************************************** ** ** At this point, we have the transformation that will convert a point ** in the local coordinate system to a point in the world coordinate ** system. ** ** We need to find the actual point in world coordinates ** where particle should be spawned. This is simply ** "the origin of the local coordinate system" transformed by ** the WorldMatrix. ** ******************************************************************/ ... ... WorldPoint = WorldMatrix * Vector(0, 0, 0, 1) ... /***************************************************************** ** ** Now that we have the particle's initial position, we ** can finally add it to our system! ** ***************************************************************/ ... ... AddParticleStartingAt( WorldPoint ) ... return }