(glut)应用arcball原理实现鼠标左键控制物体旋转(2)

百度云:vs2008工程https://pan.baidu.com/s/1eTdx4J4密码sf9w

测试发现,还是NEHE的鼠标旋转物体效果好啊,但NEHE是在基于Windows 的程序框架下编写的,不少代码融入到了windows编程中,感觉比较混乱,所以就想提取出来,在基于控制台的框架下实现出来,在此框架下代码结构比较简单,便于以后再使用这些代码,也就是便于代码复用。

按住左键旋转三维图形


代码:

ArcBall.h

[cpp] view plain copy
  1. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////  
  2. ///////////////////////////////////////////////////ArcBall.h///////////////////////////////////////////////////////////  
  3. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////  
  4. #ifndef _ArcBall_h  
  5. #define _ArcBall_h  
  6.   
  7. #include <stdlib.h>  
  8.   
  9. // 仅在Debug模式下,启用断言  
  10. #ifdef _DEBUG  
  11. # include "assert.h"  
  12. #else  
  13. # define assert(x) { }  
  14. #endif  
  15.   
  16.   
  17. //2维点  
  18. typedef union Tuple2f_t  
  19. {  
  20.     struct  
  21.     {  
  22.         GLfloat X, Y;  
  23.     } s;  
  24.   
  25.     GLfloat T[2];  
  26. } Tuple2fT;      
  27.   
  28. //3维点  
  29. typedef union Tuple3f_t  
  30. {  
  31.     struct  
  32.     {  
  33.         GLfloat X, Y, Z;  
  34.     } s;  
  35.   
  36.     GLfloat T[3];  
  37. } Tuple3fT;       
  38.   
  39. //4维点  
  40. typedef union Tuple4f_t  
  41. {  
  42.     struct  
  43.     {  
  44.         GLfloat X, Y, Z, W;  
  45.     } s;  
  46.   
  47.     GLfloat T[4];  
  48. } Tuple4fT;       
  49.   
  50.   
  51. //3x3 矩阵  
  52. typedef union Matrix3f_t  
  53. {  
  54.     struct  
  55.     {  
  56.         //column major  
  57.         union { GLfloat M00; GLfloat XX; GLfloat SX; };   
  58.         union { GLfloat M10; GLfloat XY;             };   
  59.         union { GLfloat M20; GLfloat XZ;             };   
  60.         union { GLfloat M01; GLfloat YX;             };   
  61.         union { GLfloat M11; GLfloat YY; GLfloat SY; };   
  62.         union { GLfloat M21; GLfloat YZ;             };   
  63.         union { GLfloat M02; GLfloat ZX;             };   
  64.         union { GLfloat M12; GLfloat ZY;             };   
  65.         union { GLfloat M22; GLfloat ZZ; GLfloat SZ; };   
  66.     } s;  
  67.     GLfloat M[9];  
  68. } Matrix3fT;     
  69.   
  70. //4x4 矩阵  
  71. typedef union Matrix4f_t  
  72. {  
  73.     struct  
  74.     {  
  75.         //column major  
  76.         union { GLfloat M00; GLfloat XX; GLfloat SX; };   
  77.         union { GLfloat M10; GLfloat XY;             };   
  78.         union { GLfloat M20; GLfloat XZ;             };   
  79.         union { GLfloat M30; GLfloat XW;             };   
  80.         union { GLfloat M01; GLfloat YX;             };   
  81.         union { GLfloat M11; GLfloat YY; GLfloat SY; };   
  82.         union { GLfloat M21; GLfloat YZ;             };   
  83.         union { GLfloat M31; GLfloat YW;             };   
  84.         union { GLfloat M02; GLfloat ZX;             };   
  85.         union { GLfloat M12; GLfloat ZY;             };   
  86.         union { GLfloat M22; GLfloat ZZ; GLfloat SZ; };   
  87.         union { GLfloat M32; GLfloat ZW;             };   
  88.         union { GLfloat M03; GLfloat TX;             };   
  89.         union { GLfloat M13; GLfloat TY;             };   
  90.         union { GLfloat M23; GLfloat TZ;             };   
  91.         union { GLfloat M33; GLfloat TW; GLfloat SW; };   
  92.     } s;  
  93.     GLfloat M[16];  
  94. } Matrix4fT;     
  95.   
  96.   
  97. //定义类型的别名  
  98. #define Point2fT    Tuple2fT    
  99. #define Quat4fT     Tuple4fT    
  100. #define Vector2fT   Tuple2fT    
  101. #define Vector3fT   Tuple3fT    
  102. #define FuncSqrt    sqrtf  
  103. # define Epsilon 1.0e-5  
  104.   
  105. //2维点相加  
  106. inline  
  107. static void Point2fAdd(Point2fT* NewObj, const Tuple2fT* t1)  
  108. {  
  109.     assert(NewObj && t1);  
  110.   
  111.     NewObj->s.X += t1->s.X;  
  112.     NewObj->s.Y += t1->s.Y;  
  113. }  
  114.   
  115. //2 维点相减  
  116. inline  
  117. static void Point2fSub(Point2fT* NewObj, const Tuple2fT* t1)  
  118. {  
  119.     assert(NewObj && t1);  
  120.   
  121.     NewObj->s.X -= t1->s.X;  
  122.     NewObj->s.Y -= t1->s.Y;  
  123. }  
  124.   
  125. //3 维点矢积  
  126. inline  
  127. static void Vector3fCross(Vector3fT* NewObj, const Vector3fT* v1, const Vector3fT* v2)  
  128. {  
  129.     Vector3fT Result;  
  130.   
  131.     assert(NewObj && v1 && v2);  
  132.   
  133.     Result.s.X = (v1->s.Y * v2->s.Z) - (v1->s.Z * v2->s.Y);  
  134.     Result.s.Y = (v1->s.Z * v2->s.X) - (v1->s.X * v2->s.Z);  
  135.     Result.s.Z = (v1->s.X * v2->s.Y) - (v1->s.Y * v2->s.X);  
  136.   
  137.     *NewObj = Result;  
  138. }  
  139.   
  140. //3维点点积  
  141. inline  
  142. static GLfloat Vector3fDot(const Vector3fT* NewObj, const Vector3fT* v1)  
  143. {  
  144.     assert(NewObj && v1);  
  145.   
  146.     return  (NewObj->s.X * v1->s.X) +  
  147.         (NewObj->s.Y * v1->s.Y) +  
  148.         (NewObj->s.Z * v1->s.Z);  
  149. }  
  150.   
  151. //3维点的长度的平方  
  152. inline  
  153. static GLfloat Vector3fLengthSquared(const Vector3fT* NewObj)  
  154. {  
  155.     assert(NewObj);  
  156.   
  157.     return  (NewObj->s.X * NewObj->s.X) +  
  158.         (NewObj->s.Y * NewObj->s.Y) +  
  159.         (NewObj->s.Z * NewObj->s.Z);  
  160. }  
  161.   
  162. //3维点的长度  
  163. inline  
  164. static GLfloat Vector3fLength(const Vector3fT* NewObj)  
  165. {  
  166.     assert(NewObj);  
  167.   
  168.     return FuncSqrt(Vector3fLengthSquared(NewObj));  
  169. }  
  170.   
  171. //设置3x3矩阵为0 矩阵  
  172. inline  
  173. static void Matrix3fSetZero(Matrix3fT* NewObj)  
  174. {  
  175.     NewObj->s.M00 = NewObj->s.M01 = NewObj->s.M02 =  
  176.         NewObj->s.M10 = NewObj->s.M11 = NewObj->s.M12 =  
  177.         NewObj->s.M20 = NewObj->s.M21 = NewObj->s.M22 = 0.0f;  
  178. }  
  179.   
  180. // 设置4x4矩阵为0矩阵  
  181. inline  
  182. static void Matrix4fSetZero(Matrix4fT* NewObj)  
  183. {  
  184.     NewObj->s.M00 = NewObj->s.M01 = NewObj->s.M02 =  
  185.         NewObj->s.M10 = NewObj->s.M11 = NewObj->s.M12 =  
  186.         NewObj->s.M20 = NewObj->s.M21 = NewObj->s.M22 =  
  187.         NewObj->s.M30 = NewObj->s.M31 = NewObj->s.M32 = 0.0f;  
  188. }  
  189.   
  190. // 设置3x3矩阵为单位矩阵  
  191. inline  
  192. static void Matrix3fSetIdentity(Matrix3fT* NewObj)  
  193. {  
  194.     Matrix3fSetZero(NewObj);  
  195.   
  196.     NewObj->s.M00 =  
  197.         NewObj->s.M11 =  
  198.         NewObj->s.M22 = 1.0f;  
  199. }  
  200.   
  201. // 设置4x4矩阵为单位矩阵  
  202. inline  
  203. static void Matrix4fSetIdentity(Matrix4fT* NewObj)  
  204. {  
  205.     Matrix4fSetZero(NewObj);  
  206.   
  207.     NewObj->s.M00 = 1.0f;  
  208.     NewObj->s.M11 = 1.0f;  
  209.     NewObj->s.M22 = 1.0f;  
  210.     NewObj->s.M33=1.0f;  
  211. }  
  212.   
  213. //从四元数设置旋转矩阵  
  214. inline  
  215. static void Matrix3fSetRotationFromQuat4f(Matrix3fT* NewObj, const Quat4fT* q1)  
  216. {  
  217.     GLfloat n, s;  
  218.     GLfloat xs, ys, zs;  
  219.     GLfloat wx, wy, wz;  
  220.     GLfloat xx, xy, xz;  
  221.     GLfloat yy, yz, zz;  
  222.   
  223.     assert(NewObj && q1);  
  224.   
  225.     n = (q1->s.X * q1->s.X) + (q1->s.Y * q1->s.Y) + (q1->s.Z * q1->s.Z) + (q1->s.W * q1->s.W);  
  226.     s = (n > 0.0f) ? (2.0f / n) : 0.0f;  
  227.   
  228.     xs = q1->s.X * s;  ys = q1->s.Y * s;  zs = q1->s.Z * s;  
  229.     wx = q1->s.W * xs; wy = q1->s.W * ys; wz = q1->s.W * zs;  
  230.     xx = q1->s.X * xs; xy = q1->s.X * ys; xz = q1->s.X * zs;  
  231.     yy = q1->s.Y * ys; yz = q1->s.Y * zs; zz = q1->s.Z * zs;  
  232.   
  233.     NewObj->s.XX = 1.0f - (yy + zz); NewObj->s.YX =         xy - wz;  NewObj->s.ZX =         xz + wy;  
  234.     NewObj->s.XY =         xy + wz;  NewObj->s.YY = 1.0f - (xx + zz); NewObj->s.ZY =         yz - wx;  
  235.     NewObj->s.XZ =         xz - wy;  NewObj->s.YZ =         yz + wx;  NewObj->s.ZZ = 1.0f - (xx + yy);  
  236. }  
  237.   
  238. //3x3 矩阵相乘  
  239. inline  
  240. static void Matrix3fMulMatrix3f(Matrix3fT* NewObj, const Matrix3fT* m1)  
  241. {  
  242.     Matrix3fT Result;  
  243.   
  244.     assert(NewObj && m1);  
  245.   
  246.     Result.s.M00 = (NewObj->s.M00 * m1->s.M00) + (NewObj->s.M01 * m1->s.M10) + (NewObj->s.M02 * m1->s.M20);  
  247.     Result.s.M01 = (NewObj->s.M00 * m1->s.M01) + (NewObj->s.M01 * m1->s.M11) + (NewObj->s.M02 * m1->s.M21);  
  248.     Result.s.M02 = (NewObj->s.M00 * m1->s.M02) + (NewObj->s.M01 * m1->s.M12) + (NewObj->s.M02 * m1->s.M22);  
  249.   
  250.     Result.s.M10 = (NewObj->s.M10 * m1->s.M00) + (NewObj->s.M11 * m1->s.M10) + (NewObj->s.M12 * m1->s.M20);  
  251.     Result.s.M11 = (NewObj->s.M10 * m1->s.M01) + (NewObj->s.M11 * m1->s.M11) + (NewObj->s.M12 * m1->s.M21);  
  252.     Result.s.M12 = (NewObj->s.M10 * m1->s.M02) + (NewObj->s.M11 * m1->s.M12) + (NewObj->s.M12 * m1->s.M22);  
  253.   
  254.     Result.s.M20 = (NewObj->s.M20 * m1->s.M00) + (NewObj->s.M21 * m1->s.M10) + (NewObj->s.M22 * m1->s.M20);  
  255.     Result.s.M21 = (NewObj->s.M20 * m1->s.M01) + (NewObj->s.M21 * m1->s.M11) + (NewObj->s.M22 * m1->s.M21);  
  256.     Result.s.M22 = (NewObj->s.M20 * m1->s.M02) + (NewObj->s.M21 * m1->s.M12) + (NewObj->s.M22 * m1->s.M22);  
  257.   
  258.     *NewObj = Result;  
  259. }  
  260.   
  261. //4x4 矩阵相乘  
  262. inline  
  263. static void Matrix4fSetRotationScaleFromMatrix4f(Matrix4fT* NewObj, const Matrix4fT* m1)  
  264. {  
  265.     assert(NewObj && m1);  
  266.   
  267.     NewObj->s.XX = m1->s.XX; NewObj->s.YX = m1->s.YX; NewObj->s.ZX = m1->s.ZX;  
  268.     NewObj->s.XY = m1->s.XY; NewObj->s.YY = m1->s.YY; NewObj->s.ZY = m1->s.ZY;  
  269.     NewObj->s.XZ = m1->s.XZ; NewObj->s.YZ = m1->s.YZ; NewObj->s.ZZ = m1->s.ZZ;  
  270. }  
  271.   
  272. //进行矩阵的奇异值分解,旋转矩阵被保存到rot3和 rot4中,返回矩阵的缩放因子  
  273. inline  
  274. static GLfloat Matrix4fSVD(const Matrix4fT* NewObj, Matrix3fT* rot3, Matrix4fT* rot4)  
  275. {  
  276.     GLfloat s, n;  
  277.   
  278.     assert(NewObj);  
  279.   
  280.     s = FuncSqrt(  
  281.         ( (NewObj->s.XX * NewObj->s.XX) + (NewObj->s.XY * NewObj->s.XY) + (NewObj->s.XZ * NewObj->s.XZ) +  
  282.         (NewObj->s.YX * NewObj->s.YX) + (NewObj->s.YY * NewObj->s.YY) + (NewObj->s.YZ * NewObj->s.YZ) +  
  283.         (NewObj->s.ZX * NewObj->s.ZX) + (NewObj->s.ZY * NewObj->s.ZY) + (NewObj->s.ZZ * NewObj->s.ZZ) ) / 3.0f );  
  284.   
  285.     if (rot3)    
  286.     {  
  287.         rot3->s.XX = NewObj->s.XX; rot3->s.XY = NewObj->s.XY; rot3->s.XZ = NewObj->s.XZ;  
  288.         rot3->s.YX = NewObj->s.YX; rot3->s.YY = NewObj->s.YY; rot3->s.YZ = NewObj->s.YZ;  
  289.         rot3->s.ZX = NewObj->s.ZX; rot3->s.ZY = NewObj->s.ZY; rot3->s.ZZ = NewObj->s.ZZ;  
  290.   
  291.         n = 1.0f / FuncSqrt( (NewObj->s.XX * NewObj->s.XX) +  
  292.             (NewObj->s.XY * NewObj->s.XY) +  
  293.             (NewObj->s.XZ * NewObj->s.XZ) );  
  294.         rot3->s.XX *= n;  
  295.         rot3->s.XY *= n;  
  296.         rot3->s.XZ *= n;  
  297.   
  298.         n = 1.0f / FuncSqrt( (NewObj->s.YX * NewObj->s.YX) +  
  299.             (NewObj->s.YY * NewObj->s.YY) +  
  300.             (NewObj->s.YZ * NewObj->s.YZ) );  
  301.         rot3->s.YX *= n;  
  302.         rot3->s.YY *= n;  
  303.         rot3->s.YZ *= n;  
  304.   
  305.         n = 1.0f / FuncSqrt( (NewObj->s.ZX * NewObj->s.ZX) +  
  306.             (NewObj->s.ZY * NewObj->s.ZY) +  
  307.             (NewObj->s.ZZ * NewObj->s.ZZ) );  
  308.         rot3->s.ZX *= n;  
  309.         rot3->s.ZY *= n;  
  310.         rot3->s.ZZ *= n;  
  311.     }  
  312.   
  313.     if (rot4)   
  314.     {  
  315.         if (rot4 != NewObj)  
  316.         {  
  317.             Matrix4fSetRotationScaleFromMatrix4f(rot4, NewObj);  
  318.         }  
  319.   
  320.   
  321.         n = 1.0f / FuncSqrt( (NewObj->s.XX * NewObj->s.XX) +  
  322.             (NewObj->s.XY * NewObj->s.XY) +  
  323.             (NewObj->s.XZ * NewObj->s.XZ) );  
  324.         rot4->s.XX *= n;  
  325.         rot4->s.XY *= n;  
  326.         rot4->s.XZ *= n;  
  327.   
  328.         n = 1.0f / FuncSqrt( (NewObj->s.YX * NewObj->s.YX) +  
  329.             (NewObj->s.YY * NewObj->s.YY) +  
  330.             (NewObj->s.YZ * NewObj->s.YZ) );  
  331.         rot4->s.YX *= n;  
  332.         rot4->s.YY *= n;  
  333.         rot4->s.YZ *= n;  
  334.   
  335.         n = 1.0f / FuncSqrt( (NewObj->s.ZX * NewObj->s.ZX) +  
  336.             (NewObj->s.ZY * NewObj->s.ZY) +  
  337.             (NewObj->s.ZZ * NewObj->s.ZZ) );  
  338.         rot4->s.ZX *= n;  
  339.         rot4->s.ZY *= n;  
  340.         rot4->s.ZZ *= n;  
  341.     }  
  342.   
  343.     return s;  
  344. }  
  345.   
  346. //从3x3矩阵变为4x4的旋转矩阵  
  347. inline  
  348. static void Matrix4fSetRotationScaleFromMatrix3f(Matrix4fT* NewObj, const Matrix3fT* m1)  
  349. {  
  350.     assert(NewObj && m1);  
  351.   
  352.     NewObj->s.XX = m1->s.XX; NewObj->s.YX = m1->s.YX; NewObj->s.ZX = m1->s.ZX;  
  353.     NewObj->s.XY = m1->s.XY; NewObj->s.YY = m1->s.YY; NewObj->s.ZY = m1->s.ZY;  
  354.     NewObj->s.XZ = m1->s.XZ; NewObj->s.YZ = m1->s.YZ; NewObj->s.ZZ = m1->s.ZZ;  
  355. }  
  356.   
  357. //4x4矩阵的与标量的乘积  
  358. inline  
  359. static void Matrix4fMulRotationScale(Matrix4fT* NewObj, GLfloat scale)  
  360. {  
  361.     assert(NewObj);  
  362.   
  363.     NewObj->s.XX *= scale; NewObj->s.YX *= scale; NewObj->s.ZX *= scale;  
  364.     NewObj->s.XY *= scale; NewObj->s.YY *= scale; NewObj->s.ZY *= scale;  
  365.     NewObj->s.XZ *= scale; NewObj->s.YZ *= scale; NewObj->s.ZZ *= scale;  
  366. }  
  367.   
  368. //设置旋转矩阵  
  369. inline  
  370. static void Matrix4fSetRotationFromMatrix3f(Matrix4fT* NewObj, const Matrix3fT* m1)  
  371. {  
  372.     GLfloat scale;  
  373.   
  374.     assert(NewObj && m1);  
  375.   
  376.     scale = Matrix4fSVD(NewObj, NULL, NULL);  
  377.   
  378.     Matrix4fSetRotationScaleFromMatrix3f(NewObj, m1);  
  379.     Matrix4fMulRotationScale(NewObj, scale);  
  380. }  
  381.   
  382.   
  383.   
  384. typedef class ArcBall_t  
  385. {  
  386. protected:  
  387.     //把二维点映射到三维点  
  388.     inline  
  389.         void _mapToSphere(const Point2fT* NewPt, Vector3fT* NewVec) const;  
  390.   
  391. public:  
  392.     //构造/析构函数  
  393.     ArcBall_t(GLfloat NewWidth, GLfloat NewHeight);  
  394.     ~ArcBall_t() { };  
  395.   
  396.     //设置边界  
  397.     inline  
  398.     void    setBounds(GLfloat NewWidth, GLfloat NewHeight)  
  399.     {  
  400.         assert((NewWidth > 1.0f) && (NewHeight > 1.0f));  
  401.   
  402.         //设置长宽的调整因子  
  403.         this->AdjustWidth  = 1.0f / ((NewWidth  - 1.0f) * 0.5f);  
  404.         this->AdjustHeight = 1.0f / ((NewHeight - 1.0f) * 0.5f);  
  405.     }  
  406.   
  407.     //鼠标点击  
  408.     void    click(const Point2fT* NewPt);  
  409.   
  410.     //鼠标拖动计算旋转  
  411.     void    drag(const Point2fT* NewPt, Quat4fT* NewRot);  
  412.   
  413.     //更新鼠标状态  
  414.     void    upstate();  
  415.     //void    mousemove(WPARAM wParam,LPARAM lParam);  
  416.   
  417. protected:  
  418.     Vector3fT   StVec;          //保存鼠标点击的坐标  
  419.     Vector3fT   EnVec;          //保存鼠标拖动的坐标  
  420.     GLfloat     AdjustWidth;    //宽度的调整因子  
  421.     GLfloat     AdjustHeight;   //长度的调整因子  
  422. public:  
  423.     Matrix4fT   Transform;      //计算变换             
  424.     Matrix3fT   LastRot;        //上一次的旋转  
  425.     Matrix3fT   ThisRot;        //这次的旋转  
  426.     float zoomRate;  
  427.     float lastZoomRate;  
  428.   
  429.     bool        isDragging;     // 是否拖动  
  430.     bool        isRClicked;     // 是否右击鼠标  
  431.     bool        isClicked;      // 是否点击鼠标  
  432.     bool        isZooming;    //是否正在缩放  
  433.     Point2fT    LastPt;         
  434.     Point2fT    MousePt;        // 当前的鼠标位置  
  435.   
  436. } ArcBallT;  
  437.   
  438. #endif  
