diff --git a/bone.cpp b/bone.cpp index 211cb13..71c3308 100644 --- a/bone.cpp +++ b/bone.cpp @@ -10,7 +10,7 @@ namespace vb01{ } void Bone::lookAt(Vector3 newDir, Vector3 newUp, Node *par){ - Node::lookAt(newDir, newUp, par); + Node::lookAt(newDir, newUp); for(int i = 0; i < 3; i++) this->initAxis[i] = globalAxis[i]; restPos = pos; diff --git a/node.cpp b/node.cpp index 5b00029..0f13424 100755 --- a/node.cpp +++ b/node.cpp @@ -101,60 +101,42 @@ namespace vb01{ text->setNode(this); } - void Node::lookAt(Vector3 newDir, Vector3 newUp, Node *node){ - adjustDir(newDir, node); - adjustUp(newUp, node); + void Node::lookAt(Vector3 newDir, Vector3 newUp){ + adjustDir(newDir); + adjustUp(newUp); } - void Node::lookAt(Vector3 newDir, Node *node){ - adjustDir(newDir, node); + void Node::lookAt(Vector3 newDir){ + adjustDir(newDir); } - void Node::adjustDir(Vector3 newDir, Node *node){ - Vector3 parAxis[]{ - node->getGlobalAxis(0), - node->getGlobalAxis(1), - node->getGlobalAxis(2) - }; - newDir = (parAxis[0] * newDir.x + parAxis[1] * newDir.y + parAxis[2] * newDir.z).norm(); - - float angle = globalAxis[2].getAngleBetween(newDir); - Vector3 rotAxis = globalAxis[2].cross(newDir).norm(); + 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 = globalAxis[1]; + rotAxis = Vector3::VEC_I; - Quaternion oldRot = node->localToGlobalOrientation(orientation); - Quaternion newRot = node->globalToLocalOrientation(Quaternion(angle,rotAxis)); - setOrientation(newRot * oldRot); + setOrientation(Quaternion(angle, rotAxis)); } - void Node::adjustUp(Vector3 newUp, Node *node){ - Vector3 parAxis[]{ - node->getGlobalAxis(0), - node->getGlobalAxis(1), - node->getGlobalAxis(2) - }; - newUp = (parAxis[0] * newUp.x + parAxis[1] * newUp.y + parAxis[2] * newUp.z).norm(); - + void Node::adjustUp(Vector3 newUp){ mat3 mat; - mat[0][0] = globalAxis[0].x; - mat[1][0] = globalAxis[0].y; - mat[2][0] = globalAxis[0].z; - mat[0][1] = globalAxis[1].x; - mat[1][1] = globalAxis[1].y; - mat[2][1] = globalAxis[1].z; - mat[0][2] = globalAxis[2].x; - mat[1][2] = globalAxis[2].y; - mat[2][2] = globalAxis[2].z; + mat[0][0] = 1; + mat[1][0] = 0; + mat[2][0] = 0; + mat[0][1] = 0; + mat[1][1] = 1; + mat[2][1] = 0; + mat[0][2] = 0; + mat[1][2] = 0; + mat[2][2] = 1; mat = inverse(mat); vec3 nu = vec3(newUp.x, newUp.y, newUp.z) * mat; - newUp = (globalAxis[0] * nu.x + globalAxis[1] * nu.y).norm(); - float angle = globalAxis[1].getAngleBetween(newUp); + newUp = (Vector3(1, 0, 0) * nu.x + Vector3(0, 1, 0) * nu.y).norm(); + float angle = Vector3(0, 1, 0).getAngleBetween(newUp); - Quaternion oldRot = node->localToGlobalOrientation(orientation); - Quaternion newRot = node->globalToLocalOrientation(Quaternion(angle * (nu.x < 0 ? 1 : -1), globalAxis[2])); - setOrientation(newRot * oldRot); + setOrientation(Quaternion(angle * (nu.x < 0 ? 1 : -1), Vector3::VEC_K)); } void Node::getDescendants(vector &descendants){ diff --git a/node.h b/node.h index c444343..6ac5e6c 100755 --- a/node.h +++ b/node.h @@ -31,8 +31,8 @@ namespace vb01{ void addLight(Light*); void removeLight(int); void addText(Text*); - virtual void lookAt(Vector3, Vector3, Node*); - virtual void lookAt(Vector3, Node*); + virtual void lookAt(Vector3, Vector3); + virtual void lookAt(Vector3); void updateAxis(); void setOrientation(Quaternion); void getDescendants(std::vector&); @@ -64,8 +64,8 @@ namespace vb01{ inline std::string getName(){return name;} inline void setVisible(bool v){this->visible = v;} private: - void adjustUp(Vector3, Node*); - void adjustDir(Vector3, Node*); + void adjustUp(Vector3); + void adjustDir(Vector3); Quaternion adjustRot(std::vector, Quaternion, bool); protected: void updateShaders(); diff --git a/nodeTest.cpp b/nodeTest.cpp index 32ca4ae..2b55c55 100644 --- a/nodeTest.cpp +++ b/nodeTest.cpp @@ -12,10 +12,11 @@ namespace vb01{ void NodeTest::setUp(){ rootNode = Root::getSingleton()->getRootNode(); - nodeA = new Node(); - nodeB = new Node(); - nodeC = new Node(); - nodeD = new Node(); + + lookNodeParent = new Node(); + rootNode->attachChild(lookNodeParent); + lookNode = new Node(); + lookNodeParent->attachChild(lookNode); firstChainNode = new Node(); rootNode->attachChild(firstChainNode); @@ -23,16 +24,27 @@ namespace vb01{ firstChainNode->attachChild(secondChainNode); thirdChainNode = new Node(); secondChainNode->attachChild(thirdChainNode); + + ancestorA = new Node(); + ancestorB = new Node(); + ancestorC = new Node(); + ancestorD = new Node(); + + rootNode->attachChild(ancestorA); + ancestorA->attachChild(ancestorB); + ancestorB->attachChild(ancestorC); + ancestorC->attachChild(ancestorD); } void NodeTest::tearDown(){ - /* - delete nodeD; - delete nodeC; - delete nodeB; - nodeA->dettachChild(nodeB); - delete nodeA; - */ + } + + void NodeTest::testGetAncestors(){ + vector ancestors = ancestorD->getAncestors(); + CPPUNIT_ASSERT(ancestors[ancestors.size() - 1] == rootNode); + + ancestors = ancestorD->getAncestors(ancestorB); + CPPUNIT_ASSERT(ancestors[ancestors.size() - 1] == ancestorB); } void NodeTest::testLocalToGlobalPosition(){ @@ -105,9 +117,6 @@ namespace vb01{ CPPUNIT_ASSERT(thirdChainNode->globalToLocalPosition(Vector3::VEC_ZERO) == -pos3); } - void NodeTest::testGlobalToLocalOrientation(){ - } - void NodeTest::testLocalToGlobalOrientation(){ firstChainNode->setOrientation(Quaternion::QUAT_W); secondChainNode->setOrientation(Quaternion::QUAT_W); @@ -117,13 +126,88 @@ namespace vb01{ CPPUNIT_ASSERT(secondChainNode->localToGlobalOrientation(Quaternion::QUAT_W) == Quaternion::QUAT_W); CPPUNIT_ASSERT(thirdChainNode->localToGlobalOrientation(Quaternion::QUAT_W) == Quaternion::QUAT_W); - Quaternion q0 = Quaternion(.2, Vector3(0, 1, 0)); - thirdChainNode->setOrientation(q0); - CPPUNIT_ASSERT(thirdChainNode->localToGlobalOrientation(Quaternion::QUAT_W) == q0); + float eps = .001; + + float an = .2; + Vector3 ax = Vector3(0, 1, 0).norm(); + + Quaternion q0 = Quaternion(an, ax); + secondChainNode->setOrientation(q0); + thirdChainNode->setOrientation(Quaternion::QUAT_W); + Quaternion ltg0 = secondChainNode->localToGlobalOrientation(Quaternion::QUAT_W); + Quaternion ltg01 = thirdChainNode->localToGlobalOrientation(Quaternion::QUAT_W); + CPPUNIT_ASSERT(ax.getAngleBetween(ltg0.getAxis()) < eps && fabs(an - ltg0.getAngle()) < eps); + CPPUNIT_ASSERT(ax.getAngleBetween(ltg01.getAxis()) < eps && fabs(an - ltg01.getAngle()) < eps); + + Quaternion q1 = Quaternion(an, ax); + secondChainNode->setOrientation(Quaternion::QUAT_W); + thirdChainNode->setOrientation(q1); + Quaternion ltg1 = secondChainNode->localToGlobalOrientation(Quaternion::QUAT_W); + Quaternion ltg11 = thirdChainNode->localToGlobalOrientation(Quaternion::QUAT_W); + CPPUNIT_ASSERT(ltg1 == Quaternion::QUAT_W); + CPPUNIT_ASSERT(ax.getAngleBetween(ltg11.getAxis()) < eps && fabs(an - ltg11.getAngle()) < eps); + + an = .3; + ax = Vector3(1, 0, 1).norm(); + Quaternion q2 = Quaternion(an, ax); + Quaternion q21 = Quaternion(an, ax); + secondChainNode->setOrientation(q2); + thirdChainNode->setOrientation(q21); + Quaternion ltg2 = secondChainNode->localToGlobalOrientation(Quaternion::QUAT_W); + Quaternion ltg21 = thirdChainNode->localToGlobalOrientation(Quaternion::QUAT_W); + Quaternion refQuat = q21 * q2; + CPPUNIT_ASSERT(ax.getAngleBetween(ltg2.getAxis()) < eps && fabs(an - ltg2.getAngle()) < eps); + CPPUNIT_ASSERT(refQuat.getAxis().getAngleBetween(ltg21.getAxis()) < eps && fabs(refQuat.getAngle() - ltg21.getAngle()) < eps); + + Quaternion q3 = Quaternion(an, ax); + firstChainNode->setOrientation(q3); + secondChainNode->setOrientation(Quaternion::QUAT_W); + thirdChainNode->setOrientation(Quaternion::QUAT_W); + Quaternion ltg4 = firstChainNode->localToGlobalOrientation(Quaternion::QUAT_W); + Quaternion ltg41 = secondChainNode->localToGlobalOrientation(Quaternion::QUAT_W); + Quaternion ltg42 = thirdChainNode->localToGlobalOrientation(Quaternion::QUAT_W); + CPPUNIT_ASSERT(ax.getAngleBetween(ltg4.getAxis()) < eps && fabs(an - ltg4.getAngle()) < eps); + CPPUNIT_ASSERT(ax.getAngleBetween(ltg41.getAxis()) < eps && fabs(an - ltg41.getAngle()) < eps); + CPPUNIT_ASSERT(ax.getAngleBetween(ltg42.getAxis()) < eps && fabs(an - ltg42.getAngle()) < eps); } - void NodeTest::testDetachChild(){ - nodeA->dettachChild(nodeB); - CPPUNIT_ASSERT(nodeA->getChild(0) != nodeB); + + void NodeTest::testGlobalToLocalOrientation(){ + firstChainNode->setOrientation(Quaternion::QUAT_W); + secondChainNode->setOrientation(Quaternion::QUAT_W); + thirdChainNode->setOrientation(Quaternion::QUAT_W); + + CPPUNIT_ASSERT(firstChainNode->globalToLocalOrientation(Quaternion::QUAT_W) == Quaternion::QUAT_W); + CPPUNIT_ASSERT(secondChainNode->globalToLocalOrientation(Quaternion::QUAT_W) == Quaternion::QUAT_W); + CPPUNIT_ASSERT(thirdChainNode->globalToLocalOrientation(Quaternion::QUAT_W) == Quaternion::QUAT_W); + + float eps = .001; + + float an = .4; + Vector3 ax = Vector3(1, 1, 0).norm(); + + Quaternion q0 = Quaternion(an, ax); + thirdChainNode->setOrientation(q0); + Quaternion gtl0 = thirdChainNode->globalToLocalOrientation(Quaternion::QUAT_W); + CPPUNIT_ASSERT(ax.getAngleBetween(-gtl0.getAxis()) < eps && fabs(an - gtl0.getAngle()) < eps); + + Quaternion q2 = Quaternion(an, ax); + Quaternion q21 = Quaternion(an, ax); + secondChainNode->setOrientation(q2); + thirdChainNode->setOrientation(q21); + Quaternion gtl21 = thirdChainNode->globalToLocalOrientation(Quaternion::QUAT_W); + Quaternion refQuat = q21 * q2; + CPPUNIT_ASSERT(refQuat.getAxis().getAngleBetween(-gtl21.getAxis()) < eps && fabs(refQuat.getAngle() - gtl21.getAngle()) < eps); + + Quaternion q3 = Quaternion(an, ax); + firstChainNode->setOrientation(q3); + secondChainNode->setOrientation(Quaternion::QUAT_W); + thirdChainNode->setOrientation(Quaternion::QUAT_W); + Quaternion gtl3 = firstChainNode->globalToLocalOrientation(Quaternion::QUAT_W); + Quaternion gtl31 = secondChainNode->globalToLocalOrientation(Quaternion::QUAT_W); + Quaternion gtl32 = thirdChainNode->globalToLocalOrientation(Quaternion::QUAT_W); + CPPUNIT_ASSERT(ax.getAngleBetween(-gtl3.getAxis()) < eps && fabs(an - gtl3.getAngle()) < eps); + CPPUNIT_ASSERT(ax.getAngleBetween(-gtl31.getAxis()) < eps && fabs(an - gtl31.getAngle()) < eps); + CPPUNIT_ASSERT(ax.getAngleBetween(-gtl32.getAxis()) < eps && fabs(an - gtl32.getAngle()) < eps); } void NodeTest::testAdjustDir(){ @@ -139,48 +223,47 @@ namespace vb01{ int numDirs = sizeof(dir) / sizeof(Vector3); for(int i = 0; i < numDirs; i++){ - nodeA->lookAt(dir[i], rootNode); - CPPUNIT_ASSERT(nodeA->getGlobalAxis(2).getAngleBetween(dir[i]) < maxAngle); + lookNode->lookAt(dir[i]); + CPPUNIT_ASSERT(lookNode->getGlobalAxis(2).getAngleBetween(dir[i]) < maxAngle); + } + + Quaternion rotQuat = Quaternion(.707, Vector3(1, 0 ,0)); + lookNodeParent->setOrientation(rotQuat); + + for(int i = 0; i < numDirs; i++){ + lookNode->lookAt(dir[i]); + CPPUNIT_ASSERT(lookNode->getGlobalAxis(2).getAngleBetween(rotQuat * dir[i]) < maxAngle); } } void NodeTest::testAdjustUp(){ float maxAngle = .001; - Vector3 dir[]{ - Vector3(0, 1, 0), + Vector3 up[]{ + Vector3(1, 0, 0), Vector3(.8, .2, 0).norm(), Vector3(-.6, 0, .9).norm(), Vector3(0, -1, -.4).norm(), Vector3(1, 1, 1).norm() }; - int numDirs = sizeof(dir) / sizeof(Vector3); + int numDirs = sizeof(up) / sizeof(Vector3); + + lookNodeParent->setOrientation(Quaternion::QUAT_W); for(int i = 0; i < numDirs; i++){ - /* - nodeA->lookAt(dir[i], rootNode); - CPPUNIT_ASSERT(nodeA->getGlobalAxis(2).getAngleBetween(dir[i]) < maxAngle); - */ + lookNode->lookAt(Vector3::VEC_K, up[i]); + Vector3 upClamped = Vector3(up[i].x, up[i].y, 0).norm(); + CPPUNIT_ASSERT(lookNode->getGlobalAxis(1).getAngleBetween(upClamped) < maxAngle); + } + + Quaternion rotQuat = Quaternion(.707, Vector3(1, 0 ,0)); + lookNodeParent->setOrientation(rotQuat); + + for(int i = 0; i < numDirs; i++){ + lookNode->lookAt(Vector3::VEC_K, up[i]); + Vector3 upClamped = Vector3(up[i].x, up[i].y, 0).norm(); + CPPUNIT_ASSERT(lookNode->getGlobalAxis(1).getAngleBetween(rotQuat * upClamped) < maxAngle); } } - - void NodeTest::testGetDescendants(){ - vector parentADescendants; - vector parentBDescendants; - vector parentCDescendants; - vector parentDDescendants; - - /* - parentA->getDescendants(parentADescendants); - parentB->getDescendants(parentBDescendants); - parentC->getDescendants(parentCDescendants); - parentD->getDescendants(parentDDescendants); - - parentD->getDescendants(parentDDescendants); - CPPUNIT_ASSERT(parentDDescendants[0] == childD0); - CPPUNIT_ASSERT(parentDDescendants[1] == childD1); - CPPUNIT_ASSERT(parentDDescendants[2] == childD2); - */ - } } diff --git a/nodeTest.h b/nodeTest.h index 0ac445c..e4a6b18 100644 --- a/nodeTest.h +++ b/nodeTest.h @@ -9,12 +9,9 @@ namespace vb01{ class NodeTest : public CppUnit::TestFixture{ CPPUNIT_TEST_SUITE(NodeTest); - /* - CPPUNIT_TEST(testDetachChild); + CPPUNIT_TEST(testGetAncestors); CPPUNIT_TEST(testAdjustDir); CPPUNIT_TEST(testAdjustUp); - CPPUNIT_TEST(testGetDescendants); - */ CPPUNIT_TEST(testLocalToGlobalPosition); CPPUNIT_TEST(testGlobalToLocalPosition); CPPUNIT_TEST(testLocalToGlobalOrientation); @@ -29,17 +26,19 @@ namespace vb01{ void testAdjustDir(); void testAdjustUp(); void testDetachChild(); - void testGetDescendants(); + void testGetAncestors(); void testLocalToGlobalPosition(); void testGlobalToLocalPosition(); void testLocalToGlobalOrientation(); void testGlobalToLocalOrientation(); Node *rootNode = nullptr, - *nodeA = nullptr, - *nodeB = nullptr, - *nodeC = nullptr, - *nodeD = nullptr, + *ancestorA = nullptr, + *ancestorB = nullptr, + *ancestorC = nullptr, + *ancestorD = nullptr, + *lookNodeParent = nullptr, + *lookNode = nullptr, *firstChainNode = nullptr, *secondChainNode = nullptr, *thirdChainNode = nullptr;