src/opengl/ArcBall.cpp

00001 
00018 /*************************************************************/
00019 
00020 #if __APPLE__
00021 #include <opengl/gl.h>
00022 #include <opengl/glu.h>
00023 #include <glut/glut.h>
00024 #else
00025 #include <GL/gl.h>                                                                                              // Header File For The OpenGL32 Library
00026 #include <GL/glu.h>                                                                                             // Header File For The GLu32 Library
00027 #include <stdio.h>
00028 #endif
00029 
00030 #include "math.h"                                               // Needed for sqrtf
00031 
00032 #include "ArcBall.h"                                            // ArcBall header
00033 
00034 //Arcball sphere constants:
00035 //Diameter is       2.0f
00036 //Radius is         1.0f
00037 //Radius squared is 1.0f
00038 
00039 void ArcBall_t::_mapToSphere(const Point2fT* NewPt, Vector3fT* NewVec) const
00040 {
00041     Point2fT TempPt;
00042     GLfloat length;
00043 
00044     //Copy paramter into temp point
00045     TempPt = *NewPt;
00046 
00047     //Adjust point coords and scale down to range of [-1 ... 1]
00048     TempPt.s.X  =        (TempPt.s.X * this->AdjustWidth)  - 1.0f;
00049     TempPt.s.Y  = 1.0f - (TempPt.s.Y * this->AdjustHeight);
00050 
00051     //Compute the square of the length of the vector to the point from the center
00052     length      = (TempPt.s.X * TempPt.s.X) + (TempPt.s.Y * TempPt.s.Y);
00053 
00054     //If the point is mapped outside of the sphere... (length > radius squared)
00055     if (length > 1.0f)
00056     {
00057         GLfloat norm;
00058 
00059         //Compute a normalizing factor (radius / sqrt(length))
00060         norm    = 1.0f / FuncSqrt(length);
00061 
00062         //Return the "normalized" vector, a point on the sphere
00063         NewVec->s.X = TempPt.s.X * norm;
00064         NewVec->s.Y = TempPt.s.Y * norm;
00065         NewVec->s.Z = 0.0f;
00066     }
00067     else    //Else it's on the inside
00068     {
00069         //Return a vector to a point mapped inside the sphere sqrt(radius squared - length)
00070         NewVec->s.X = TempPt.s.X;
00071         NewVec->s.Y = TempPt.s.Y;
00072         NewVec->s.Z = FuncSqrt(1.0f - length);
00073     }
00074 }
00075 
00076 //Create/Destroy
00077 ArcBall_t::ArcBall_t(GLfloat NewWidth, GLfloat NewHeight)
00078 {
00079     //Clear initial values
00080     this->StVec.s.X     =
00081     this->StVec.s.Y     = 
00082     this->StVec.s.Z     = 
00083 
00084     this->EnVec.s.X     =
00085     this->EnVec.s.Y     = 
00086     this->EnVec.s.Z     = 0.0f;
00087 
00088     //Set initial bounds
00089     this->setBounds(NewWidth, NewHeight);
00090 }
00091 
00092 //Mouse down
00093 void    ArcBall_t::click(const Point2fT* NewPt)
00094 {
00095     //Map the point to the sphere
00096     this->_mapToSphere(NewPt, &this->StVec);
00097 }
00098 
00099 //Mouse drag, calculate rotation
00100 void    ArcBall_t::drag(const Point2fT* NewPt, Quat4fT* NewRot)
00101 {
00102     //Map the point to the sphere
00103     this->_mapToSphere(NewPt, &this->EnVec);
00104 
00105     //Return the quaternion equivalent to the rotation
00106     if (NewRot)
00107     {
00108         Vector3fT  Perp;
00109 
00110         //Compute the vector perpendicular to the begin and end vectors
00111         Vector3fCross(&Perp, &this->StVec, &this->EnVec);
00112 
00113         //Compute the length of the perpendicular vector
00114         if (Vector3fLength(&Perp) > Epsilon)    //if its non-zero
00115         {
00116             //We're ok, so return the perpendicular vector as the transform after all
00117             NewRot->s.X = Perp.s.X;
00118             NewRot->s.Y = Perp.s.Y;
00119             NewRot->s.Z = Perp.s.Z;
00120             //In the quaternion values, w is cosine (theta / 2), where theta is rotation angle
00121             NewRot->s.W= Vector3fDot(&this->StVec, &this->EnVec);
00122         }
00123         else                                    //if its zero
00124         {
00125             //The begin and end vectors coincide, so return an identity transform
00126             NewRot->s.X = 
00127             NewRot->s.Y = 
00128             NewRot->s.Z = 
00129             NewRot->s.W = 0.0f;
00130         }
00131     }
00132 }
00133 

Generated on Wed Apr 11 16:50:50 2007 for open_prospect by  doxygen 1.4.6