ArcBall.cpp

[cpp] view plain copy
  1. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////  
  2. ///////////////////////////////////////////////////ArcBall.cpp////////////////////////////////////////////////////////  
  3. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////  
  4. //#include <windows.h>                                 
  5. #include <glut.h>         
  6.   
  7. #include <math.h>                                     
  8. #include "ArcBall.h"                                  
  9.   
  10. //轨迹球参数:  
  11. //直径                    2.0f  
  12. //半径                    1.0f  
  13. //半径平方                1.0f  
  14.   
  15.   
  16. void ArcBall_t::_mapToSphere(const Point2fT* NewPt, Vector3fT* NewVec) const  
  17. {  
  18.     Point2fT TempPt;  
  19.     GLfloat length;  
  20.   
  21.     //复制到临时变量  
  22.     TempPt = *NewPt;  
  23.   
  24.     //把长宽调整到[-1 ... 1]区间  
  25.     TempPt.s.X  =        (TempPt.s.X * this->AdjustWidth)  - 1.0f;  
  26.     TempPt.s.Y  = 1.0f - (TempPt.s.Y * this->AdjustHeight);  
  27.   
  28.     //计算长度的平方  
  29.     length      = (TempPt.s.X * TempPt.s.X) + (TempPt.s.Y * TempPt.s.Y);  
  30.   
  31.     //如果点映射到球的外面  
  32.     if (length > 1.0f)  
  33.     {  
  34.         GLfloat norm;  
  35.   
  36.         //缩放到球上  
  37.         norm    = 1.0f / FuncSqrt(length);  
  38.   
  39.         //设置z坐标为0  
  40.         NewVec->s.X = TempPt.s.X * norm;  
  41.         NewVec->s.Y = TempPt.s.Y * norm;  
  42.         NewVec->s.Z = 0.0f;  
  43.     }  
  44.     //如果在球内  
  45.     else    
  46.     {  
  47.         //利用半径的平方为1,求出z坐标  
  48.         NewVec->s.X = TempPt.s.X;  
  49.         NewVec->s.Y = TempPt.s.Y;  
  50.         NewVec->s.Z = FuncSqrt(1.0f - length);  
  51.     }  
  52. }  
  53.   
  54. ArcBall_t::ArcBall_t(GLfloat NewWidth, GLfloat NewHeight)  
  55. {  
  56.     this->StVec.s.X     =0.0f;  
  57.     this->StVec.s.Y     = 0.0f;  
  58.     this->StVec.s.Z     = 0.0f;  
  59.   
  60.     this->EnVec.s.X     =0.0f;  
  61.     this->EnVec.s.Y     = 0.0f;  
  62.     this->EnVec.s.Z     = 0.0f;  
  63.   
  64.   
  65.     Matrix4fSetIdentity(&Transform);  
  66.     Matrix3fSetIdentity(&LastRot);  
  67.     Matrix3fSetIdentity(&ThisRot);  
  68.   
  69.     this->isDragging=false;  
  70.     this->isClicked= false;  
  71.     this->isRClicked = false;  
  72.     this->isZooming = false;  
  73.     this->zoomRate = 1;  
  74.     this->setBounds(NewWidth, NewHeight);  
  75. }  
  76.   
  77. //新加的  
  78. void ArcBall_t::upstate()  
  79. {  
  80.     if(!this->isZooming && this->isRClicked){                    // 开始拖动  
  81.         this->isZooming = true;                                        // 设置拖动为变量为true         
  82.         this->LastPt = this->MousePt;  
  83.         this->lastZoomRate = this->zoomRate;  
  84.     }  
  85.     else if(this->isZooming){//正在拖动  
  86.         if(this->isRClicked){                //拖动         
  87.             Point2fSub(&this->MousePt, &this->LastPt);  
  88.             this->zoomRate = this->lastZoomRate + this->MousePt.s.X * this->AdjustWidth * 2;  
  89.         }  
  90.         else{                                            //停止拖动  
  91.             this->isZooming = false;  
  92.         }  
  93.     }  
  94.     else if (!this->isDragging && this->isClicked){                                                // 如果没有拖动  
  95.         this->isDragging = true;                                        // 设置拖动为变量为true  
  96.         this->LastRot = this->ThisRot;                                         
  97.         this->click(&this->MousePt);                                 
  98.     }  
  99.     else if(this->isDragging){  
  100.         if (this->isClicked){                                            //如果按住拖动  
  101.             Quat4fT     ThisQuat;  
  102.   
  103.             this->drag(&this->MousePt, &ThisQuat);                        // 更新轨迹球的变量  
  104.             Matrix3fSetRotationFromQuat4f(&this->ThisRot, &ThisQuat);        // 计算旋转量  
  105.             Matrix3fMulMatrix3f(&this->ThisRot, &this->LastRot);                 
  106.             Matrix4fSetRotationFromMatrix3f(&this->Transform, &this->ThisRot);     
  107.         }  
  108.         else                                                        // 如果放开鼠标,设置拖动为false  
  109.             this->isDragging = false;  
  110.     }  
  111. }  
  112. /* 
  113. void ArcBall_t::mousemove(WPARAM wParam,LPARAM lParam) 
  114. { 
  115. this->MousePt.s.X = (GLfloat)LOWORD(lParam); 
  116. this->MousePt.s.Y = (GLfloat)HIWORD(lParam); 
  117. this->isClicked   = (LOWORD(wParam) & MK_LBUTTON) ? true : false; 
  118. this->isRClicked  = (LOWORD(wParam) & MK_RBUTTON) ? true : false; 
  119. } 
  120. */  
  121. //按下鼠标,记录当前对应的轨迹球的位置  
  122. void    ArcBall_t::click(const Point2fT* NewPt)  
  123. {  
  124.     this->_mapToSphere(NewPt, &this->StVec);  
  125. }  
  126.   
  127. //鼠标拖动,计算旋转四元数  
  128. void    ArcBall_t::drag(const Point2fT* NewPt, Quat4fT* NewRot)  
  129. {  
  130.     //新的位置  
  131.     this->_mapToSphere(NewPt, &this->EnVec);  
  132.   
  133.     //计算旋转  
  134.     if (NewRot)  
  135.     {  
  136.         Vector3fT  Perp;  
  137.   
  138.         //计算旋转轴  
  139.         Vector3fCross(&Perp, &this->StVec, &this->EnVec);  
  140.   
  141.         //如果不为0  
  142.         if (Vector3fLength(&Perp) > Epsilon)     
  143.         {  
  144.             //记录旋转轴  
  145.             NewRot->s.X = Perp.s.X;  
  146.             NewRot->s.Y = Perp.s.Y;  
  147.             NewRot->s.Z = Perp.s.Z;  
  148.             //在四元数中,w=cos(a/2),a为旋转的角度  
  149.             NewRot->s.W= Vector3fDot(&this->StVec, &this->EnVec);  
  150.         }  
  151.         //是0,说明没有旋转  
  152.         else                                  
  153.         {  
  154.             NewRot->s.X =  
  155.                 NewRot->s.Y =  
  156.                 NewRot->s.Z =  
  157.                 NewRot->s.W = 0.0f;  
  158.         }  
  159.     }  
  160. }  
