From 3f0f1c60d9a316fa363cfc71dacd0cb28c852bd8 Mon Sep 17 00:00:00 2001 From: devZoGok Date: Fri, 4 Mar 2022 21:26:24 +0200 Subject: [PATCH] skeleton assignment improvements --- node.cpp | 13 +++++++-- node.h | 2 ++ script.py | 19 ++++++------ xmlModelReader.cpp | 72 +++++++++++++++++++++++++++++++++++----------- 4 files changed, 79 insertions(+), 27 deletions(-) diff --git a/node.cpp b/node.cpp index 7935bca..196c84d 100755 --- a/node.cpp +++ b/node.cpp @@ -6,6 +6,7 @@ #include "text.h" #include "material.h" #include "matrix.h" +#include "skeleton.h" #include "animationController.h" #include @@ -45,15 +46,23 @@ namespace vb01{ if(visible){ for(Light *l : lights) l->update(); + for(Mesh *m : meshes) m->update(); + for(Text *t : texts) t->update(); - for(Node *c : children) - c->update(); + for(ParticleEmitter *p : emitters) p->update(); + + for(Skeleton *sk : skeletons) + sk->update(); + + for(Node *c : children) + c->update(); } + for(Driver *driver : drivers) driver->drive(getDriverValue(driver->getType())); } diff --git a/node.h b/node.h index 252ea04..c9325c5 100755 --- a/node.h +++ b/node.h @@ -44,8 +44,10 @@ namespace vb01{ Quaternion globalToLocalOrientation(Quaternion); Vector3 localToGlobalScale(Vector3); Vector3 globalToLocalScale(Vector3); + inline Skeleton* getSkeleton(int i){return skeletons[i];} inline Text* getText(int i){return texts[i];} inline std::vector& getMeshes(){return meshes;} + inline std::vector& getSkeletons(){return skeletons;} inline Mesh* getMesh(int i){return meshes[i];} inline Node* getParent(){return parent;} inline void setParent(Node *par){this->parent = par;} diff --git a/script.py b/script.py index 558c977..1bf7930 100644 --- a/script.py +++ b/script.py @@ -165,8 +165,8 @@ def export(node, parentTag): norm = vert.normal vertDataTag = ET.SubElement(meshTag, 'vertdata') vertDataTag.set('px', str(pos.x)) - vertDataTag.set('py', str(pos.y)) - vertDataTag.set('pz', str(pos.z)) + vertDataTag.set('py', str(pos.z)) + vertDataTag.set('pz', str(-pos.y)) vertDataTag.set('nx', str(norm.x)) vertDataTag.set('ny', str(norm.y)) vertDataTag.set('nz', str(norm.z)) @@ -201,11 +201,11 @@ def export(node, parentTag): vertTag.set('uvx', str(uv.x)) vertTag.set('uvy', str(uv.y)) vertTag.set('tx', str(tan.x)) - vertTag.set('ty', str(tan.y)) - vertTag.set('tz', str(tan.z)) + vertTag.set('ty', str(tan.z)) + vertTag.set('tz', str(-tan.y)) vertTag.set('bx', str(bitan.x)) - vertTag.set('by', str(bitan.y)) - vertTag.set('bz', str(bitan.z)) + vertTag.set('by', str(bitan.z)) + vertTag.set('bz', str(-bitan.y)) mesh.free_tangents() @@ -224,8 +224,8 @@ def export(node, parentTag): pos = vert.co vertTag = ET.SubElement(shapeKeyTag, 'vert') vertTag.set('px', str(pos.x)) - vertTag.set('py', str(pos.y)) - vertTag.set('pz', str(pos.z)) + vertTag.set('py', str(pos.z)) + vertTag.set('pz', str(-pos.y)) i = i + 1 @@ -233,9 +233,10 @@ def export(node, parentTag): if(node.modifiers and node.modifiers[armatureMod] and node.modifiers[armatureMod].object): skeleton = node.modifiers[armatureMod].object - meshTag.set('skeleton', skeleton.name) + meshTag.set('skeleton', skeleton.name + '.' + skeleton.data.name_full) elif node.type == 'ARMATURE': skeletonTag = ET.SubElement(nodeTag, 'skeleton') + skeletonTag.set('name', node.data.name_full) exportBone(node, node.data.bones[0], skeletonTag, True) elif node.type == 'LIGHT': lightTag = ET.SubElement(nodeTag, 'light') diff --git a/xmlModelReader.cpp b/xmlModelReader.cpp index 2356c88..30e52d9 100644 --- a/xmlModelReader.cpp +++ b/xmlModelReader.cpp @@ -3,6 +3,7 @@ #include "skeleton.h" #include "bone.h" #include "vector.h" +#include "animationController.h" #include @@ -16,8 +17,27 @@ namespace vb01{ XMLDocument *doc = new XMLDocument(); doc->LoadFile(path.c_str()); - XMLNode *root = doc->FirstChild(); - model->attachChild(processNode(model, (XMLElement*)root)); + XMLElement *root = doc->FirstChildElement(); + + for(XMLElement *ch = root->FirstChildElement(); ch; ch = ch->NextSiblingElement()) + model->attachChild(processNode(model, ch)); + + vector descendants; + model->getDescendants(descendants); + vector meshes; + + for(Node *desc : descendants) + for(Mesh *m : desc->getMeshes()) + if(m->getSkeleton()) + meshes.push_back(m); + + for(Mesh *m : meshes) + for(Node *desc : descendants) + for(Skeleton *sk : desc->getSkeletons()) + if(m->getSkeleton()->getName() == sk->getName()){ + delete m->getSkeleton(); + m->setSkeleton(sk); + } } Mesh* XmlModelReader::processMesh(XMLElement *meshEl){ @@ -50,7 +70,6 @@ namespace vb01{ i = 0; int numVertices = 3 * atoi(meshEl->Attribute("num_faces")); - int numBones; Mesh::Vertex *vertices = new Mesh::Vertex[numVertices]; tagName = "vert"; vector vertIds; @@ -81,10 +100,10 @@ namespace vb01{ vertex.tan = tan; vertex.biTan = biTan; - for(int j = 0, boneIndex = 0; j < numBones; j++){ - if(weights[id * numBones + j] > 0){ + for(int j = 0, boneIndex = 0; j < numVertexGroups; j++){ + if(weights[id * numVertexGroups + j] > 0){ vertex.boneIndices[boneIndex] = j; - vertex.weights[boneIndex] = weights[id * numBones + j]; + vertex.weights[boneIndex] = weights[id * numVertexGroups + j]; boneIndex++; } } @@ -119,20 +138,38 @@ namespace vb01{ } } - Mesh *mesh = new Mesh(vertices, indices, numVertices / 3, vertexGroups, numBones, shapeKeys, numShapeKeys); + Mesh *mesh = new Mesh(vertices, indices, numVertices / 3, vertexGroups, numVertexGroups, shapeKeys, numShapeKeys); + mesh->construct(); + + const char *skeletonName = meshEl->Attribute("skeleton"); + + if(skeletonName){ + int dotId = string(skeletonName).find_first_of("."); + string name = string(skeletonName).substr(dotId + 1, string::npos); + mesh->setSkeleton(new Skeleton(name)); + } + return mesh; } Skeleton* XmlModelReader::processSkeleton(Node *root, XMLElement *skeletonEl){ XMLElement *rootBoneEl = skeletonEl->FirstChildElement("bone"); - Skeleton *skeleton = new Skeleton(nullptr); - skeleton->addBone((Bone*)processNode(root, rootBoneEl, true), (Bone*)root); + Bone *rootBone = (Bone*)processNode(root, rootBoneEl, true); + vector bones; + rootBone->getDescendants(bones); + + Skeleton *skeleton = new Skeleton(skeletonEl->Attribute("name")); + skeleton->addBone(rootBone, (Bone*)root); + + for(Node *bone : bones) + skeleton->addBone((Bone*)bone, (Bone*)bone->getParent()); return skeleton; } Node* XmlModelReader::processNode(Node *parent, XMLElement *xmlEl, bool bone){ Node *node = nullptr; + const char *name = xmlEl->Attribute("name"); if(bone){ float headX = atof(xmlEl->Attribute("hx")); @@ -150,14 +187,14 @@ namespace vb01{ float yAxisZ = atof(xmlEl->Attribute("yaxisz")); Vector3 yAxis = Vector3(yAxisX, yAxisY, yAxisZ); - string name = xmlEl->Attribute("name"); float length = atof(xmlEl->Attribute("length")); Vector3 zAxis = xAxis.cross(yAxis).norm(); Vector3 pos = head; /* - if(!parent){ + */ + if(xmlEl->Parent()->ToElement()->Name() == "skeleton"){ parent = model; swap(pos.y, pos.z); pos.z = -pos.z; @@ -167,7 +204,6 @@ namespace vb01{ zAxis.z = -zAxis.z; } else - */ pos = pos + Vector3(0, ((Bone*)parent)->getLength(), 0); node = new Bone(name, length, pos, Quaternion::QUAT_W, Vector3::VEC_IJK); @@ -180,21 +216,25 @@ namespace vb01{ ((Bone*)node)->setIkChainLength(ikChainLength); } } + else + node = new Node(Vector3::VEC_ZERO, Quaternion::QUAT_W, Vector3::VEC_IJK, name); XMLElement *skeletonTag = xmlEl->FirstChildElement("skeleton"); if(skeletonTag) - processSkeleton(node, skeletonTag); + node->addSkeleton(processSkeleton(node, skeletonTag)); XMLElement *meshTag = xmlEl->FirstChildElement("mesh"); if(meshTag) - processMesh(meshTag); + node->attachMesh(processMesh(meshTag)); XMLElement *lightTag = xmlEl->FirstChildElement("light"); - for(XMLElement *el = xmlEl->FirstChildElement("node"); el; el = el->NextSiblingElement()) - parent->attachChild(processNode(parent, el, bone)); + const char *tagName = (bone ? "bone" : "node"); + + for(XMLElement *el = xmlEl->FirstChildElement(tagName); el; el = el->NextSiblingElement()) + node->attachChild(processNode(node, el, bone)); return node; }