Fix memory handling of xml-nodes in the parser.

This commit is contained in:
Kim Kulling
2020-09-01 21:48:50 +02:00
parent 3c2133a3b9
commit 73fa2cbe88
10 changed files with 86 additions and 406 deletions

View File

@@ -225,12 +225,12 @@ MeshXml *OgreXmlSerializer::ImportMesh(XmlParser *parser) {
}
void OgreXmlSerializer::ReadMesh(MeshXml *mesh) {
XmlNode *root = mParser->getRootNode();
if (nullptr == root || std::string(nnMesh)!=root->name()) {
throw DeadlyImportError("Root node is <" + std::string(root->name()) + "> expecting <mesh>");
XmlNode root = mParser->getRootNode();
if (nullptr == root || std::string(nnMesh) != root.name()) {
throw DeadlyImportError("Root node is <" + std::string(root.name()) + "> expecting <mesh>");
}
for (XmlNode currentNode : root->children()) {
for (XmlNode currentNode : root.children()) {
const std::string currentName = currentNode.name();
if (currentName == nnSharedGeometry) {
mesh->sharedVertexData = new VertexDataXml();
@@ -242,43 +242,8 @@ void OgreXmlSerializer::ReadMesh(MeshXml *mesh) {
} else if (currentName == nnSkeletonLink) {
}
}
/*if (NextNode() != nnMesh) {
}*/
ASSIMP_LOG_VERBOSE_DEBUG("Reading Mesh");
//NextNode();
// Root level nodes
/*while (m_currentNodeName == nnSharedGeometry ||
m_currentNodeName == nnSubMeshes ||
m_currentNodeName == nnSkeletonLink ||
m_currentNodeName == nnBoneAssignments ||
m_currentNodeName == nnLOD ||
m_currentNodeName == nnSubMeshNames ||
m_currentNodeName == nnExtremes ||
m_currentNodeName == nnPoses ||
m_currentNodeName == nnAnimations) {
if (m_currentNodeName == nnSharedGeometry) {
mesh->sharedVertexData = new VertexDataXml();
ReadGeometry(mesh->sharedVertexData);
} else if (m_currentNodeName == nnSubMeshes) {
NextNode();
while (m_currentNodeName == nnSubMesh) {
ReadSubMesh(mesh);
}
} else if (m_currentNodeName == nnBoneAssignments) {
ReadBoneAssignments(mesh->sharedVertexData);
} else if (m_currentNodeName == nnSkeletonLink) {
mesh->skeletonRef = ReadAttribute<std::string>("name");
ASSIMP_LOG_VERBOSE_DEBUG_F("Read skeleton link ", mesh->skeletonRef);
NextNode();
}
// Assimp incompatible/ignored nodes
else {
SkipCurrentNode();
}
}*/
}
void OgreXmlSerializer::ReadGeometry(XmlNode &node, VertexDataXml *dest) {
@@ -291,10 +256,6 @@ void OgreXmlSerializer::ReadGeometry(XmlNode &node, VertexDataXml *dest) {
ReadGeometryVertexBuffer(currentNode, dest);
}
}
//NextNode();
/*while (m_currentNodeName == nnVertexBuffer) {
ReadGeometryVertexBuffer(dest);
}*/
}
void OgreXmlSerializer::ReadGeometryVertexBuffer(XmlNode &node, VertexDataXml *dest) {
@@ -328,11 +289,6 @@ void OgreXmlSerializer::ReadGeometryVertexBuffer(XmlNode &node, VertexDataXml *d
}
}
/*bool warnBinormal = true;
bool warnColorDiffuse = true;
bool warnColorSpecular = true;*/
//NextNode();
for (XmlNode currentNode : node.children()) {
const std::string &currentName = currentNode.name();
if (positions && currentName == nnPosition) {
@@ -363,84 +319,6 @@ void OgreXmlSerializer::ReadGeometryVertexBuffer(XmlNode &node, VertexDataXml *d
}
}
/*while (m_currentNodeName == nnVertex ||
m_currentNodeName == nnPosition ||
m_currentNodeName == nnNormal ||
m_currentNodeName == nnTangent ||
m_currentNodeName == nnBinormal ||
m_currentNodeName == nnTexCoord ||
m_currentNodeName == nnColorDiffuse ||
m_currentNodeName == nnColorSpecular) {
if (m_currentNodeName == nnVertex) {
NextNode();
}
/// @todo Implement nnBinormal, nnColorDiffuse and nnColorSpecular
if (positions && m_currentNodeName == nnPosition) {
aiVector3D pos;
pos.x = ReadAttribute<float>(anX);
pos.y = ReadAttribute<float>(anY);
pos.z = ReadAttribute<float>(anZ);
dest->positions.push_back(pos);
} else if (normals && m_currentNodeName == nnNormal) {
aiVector3D normal;
normal.x = ReadAttribute<float>(anX);
normal.y = ReadAttribute<float>(anY);
normal.z = ReadAttribute<float>(anZ);
dest->normals.push_back(normal);
} else if (tangents && m_currentNodeName == nnTangent) {
aiVector3D tangent;
tangent.x = ReadAttribute<float>(anX);
tangent.y = ReadAttribute<float>(anY);
tangent.z = ReadAttribute<float>(anZ);
dest->tangents.push_back(tangent);
} else if (uvs > 0 && m_currentNodeName == nnTexCoord) {
for (auto &curUvs : dest->uvs) {
if (m_currentNodeName != nnTexCoord) {
throw DeadlyImportError("Vertex buffer declared more UVs than can be found in a vertex");
}
aiVector3D uv;
uv.x = ReadAttribute<float>("u");
uv.y = (ReadAttribute<float>("v") * -1) + 1; // Flip UV from Ogre to Assimp form
curUvs.push_back(uv);
NextNode();
}
// Continue main loop as above already read next node
continue;
} else {
/// @todo Remove this stuff once implemented. We only want to log warnings once per element.
bool warn = true;
if (m_currentNodeName == nnBinormal) {
if (warnBinormal) {
warnBinormal = false;
} else {
warn = false;
}
} else if (m_currentNodeName == nnColorDiffuse) {
if (warnColorDiffuse) {
warnColorDiffuse = false;
} else {
warn = false;
}
} else if (m_currentNodeName == nnColorSpecular) {
if (warnColorSpecular) {
warnColorSpecular = false;
} else {
warn = false;
}
}
if (warn) {
ASSIMP_LOG_WARN_F("Vertex buffer attribute read not implemented for element: ", m_currentNodeName);
}
}*/
// Advance
//NextNode();
//}
// Sanity checks
if (dest->positions.size() != dest->count) {
throw DeadlyImportError(Formatter::format() << "Read only " << dest->positions.size() << " positions when should have read " << dest->count);
@@ -525,57 +403,6 @@ void OgreXmlSerializer::ReadSubMesh(XmlNode &node, MeshXml *mesh) {
}
}
/*NextNode();
while (m_currentNodeName == nnFaces ||
m_currentNodeName == nnGeometry ||
m_currentNodeName == nnTextures ||
m_currentNodeName == nnBoneAssignments) {
if (m_currentNodeName == nnFaces) {
submesh->indexData->faceCount = ReadAttribute<uint32_t>(anCount);
submesh->indexData->faces.reserve(submesh->indexData->faceCount);
NextNode();
while (m_currentNodeName == nnFace) {
aiFace face;
face.mNumIndices = 3;
face.mIndices = new unsigned int[3];
face.mIndices[0] = ReadAttribute<uint32_t>(anV1);
face.mIndices[1] = ReadAttribute<uint32_t>(anV2);
face.mIndices[2] = ReadAttribute<uint32_t>(anV3);
/// @todo Support quads if Ogre even supports them in XML (I'm not sure but I doubt it)
if (!quadWarned && HasAttribute(anV4)) {
ASSIMP_LOG_WARN("Submesh <face> has quads with <v4>, only triangles are supported at the moment!");
quadWarned = true;
}
submesh->indexData->faces.push_back(face);
// Advance
NextNode();
}
if (submesh->indexData->faces.size() == submesh->indexData->faceCount) {
ASSIMP_LOG_VERBOSE_DEBUG_F(" - Faces ", submesh->indexData->faceCount);
} else {
throw DeadlyImportError(Formatter::format() << "Read only " << submesh->indexData->faces.size() << " faces when should have read " << submesh->indexData->faceCount);
}
} else if (m_currentNodeName == nnGeometry) {
if (submesh->usesSharedVertexData) {
throw DeadlyImportError("Found <geometry> in <submesh> when use shared geometry is true. Invalid mesh file.");
}
submesh->vertexData = new VertexDataXml();
ReadGeometry(submesh->vertexData);
} else if (m_currentNodeName == nnBoneAssignments) {
ReadBoneAssignments(submesh->vertexData);
}
// Assimp incompatible/ignored nodes
else {
SkipCurrentNode();
}
}*/
submesh->index = static_cast<unsigned int>(mesh->subMeshes.size());
mesh->subMeshes.push_back(submesh);
}
@@ -603,19 +430,6 @@ void OgreXmlSerializer::ReadBoneAssignments(XmlNode &node, VertexDataXml *dest)
}
}
/*NextNode();
while (m_currentNodeName == nnVertexBoneAssignment) {
VertexBoneAssignment ba;
ba.vertexIndex = ReadAttribute<uint32_t>(anVertexIndex);
ba.boneIndex = ReadAttribute<uint16_t>(anBoneIndex);
ba.weight = ReadAttribute<float>(anWeight);
dest->boneAssignments.push_back(ba);
influencedVertices.insert(ba.vertexIndex);
NextNode();
}*/
/** Normalize bone weights.
Some exporters won't care if the sum of all bone weights
for a single vertex equals 1 or not, so validate here. */
@@ -662,8 +476,8 @@ bool OgreXmlSerializer::ImportSkeleton(Assimp::IOSystem *pIOHandler, MeshXml *me
Skeleton *skeleton = new Skeleton();
OgreXmlSerializer serializer(xmlParser.get());
XmlNode *root = xmlParser->getRootNode();
serializer.ReadSkeleton(*root, skeleton);
XmlNode root = xmlParser->getRootNode();
serializer.ReadSkeleton(root, skeleton);
mesh->skeleton = skeleton;
return true;
}
@@ -680,12 +494,9 @@ bool OgreXmlSerializer::ImportSkeleton(Assimp::IOSystem *pIOHandler, Mesh *mesh)
Skeleton *skeleton = new Skeleton();
OgreXmlSerializer serializer(xmlParser.get());
XmlNode *root = xmlParser->getRootNode();
if (nullptr == root) {
return false;
}
XmlNode root = xmlParser->getRootNode();
serializer.ReadSkeleton(*root, skeleton);
serializer.ReadSkeleton(root, skeleton);
mesh->skeleton = skeleton;
return true;
@@ -736,22 +547,6 @@ void OgreXmlSerializer::ReadSkeleton(XmlNode &node, Skeleton *skeleton) {
ReadAnimations(currentNode, skeleton);
}
}
/*NextNode();
// Root level nodes
while (m_currentNodeName == nnBones ||
m_currentNodeName == nnBoneHierarchy ||
m_currentNodeName == nnAnimations ||
m_currentNodeName == nnAnimationLinks) {
if (m_currentNodeName == nnBones)
ReadBones(skeleton);
else if (m_currentNodeName == nnBoneHierarchy)
ReadBoneHierarchy(skeleton);
else if (m_currentNodeName == nnAnimations)
ReadAnimations(skeleton);
else
SkipCurrentNode();
}*/
}
void OgreXmlSerializer::ReadAnimations(XmlNode &node, Skeleton *skeleton) {
@@ -778,22 +573,6 @@ void OgreXmlSerializer::ReadAnimations(XmlNode &node, Skeleton *skeleton) {
}
}
}
/* NextNode();
while (m_currentNodeName == nnAnimation) {
Animation *anim = new Animation(skeleton);
anim->name = ReadAttribute<std::string>("name");
anim->length = ReadAttribute<float>("length");
if (NextNode() != nnTracks) {
throw DeadlyImportError(Formatter::format() << "No <tracks> found in <animation> " << anim->name);
}
ReadAnimationTracks(anim);
skeleton->animations.push_back(anim);
ASSIMP_LOG_VERBOSE_DEBUG_F(" ", anim->name, " (", anim->length, " sec, ", anim->tracks.size(), " tracks)");
}*/
}
void OgreXmlSerializer::ReadAnimationTracks(XmlNode &node, Animation *dest) {
@@ -815,20 +594,6 @@ void OgreXmlSerializer::ReadAnimationTracks(XmlNode &node, Animation *dest) {
}
}
/*NextNode();
while (m_currentNodeName == nnTrack) {
VertexAnimationTrack track;
track.type = VertexAnimationTrack::VAT_TRANSFORM;
track.boneName = ReadAttribute<std::string>("bone");
if (NextNode() != nnKeyFrames) {
throw DeadlyImportError(Formatter::format() << "No <keyframes> found in <track> " << dest->name);
}
ReadAnimationKeyFrames(dest, &track);
dest->tracks.push_back(track);
}*/
}
void OgreXmlSerializer::ReadAnimationKeyFrames(XmlNode &node, Animation *anim, VertexAnimationTrack *dest) {
@@ -873,46 +638,6 @@ void OgreXmlSerializer::ReadAnimationKeyFrames(XmlNode &node, Animation *anim, V
}
dest->transformKeyFrames.push_back(keyframe);
}
/*NextNode();
while (m_currentNodeName == nnKeyFrame) {
TransformKeyFrame keyframe;
keyframe.timePos = ReadAttribute<float>("time");
NextNode();
while (m_currentNodeName == nnTranslate || m_currentNodeName == nnRotate || m_currentNodeName == nnScale) {
if (m_currentNodeName == nnTranslate) {
keyframe.position.x = ReadAttribute<float>(anX);
keyframe.position.y = ReadAttribute<float>(anY);
keyframe.position.z = ReadAttribute<float>(anZ);
} else if (m_currentNodeName == nnRotate) {
float angle = ReadAttribute<float>("angle");
if (NextNode() != nnAxis) {
throw DeadlyImportError("No axis specified for keyframe rotation in animation " + anim->name);
}
aiVector3D axis;
axis.x = ReadAttribute<float>(anX);
axis.y = ReadAttribute<float>(anY);
axis.z = ReadAttribute<float>(anZ);
if (axis.Equal(zeroVec)) {
axis.x = 1.0f;
if (angle != 0) {
ASSIMP_LOG_WARN_F("Found invalid a key frame with a zero rotation axis in animation: ", anim->name);
}
}
keyframe.rotation = aiQuaternion(axis, angle);
} else if (m_currentNodeName == nnScale) {
keyframe.scale.x = ReadAttribute<float>(anX);
keyframe.scale.y = ReadAttribute<float>(anY);
keyframe.scale.z = ReadAttribute<float>(anZ);
}
NextNode();
}
dest->transformKeyFrames.push_back(keyframe);
}*/
}
void OgreXmlSerializer::ReadBoneHierarchy(XmlNode &node, Skeleton *skeleton) {
@@ -937,20 +662,6 @@ void OgreXmlSerializer::ReadBoneHierarchy(XmlNode &node, Skeleton *skeleton) {
}
}
/*while (NextNode() == nnBoneParent) {
const std::string name = ReadAttribute<std::string>("bone");
const std::string parentName = ReadAttribute<std::string>("parent");
Bone *bone = skeleton->BoneByName(name);
Bone *parent = skeleton->BoneByName(parentName);
if (bone && parent)
parent->AddChild(bone);
else
throw DeadlyImportError("Failed to find bones for parenting: Child " + name + " for parent " + parentName);
}*/
// Calculate bone matrices for root bones. Recursively calculates their children.
for (size_t i = 0, len = skeleton->bones.size(); i < len; ++i) {
Bone *bone = skeleton->bones[i];
@@ -1014,54 +725,6 @@ void OgreXmlSerializer::ReadBones(XmlNode &node, Skeleton *skeleton) {
}
}
/*NextNode();
while (m_currentNodeName == nnBone) {
Bone *bone = new Bone();
bone->id = ReadAttribute<uint16_t>("id");
bone->name = ReadAttribute<std::string>("name");
NextNode();
while (m_currentNodeName == nnPosition ||
m_currentNodeName == nnRotation ||
m_currentNodeName == nnScale) {
if (m_currentNodeName == nnPosition) {
bone->position.x = ReadAttribute<float>(anX);
bone->position.y = ReadAttribute<float>(anY);
bone->position.z = ReadAttribute<float>(anZ);
} else if (m_currentNodeName == nnRotation) {
float angle = ReadAttribute<float>("angle");
if (NextNode() != nnAxis) {
throw DeadlyImportError(Formatter::format() << "No axis specified for bone rotation in bone " << bone->id);
}
aiVector3D axis;
axis.x = ReadAttribute<float>(anX);
axis.y = ReadAttribute<float>(anY);
axis.z = ReadAttribute<float>(anZ);
bone->rotation = aiQuaternion(axis, angle);
} else if (m_currentNodeName == nnScale) {
/// @todo Implement taking scale into account in matrix/pose calculations!
if (HasAttribute("factor")) {
float factor = ReadAttribute<float>("factor");
bone->scale.Set(factor, factor, factor);
} else {
if (HasAttribute(anX))
bone->scale.x = ReadAttribute<float>(anX);
if (HasAttribute(anY))
bone->scale.y = ReadAttribute<float>(anY);
if (HasAttribute(anZ))
bone->scale.z = ReadAttribute<float>(anZ);
}
}
NextNode();
}
skeleton->bones.push_back(bone);
}*/
// Order bones by Id
std::sort(skeleton->bones.begin(), skeleton->bones.end(), BoneCompare);