main.cpp

#include <stdlib.h>
#include <glut.h>
#include <stdio.h>
#include "math.h"
#include "ArcBall.h"
// object
GLfloat vertices[] = {-1.0,-1.0,-1.0,1.0,-1.0,-1.0,
1.0,1.0,-1.0, -1.0,1.0,-1.0, -1.0,-1.0,1.0,
1.0,-1.0,1.0, 1.0,1.0,1.0, -1.0,1.0,1.0};
GLfloat colors[] = {0.0,0.0,0.0,1.0,0.0,0.0,
1.0,1.0,0.0, 0.0,1.0,0.0, 0.0,0.0,1.0,
1.0,0.0,1.0, 1.0,1.0,1.0, 0.0,1.0,1.0};
GLubyte cubeIndices[]={0,3,2,1,2,3,7,6,0,4,7,3,1,2,6,5,4,5,6,7,0,1,5,4};
// mouse control
Matrix4fT   Transform   = {  1.0f,  0.0f,  0.0f,  0.0f,                // NEW: Final Transform
0.0f,  1.0f,  0.0f,  0.0f,
0.0f,  0.0f,  1.0f,  0.0f,
0.0f,  0.0f,  0.0f,  1.0f };
Matrix3fT   LastRot     = {  1.0f,  0.0f,  0.0f,                    // NEW: Last Rotation
0.0f,  1.0f,  0.0f,
0.0f,  0.0f,  1.0f };
Matrix3fT   ThisRot     = {  1.0f,  0.0f,  0.0f,                    // NEW: This Rotation
0.0f,  1.0f,  0.0f,
0.0f,  0.0f,  1.0f };
ArcBallT    ArcBall(640.0f, 480.0f);                                // NEW: ArcBall Instance
Point2fT    MousePt;                                                // NEW: Current Mouse Point
bool        isClicked  = false;                                        // NEW: Clicking The Mouse?
bool        isDragging = false;                                        // NEW: Dragging The Mouse?

