From e23ee522575885eb6085bde0649ed0ab49a3d3e9 Mon Sep 17 00:00:00 2001 From: devZoGok Date: Tue, 8 Mar 2022 19:03:13 +0200 Subject: [PATCH] improved skeleton loading --- main.cpp | 2 -- node.cpp | 61 ++++++++++++++++++++-------------------------- nodeTest.cpp | 17 +++++++++++++ xmlModelReader.cpp | 42 ++++++++++++++++++------------- 4 files changed, 69 insertions(+), 53 deletions(-) diff --git a/main.cpp b/main.cpp index 24ad8ad..8ff7e1a 100755 --- a/main.cpp +++ b/main.cpp @@ -6,7 +6,6 @@ #include "cameraTest.h" #include "nodeTest.h" #include "boneTest.h" -#include "vbModelReaderTest.h" #include "animationChannelTest.h" #include "shaderTest.h" #include "particleEmitterTest.h" @@ -20,7 +19,6 @@ int main(){ runner.addTest(CameraTest::suite()); runner.addTest(NodeTest::suite()); runner.addTest(BoneTest::suite()); - runner.addTest(VbModelReaderTest::suite()); runner.addTest(AnimationChannelTest::suite()); runner.addTest(ShaderTest::suite()); runner.addTest(ParticleEmitterTest::suite()); diff --git a/node.cpp b/node.cpp index 196c84d..ce4e36c 100755 --- a/node.cpp +++ b/node.cpp @@ -30,16 +30,18 @@ namespace vb01{ Node::~Node(){ for(Mesh *m : meshes) delete m; + for(Light *l : lights) delete l; + for(ParticleEmitter *p : emitters) delete p; + for(Text *t : texts) delete t; - for(Node *c : children){ - //dettachChild(c); + + for(Node *c : children) delete c; - } } void Node::update(){ @@ -69,6 +71,7 @@ namespace vb01{ float Node::getDriverValue(Driver::VariableType type){ float driverValue; + switch(type){ case Driver::POS_X: driverValue = pos.x; @@ -101,6 +104,7 @@ namespace vb01{ driverValue = scale.z; break; } + return driverValue; } @@ -113,11 +117,13 @@ namespace vb01{ void Node::dettachChild(Node *child){ child->setParent(nullptr); int id = -1; + for(int i = 0; i < children.size(); i++) if(children[i] == child){ id = i; break; } + if(id != -1) children.erase(children.begin() + id); } @@ -168,6 +174,7 @@ namespace vb01{ void Node::adjustDir(Vector3 newDir){ float angle = Vector3(0, 0, 1).getAngleBetween(newDir); Vector3 rotAxis = Vector3(0, 0, 1).cross(newDir).norm(); + if(rotAxis == Vector3::VEC_ZERO) rotAxis = Vector3::VEC_I; @@ -175,39 +182,21 @@ namespace vb01{ } void Node::adjustUp(Vector3 newUp){ - Vector3 xDir = - parent->globalToLocalPosition(localToGlobalPosition(Vector3::VEC_I)) - - parent->globalToLocalPosition(localToGlobalPosition(Vector3::VEC_ZERO)); + Vector3 xDir = orientation * Vector3(1, 0, 0), + yDir = orientation * Vector3(0, 1, 0), + zDir = orientation * Vector3(0, 0, 1); + newUp = Vector3(newUp.x, newUp.y, 0).norm(); - Vector3 yDir = - parent->globalToLocalPosition(localToGlobalPosition(Vector3::VEC_J)) - - parent->globalToLocalPosition(localToGlobalPosition(Vector3::VEC_ZERO)); - - Vector3 zDir = xDir.cross(yDir).norm(); - - mat3 mat; - mat[0][0] = xDir.x; - mat[1][0] = xDir.y; - mat[2][0] = xDir.z; - mat[0][1] = yDir.x; - mat[1][1] = yDir.y; - mat[2][1] = yDir.z; - mat[0][2] = zDir.x; - mat[1][2] = zDir.y; - mat[2][2] = zDir.z; - - vec3 nu = vec3(newUp.x, newUp.y, newUp.z) * inverse(mat); - newUp = (xDir * nu.x + yDir * nu.y).norm(); if(newUp != Vector3::VEC_ZERO){ float angle = yDir.getAngleBetween(newUp); - - setOrientation(Quaternion(angle * (nu.x < 0 ? 1 : -1), zDir) * orientation); + setOrientation(Quaternion(angle * (newUp.x < 0 ? 1 : -1), zDir) * orientation); } } void Node::getDescendants(vector &descendants){ for(Node *child : getChildren()){ descendants.push_back(child); + if(!child->getChildren().empty()) child->getDescendants(descendants); } @@ -216,20 +205,24 @@ namespace vb01{ vector Node::getAncestors(Node *topAncestor){ vector ancestors; Node *parent = this; + while(parent){ ancestors.push_back(parent); + if(parent == topAncestor) break; + parent = parent->getParent(); } + return ancestors; } void Node::updateAxis(){ Vector3 parGlobalAxis[3]{ - parent->getGlobalAxis(0), - parent->getGlobalAxis(1), - parent->getGlobalAxis(2) + parent ? parent->getGlobalAxis(0) : Vector3::VEC_I, + parent ? parent->getGlobalAxis(1) : Vector3::VEC_J, + parent ? parent->getGlobalAxis(2) : Vector3::VEC_K }; float rotAngle = orientation.getAngle(); @@ -256,6 +249,7 @@ namespace vb01{ par ? par->getGlobalAxis(1) : Vector3::VEC_J, par ? par->getGlobalAxis(2) : Vector3::VEC_K }; + Vector3 p = ancestors[id]->getPosition(); origin = origin + parAxis[0] * p.x + parAxis[1] * p.y+parAxis[2] * p.z; ancestors.pop_back(); @@ -320,17 +314,13 @@ namespace vb01{ Quaternion Node::localToGlobalOrientation(Quaternion localRot){ vector ancestors = getAncestors(); - Quaternion origin = adjustRot(ancestors, Quaternion::QUAT_W, true); - return localRot * origin; } Quaternion Node::globalToLocalOrientation(Quaternion globalRot){ vector ancestors = getAncestors(); - Quaternion origin = adjustRot(ancestors, globalRot, false); - return origin; } @@ -344,6 +334,7 @@ namespace vb01{ for(Node *n : descendants){ vector meshes = n->getMeshes(); + for(Mesh *m : meshes){ Material *mat = m->getMaterial(); int numLights = root->getNumLights(); @@ -363,6 +354,7 @@ namespace vb01{ void Node::animate(float value, KeyframeChannel keyframeChannel){ Vector3 newPos = pos, newScale = scale; Quaternion newRot = orientation; + switch(keyframeChannel.type){ case KeyframeChannel::POS_X: newPos.x = value; @@ -395,6 +387,7 @@ namespace vb01{ newScale.z = value; break; } + setPosition(newPos); setOrientation(newRot); setScale(newScale); diff --git a/nodeTest.cpp b/nodeTest.cpp index 83ffef1..11250d8 100644 --- a/nodeTest.cpp +++ b/nodeTest.cpp @@ -220,6 +220,7 @@ namespace vb01{ Vector3(0, -1, -.4).norm(), Vector3(1, 1, 1).norm() }; + int numDirs = sizeof(dir) / sizeof(Vector3); for(int i = 0; i < numDirs; i++){ @@ -234,6 +235,13 @@ namespace vb01{ lookNode->lookAt(dir[i]); CPPUNIT_ASSERT(lookNode->getGlobalAxis(2).getAngleBetween(rotQuat * dir[i]) < maxAngle); } + + for(int i = 0; i < numDirs; i++){ + lookNodeParent->dettachChild(lookNode); + lookNode->lookAt(dir[i]); + lookNodeParent->attachChild(lookNode); + CPPUNIT_ASSERT(lookNode->getGlobalAxis(2).getAngleBetween(rotQuat * dir[i]) < maxAngle); + } } void NodeTest::testAdjustUp(){ @@ -256,6 +264,7 @@ namespace vb01{ Vector3 upClamped = Vector3(up[i].x, up[i].y, 0).norm(); CPPUNIT_ASSERT(lookNode->getGlobalAxis(1).getAngleBetween(upClamped) < maxAngle); } + lookNode->setOrientation(Quaternion::QUAT_W); lookNode->lookAt(Vector3::VEC_K, Vector3::VEC_K); CPPUNIT_ASSERT(lookNode->getGlobalAxis(1) == Vector3::VEC_J); @@ -268,5 +277,13 @@ namespace vb01{ Vector3 upClamped = Vector3(up[i].x, up[i].y, 0).norm(); CPPUNIT_ASSERT(lookNode->getGlobalAxis(1).getAngleBetween(rotQuat * upClamped) < maxAngle); } + + for(int i = 0; i < numDirs; i++){ + lookNodeParent->dettachChild(lookNode); + lookNode->lookAt(Vector3::VEC_K, up[i]); + lookNodeParent->attachChild(lookNode); + Vector3 upClamped = Vector3(up[i].x, up[i].y, 0).norm(); + CPPUNIT_ASSERT(lookNode->getGlobalAxis(1).getAngleBetween(rotQuat * upClamped) < maxAngle); + } } } diff --git a/xmlModelReader.cpp b/xmlModelReader.cpp index 30e52d9..05d83c2 100644 --- a/xmlModelReader.cpp +++ b/xmlModelReader.cpp @@ -172,29 +172,37 @@ namespace vb01{ const char *name = xmlEl->Attribute("name"); if(bone){ - float headX = atof(xmlEl->Attribute("hx")); - float headY = atof(xmlEl->Attribute("hy")); - float headZ = atof(xmlEl->Attribute("hz")); - Vector3 head = Vector3(headX, headY, headZ); + float components[]{ + atof(xmlEl->Attribute("hx")), + atof(xmlEl->Attribute("hy")), + atof(xmlEl->Attribute("hz")), + atof(xmlEl->Attribute("xaxisx")), + atof(xmlEl->Attribute("xaxisy")), + atof(xmlEl->Attribute("xaxisz")), + atof(xmlEl->Attribute("yaxisx")), + atof(xmlEl->Attribute("yaxisy")), + atof(xmlEl->Attribute("yaxisz")) + }; - float xAxisX = atof(xmlEl->Attribute("xaxisx")); - float xAxisY = atof(xmlEl->Attribute("xaxisy")); - float xAxisZ = atof(xmlEl->Attribute("xaxisz")); - Vector3 xAxis = Vector3(xAxisX, xAxisY, xAxisZ); - - float yAxisX = atof(xmlEl->Attribute("yaxisx")); - float yAxisY = atof(xmlEl->Attribute("yaxisy")); - float yAxisZ = atof(xmlEl->Attribute("yaxisz")); - Vector3 yAxis = Vector3(yAxisX, yAxisY, yAxisZ); + float eps = pow(10, -2); + + for(int i = 0; i < 9; i++){ + if(fabs(components[i]) < eps) + components[i] = 0; + } + /* + else if(fabs(components[i]) > 1.0) + components[i] = 1.0; + */ + Vector3 head = Vector3(components[0], components[1], components[2]); + Vector3 xAxis = Vector3(components[3], components[4], components[5]); + Vector3 yAxis = Vector3(components[6], components[7], components[8]); float length = atof(xmlEl->Attribute("length")); - Vector3 zAxis = xAxis.cross(yAxis).norm(); Vector3 pos = head; - /* - */ - if(xmlEl->Parent()->ToElement()->Name() == "skeleton"){ + if(strcmp(xmlEl->Parent()->ToElement()->Name(), "skeleton") == 0){ parent = model; swap(pos.y, pos.z); pos.z = -pos.z;