int main (int argc, char **argv) { google::InitGoogleLogging(argv[0]); if (argc == 2) { std::string xml_filename(argv[1]); nCache::nCacheLoader cache_loader; cache_loader.process(xml_filename); } else { std::cerr << boost::format("Usage : %1% <ncache xml>") % argv[0] << std::endl; return 1; } return 0; }
StdMesh *StdMeshLoader::LoadMeshXml(const char* xml_data, size_t size, const StdMeshMatManager& manager, StdMeshSkeletonLoader& skel_loader, const char* filename) { StdMeshXML xml(filename ? filename : "<unknown>", xml_data); std::unique_ptr<StdMesh> mesh(new StdMesh); TiXmlElement* mesh_elem = xml.RequireFirstChild(NULL, "mesh"); // Load shared geometry, if any TiXmlElement* sharedgeometry_elem = mesh_elem->FirstChildElement("sharedgeometry"); if(sharedgeometry_elem != NULL) xml.LoadGeometry(*mesh, mesh->SharedVertices, sharedgeometry_elem); TiXmlElement* submeshes_elem = xml.RequireFirstChild(mesh_elem, "submeshes"); TiXmlElement* submesh_elem_base = xml.RequireFirstChild(submeshes_elem, "submesh"); for (TiXmlElement* submesh_elem = submesh_elem_base; submesh_elem != NULL; submesh_elem = submesh_elem->NextSiblingElement("submesh")) { mesh->SubMeshes.push_back(StdSubMesh()); StdSubMesh& submesh = mesh->SubMeshes.back(); const char* material = xml.RequireStrAttribute(submesh_elem, "material"); submesh.Material = manager.GetMaterial(material); if (!submesh.Material) xml.Error(FormatString("There is no such material named '%s'", material), submesh_elem); const char* usesharedvertices = submesh_elem->Attribute("usesharedvertices"); const std::vector<StdMesh::Vertex>* vertices; if(!usesharedvertices || strcmp(usesharedvertices, "true") != 0) { TiXmlElement* geometry_elem = xml.RequireFirstChild(submesh_elem, "geometry"); xml.LoadGeometry(*mesh, submesh.Vertices, geometry_elem); vertices = &submesh.Vertices; } else { if(mesh->SharedVertices.empty()) xml.Error(StdCopyStrBuf("Submesh specifies to use shared vertices but there is no shared geometry"), submesh_elem); vertices = &mesh->SharedVertices; } TiXmlElement* faces_elem = xml.RequireFirstChild(submesh_elem, "faces"); int FaceCount = xml.RequireIntAttribute(faces_elem, "count"); submesh.Faces.resize(FaceCount); unsigned int i = 0; for (TiXmlElement* face_elem = faces_elem->FirstChildElement("face"); face_elem != NULL && i < submesh.Faces.size(); face_elem = face_elem->NextSiblingElement("face"), ++i) { int v[3]; v[0] = xml.RequireIntAttribute(face_elem, "v1"); v[1] = xml.RequireIntAttribute(face_elem, "v2"); v[2] = xml.RequireIntAttribute(face_elem, "v3"); for (unsigned int j = 0; j < 3; ++j) { if (v[j] < 0 || static_cast<unsigned int>(v[j]) >= vertices->size()) xml.Error(FormatString("Vertex index v%u (%d) is out of range", j+1, v[j]), face_elem); submesh.Faces[i].Vertices[j] = v[j]; } } } // We allow bounding box to be empty if it's only due to Z direction since // this is what goes inside the screen in Clonk. if(mesh->BoundingBox.x1 == mesh->BoundingBox.x2 || mesh->BoundingBox.y1 == mesh->BoundingBox.y2) xml.Error(StdCopyStrBuf("Bounding box is empty"), mesh_elem); // Read skeleton, if any TiXmlElement* skeletonlink_elem = mesh_elem->FirstChildElement("skeletonlink"); if (skeletonlink_elem) { const char* name = xml.RequireStrAttribute(skeletonlink_elem, "name"); StdCopyStrBuf xml_filename(name); xml_filename.Append(".xml"); StdCopyStrBuf skeleton_filename; StdMeshSkeletonLoader::MakeFullSkeletonPath(skeleton_filename, filename, xml_filename.getData()); mesh->Skeleton = skel_loader.GetSkeletonByName(skeleton_filename); if (!mesh->Skeleton) xml.Error(FormatString("Failed to load '%s'", skeleton_filename.getData()), skeletonlink_elem); // Vertex<->Bone assignments for shared geometry if (sharedgeometry_elem) { TiXmlElement* boneassignments_elem = xml.RequireFirstChild(mesh_elem, "boneassignments"); xml.LoadBoneAssignments(*mesh, mesh->SharedVertices, boneassignments_elem); } // Vertex<->Bone assignments for all vertices (need to go through SubMeshes again...) unsigned int submesh_index = 0; for (TiXmlElement* submesh_elem = submesh_elem_base; submesh_elem != NULL; submesh_elem = submesh_elem->NextSiblingElement("submesh"), ++submesh_index) { StdSubMesh& submesh = mesh->SubMeshes[submesh_index]; if (!submesh.Vertices.empty()) { TiXmlElement* boneassignments_elem = xml.RequireFirstChild(submesh_elem, "boneassignments"); xml.LoadBoneAssignments(*mesh, submesh.Vertices, boneassignments_elem); } } } else { // Mesh has no skeleton // Bone assignements do not make sense then, as the // actual bones are defined in the skeleton file. for (TiXmlElement* submesh_elem = submesh_elem_base; submesh_elem != NULL; submesh_elem = submesh_elem->NextSiblingElement("submesh")) { TiXmlElement* boneassignments_elem = submesh_elem->FirstChildElement("boneassignments"); if (boneassignments_elem) xml.Error(StdStrBuf("Mesh has bone assignments, but no skeleton"), boneassignments_elem); } TiXmlElement* boneassignments_elem = mesh_elem->FirstChildElement("boneassignments"); if (boneassignments_elem) xml.Error(StdStrBuf("Mesh has bone assignments, but no skeleton"), boneassignments_elem); } return mesh.release(); }