void display(void)
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();
	glPushMatrix();                                                    // NEW: Prepare Dynamic Transform
	glMultMatrixf(Transform.M);                                        // NEW: Apply Dynamic Transform
	glDrawElements(GL_QUADS, 24, GL_UNSIGNED_BYTE, cubeIndices);
	glPopMatrix();   
	glutSwapBuffers();
}
void mouse(int btn, int state, int x, int y)
{
	if(btn==GLUT_LEFT_BUTTON)
	{
		switch(state)
		{
		case GLUT_DOWN:           
			isClicked = true;
			printf_s("startmotion: x = %d, y = %d\n",x,y);
			break;
		case GLUT_UP:
			isClicked = false;
			isDragging = false;
			printf_s("stopmotion: x = %d, y = %d\n",x,y);
			break;
		}
	}
	if(btn==GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
	{
		Matrix3fSetIdentity(&LastRot);                                // Reset Rotation
		Matrix3fSetIdentity(&ThisRot);                                // Reset Rotation
		Matrix4fSetRotationFromMatrix3f(&Transform, &ThisRot);        // Reset Rotation
		glutPostRedisplay();
	}
}
void mouseMotion(int x, int y)
{
	MousePt.s.X = x;
	MousePt.s.Y = y;   
	if (!isDragging)                                                // Not Dragging
	{
		if (isClicked)                                                // First Click
		{
			isDragging = true;                                        // Prepare For Dragging
			LastRot = ThisRot;                                        // Set Last Static Rotation To Last Dynamic One           
			ArcBall.click(&MousePt);                                // Update Start Vector And Prepare For Dragging
		}
	}
	else
	{
		if (isClicked)                                                // Still Clicked, So Still Dragging
		{
			Quat4fT     ThisQuat;
			ArcBall.drag(&MousePt, &ThisQuat);                        // Update End Vector And Get Rotation As Quaternion
			Matrix3fSetRotationFromQuat4f(&ThisRot, &ThisQuat);        // Convert Quaternion Into Matrix3fT
			Matrix3fMulMatrix3f(&ThisRot, &LastRot);                // Accumulate Last Rotation Into This One
			Matrix4fSetRotationFromMatrix3f(&Transform, &ThisRot);    // Set Our Final Transform's Rotation From This One
		}
	}
	glutPostRedisplay();
}
void keyboard(unsigned char key, int x, int y)
{
	switch (key)
	{
	case 27: // VK_ESCAPE
		exit(0);
		break;
	}
}
void myReshape(int w, int h)
{
	glViewport(0, 0, w, h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	if (w <= h)
		glOrtho(-2.0, 2.0, -2.0 * (GLfloat) h / (GLfloat) w, 2.0 * (GLfloat) h / (GLfloat) w, -10.0, 10.0);
	else
		glOrtho(-2.0 * (GLfloat) w / (GLfloat) h, 2.0 * (GLfloat) w / (GLfloat) h, -2.0, 2.0, -10.0, 10.0);
	glMatrixMode(GL_MODELVIEW);
}
void main(int argc, char **argv)
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
	glutInitWindowSize(500, 500);
	glutCreateWindow("colorcube");
	glutReshapeFunc(myReshape);
	glutDisplayFunc(display);
	glutMouseFunc(mouse);
	glutMotionFunc(mouseMotion);
	glutKeyboardFunc(keyboard);
	glEnable(GL_DEPTH_TEST);
	glEnableClientState(GL_COLOR_ARRAY);
	glEnableClientState(GL_VERTEX_ARRAY);
	glVertexPointer(3, GL_FLOAT, 0, vertices);
	glColorPointer(3,GL_FLOAT, 0, colors);
	glClearColor(0.0,0.0,0.0,1.0);
	glColor3f(1.0,1.0,1.0);
	glutMainLoop();
}


展开阅读全文

没有更多推荐了,返回首页