28 StdMeshXML(
const char* filename,
const char* xml_data);
36 void LoadGeometry(
StdMesh& mesh, std::vector<StdSubMesh::Vertex>& vertices, TiXmlElement* boneassignments_elem);
43 TiXmlDocument Document;
50 Document.Parse(xml_data);
57 const char* value = element->Attribute(attribute);
58 if (!value) Error(
FormatString(
"Element '%s' does not have attribute '%s'", element->Value(), attribute), element);
65 if (element->QueryIntAttribute(attribute, &retval) != TIXML_SUCCESS)
66 Error(
FormatString(
"Element '%s' does not have integer attribute '%s'", element->Value(), attribute), element);
73 if (element->QueryFloatAttribute(attribute, &retval) != TIXML_SUCCESS)
74 Error(
FormatString(
"Element '%s' does not have floating point attribute '%s'", element->Value(), attribute), element);
84 retval = element->FirstChildElement(child);
86 Error(
FormatString(
"Element '%s' does not contain '%s' child", element->Value(), child), element);
90 retval = Document.RootElement();
91 if (strcmp(retval->Value(), child) != 0)
92 Error(
FormatString(
"Root element is not '%s'", child), retval);
100 Error(message, element->Row());
112 bool hasVertices =
false;
113 if(!mesh.SharedVertices.empty()) hasVertices =
true;
114 for(
auto & SubMesh : mesh.SubMeshes)
115 if(!SubMesh.Vertices.empty())
118 int VertexCount = RequireIntAttribute(geometry_elem,
"vertexcount");
119 vertices.resize(VertexCount);
121 static const unsigned int POSITIONS = 1;
122 static const unsigned int NORMALS = 2;
123 static const unsigned int TEXCOORDS = 4;
126 unsigned int loaded_attributes = 0;
127 for(TiXmlElement* buffer_elem = geometry_elem->FirstChildElement(
"vertexbuffer"); buffer_elem !=
nullptr; buffer_elem = buffer_elem->NextSiblingElement(
"vertexbuffer"))
129 unsigned int attributes = 0;
130 if(buffer_elem->Attribute(
"positions")) attributes |= POSITIONS;
131 if(buffer_elem->Attribute(
"normals")) attributes |= NORMALS;
132 if(buffer_elem->Attribute(
"texture_coords")) attributes |= TEXCOORDS;
135 TiXmlElement* vertex_elem;
136 for (vertex_elem = buffer_elem->FirstChildElement(
"vertex"), i = 0; vertex_elem !=
nullptr && i < vertices.size(); vertex_elem = vertex_elem->NextSiblingElement(
"vertex"), ++i)
138 if(attributes & POSITIONS)
140 TiXmlElement* position_elem = RequireFirstChild(vertex_elem,
"position");
142 vertices[i].x = RequireFloatAttribute(position_elem,
"x");
143 vertices[i].y = RequireFloatAttribute(position_elem,
"y");
144 vertices[i].z = RequireFloatAttribute(position_elem,
"z");
147 if(attributes & NORMALS)
149 TiXmlElement* normal_elem = RequireFirstChild(vertex_elem,
"normal");
151 vertices[i].nx = RequireFloatAttribute(normal_elem,
"x");
152 vertices[i].ny = RequireFloatAttribute(normal_elem,
"y");
153 vertices[i].nz = RequireFloatAttribute(normal_elem,
"z");
156 if(attributes & TEXCOORDS)
160 TiXmlElement* texcoord_elem = RequireFirstChild(vertex_elem,
"texcoord");
161 vertices[i].u = RequireFloatAttribute(texcoord_elem,
"u");
162 vertices[i].v = RequireFloatAttribute(texcoord_elem,
"v");
167 if (attributes & POSITIONS)
169 const float d = std::sqrt(vertices[i].x*vertices[i].x
170 + vertices[i].y*vertices[i].y
171 + vertices[i].
z*vertices[i].
z);
175 if (i == 0 && !hasVertices)
178 BoundingBox.
x1 = BoundingBox.
x2 = vertices[i].x;
179 BoundingBox.
y1 = BoundingBox.
y2 = vertices[i].y;
180 BoundingBox.
z1 = BoundingBox.
z2 = vertices[i].z;
181 mesh.BoundingRadius = d;
185 BoundingBox.
x1 = std::min(vertices[i].x, BoundingBox.
x1);
186 BoundingBox.
x2 = std::max(vertices[i].x, BoundingBox.
x2);
187 BoundingBox.
y1 = std::min(vertices[i].y, BoundingBox.
y1);
188 BoundingBox.
y2 = std::max(vertices[i].y, BoundingBox.
y2);
189 BoundingBox.
z1 = std::min(vertices[i].
z, BoundingBox.
z1);
190 BoundingBox.
z2 = std::max(vertices[i].
z, BoundingBox.
z2);
191 mesh.BoundingRadius = std::max(mesh.BoundingRadius, d);
196 if(vertex_elem !=
nullptr)
197 Error(
FormatString(
"Too many vertices in vertexbuffer"), buffer_elem);
198 if(i < vertices.size())
199 Error(
FormatString(
"Not enough vertices in vertexbuffer"), buffer_elem);
201 loaded_attributes |= attributes;
204 static const unsigned int REQUIRED_ATTRIBUTES = POSITIONS | NORMALS | TEXCOORDS;
205 if((loaded_attributes & REQUIRED_ATTRIBUTES) != REQUIRED_ATTRIBUTES)
206 Error(
FormatString(
"Not all required vertex attributes (positions, normals, texcoords) present in mesh geometry"), geometry_elem);
211 for (TiXmlElement* vertexboneassignment_elem = boneassignments_elem->FirstChildElement(
"vertexboneassignment"); vertexboneassignment_elem !=
nullptr; vertexboneassignment_elem = vertexboneassignment_elem->NextSiblingElement(
"vertexboneassignment"))
213 int BoneID = RequireIntAttribute(vertexboneassignment_elem,
"boneindex");
214 int VertexIndex = RequireIntAttribute(vertexboneassignment_elem,
"vertexindex");
215 float weight = RequireFloatAttribute(vertexboneassignment_elem,
"weight");
217 if (VertexIndex < 0 ||
static_cast<unsigned int>(VertexIndex) >= vertices.size())
218 Error(
FormatString(
"Vertex index in bone assignment (%d) is out of range", VertexIndex), vertexboneassignment_elem);
222 for (
unsigned int i = 0; !bone && i < mesh.
GetSkeleton().GetNumBones(); ++i)
226 if (!bone) Error(
FormatString(
"There is no such bone with ID %d", BoneID), vertexboneassignment_elem);
248 for (
auto & vertex : vertices)
251 for (
float weight : vertex.bone_weight)
254 for (
float &weight : vertex.bone_weight)
257 vertex.bone_weight[0] = 1.0f;
263 StdMeshXML xml(filename ? filename :
"<unknown>", xml_data);
265 std::unique_ptr<StdMesh> mesh(
new StdMesh);
270 TiXmlElement* sharedgeometry_elem = mesh_elem->FirstChildElement(
"sharedgeometry");
271 if(sharedgeometry_elem !=
nullptr)
272 xml.
LoadGeometry(*mesh, mesh->SharedVertices, sharedgeometry_elem);
276 TiXmlElement* submesh_elem_base = xml.
RequireFirstChild(submeshes_elem,
"submesh");
277 for (TiXmlElement* submesh_elem = submesh_elem_base; submesh_elem !=
nullptr; submesh_elem = submesh_elem->NextSiblingElement(
"submesh"))
284 if (!submesh.Material)
285 xml.
Error(
FormatString(
"There is no such material named '%s'", material), submesh_elem);
287 const char* usesharedvertices = submesh_elem->Attribute(
"usesharedvertices");
288 const std::vector<StdMesh::Vertex>* vertices;
289 if(!usesharedvertices || strcmp(usesharedvertices,
"true") != 0)
292 xml.
LoadGeometry(*mesh, submesh.Vertices, geometry_elem);
293 vertices = &submesh.Vertices;
297 if(mesh->SharedVertices.empty())
298 xml.
Error(
StdCopyStrBuf(
"Submesh specifies to use shared vertices but there is no shared geometry"), submesh_elem);
299 vertices = &mesh->SharedVertices;
304 submesh.Faces.resize(FaceCount);
307 for (TiXmlElement* face_elem = faces_elem->FirstChildElement(
"face"); face_elem !=
nullptr && i < submesh.Faces.size(); face_elem = face_elem->NextSiblingElement(
"face"), ++i)
315 for (
unsigned int j = 0; j < 3; ++j)
317 if (v[j] < 0 ||
static_cast<unsigned int>(v[j]) >= vertices->size())
318 xml.
Error(
FormatString(
"Vertex index v%u (%d) is out of range", j+1, v[j]), face_elem);
319 submesh.Faces[i].Vertices[j] = v[j];
326 if(mesh->BoundingBox.x1 == mesh->BoundingBox.x2 || mesh->BoundingBox.y1 == mesh->BoundingBox.y2)
330 TiXmlElement* skeletonlink_elem = mesh_elem->FirstChildElement(
"skeletonlink");
331 if (skeletonlink_elem)
340 if (!mesh->Skeleton) xml.
Error(
FormatString(
"Failed to load '%s'", skeleton_filename.
getData()), skeletonlink_elem);
343 if (sharedgeometry_elem)
345 TiXmlElement* boneassignments_elem = xml.
RequireFirstChild(mesh_elem,
"boneassignments");
350 unsigned int submesh_index = 0;
351 for (TiXmlElement* submesh_elem = submesh_elem_base; submesh_elem !=
nullptr; submesh_elem = submesh_elem->NextSiblingElement(
"submesh"), ++submesh_index)
353 StdSubMesh& submesh = mesh->SubMeshes[submesh_index];
354 if (!submesh.Vertices.empty())
356 TiXmlElement* boneassignments_elem = xml.
RequireFirstChild(submesh_elem,
"boneassignments");
366 for (TiXmlElement* submesh_elem = submesh_elem_base; submesh_elem !=
nullptr; submesh_elem = submesh_elem->NextSiblingElement(
"submesh"))
368 TiXmlElement* boneassignments_elem = submesh_elem->FirstChildElement(
"boneassignments");
369 if (boneassignments_elem)
370 xml.
Error(
StdStrBuf(
"Mesh has bone assignments, but no skeleton"), boneassignments_elem);
373 TiXmlElement* boneassignments_elem = mesh_elem->FirstChildElement(
"boneassignments");
374 if (boneassignments_elem)
375 xml.
Error(
StdStrBuf(
"Mesh has bone assignments, but no skeleton"), boneassignments_elem);
378 return mesh.release();
383 if (sourcefile ==
nullptr)
385 throw Ogre::InsufficientData(
FormatString(
"Failed to load '%s/%s'", groupname, filename).getData());
390 TiXmlElement* skeleton_elem = skeleton->RequireFirstChild(
nullptr,
"skeleton");
391 TiXmlElement* bones_elem = skeleton->RequireFirstChild(skeleton_elem,
"bones");
396 std::vector<StdMeshBone*> bones;
397 for (TiXmlElement* bone_elem = bones_elem->FirstChildElement(
"bone"); bone_elem !=
nullptr; bone_elem = bone_elem->NextSiblingElement(
"bone"))
400 bones.push_back(bone);
402 bone->
ID = skeleton->RequireIntAttribute(bone_elem,
"id");
403 bone->
Name = skeleton->RequireStrAttribute(bone_elem,
"name");
406 bone->Parent =
nullptr;
409 TiXmlElement* position_elem = skeleton->RequireFirstChild(bone_elem,
"position");
410 TiXmlElement* rotation_elem = skeleton->RequireFirstChild(bone_elem,
"rotation");
411 TiXmlElement* axis_elem = skeleton->RequireFirstChild(rotation_elem,
"axis");
414 d.
x = skeleton->RequireFloatAttribute(position_elem,
"x");
415 d.
y = skeleton->RequireFloatAttribute(position_elem,
"y");
416 d.
z = skeleton->RequireFloatAttribute(position_elem,
"z");
417 float angle = skeleton->RequireFloatAttribute(rotation_elem,
"angle");
418 r.
x = skeleton->RequireFloatAttribute(axis_elem,
"x");
419 r.
y = skeleton->RequireFloatAttribute(axis_elem,
"y");
420 r.
z = skeleton->RequireFloatAttribute(axis_elem,
"z");
431 TiXmlElement* bonehierarchy_elem = skeleton->RequireFirstChild(skeleton_elem,
"bonehierarchy");
432 for (TiXmlElement* boneparent_elem = bonehierarchy_elem->FirstChildElement(
"boneparent"); boneparent_elem !=
nullptr; boneparent_elem = boneparent_elem->NextSiblingElement(
"boneparent"))
434 const char* child_name = skeleton->RequireStrAttribute(boneparent_elem,
"bone");
435 const char* parent_name = skeleton->RequireStrAttribute(boneparent_elem,
"parent");
440 for (
unsigned int i = 0; i < bones.size() && (!child || !parent); ++i)
442 if (!child && bones[i]->Name == child_name)
444 if (!parent && bones[i]->Name == parent_name)
448 if (!child) skeleton->Error(
FormatString(
"There is no such bone with name '%s'", child_name), boneparent_elem);
449 if (!parent) skeleton->Error(
FormatString(
"There is no such bone with name '%s'", parent_name), boneparent_elem);
451 child->Parent = parent;
452 parent->Children.push_back(child);
458 for (
auto & bone : bones)
459 if (bone->Parent ==
nullptr)
460 Skeleton->AddMasterBone(bone);
463 TiXmlElement* animations_elem = skeleton_elem->FirstChildElement(
"animations");
466 for (TiXmlElement* animation_elem = animations_elem->FirstChildElement(
"animation"); animation_elem !=
nullptr; animation_elem = animation_elem->NextSiblingElement(
"animation"))
468 StdCopyStrBuf name(skeleton->RequireStrAttribute(animation_elem,
"name"));
469 if (Skeleton->Animations.find(name) != Skeleton->Animations.end())
470 skeleton->Error(
FormatString(
"There is already an animation with name '%s'", name.
getData()), animation_elem);
473 animation.
Name = name;
474 animation.
Length = skeleton->RequireFloatAttribute(animation_elem,
"length");
475 animation.Tracks.resize(Skeleton->GetNumBones());
476 animation.OriginSkeleton = &(*Skeleton);
478 TiXmlElement* tracks_elem = skeleton->RequireFirstChild(animation_elem,
"tracks");
479 for (TiXmlElement* track_elem = tracks_elem->FirstChildElement(
"track"); track_elem !=
nullptr; track_elem = track_elem->NextSiblingElement(
"track"))
481 const char* bone_name = skeleton->RequireStrAttribute(track_elem,
"bone");
483 for (
unsigned int i = 0; !bone && i < Skeleton->GetNumBones(); ++i)
484 if (Skeleton->Bones[i]->Name == bone_name)
485 bone = Skeleton->Bones[i];
486 if (!bone) skeleton->Error(
FormatString(
"There is no such bone with name '%s'", bone_name), track_elem);
488 if (animation.Tracks[bone->
Index] !=
nullptr) skeleton->Error(
FormatString(
"There is already a track for bone '%s' in animation '%s'", bone_name, animation.
Name.
getData()), track_elem);
491 animation.Tracks[bone->
Index] = track;
493 TiXmlElement* keyframes_elem = skeleton->RequireFirstChild(track_elem,
"keyframes");
494 for (TiXmlElement* keyframe_elem = keyframes_elem->FirstChildElement(
"keyframe"); keyframe_elem !=
nullptr; keyframe_elem = keyframe_elem->NextSiblingElement(
"keyframe"))
496 float time = skeleton->RequireFloatAttribute(keyframe_elem,
"time");
499 TiXmlElement* translate_elem = keyframe_elem->FirstChildElement(
"translate");
500 TiXmlElement* rotate_elem = keyframe_elem->FirstChildElement(
"rotate");
501 TiXmlElement* scale_elem = keyframe_elem->FirstChildElement(
"scale");
504 d.
x = d.
y = d.
z = 0.0f;
506 r.
x = r.
y = 0.0f; r.
z = 1.0f;
511 d.
x = skeleton->RequireFloatAttribute(translate_elem,
"x");
512 d.
y = skeleton->RequireFloatAttribute(translate_elem,
"y");
513 d.
z = skeleton->RequireFloatAttribute(translate_elem,
"z");
518 TiXmlElement* axis_elem = skeleton->RequireFirstChild(rotate_elem,
"axis");
519 angle = skeleton->RequireFloatAttribute(rotate_elem,
"angle");
520 r.
x = skeleton->RequireFloatAttribute(axis_elem,
"x");
521 r.
y = skeleton->RequireFloatAttribute(axis_elem,
"y");
522 r.
z = skeleton->RequireFloatAttribute(axis_elem,
"z");
527 s.x = skeleton->RequireFloatAttribute(scale_elem,
"x");
528 s.y = skeleton->RequireFloatAttribute(scale_elem,
"y");
529 s.z = skeleton->RequireFloatAttribute(scale_elem,
"z");
547 for (
unsigned int i = 0; i < Skeleton->GetNumBones(); ++i)
550 if (Skeleton->Bones[i]->Parent)
559 StoreSkeleton(groupname, filename, Skeleton);
StdStrBuf FormatString(const char *szFmt,...)
StdMeshTransformation Transformation
StdMeshTransformation InverseTransformation
StdMeshTransformation Transformation
const StdMeshSkeleton & GetSkeleton() const
void LoadGeometry(StdMesh &mesh, std::vector< StdSubMesh::Vertex > &vertices, TiXmlElement *boneassignments_elem)
const char * RequireStrAttribute(TiXmlElement *element, const char *attribute) const
int RequireIntAttribute(TiXmlElement *element, const char *attribute) const
float RequireFloatAttribute(TiXmlElement *element, const char *attribute) const
void Error(const StdStrBuf &message, TiXmlElement *element) const
void LoadBoneAssignments(StdMesh &mesh, std::vector< StdSubMesh::Vertex > &vertices, TiXmlElement *boneassignments_elem)
TiXmlElement * RequireFirstChild(TiXmlElement *element, const char *child)
StdMeshXML(const char *filename, const char *xml_data)
static StdMesh * LoadMeshXml(const char *sourcefile, size_t size, const StdMeshMatManager &mat_mgr, StdMeshSkeletonLoader &loader, const char *filename=nullptr)
const StdMeshMaterial * GetMaterial(const char *material_name) const
const StdMeshBone & GetBone(size_t i) const
static void MakeFullSkeletonPath(StdCopyStrBuf &out, const char *groupname, const char *filename)
std::shared_ptr< StdMeshSkeleton > GetSkeletonByName(const StdStrBuf &name) const
void LoadSkeletonXml(const char *groupname, const char *filename, const char *sourcefile, size_t size)
const char * getData() const
void Append(const char *pnData, size_t iChars)
StdSubMesh::Vertex TransformVertex(const StdSubMesh::Vertex &vertex)
StdMeshTransformation TransformTransformation(const StdMeshTransformation &trans)
static StdMeshQuaternion AngleAxis(float theta, const StdMeshVector &axis)
static StdMeshVector UnitScale()
uint16_t bone_index[MaxBoneWeightCount]
static const size_t MaxBoneWeightCount
float bone_weight[MaxBoneWeightCount]