Fix pivot and animation in building LWS node graph.

When building the graph for an object, we always have:
ParentAttachNode -> PivotNode -> AttachNode -> MeshNode -> Meshes
PivotNode receives animations if any.
AttachNode receives the -pivotPos transform, as well as the child nodes,
MeshNode has no transformation and contains the meshes.
MeshNode and Meshes are already converted to RH by LWOLoader.
PivotNode and AttachNode are LH until they get converted to RH later and separately.
The pivot position, when not available in the LWS file is obtained from the LWO object, converted back from RH to LH.
pull/3/head
Gellule Xg 2011-12-07 09:33:58 -10:00
parent 8913a21eed
commit 9178570c4c
1 changed files with 58 additions and 47 deletions

View File

@ -314,18 +314,62 @@ void LWSImporter::BuildGraph(aiNode* nd, LWS::NodeDesc& src, std::vector<Attachm
{ {
// Setup a very cryptic name for the node, we want the user to be happy // Setup a very cryptic name for the node, we want the user to be happy
SetupNodeName(nd,src); SetupNodeName(nd,src);
aiNode* ndAnim = nd;
// If this is an object from an external file - get the scene and setup proper attachment tags // If the node is an object
aiScene* obj = NULL; if (src.type == LWS::NodeDesc::OBJECT) {
if (src.type == LWS::NodeDesc::OBJECT && src.path.length() ) {
obj = batch.GetImport(src.id); // If the object is from an external file, get it
if (!obj) { aiScene* obj = NULL;
DefaultLogger::get()->error("LWS: Failed to read external file " + src.path); if (src.path.length() ) {
} obj = batch.GetImport(src.id);
else { if (!obj) {
attach.push_back(AttachmentInfo(obj,nd)); DefaultLogger::get()->error("LWS: Failed to read external file " + src.path);
} }
} else {
if (obj->mRootNode->mNumChildren == 1) {
//If the pivot is not set for this layer, get it from the external object
if (!src.isPivotSet) {
src.pivotPos.x = +obj->mRootNode->mTransformation.a4;
src.pivotPos.y = +obj->mRootNode->mTransformation.b4;
src.pivotPos.z = -obj->mRootNode->mTransformation.c4; //The sign is the RH to LH back conversion
}
//Remove first node from obj (the old pivot), reset transform of second node (the mesh node)
aiNode* newRootNode = obj->mRootNode->mChildren[0];
free(obj->mRootNode->mChildren);
free(obj->mRootNode);
obj->mRootNode = newRootNode;
obj->mRootNode->mTransformation.a4 = 0.0;
obj->mRootNode->mTransformation.b4 = 0.0;
obj->mRootNode->mTransformation.c4 = 0.0;
}
}
}
//Setup the pivot node (also the animation node), the one we received
nd->mName = std::string("Pivot:") + nd->mName.data;
ndAnim = nd;
//Add the attachment node to it
nd->mNumChildren = 1;
nd->mChildren = new aiNode*[1];
nd->mChildren[0] = new aiNode();
nd->mChildren[0]->mParent = nd;
nd->mChildren[0]->mTransformation.a4 = -src.pivotPos.x;
nd->mChildren[0]->mTransformation.b4 = -src.pivotPos.y;
nd->mChildren[0]->mTransformation.c4 = -src.pivotPos.z;
SetupNodeName(nd->mChildren[0], src);
//Update the attachment node
nd = nd->mChildren[0];
//Push attachment, if the object came from an external file
if (obj) {
attach.push_back(AttachmentInfo(obj,nd));
}
}
// If object is a light source - setup a corresponding ai structure // If object is a light source - setup a corresponding ai structure
else if (src.type == LWS::NodeDesc::LIGHT) { else if (src.type == LWS::NodeDesc::LIGHT) {
@ -369,7 +413,7 @@ void LWSImporter::BuildGraph(aiNode* nd, LWS::NodeDesc& src, std::vector<Attachm
// Get the node transformation from the LWO key // Get the node transformation from the LWO key
LWO::AnimResolver resolver(src.channels,fps); LWO::AnimResolver resolver(src.channels,fps);
resolver.ExtractBindPose(nd->mTransformation); resolver.ExtractBindPose(ndAnim->mTransformation);
// .. and construct animation channels // .. and construct animation channels
aiNodeAnim* anim = NULL; aiNodeAnim* anim = NULL;
@ -378,44 +422,11 @@ void LWSImporter::BuildGraph(aiNode* nd, LWS::NodeDesc& src, std::vector<Attachm
resolver.SetAnimationRange(first,last); resolver.SetAnimationRange(first,last);
resolver.ExtractAnimChannel(&anim,AI_LWO_ANIM_FLAG_SAMPLE_ANIMS|AI_LWO_ANIM_FLAG_START_AT_ZERO); resolver.ExtractAnimChannel(&anim,AI_LWO_ANIM_FLAG_SAMPLE_ANIMS|AI_LWO_ANIM_FLAG_START_AT_ZERO);
if (anim) { if (anim) {
anim->mNodeName = nd->mName; anim->mNodeName = ndAnim->mName;
animOut.push_back(anim); animOut.push_back(anim);
} }
} }
// process pivot point, if any
if (src.pivotPos != aiVector3D()) {
aiMatrix4x4 tmp;
aiMatrix4x4::Translation(-src.pivotPos,tmp);
if (anim) {
// We have an animation channel for this node. Problem: to combine the pivot
// point with the node anims, we'd need to interpolate *all* keys, get
// transformation matrices from them, apply the translation and decompose
// the resulting matrices again in order to reconstruct the keys. This
// solution here is *much* easier ... we're just inserting an extra node
// in the hierarchy.
// Maybe the final optimization here will be done during postprocessing.
aiNode* pivot = new aiNode();
pivot->mName.length = sprintf( pivot->mName.data, "$Pivot_%s",nd->mName.data);
pivot->mTransformation = tmp;
pivot->mChildren = new aiNode*[pivot->mNumChildren = 1];
pivot->mChildren[0] = nd;
pivot->mParent = nd->mParent;
nd->mParent = pivot;
// swap children and hope the parents wont see a huge difference
pivot->mParent->mChildren[pivot->mParent->mNumChildren-1] = pivot;
}
else {
nd->mTransformation = tmp*nd->mTransformation;
}
}
// Add children // Add children
if (src.children.size()) { if (src.children.size()) {
nd->mChildren = new aiNode*[src.children.size()]; nd->mChildren = new aiNode*[src.children.size()];
@ -870,7 +881,7 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
// .. ccw // .. ccw
FlipWindingOrderProcess flipper; FlipWindingOrderProcess flipper;
flipper.Execute(pScene); flipper.Execute(master);
// OK ... finally build the output graph // OK ... finally build the output graph
SceneCombiner::MergeScenes(&pScene,master,attach, SceneCombiner::MergeScenes(&pScene,master,attach,