From 355650ac1d311658aa274d5f279a3cbda6ac7f07 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Thu, 27 Jan 2005 14:39:58 +0000 Subject: [PATCH] From Nicolas Brodu, new faster osg::Quat::makeRotate(Vec3d,Vec3d) implmentation. From Robert Osfield, modes to osg::Quat to keep the original implmentation around as makeRotate_original(,) and added tests into osgunittest to test the new methods provide equivilant results to the original implemementation. The orignal implementation will be removed once the new method is more widely tested. --- examples/osgunittests/osgunittests.cpp | 27 ++++++++ include/osg/Quat | 2 + src/osg/Quat.cpp | 96 +++++++++++++++++++++++++- 3 files changed, 123 insertions(+), 2 deletions(-) diff --git a/examples/osgunittests/osgunittests.cpp b/examples/osgunittests/osgunittests.cpp index 0e0a80a6b..5640ebbe2 100644 --- a/examples/osgunittests/osgunittests.cpp +++ b/examples/osgunittests/osgunittests.cpp @@ -119,6 +119,21 @@ void sizeOfTest() } +void testQuatRotate(const osg::Vec3d& from, const osg::Vec3d& to) +{ + osg::Quat q_nicolas; + q_nicolas.makeRotate(from,to); + + osg::Quat q_original; + q_original.makeRotate_original(from,to); + + std::cout<<"osg::Quat::makeRotate("<0.6 for a normalized vector. + if (fabs(sourceVector.x()) < 0.6) { + const double norm = sqrt(1.0 - sourceVector.x() * sourceVector.x()); + _v[0] = 0.0; + _v[1] = sourceVector.z() / norm; + _v[2] = -sourceVector.y() / norm; + _v[3] = 0.0; + } else if (fabs(sourceVector.y()) < 0.6) { + const double norm = sqrt(1.0 - sourceVector.y() * sourceVector.y()); + _v[0] = -sourceVector.z() / norm; + _v[1] = 0.0; + _v[2] = sourceVector.x() / norm; + _v[3] = 0.0; + } else { + const double norm = sqrt(1.0 - sourceVector.z() * sourceVector.z()); + _v[0] = sourceVector.y() / norm; + _v[1] = -sourceVector.x() / norm; + _v[2] = 0.0; + _v[3] = 0.0; + } + } + + else { + // Find the shortest angle quaternion that transforms normalized vectors + // into one other. Formula is still valid when vectors are colinear + const double s = sqrt(0.5 * dotProdPlus1); + const Vec3d tmp = sourceVector ^ targetVector / (2.0*s); + _v[0] = tmp.x(); + _v[1] = tmp.y(); + _v[2] = tmp.z(); + _v[3] = s; + } +} + + // Make a rotation Quat which will rotate vec1 to vec2 // Generally take adot product to get the angle between these // and then use a cross product to get the rotation axis // Watch out for the two special cases of when the vectors // are co-incident or opposite in direction. -void Quat::makeRotate( const Vec3d& from, const Vec3d& to ) +void Quat::makeRotate_original( const Vec3d& from, const Vec3d& to ) { const value_type epsilon = 0.0000001; @@ -165,7 +258,6 @@ void Quat::makeRotate( const Vec3d& from, const Vec3d& to ) } } - void Quat::getRotate( value_type& angle, Vec3f& vec ) const { value_type x,y,z;