trans and rot object nodes procedurally

So I know how to apply bone animations to an object and that is fine. What I can’t seem to figure out is how to procedurally translate and/or rotate an object. Lets say I am programming a first person shooter and I want to move the actor actor around the scene; how would I do that (I am using powervr’s sdk for iphone)?


I am just not sure if this is something that is built-in or if I need to add an additional transform matrix to the SPODNode struct and multiply that through after bone animations? This would also need to recurse up through the parent nodes

So I went ahead and added an additional transform to the SPODNode struct so that the struct now reads as follows:


struct SPODNode {


…     





     PVRTMat4     objectTransform;


}





initializing it to the identity matrix in the ReadNode method (PVRTModelPOD.cpp)


static bool ReadNode(


     SPODNode     &s,


     CSource          &src)


{





                    if(s.pfAnimScale)


                         s.nAnimFlags |= ePODHasScaleAni;


                    else


                    {


                         s.pfAnimScale = (VERTTYPE*) malloc(sizeof(fScale));


                         memcpy(s.pfAnimScale, fScale, sizeof(fScale));


                    }


             Â }





             Â s.objectTransform = PVRTMat4::Identity();   //initialize the objectTransform


              return true;





          case ePODFileNodeIdx:          if(!src.Read32(s.nIdx)) return false;                                        break;


          case ePODFileNodeName:          if(!src.ReadAfterAlloc(s.pszName, nLen)) return false;              Â break;








}








So then I added a method to the CPVRTModelPOD class:


void CPVRTModelPOD::FlushCache(const SPODNode& node){// flush the matrix cache of a specific node


     VERTTYPE fFrame = m_pImpl->fFrame;


     if (fFrame != 0) {


          SetFrame(0);


     }


     


     unsigned int nIdx = (unsigned int)(&node - pNode);


     // Pre-calc frame zero matrix


     GetWorldMatrixNoCache(m_pImpl->pWmZeroCache[nIdx], pNode[nIdx]);


     // Load cache with frame-zero data


     memcpy(&(m_pImpl->pWmCache[nIdx]), &(m_pImpl->pWmZeroCache[nIdx]), sizeof(m_pImpl->pWmCache));


     m_pImpl->pfCache[nIdx] = 0;





     if (fFrame != 0) {


          SetFrame(fFrame);


     }


}





And modified the GetWorldMatrixNoCache method so that it now reads as follows:


void CPVRTModelPOD::GetWorldMatrixNoCache(


     PVRTMATRIX          &mOut,


     const SPODNode     &node) const


{


     PVRTMATRIX mTmp;





     GetTransformationMatrix(mOut, node);


     


     PVRTMatrixMultiply(mOut, mOut, node.objectTransform);





}





With that code in place I ran a successful test (except I did not test to see what this does to the other animations that could be attached to a node; i.e. bone animation). See example usage code below:





     static float yOffset = 10;


     static float amplitude = 2;;


     static float y = 0;


     y += .1;


     static float rot = 0;


     rot += .2;





     float sinY = sin(y);


     ball->objectTransform = (PVRTMat4::Translation(0, yOffset + amplitude
fabsf(sinY), 0) * PVRTMat4::Scale(sinY, sinY, sinY) * PVRTMat4::RotationZ(rot));


     m_Scene.FlushCache(*ball);








So far this approach seems to work. Anyone have any feedback or a different approach?


shall72011-08-22 19:56:56

You would normally keep a separate list or tree of objects that are in your application.





An app loads multiple POD files, one for each object or level/world.





Each object is likely procedurally instanced into the world multiple times, so you need a structure to hold data about the instance, like it’s position and purpose. In a game it would also contain its physics state, it’s current goal, AI, etc.





I wouldn’t edit the POD structures to add all this data; you be better to create your own, and have a pointer/index in it to the actual POD to be rendered.





Graphics is just one element of apps such as a game. Your core data structures should have some kind of reference to each of the graphics data, the sound data, the AI data, the physics data, etc. You wouldn’t jam everything together into some kind of mega-structure.





Aaron.


I see what you are saying about avoiding a ‘mega-structure’, that makes sense. So in having a separate structure to hold position and purpose information etc., I suppose that you would also have methods to calculate the position of an object taking into account the position of its parents? I am thinking of the GetWorldTransform method in the sdk where it will calculate the position by recursing through the parents. So you would also recommend having a similar method outside of the sdk that would calculate the position of an object (according to the game) by recursing through the parents? Then pass the product of that transform and the transform returned from the sdk to the shader (i am using opengles 2.0)?

Don’t put multiple objects in a POD file; if each POD file is an object (ie a person, or a bush, or a gun) then there’s usually no need to worry about the structure of the parenting within the POD. Just take the world matrix of the instance, and insert it after the GetWorldTransform of each mesh in the POD. So the transforms go something like WorldMatrix.InstanceMatrix.ViewMatrix.ProjectionMatrix.





Maybe you’re talking about attaching objects to other objects? Ie you want an instance of a Gun object in the hand of a Person object. In that case you just need to query for the World matrix of the ‘hand’ node, and let the POD code worry about the fact that the hand has an ‘arm’ parent etc - that’s automatic. In that case the gun’s transform is something like GunWorldMatrix.HandWorldMatrix.PersonInstanceMatrix.ViewMatrix.ProjectionMatrix.





Or, maybe in your world you want to have parenting? So a character might pick up a gun and become its parent, or get in a car and become its child. This level of parenting is up to your engine but yes it’s identical to the recursion that happens inside the POD file.





If you like, you could say that the POD data contains static animation and static parenting. Any dynamic (procedural) animation or dynamic parenting happens in the engine. I recommend putting instanced objects in their own POD files in order to simplify that.





Aaron.