// -------------------------------------------- void RotateHelper::createZ ( uint pos ) { double axis[] = { 0, 0, 1, COLLADABU::Math::Utils::radToDeg ( rotation.z ) }; std::vector<double> axisVec (axis, axis + sizeof(axis) / sizeof(double) ); rotationMatrix.push_back ( axisVec ); rotationParameters.push_back ( *Z_PARAMETER ); // rotationMatrix[pos] = { 0, 0, 1, COLLADABU::Math::Utils::radToDeg ( rotation.z ) }; }
void WriteOutput(const String& outputFileName, bool exportAnimations, bool rotationsOnly, bool saveMaterialList) { // Begin serialization { File dest(context_); if (!dest.Open(outputFileName, FILE_WRITE)) ErrorExit("Could not open output file " + outputFileName); // ID dest.WriteFileID("UMDL"); // Vertexbuffers dest.WriteUInt(vertexBuffers_.Size()); for (unsigned i = 0; i < vertexBuffers_.Size(); ++i) vertexBuffers_[i].WriteData(dest); // Indexbuffers dest.WriteUInt(indexBuffers_.Size()); for (unsigned i = 0; i < indexBuffers_.Size(); ++i) indexBuffers_[i].WriteData(dest); // Subgeometries dest.WriteUInt(subGeometries_.Size()); for (unsigned i = 0; i < subGeometries_.Size(); ++i) { // Write bone mapping info from the first LOD level. It does not change for further LODs dest.WriteUInt(subGeometries_[i][0].boneMapping_.Size()); for (unsigned k = 0; k < subGeometries_[i][0].boneMapping_.Size(); ++k) dest.WriteUInt(subGeometries_[i][0].boneMapping_[k]); // Lod levels for this subgeometry dest.WriteUInt(subGeometries_[i].Size()); for (unsigned j = 0; j < subGeometries_[i].Size(); ++j) { dest.WriteFloat(subGeometries_[i][j].distance_); dest.WriteUInt((unsigned)subGeometries_[i][j].primitiveType_); dest.WriteUInt(subGeometries_[i][j].vertexBuffer_); dest.WriteUInt(subGeometries_[i][j].indexBuffer_); dest.WriteUInt(subGeometries_[i][j].indexStart_); dest.WriteUInt(subGeometries_[i][j].indexCount_); } } // Morphs dest.WriteUInt(morphs_.Size()); for (unsigned i = 0; i < morphs_.Size(); ++i) morphs_[i].WriteData(dest); // Skeleton dest.WriteUInt(bones_.Size()); for (unsigned i = 0; i < bones_.Size(); ++i) { dest.WriteString(bones_[i].name_); dest.WriteUInt(bones_[i].parentIndex_); dest.WriteVector3(bones_[i].bindPosition_); dest.WriteQuaternion(bones_[i].bindRotation_); dest.WriteVector3(bones_[i].bindScale_); Matrix3x4 offsetMatrix(bones_[i].derivedPosition_, bones_[i].derivedRotation_, bones_[i].derivedScale_); offsetMatrix = offsetMatrix.Inverse(); dest.Write(offsetMatrix.Data(), sizeof(Matrix3x4)); dest.WriteUByte(bones_[i].collisionMask_); if (bones_[i].collisionMask_ & 1) dest.WriteFloat(bones_[i].radius_); if (bones_[i].collisionMask_ & 2) dest.WriteBoundingBox(bones_[i].boundingBox_); } // Bounding box dest.WriteBoundingBox(boundingBox_); // Geometry centers for (unsigned i = 0; i < subGeometryCenters_.Size(); ++i) dest.WriteVector3(subGeometryCenters_[i]); } if (saveMaterialList) { String materialListName = ReplaceExtension(outputFileName, ".txt"); File listFile(context_); if (listFile.Open(materialListName, FILE_WRITE)) { for (unsigned i = 0; i < materialNames_.Size(); ++i) { // Assume the materials will be located inside the standard Materials subdirectory listFile.WriteLine("Materials/" + ReplaceExtension(SanitateAssetName(materialNames_[i]), ".xml")); } } else PrintLine("Warning: could not write material list file " + materialListName); } XMLElement skeletonRoot = skelFile_->GetRoot("skeleton"); if (skeletonRoot && exportAnimations) { // Go through animations XMLElement animationsRoot = skeletonRoot.GetChild("animations"); if (animationsRoot) { XMLElement animation = animationsRoot.GetChild("animation"); while (animation) { ModelAnimation newAnimation; newAnimation.name_ = animation.GetAttribute("name"); newAnimation.length_ = animation.GetFloat("length"); XMLElement tracksRoot = animation.GetChild("tracks"); XMLElement track = tracksRoot.GetChild("track"); while (track) { String trackName = track.GetAttribute("bone"); ModelBone* bone = 0; for (unsigned i = 0; i < bones_.Size(); ++i) { if (bones_[i].name_ == trackName) { bone = &bones_[i]; break; } } if (!bone) ErrorExit("Found animation track for unknown bone " + trackName); AnimationTrack newAnimationTrack; newAnimationTrack.name_ = trackName; if (!rotationsOnly) newAnimationTrack.channelMask_ = CHANNEL_POSITION | CHANNEL_ROTATION; else newAnimationTrack.channelMask_ = CHANNEL_ROTATION; XMLElement keyFramesRoot = track.GetChild("keyframes"); XMLElement keyFrame = keyFramesRoot.GetChild("keyframe"); while (keyFrame) { AnimationKeyFrame newKeyFrame; // Convert from right- to left-handed XMLElement position = keyFrame.GetChild("translate"); float x = position.GetFloat("x"); float y = position.GetFloat("y"); float z = position.GetFloat("z"); Vector3 pos(x, y, -z); XMLElement rotation = keyFrame.GetChild("rotate"); XMLElement axis = rotation.GetChild("axis"); float angle = -rotation.GetFloat("angle") * M_RADTODEG; x = axis.GetFloat("x"); y = axis.GetFloat("y"); z = axis.GetFloat("z"); Vector3 axisVec(x, y, -z); Quaternion rot(angle, axisVec); // Transform from bind-pose relative into absolute pos = bone->bindPosition_ + bone->bindRotation_ * pos; rot = bone->bindRotation_ * rot; newKeyFrame.time_ = keyFrame.GetFloat("time"); newKeyFrame.position_ = pos; newKeyFrame.rotation_ = rot; newAnimationTrack.keyFrames_.Push(newKeyFrame); keyFrame = keyFrame.GetNext("keyframe"); } // Make sure keyframes are sorted from beginning to end Sort(newAnimationTrack.keyFrames_.Begin(), newAnimationTrack.keyFrames_.End(), CompareKeyFrames); // Do not add tracks with no keyframes if (newAnimationTrack.keyFrames_.Size()) newAnimation.tracks_.Push(newAnimationTrack); track = track.GetNext("track"); } // Write each animation into a separate file String animationFileName = outputFileName.Replaced(".mdl", ""); animationFileName += "_" + newAnimation.name_ + ".ani"; File dest(context_); if (!dest.Open(animationFileName, FILE_WRITE)) ErrorExit("Could not open output file " + animationFileName); dest.WriteFileID("UANI"); dest.WriteString(newAnimation.name_); dest.WriteFloat(newAnimation.length_); dest.WriteUInt(newAnimation.tracks_.Size()); for (unsigned i = 0; i < newAnimation.tracks_.Size(); ++i) { AnimationTrack& track = newAnimation.tracks_[i]; dest.WriteString(track.name_); dest.WriteUByte(track.channelMask_); dest.WriteUInt(track.keyFrames_.Size()); for (unsigned j = 0; j < track.keyFrames_.Size(); ++j) { AnimationKeyFrame& keyFrame = track.keyFrames_[j]; dest.WriteFloat(keyFrame.time_); if (track.channelMask_ & CHANNEL_POSITION) dest.WriteVector3(keyFrame.position_); if (track.channelMask_ & CHANNEL_ROTATION) dest.WriteQuaternion(keyFrame.rotation_); if (track.channelMask_ & CHANNEL_SCALE) dest.WriteVector3(keyFrame.scale_); } } animation = animation.GetNext("animation"); PrintLine("Processed animation " + newAnimation.name_); } } } }
void LoadSkeleton(const String& skeletonFileName) { // Process skeleton first (if found) XMLElement skeletonRoot; File skeletonFileSource(context_); skeletonFileSource.Open(skeletonFileName); if (!skelFile_->Load(skeletonFileSource)) PrintLine("Failed to load skeleton " + skeletonFileName); skeletonRoot = skelFile_->GetRoot(); if (skeletonRoot) { XMLElement bonesRoot = skeletonRoot.GetChild("bones"); XMLElement bone = bonesRoot.GetChild("bone"); while (bone) { unsigned index = bone.GetInt("id"); String name = bone.GetAttribute("name"); if (index >= bones_.Size()) bones_.Resize(index + 1); // Convert from right- to left-handed XMLElement position = bone.GetChild("position"); float x = position.GetFloat("x"); float y = position.GetFloat("y"); float z = position.GetFloat("z"); Vector3 pos(x, y, -z); XMLElement rotation = bone.GetChild("rotation"); XMLElement axis = rotation.GetChild("axis"); float angle = -rotation.GetFloat("angle") * M_RADTODEG; x = axis.GetFloat("x"); y = axis.GetFloat("y"); z = axis.GetFloat("z"); Vector3 axisVec(x, y, -z); Quaternion rot(angle, axisVec); bones_[index].name_ = name; bones_[index].parentIndex_ = index; // Fill in the correct parent later bones_[index].bindPosition_ = pos; bones_[index].bindRotation_ = rot; bones_[index].bindScale_ = Vector3::ONE; bones_[index].collisionMask_ = 0; bones_[index].radius_ = 0.0f; bone = bone.GetNext("bone"); } // Go through the bone hierarchy XMLElement boneHierarchy = skeletonRoot.GetChild("bonehierarchy"); XMLElement boneParent = boneHierarchy.GetChild("boneparent"); while (boneParent) { String bone = boneParent.GetAttribute("bone"); String parent = boneParent.GetAttribute("parent"); unsigned i = 0, j = 0; for (i = 0; i < bones_.Size() && bones_[i].name_ != bone; ++i); for (j = 0; j < bones_.Size() && bones_[j].name_ != parent; ++j); if (i >= bones_.Size() || j >= bones_.Size()) ErrorExit("Found indeterminate parent bone assignment"); bones_[i].parentIndex_ = j; boneParent = boneParent.GetNext("boneparent"); } // Calculate bone derived positions for (unsigned i = 0; i < bones_.Size(); ++i) { Vector3 derivedPosition = bones_[i].bindPosition_; Quaternion derivedRotation = bones_[i].bindRotation_; Vector3 derivedScale = bones_[i].bindScale_; unsigned index = bones_[i].parentIndex_; if (index != i) { for (;;) { derivedPosition = bones_[index].bindPosition_ + (bones_[index].bindRotation_ * (bones_[index].bindScale_ * derivedPosition)); derivedRotation = bones_[index].bindRotation_ * derivedRotation; derivedScale = bones_[index].bindScale_ * derivedScale; if (bones_[index].parentIndex_ != index) index = bones_[index].parentIndex_; else break; } } bones_[i].derivedPosition_ = derivedPosition; bones_[i].derivedRotation_ = derivedRotation; bones_[i].derivedScale_ = derivedScale; bones_[i].worldTransform_ = Matrix3x4(derivedPosition, derivedRotation, derivedScale); bones_[i].inverseWorldTransform_ = bones_[i].worldTransform_.Inverse(); } PrintLine("Processed skeleton"); } }