void TSShapeLoader::generateGroundAnimation(TSShape::Sequence& seq, const AppSequence* appSeq) { seq.firstGroundFrame = shape->groundTranslations.size(); seq.numGroundFrames = 0; if (!boundsNode) return; // Check if the bounds node is animated by this sequence seq.numGroundFrames = (S32)((seq.duration + 0.25f/AppGroundFrameRate) * AppGroundFrameRate); seq.flags |= TSShape::MakePath; // Get ground transform at the start of the sequence MatrixF invStartMat = boundsNode->getNodeTransform(appSeq->getStart()); zapScale(invStartMat); invStartMat.inverse(); for (int iFrame = 0; iFrame < seq.numGroundFrames; iFrame++) { F32 time = appSeq->getStart() + seq.duration * iFrame / getMax(1, seq.numGroundFrames - 1); // Determine delta bounds node transform at 't' MatrixF mat = boundsNode->getNodeTransform(time); zapScale(mat); mat = invStartMat * mat; // Add ground transform Quat16 rotation; rotation.set(QuatF(mat)); shape->groundTranslations.push_back(mat.getPosition()); shape->groundRotations.push_back(rotation); } }
void getDeltaTransform(AppNode * node, const AppTime & time1, const AppTime & time2, Quaternion & rot, Point3D & trans, Quaternion & srot, Point3D & scale) { Matrix<4,4,F32> m1 = node->getNodeTransform(time1); Matrix<4,4,F32> m2 = node->getNodeTransform(time2); zapScale(m1); zapScale(m2); Matrix<4,4,F32> mat = m1.inverse() * m2; convertToTransform(mat,rot,trans,srot,scale); }
MatrixF TSShapeLoader::getLocalNodeMatrix(AppNode* node, F32 t) { MatrixF m1 = node->getNodeTransform(t); // multiply by inverse scale at t=0 MatrixF m10 = node->getNodeTransform(DefaultTime); m1.scale(Point3F(1.0f/m10.getScale().x, 1.0f/m10.getScale().y, 1.0f/m10.getScale().z)); if (node->mParentIndex >= 0) { AppNode *parent = appNodes[node->mParentIndex]; MatrixF m2 = parent->getNodeTransform(t); // multiply by inverse scale at t=0 MatrixF m20 = parent->getNodeTransform(DefaultTime); m2.scale(Point3F(1.0f/m20.getScale().x, 1.0f/m20.getScale().y, 1.0f/m20.getScale().z)); // get local transform by pre-multiplying by inverted parent transform m1 = m2.inverse() * m1; } else if (boundsNode && node != boundsNode) { // make transform relative to bounds node transform at time=t MatrixF mb = boundsNode->getNodeTransform(t); zapScale(mb); m1 = mb.inverse() * m1; } return m1; }
bool TSShapeLoader::processNode(AppNode* node) { // Detect bounds node if ( node->isBounds() ) { if ( boundsNode ) { Con::warnf( "More than one bounds node found" ); return false; } boundsNode = node; // Process bounds geometry MatrixF boundsMat(boundsNode->getNodeTransform(DefaultTime)); boundsMat.inverse(); zapScale(boundsMat); for (S32 iMesh = 0; iMesh < boundsNode->getNumMesh(); iMesh++) { AppMesh* mesh = boundsNode->getMesh(iMesh); MatrixF transform = mesh->getMeshTransform(DefaultTime); transform.mulL(boundsMat); mesh->lockMesh(DefaultTime, transform); } return true; } // Detect sequence markers if ( node->isSequence() ) { //appSequences.push_back(new AppSequence(node)); return false; } // Add this node to the subshape (create one if needed) if ( subshapes.size() == 0 ) subshapes.push_back( new TSShapeLoader::Subshape ); subshapes.last()->branches.push_back( node ); return true; }
void TSShapeLoader::generateDefaultStates() { // Generate default object states (includes initial geometry) for (int iObject = 0; iObject < shape->objects.size(); iObject++) { updateProgress(Load_GenerateDefaultStates, "Generating initial mesh and node states...", shape->objects.size(), iObject); TSShape::Object& obj = shape->objects[iObject]; // Calculate the objectOffset for each mesh at T=0 for (int iMesh = 0; iMesh < obj.numMeshes; iMesh++) { AppMesh* appMesh = appMeshes[obj.startMeshIndex + iMesh]; AppNode* appNode = obj.nodeIndex >= 0 ? appNodes[obj.nodeIndex] : boundsNode; MatrixF meshMat(appMesh->getMeshTransform(DefaultTime)); MatrixF nodeMat(appMesh->isSkin() ? meshMat : appNode->getNodeTransform(DefaultTime)); zapScale(nodeMat); appMesh->objectOffset = nodeMat.inverse() * meshMat; } generateObjectState(shape->objects[iObject], DefaultTime, true, true); } // Generate default node transforms for (int iNode = 0; iNode < appNodes.size(); iNode++) { // Determine the default translation and rotation for the node QuatF rot, srot; Point3F trans, scale; generateNodeTransform(appNodes[iNode], DefaultTime, false, 0, rot, trans, srot, scale); // Add default node translation and rotation addNodeRotation(rot, true); addNodeTranslation(trans, true); } }