bool MD5AnimParser::Parse() { while (Advance(false)) { switch (m_currentLine[0]) { #if NAZARA_UTILITY_STRICT_RESOURCE_PARSING case 'M': // MD5Version if (m_currentLine.GetWord(0) != "MD5Version") UnrecognizedLine(); break; #endif case 'b': // baseframe/bounds if (m_currentLine.StartsWith("baseframe {")) { if (!ParseBaseframe()) { Error("Failed to parse baseframe"); return false; } } else if (m_currentLine.StartsWith("bounds {")) { if (!ParseBounds()) { Error("Failed to parse bounds"); return false; } } #if NAZARA_UTILITY_STRICT_RESOURCE_PARSING else UnrecognizedLine(); #endif break; #if NAZARA_UTILITY_STRICT_RESOURCE_PARSING case 'c': // commandline if (m_currentLine.GetWord(0) != "commandline") UnrecognizedLine(); break; #endif case 'f': { unsigned int index; if (std::sscanf(&m_currentLine[0], "frame %u {", &index) == 1) { if (m_frameIndex != index) { Error("Unexpected frame index (expected " + String::Number(m_frameIndex) + ", got " + String::Number(index) + ')'); return false; } if (!ParseFrame()) { Error("Failed to parse frame"); return false; } m_frameIndex++; } else if (std::sscanf(&m_currentLine[0], "frameRate %u", &m_frameRate) != 1) { #if NAZARA_UTILITY_STRICT_RESOURCE_PARSING UnrecognizedLine(); #endif } break; } case 'h': // hierarchy if (m_currentLine.StartsWith("hierarchy {")) { if (!ParseHierarchy()) { Error("Failed to parse hierarchy"); return false; } } #if NAZARA_UTILITY_STRICT_RESOURCE_PARSING else UnrecognizedLine(); #endif break; case 'n': // num[Frames/Joints] { unsigned int count; if (std::sscanf(&m_currentLine[0], "numAnimatedComponents %u", &count) == 1) { #if NAZARA_UTILITY_STRICT_RESOURCE_PARSING if (!m_animatedComponents.empty()) Warning("Animated components count is already defined"); #endif m_animatedComponents.resize(count); } else if (std::sscanf(&m_currentLine[0], "numFrames %u", &count) == 1) { #if NAZARA_UTILITY_STRICT_RESOURCE_PARSING if (!m_frames.empty()) Warning("Frame count is already defined"); #endif m_frames.resize(count); } else if (std::sscanf(&m_currentLine[0], "numJoints %u", &count) == 1) { #if NAZARA_UTILITY_STRICT_RESOURCE_PARSING if (!m_joints.empty()) Warning("Joint count is already defined"); #endif m_joints.resize(count); } #if NAZARA_UTILITY_STRICT_RESOURCE_PARSING else UnrecognizedLine(); #endif break; } default: #if NAZARA_UTILITY_STRICT_RESOURCE_PARSING UnrecognizedLine(); #endif break; } } unsigned int frameCount = m_frames.size(); if (frameCount == 0) { NazaraError("Frame count is invalid or missing"); return false; } unsigned int jointCount = m_joints.size(); if (jointCount == 0) { NazaraError("Joint count is invalid or missing"); return false; } if (m_frameIndex != frameCount) { NazaraError("Missing frame infos: [" + String::Number(m_frameIndex) + ',' + String::Number(frameCount) + ']'); return false; } if (m_frameRate == 0) { NazaraWarning("Framerate is either invalid or missing, assuming a default value of 24"); m_frameRate = 24; } return true; }
bool NzMD5AnimParser::Parse(NzAnimation* animation) { while (Advance(false)) { switch (m_currentLine[0]) { #if NAZARA_UTILITY_STRICT_RESOURCE_PARSING case 'M': // MD5Version if (m_currentLine.GetWord(0) != "MD5Version") UnrecognizedLine(); break; #endif case 'b': // baseframe/bounds if (m_currentLine.StartsWith("baseframe {")) { if (!ParseBaseframe()) { Error("Failed to parse baseframe"); return false; } } else if (m_currentLine.StartsWith("bounds {")) { if (!ParseBounds()) { Error("Failed to parse bounds"); return false; } } #if NAZARA_UTILITY_STRICT_RESOURCE_PARSING else UnrecognizedLine(); #endif break; #if NAZARA_UTILITY_STRICT_RESOURCE_PARSING case 'c': // commandline if (m_currentLine.GetWord(0) != "commandline") UnrecognizedLine(); break; #endif case 'f': { unsigned int index; if (std::sscanf(&m_currentLine[0], "frame %u {", &index) == 1) { if (m_frameIndex != index) { Error("Unexpected frame index (expected " + NzString::Number(m_frameIndex) + ", got " + NzString::Number(index) + ')'); return false; } if (!ParseFrame()) { Error("Failed to parse frame"); return false; } m_frameIndex++; } else if (std::sscanf(&m_currentLine[0], "frameRate %u", &m_frameRate) != 1) { #if NAZARA_UTILITY_STRICT_RESOURCE_PARSING UnrecognizedLine(); #endif } break; } case 'h': // hierarchy if (m_currentLine.StartsWith("hierarchy {")) { if (!ParseHierarchy()) { Error("Failed to parse hierarchy"); return false; } } #if NAZARA_UTILITY_STRICT_RESOURCE_PARSING else UnrecognizedLine(); #endif break; case 'n': // num[Frames/Joints] { unsigned int count; if (std::sscanf(&m_currentLine[0], "numAnimatedComponents %u", &count) == 1) { #if NAZARA_UTILITY_STRICT_RESOURCE_PARSING if (!m_animatedComponents.empty()) Warning("Animated components count is already defined"); #endif m_animatedComponents.resize(count); } else if (std::sscanf(&m_currentLine[0], "numFrames %u", &count) == 1) { #if NAZARA_UTILITY_STRICT_RESOURCE_PARSING if (!m_frames.empty()) Warning("Frame count is already defined"); #endif m_frames.resize(count); } else if (std::sscanf(&m_currentLine[0], "numJoints %u", &count) == 1) { #if NAZARA_UTILITY_STRICT_RESOURCE_PARSING if (!m_joints.empty()) Warning("Joint count is already defined"); #endif m_joints.resize(count); } #if NAZARA_UTILITY_STRICT_RESOURCE_PARSING else UnrecognizedLine(); #endif break; } default: #if NAZARA_UTILITY_STRICT_RESOURCE_PARSING UnrecognizedLine(); #endif break; } } unsigned int frameCount = m_frames.size(); if (frameCount == 0) { NazaraError("Frame count is invalid or missing"); return false; } unsigned int jointCount = m_joints.size(); if (jointCount == 0) { NazaraError("Joint count is invalid or missing"); return false; } if (m_frameIndex != frameCount) { NazaraError("Missing frame infos: [" + NzString::Number(m_frameIndex) + ',' + NzString::Number(frameCount) + ']'); return false; } if (m_frameRate == 0) { NazaraWarning("Framerate is either invalid or missing, assuming a default value of 24"); m_frameRate = 24; } // À ce stade, nous sommes censés avoir assez d'informations pour créer l'animation if (!animation->CreateSkeletal(frameCount, jointCount)) { NazaraError("Failed to create animation"); return false; } NzSequence sequence; sequence.firstFrame = 0; sequence.frameCount = m_frames.size(); sequence.frameRate = m_frameRate; sequence.name = m_stream.GetPath().SubStringFrom(NAZARA_DIRECTORY_SEPARATOR, -1, true); if (!animation->AddSequence(sequence)) NazaraWarning("Failed to add sequence"); NzSequenceJoint* sequenceJoints = animation->GetSequenceJoints(); // Pour que le squelette soit correctement aligné, il faut appliquer un quaternion "de correction" aux joints à la base du squelette NzQuaternionf rotationQuat = NzEulerAnglesf(-90.f, 90.f, 0.f); for (unsigned int i = 0; i < jointCount; ++i) { int parent = m_joints[i].parent; for (unsigned int j = 0; j < frameCount; ++j) { NzSequenceJoint& sequenceJoint = sequenceJoints[j*jointCount + i]; if (parent >= 0) { sequenceJoint.position = m_frames[j].joints[i].pos; sequenceJoint.rotation = m_frames[j].joints[i].orient; } else { sequenceJoint.position = rotationQuat * m_frames[j].joints[i].pos; sequenceJoint.rotation = rotationQuat * m_frames[j].joints[i].orient; } sequenceJoint.scale = NzVector3f(1.f, 1.f, 1.f); } } return true; }