ofVec3f GrainViewTransform(ofVec3f InPutPoint, ofVec3f Eye, ofVec3f Target, ofVec3f UpVec){ // Transform the cordinates of a point InPutPoint. For a camera placed at Eye and looking at target with Up vector UpVec ofMatrix4x4 ViewMat; ofVec3f zaxis(Target - Eye); zaxis.normalize(); ofVec3f xaxis = UpVec.getCrossed(zaxis); xaxis.normalize(); ofVec3f yaxis = zaxis.getCrossed(xaxis); // translate vect InPutPoint -= Eye; // project on each axis ofVec3f Outpos; Outpos.x = -xaxis.dot(InPutPoint); Outpos.y = -yaxis.dot(InPutPoint); Outpos.z = zaxis.dot(InPutPoint); return Outpos; }
//---------------------------------------- void ofNode::lookAt(const ofVec3f& lookAtPosition, ofVec3f upVector) { if(parent) upVector = upVector * ofMatrix4x4::getInverseOf(parent->getGlobalTransformMatrix()); ofVec3f zaxis = (getGlobalPosition() - lookAtPosition).normalized(); ofVec3f xaxis = upVector.getCrossed(zaxis).normalized(); ofVec3f yaxis = zaxis.getCrossed(xaxis); ofMatrix4x4 m; m._mat[0].set(xaxis.x, xaxis.y, xaxis.z, 0); m._mat[1].set(yaxis.x, yaxis.y, yaxis.z, 0); m._mat[2].set(zaxis.x, zaxis.y, zaxis.z, 0); setGlobalOrientation(m.getRotate()); }
void Creature::slerp(const ofVec3f& target, const ofVec3f& upVector) { ofVec3f zaxis = (getPosition() - target).normalized(); ofVec3f xaxis = upVector.getCrossed(zaxis).normalized(); ofVec3f yaxis = zaxis.getCrossed(xaxis); ofMatrix4x4 m; m._mat[0].set(xaxis.x, xaxis.y, xaxis.z, 0); m._mat[1].set(yaxis.x, yaxis.y, yaxis.z, 0); m._mat[2].set(zaxis.x, zaxis.y, zaxis.z, 0); ofQuaternion targetQuat = m.getRotate(); ofQuaternion currentQuat = getOrientationQuat(); currentQuat.slerp(0.1, currentQuat, targetQuat); setOrientation(currentQuat); }
// if axis1 and axis2 are not orthogonal, only axis1 will be preserved ofQuaternion makeRotate(const ofVec3f& axis1, const ofVec3f& axis2) { ofVec3f avg = (axis1 + axis2) / 2; ofVec3f z = axis1.getCrossed(axis2); ofVec3f x = axis1; ofVec3f y = z.getCrossed(x); ofMatrix4x4 mat; vector<ofVec3f> axes; axes.push_back(x.normalize()); axes.push_back(y.normalize()); axes.push_back(z.normalize()); for(int i = 0; i < 3; i++) { for(int j = 0; j < 3; j++) { mat(i, j) = axes[i][j]; } } return mat.getRotate(); }
// 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 ofQuaternion::makeRotate_original( const ofVec3f& from, const ofVec3f& to ) { const float epsilon = 0.0000001f; float length1 = from.length(); float length2 = to.length(); // dot product vec1*vec2 float cosangle = from.dot(to) / (length1 * length2); if ( fabs(cosangle - 1) < epsilon ) { //osg::notify(osg::INFO)<<"*** Quat::makeRotate(from,to) with near co-linear vectors, epsilon= "<<fabs(cosangle-1)<<std::endl; // cosangle is close to 1, so the vectors are close to being coincident // Need to generate an angle of zero with any vector we like // We'll choose (1,0,0) makeRotate( 0.0, 0.0, 0.0, 1.0 ); } else if ( fabs(cosangle + 1.0) < epsilon ) { // vectors are close to being opposite, so will need to find a // vector orthongonal to from to rotate about. ofVec3f tmp; if (fabs(from.x) < fabs(from.y)) if (fabs(from.x) < fabs(from.z)) tmp.set(1.0, 0.0, 0.0); // use x axis. else tmp.set(0.0, 0.0, 1.0); else if (fabs(from.y) < fabs(from.z)) tmp.set(0.0, 1.0, 0.0); else tmp.set(0.0, 0.0, 1.0); ofVec3f fromd(from.x, from.y, from.z); // find orthogonal axis. ofVec3f axis(fromd.getCrossed(tmp)); axis.normalize(); _v[0] = axis[0]; // sin of half angle of PI is 1.0. _v[1] = axis[1]; // sin of half angle of PI is 1.0. _v[2] = axis[2]; // sin of half angle of PI is 1.0. _v[3] = 0; // cos of half angle of PI is zero. } else { // This is the usual situation - take a cross-product of vec1 and vec2 // and that is the axis around which to rotate. ofVec3f axis(from.getCrossed(to)); float angle = acos( cosangle ); makeRotate( angle, axis ); } }