00001 
00018 
00019 
00020 #include <windows.h>                                                                                    
00021 #include <gl\gl.h>                                                                                              
00022 #include <gl\glu.h>                                                                                             
00023 #include <gl\glaux.h>                                                                                   
00024 
00025 #include "math.h"                                               
00026 
00027 #include "ArcBall.h"                                            
00028 
00029 
00030 
00031 
00032 
00033 
00034 void ArcBall_t::_mapToSphere(const Point2fT* NewPt, Vector3fT* NewVec) const
00035 {
00036     Point2fT TempPt;
00037     GLfloat length;
00038 
00039     
00040     TempPt = *NewPt;
00041 
00042     
00043     TempPt.s.X  =        (TempPt.s.X * this->AdjustWidth)  - 1.0f;
00044     TempPt.s.Y  = 1.0f - (TempPt.s.Y * this->AdjustHeight);
00045 
00046     
00047     length      = (TempPt.s.X * TempPt.s.X) + (TempPt.s.Y * TempPt.s.Y);
00048 
00049     
00050     if (length > 1.0f)
00051     {
00052         GLfloat norm;
00053 
00054         
00055         norm    = 1.0f / FuncSqrt(length);
00056 
00057         
00058         NewVec->s.X = TempPt.s.X * norm;
00059         NewVec->s.Y = TempPt.s.Y * norm;
00060         NewVec->s.Z = 0.0f;
00061     }
00062     else    
00063     {
00064         
00065         NewVec->s.X = TempPt.s.X;
00066         NewVec->s.Y = TempPt.s.Y;
00067         NewVec->s.Z = FuncSqrt(1.0f - length);
00068     }
00069 }
00070 
00071 
00072 ArcBall_t::ArcBall_t(GLfloat NewWidth, GLfloat NewHeight)
00073 {
00074     
00075     this->StVec.s.X     =
00076     this->StVec.s.Y     = 
00077     this->StVec.s.Z     = 
00078 
00079     this->EnVec.s.X     =
00080     this->EnVec.s.Y     = 
00081     this->EnVec.s.Z     = 0.0f;
00082 
00083     
00084     this->setBounds(NewWidth, NewHeight);
00085 }
00086 
00087 
00088 void    ArcBall_t::click(const Point2fT* NewPt)
00089 {
00090     
00091     this->_mapToSphere(NewPt, &this->StVec);
00092 }
00093 
00094 
00095 void    ArcBall_t::drag(const Point2fT* NewPt, Quat4fT* NewRot)
00096 {
00097     
00098     this->_mapToSphere(NewPt, &this->EnVec);
00099 
00100     
00101     if (NewRot)
00102     {
00103         Vector3fT  Perp;
00104 
00105         
00106         Vector3fCross(&Perp, &this->StVec, &this->EnVec);
00107 
00108         
00109         if (Vector3fLength(&Perp) > Epsilon)    
00110         {
00111             
00112             NewRot->s.X = Perp.s.X;
00113             NewRot->s.Y = Perp.s.Y;
00114             NewRot->s.Z = Perp.s.Z;
00115             
00116             NewRot->s.W= Vector3fDot(&this->StVec, &this->EnVec);
00117         }
00118         else                                    
00119         {
00120             
00121             NewRot->s.X = 
00122             NewRot->s.Y = 
00123             NewRot->s.Z = 
00124             NewRot->s.W = 0.0f;
00125         }
00126     }
00127 }
00128