MF3DHelper.cpp
上传用户:qzpk666
上传日期:2022-08-04
资源大小:59k
文件大小:16k
源码类别:

对话框与窗口

开发平台:

Visual C++

  1. // MF3DHelper.cpp: implementation of the CMF3DHelper class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include <LIMITS.H>
  6. #include <FLOAT.H>
  7. #include "MF3DHelper.h"
  8. #ifdef _DEBUG
  9. #undef THIS_FILE
  10. static char THIS_FILE[]=__FILE__;
  11. #define new DEBUG_NEW
  12. #endif
  13. //using namespace NeHe;
  14. #ifndef PI
  15. const float PI = 3.1415927f;
  16. #define RAD(x) (x*PI/180.0f)
  17. #define DEG(x) (x*180.0f/PI)
  18. #define RAD2DEG(x)  (x*180.f/PI);
  19. #define DEG2RAD(x)  (x*PI / 180.0f);
  20. #endif
  21. //////////////////////////////////////////////////////////////////////
  22. // Construction/Destruction
  23. //////////////////////////////////////////////////////////////////////
  24. CMF3DHelper::CMF3DHelper()
  25. {
  26. m_mProjection.Id();
  27. m_fViewport_x = 0.0f;
  28. m_fViewport_y = 0.0f;
  29. m_fViewport_widht = 640.0f;
  30. m_fViewport_height = 480.0f;
  31. m_bShadowUpdateRequired = TRUE;
  32. }
  33. CMF3DHelper::~CMF3DHelper()
  34. {
  35. }
  36. float CMF3DHelper::cotangens(float x) {
  37. float s = (float)sin(RAD(x));
  38. float c = (float)cos(RAD(x));
  39. if(s!=0.0f) {
  40. return c/s;
  41. }
  42. return 0.0f;
  43. }
  44. void CMF3DHelper::emul_glLoadIdentity()
  45. {
  46. m_mProjection.Id();
  47. m_mModel.Id();
  48. }
  49. void CMF3DHelper::emul_glViewport(int x, int y, int widht, int height)
  50. {
  51. m_fViewport_x = (float)x;
  52. m_fViewport_y = (float)y;
  53. m_fViewport_widht = (float)widht;
  54. m_fViewport_height = (float)height;
  55. }
  56. void CMF3DHelper::Scale(float xFactor,float yFactor,float zFactor)
  57. {
  58. m_bShadowUpdateRequired = TRUE;
  59. emul_glScalef(xFactor, yFactor, zFactor);
  60. }
  61. void CMF3DHelper::emul_glScalef(float x, float y, float z)
  62. {
  63. #define M(x,y) m_mProjection.m[Idx(x,y)]
  64. M(0,0) *= x;   M(0,1) *= y;   M(0,2)  *= z;
  65. M(1,0) *= x;   M(1,1) *= y;   M(1,2)  *= z;
  66. M(2,0) *= x;   M(2,1) *= y;   M(2,2)  *= z;
  67. M(3,0) *= x;   M(3,1) *= y;   M(3,2)  *= z;
  68. #undef M
  69. }
  70. void CMF3DHelper::Translate(float x,float y,float z)
  71. {
  72. emul_glTranslatef(x,y,z);
  73. }
  74. void CMF3DHelper::emul_glTranslatef(float x, float y, float z)
  75. {
  76. #define M(x,y) m_mModel.m[Idx(x,y)]
  77. M(0,3) = M(0,0) * x + M(0,1) * y + M(0,2) * z + M(0,3);
  78. M(1,3) = M(1,0) * x + M(1,1) * y + M(1,2) * z + M(1,3);
  79. M(2,3) = M(2,0) * x + M(2,1) * y + M(2,2) * z + M(2,3);
  80. M(3,3) = M(3,0) * x + M(3,1) * y + M(3,2) * z + M(3,3);
  81. #undef M
  82. void CMF3DHelper::emul_glRotatef(float angle, float x, float y, float z)
  83. {
  84. NeHe::Matrix mR;
  85. float s, c;
  86. float xx, yy, zz, xy, yz, zx, xs, ys, zs, one_c;
  87. s = (float)sin(RAD(angle));
  88. c = (float)cos(RAD(angle));
  89. mR.Id();
  90. float mag = sqrtf(x*x + y*y + z*z);
  91. if (mag <= 1.0e-4) {
  92. /* no rotation, leave mat as-is */
  93. return;
  94. }
  95. x /= mag;
  96. y /= mag;
  97.     z /= mag; 
  98. xx = x * x;
  99. yy = y * y;
  100. zz = z * z;
  101. xy = x * y;
  102. yz = y * z;
  103. zx = z * x;
  104. xs = x * s;
  105. ys = y * s;
  106.     zs = z * s; 
  107. one_c = 1.0F - c; 
  108. #define M(x,y)  mR.m[Idx(x,y)]
  109. M(0,0) = (one_c * xx) + c;
  110. M(0,1) = (one_c * xy) - zs;
  111. M(0,2) = (one_c * zx) + ys;
  112. M(0,3) = 0.0f; 
  113. M(1,0) = (one_c * xy) + zs;
  114. M(1,1) = (one_c * yy) + c;
  115. M(1,2) = (one_c * yz) - xs;
  116. M(1,3) = 0.0f;
  117. M(2,0) = (one_c * zx) - ys;
  118. M(2,1) = (one_c * yz) + xs;
  119. M(2,2) = (one_c * zz) + c;
  120. M(2,3) = 0.0F;
  121. M(3,0) = 0.0F;
  122. M(3,1) = 0.0F;
  123. M(3,2) = 0.0F;
  124. M(3,3) = 1.0F;
  125. #undef M
  126. // IMPORTANT!!!
  127. // We need to perform multiplication in form R(otation)xP(erspective)(and not otherwise!!!)
  128. m_mRotation = mR;
  129. NeHe::Matrix mRotTemp = m_mModel;
  130. m_mModel  = mR * mRotTemp;
  131. }
  132. void CMF3DHelper::RotateVector(float fAngle,float fVectorX,float fVectorY, float fVectorZ, BOOL bAbsolute)
  133. {
  134. m_bShadowUpdateRequired = TRUE;
  135. if(bAbsolute==TRUE) {
  136. m_mModel.Id();
  137. }
  138. emul_glRotatef(fAngle, fVectorX, fVectorY, fVectorZ);
  139. return;
  140. }
  141. void CMF3DHelper::Rotate(float angleX,float angleY,float angleZ, BOOL bAbsolute)
  142. {
  143. m_bShadowUpdateRequired = TRUE;
  144. if(bAbsolute==TRUE) {
  145. m_mModel.Id();
  146. }
  147. emul_glRotatef(angleX, 1.0f,0.0f,0.0f);
  148. emul_glRotatef(angleY, 0.0f,1.0f,0.0f);
  149. emul_glRotatef(angleZ, 0.0f,0.0f,1.0f);
  150. m_cTrackBall.SetRotation(angleX, angleY, angleZ);
  151. return;
  152. }
  153. double calculateFov(double size, double distance)
  154. {
  155. const double PI = 3.1415926535;
  156.     double radtheta, degtheta; 
  157.     radtheta = 2.0 * atan2 (size/2.0, distance);
  158.     degtheta = (180.0 * radtheta) / PI;
  159.     return (degtheta);
  160. }
  161. double calculateZNear(double fov, double top, double bottom) 
  162. {
  163. double zNear = (top - bottom) /(2.0f*tan(RAD(fov) / 2.0f));
  164. return zNear;
  165. }
  166. BOOL CMF3DHelper::emul_gluPerspective(float fovy, float aspect, float zNear, float zFar)
  167. {
  168. const float PI = 3.1415f;
  169. if(aspect == 0.0f) {
  170. return FALSE;
  171. }
  172. if((zFar-zNear)==0.0f) {
  173. return FALSE;
  174. }
  175. NeHe::Matrix mT1, mT2;
  176. mT1.Zero();
  177. float f = cotangens(fovy / 2.0f);
  178. #define M(x,y) mT1.m[Idx(x,y)]
  179. M(0,0) = f / aspect;
  180. M(1,1) = f;
  181. M(2,2)= (zFar+zNear) / (zNear-zFar);
  182. M(2,3)= (2*zFar*zNear) / (zNear-zFar);
  183. M(3,2)= -1.0f;
  184. #undef M
  185. m_mProjection =mT1;
  186. return TRUE;
  187. }
  188. BOOL CMF3DHelper::setupPerspective(float fovy, float aspect, float zNear, float zFar)
  189. {
  190. // New should always be less than zFar
  191. if(zNear > zFar) {
  192. float t = zNear;
  193. zNear = zFar;
  194. zFar = zNear;
  195. }
  196. // Calculate bounding sphere
  197. float fDX, fDY, fDZ;
  198. fDX = m_vCubeMax.x - m_vCubeMin.x;
  199. fDY = m_vCubeMax.y - m_vCubeMin.y;
  200. fDZ = m_vCubeMax.z - m_vCubeMin.z;
  201. // Calculate maximal bounding sphere diameter
  202. float fDM = max(fDX, max(fDY, fDZ)) / 2.0f;
  203. float fOffset = 1.0f-zNear; // How much do we have to offset the position of zNear to start at position +1.0
  204. float zNearMod= 1.0f;
  205. float zFarMod = 0.0f;
  206. float zNearX= (float)calculateZNear((double)fovy, (double)m_vCubeMax.x, (double)m_vCubeMin.x);// Optimal zNear for cube (0,0,0/1,1,,1);
  207. float zNearY= (float)calculateZNear((double)fovy, (double)m_vCubeMax.y, (double)m_vCubeMin.y);
  208. zNearMod = max(zNearX, zNearY);
  209. zFarMod  = zNearMod + fDM;
  210. m_mModel.Id();
  211. if(FALSE == emul_gluPerspective(fovy, aspect, zNearMod, zFarMod)) {
  212. return FALSE;
  213. }
  214. // Force visibility of cube (e.g. -1,-1,-1/+1,+1,+1);
  215. float xCenter = (m_vCubeMin.x + m_vCubeMax.x) / 2.0f;
  216. float yCenter = (m_vCubeMin.y + m_vCubeMax.y) / 2.0f;
  217. float zCenter = (m_vCubeMin.z + m_vCubeMax.z) / 2.0f;
  218. float fTranslate = (float)zNearMod + fDM;//+ 1.0f; // cube is -1..1 so shift by e.g 1 unit
  219. NeHe::Matrix mTmp = m_mModel;
  220. m_mModel = m_mProjection;
  221. emul_glTranslatef(-xCenter, -yCenter, fTranslate);; // m_mProjection now holds translation also
  222. m_mProjection = m_mModel;
  223. m_mModel = mTmp;
  224. return TRUE;
  225. }
  226. BOOL CMF3DHelper::Initialize(CDC *pTargetDC, NeHe::Vector vMin, NeHe::Vector vMax, BOOL bSupportTrackBall)
  227. {
  228. try {
  229. if(pTargetDC==NULL) {
  230. return FALSE;
  231. }
  232. CRect rcDraw;
  233. pTargetDC->GetWindow()->GetClientRect(&rcDraw);
  234. if(rcDraw.IsRectEmpty() == TRUE) {
  235. return FALSE;
  236. }
  237. // Mark shadow matrix as "dirty"
  238. m_bShadowUpdateRequired = TRUE;
  239. m_fViewport_x = 0.0f;
  240. m_fViewport_y = 0.0f;
  241. m_fViewport_widht = (float)rcDraw.Width();
  242. m_fViewport_height = (float)rcDraw.Height();
  243. // Set up arc ball also!
  244. m_cTrackBall.Initialize(rcDraw.Width(), rcDraw.Height());
  245. emul_glViewport((int)m_fViewport_x, (int)m_fViewport_y, (int)m_fViewport_widht, (int)m_fViewport_height);
  246. NeHe::Vector vDelta = vMax - vMin;
  247. m_vCubeMin = vMin;
  248. m_vCubeMax = vMax;
  249. float fovy, aspect, zNear, zFar;
  250. fovy = 45.0f;
  251. aspect = (float)rcDraw.Width() / (float)rcDraw.Height();
  252. zNear = vMin.z;
  253. zFar  = vMax.z;
  254. setupPerspective(fovy, aspect, zNear, zFar);
  255. return TRUE;
  256. } catch(...) {
  257. return FALSE;
  258. }
  259. }
  260. BOOL CMF3DHelper::Reset(CDC *pTargetDC, NeHe::Vector vMin, NeHe::Vector vMax, BOOL bSupportTrackBall)
  261. {
  262. m_bShadowUpdateRequired = TRUE; // Matrix needs recalculation!
  263. return Initialize(pTargetDC, vMin, vMax, bSupportTrackBall);
  264. }
  265. void CMF3DHelper::UpdateTrackBall(CDC *pDC) {
  266. NeHe::Vector cRotDelta, cRot;
  267. if(TRUE == m_cTrackBall.Update(pDC, cRotDelta, cRot)) {
  268. Rotate(cRot.x, cRot.y, cRot.z, TRUE);
  269. }
  270. }
  271. NeHe::Vector CMF3DHelper::RenderPoint(NeHe::Vector v3DPoint) 
  272. {
  273. NeHe::Vector vR;
  274. v3DPoint.w = 1.0f; // Need to be homogeneous
  275. NeHe::Vector vR5;
  276. if(m_bShadowUpdateRequired == TRUE) {
  277. m_mShadow = m_mModel*m_mProjection;
  278. m_bShadowUpdateRequired = FALSE;
  279. }
  280. vR = m_mShadow*v3DPoint;
  281. float xk,yk;
  282. xk = (vR.x*0.5f / vR.w + 0.5f)*(float)m_fViewport_widht;
  283. yk = (vR.y*0.5f / vR.w + 0.5f)*(float)m_fViewport_height;
  284. vR.x = xk;
  285. vR.y = yk;
  286. return vR;
  287. }
  288. CString v3DString(float x, float y, float z) {
  289. CString szV;
  290. szV.Format(_T("(%.1f, %.1f, %.1f)"), x,y,z);
  291. return szV;
  292. }
  293. // Draw the cube given as min/max pair of data-range
  294. void CMF3DHelper::DrawVisibilityCube(CDC* pDC, BOOL bDrawAxes, BOOL bDrawBoundingCoordinates)
  295. {
  296. CPen cPen(PS_SOLID, 1, RGB(255,255,255));
  297. CPen cPenR(PS_DASH, 1, RGB(255,64,64));
  298. CPen cPenG(PS_DASH, 1, RGB(64,255,64));
  299. CPen cPenB(PS_DASH, 1, RGB(64,64,255));
  300. CPen *pOld = pDC->SelectObject(&cPen);
  301. float lx,ly,lz,rx,ry,rz,cx,cy,cz;
  302. #define L m_vCubeMin
  303. #define R m_vCubeMax
  304. lx = L.x;
  305. ly = L.y;
  306. lz = L.z;
  307. rx = R.x;
  308. ry = R.y;
  309. rz = R.z;
  310. cx = (lx+rx)/2.0f;
  311. cy = (ly+ry)/2.0f;
  312. cz = (lz+rz)/2.0f;
  313. NeHe::Vector v1(lx,ly,lz);//n,n,n);
  314. NeHe::Vector v2(rx,ly,lz);//p,n,n);
  315. NeHe::Vector v3(rx,ry,lz);//p,p,n);
  316. NeHe::Vector v4(lx,ry,lz);//n,p,n);
  317. NeHe::Vector v5(lx,ly,rz);//n,n,p);
  318. NeHe::Vector v6(rx,ly,rz);//p,n,p);
  319. NeHe::Vector v7(rx,ry,rz);//p,p,p);
  320. NeHe::Vector v8(lx,ry,rz);//n,p,p);
  321. NeHe::Vector vc1(cx,cy,cz);//c,c,c);
  322. NeHe::Vector vc2(rx,cy,cz);//p,c,c);
  323. NeHe::Vector vc3(cx,ry,cz);//c,p,c);
  324. NeHe::Vector vc4(cx,cy,rz);//c,c,p);
  325. CString szV1= v3DString(lx,ly,lz);
  326. CString szV2= v3DString(rx,ly,lz);
  327. CString szV3= v3DString(rx,ry,lz);
  328. CString szV4= v3DString(lx,ry,lz);
  329. CString szV5= v3DString(lx,ly,rz);
  330. CString szV6= v3DString(rx,ly,rz);
  331. CString szV7= v3DString(rx,ry,rz);
  332. CString szV8= v3DString(lx,ry,rz);
  333. NeHe::Vector o1, o2, o3, o4, o5, o6, o7, o8, c1,c2,c3, c4;
  334. o1 = RenderPoint(v1);
  335. o2 = RenderPoint(v2);
  336. o3 = RenderPoint(v3);
  337. o4 = RenderPoint(v4);
  338. o5 = RenderPoint(v5);
  339. o6 = RenderPoint(v6);
  340. o7 = RenderPoint(v7);
  341. o8 = RenderPoint(v8);
  342. c1 =RenderPoint(vc1);
  343. c2 =RenderPoint(vc2);
  344. c3 =RenderPoint(vc3);
  345. c4 =RenderPoint(vc4);
  346. // Draw front rectangle
  347. pDC->MoveTo((int)o1.x, (int)o1.y);
  348. pDC->LineTo((int)o2.x, (int)o2.y);
  349. pDC->LineTo((int)o3.x, (int)o3.y);
  350. pDC->LineTo((int)o4.x, (int)o4.y);
  351. pDC->LineTo((int)o1.x, (int)o1.y);
  352. // Draw connecing lines
  353. pDC->MoveTo((int)o1.x, (int)o1.y);
  354. pDC->LineTo((int)o5.x, (int)o5.y);
  355. pDC->MoveTo((int)o2.x, (int)o2.y);
  356. pDC->LineTo((int)o6.x, (int)o6.y);
  357. pDC->MoveTo((int)o3.x, (int)o3.y);
  358. pDC->LineTo((int)o7.x, (int)o7.y);
  359. pDC->MoveTo((int)o4.x, (int)o4.y);
  360. pDC->LineTo((int)o8.x, (int)o8.y);
  361. // Draw rear rectangle
  362. pDC->MoveTo((int)o5.x, (int)o5.y);
  363. pDC->LineTo((int)o6.x, (int)o6.y);
  364. pDC->LineTo((int)o7.x, (int)o7.y);
  365. pDC->LineTo((int)o8.x, (int)o8.y);
  366. pDC->LineTo((int)o5.x, (int)o5.y);
  367. int iBKModeOld = pDC->GetBkMode();
  368. COLORREF rgbTextOld = pDC->GetTextColor();
  369. pDC->SetBkMode(TRANSPARENT);
  370. // Draw the coordinate axes
  371. // x-axis
  372. if(bDrawAxes==TRUE) {
  373. pDC->SetTextColor(RGB(255,25,255));
  374. pDC->MoveTo((int)c1.x, (int)c1.y);
  375. pDC->SelectObject(&cPenR);
  376. pDC->LineTo((int)c2.x, (int)c2.y);
  377. pDC->TextOut((int)c2.x, (int)c2.y, _T("+X"));
  378. // y-Axis
  379. pDC->MoveTo((int)c1.x, (int)c1.y);
  380. pDC->SelectObject(&cPenG);
  381. pDC->LineTo((int)c3.x, (int)c3.y);
  382. pDC->TextOut((int)c3.x, (int)c3.y, _T("+Y"));
  383. // z-Axis
  384. pDC->MoveTo((int)c1.x, (int)c1.y);
  385. pDC->SelectObject(&cPenB);
  386. pDC->LineTo((int)c4.x, (int)c4.y);
  387. pDC->TextOut((int)c4.x, (int)c4.y, _T("+Z"));
  388. }
  389. if(bDrawBoundingCoordinates==TRUE) {
  390. pDC->SetTextColor(RGB(255,25,255));
  391. pDC->TextOut((int)o1.x, (int)o1.y, szV1);
  392. pDC->TextOut((int)o2.x, (int)o2.y, szV2);
  393. pDC->TextOut((int)o3.x, (int)o3.y, szV3);
  394. pDC->TextOut((int)o4.x, (int)o4.y, szV4);
  395. pDC->TextOut((int)o5.x, (int)o5.y, szV5);
  396. pDC->TextOut((int)o6.x, (int)o6.y, szV6);
  397. pDC->TextOut((int)o7.x, (int)o7.y, szV7);
  398. pDC->TextOut((int)o8.x, (int)o8.y, szV8);
  399. }
  400. pDC->SetBkMode(iBKModeOld);
  401. pDC->SetTextColor(rgbTextOld);
  402. // Finish!
  403. pDC->SelectObject(pOld);
  404. }
  405. NeHe::CMFArcBall::CMFArcBall()
  406. {
  407. m_cMousePoint = CPoint(0,0);
  408. m_bLButtonDown = FALSE;
  409. m_fXRotation = 0.0f;
  410. m_fYRotation = 0.0f;
  411. m_fZRotation = 0.0f;
  412. m_iWidth = 0;
  413. m_iHeight = 0;
  414. }
  415. NeHe::CMFArcBall::~CMFArcBall()
  416. {
  417. }
  418. BOOL NeHe::CMFArcBall::getMousePosition(BOOL &bLDown, BOOL &bLToggled, BOOL &bRDown, BOOL &bRToggled, int &xPos, int &yPos, CDC* pDC)
  419. {
  420. if(pDC==NULL) {
  421. return FALSE;
  422. }
  423. bLDown = bRDown = FALSE;
  424. xPos = yPos = 0;
  425. CPoint ptMouse;
  426. GetCursorPos(&ptMouse);
  427. pDC->GetWindow()->ScreenToClient(&ptMouse);
  428. xPos = ptMouse.x;
  429. yPos = ptMouse.y;
  430. SHORT lButton ,rButton;
  431. lButton = GetAsyncKeyState(VK_LBUTTON);
  432. rButton = GetAsyncKeyState(VK_RBUTTON);
  433. // BOOL bLToggled, bRToggled, bLDown, bRDown;
  434. bLDown = ((lButton & 0x8000) != 0);
  435. bLToggled = ((lButton & 0x0001) != 0);
  436. bRDown = ((rButton & 0x8000) != 0);
  437. bRToggled = ((rButton & 0x0001) != 0);
  438. return TRUE;
  439. }
  440. void NeHe::CMFArcBall::mouseToArc(CPoint cPt, float &fx, float &fy) 
  441. {
  442. #ifndef EPSILON
  443. #define EPSILON (1.0e-9)
  444. #endif
  445. int xPos = (cPt.x-m_iWidth/2);  // Position from center
  446. int yPos = (cPt.y-m_iHeight/2);
  447. float xb = (float)xPos / (float)(m_iWidth/2);
  448. float yh = (float)yPos / (float)(m_iHeight/2);
  449. if(xb<(-1.0f-EPSILON)) {
  450. fx = -180;
  451. } else  {
  452. if(xb > (1.0f-EPSILON)) {
  453. fx = 0;
  454. }else {
  455. fy = -DEG(acosf(xb));
  456. }
  457. }
  458. if(yh<(-1.0f-EPSILON)) {
  459. fy = 90.0f;
  460. } else  {
  461. if(yh > (1.0f-EPSILON)) {
  462. fy = -90.0f;
  463. }else {
  464. fx = -DEG(asinf(yh));
  465. }
  466. }
  467. }
  468. // Returns TRUE only if a rotation is needed
  469. BOOL NeHe::CMFArcBall::Update(CDC* pDC, NeHe::Vector &cRotationDelta, NeHe::Vector &cRotationCumulative)
  470. {
  471. if(pDC == NULL) {
  472. return FALSE;
  473. }
  474. int x, y;
  475. BOOL bLToggled, bRToggled, bLDown, bRDown;
  476.     getMousePosition(bLDown, bLToggled, bRDown, bRToggled, x, y, pDC);
  477. CRect rcScreen(0,0,m_iWidth, m_iHeight);
  478. CPoint point(x,y);
  479. // Mouse is outside the *usable* window
  480. if(FALSE == rcScreen.PtInRect(point)) {
  481. return FALSE;
  482. }
  483. if(bRDown==TRUE) {
  484. m_fXRotation = m_fYRotation = m_fZRotation = 0.0f;
  485. m_bLButtonDown = FALSE;
  486. m_cMousePoint = CPoint(0,0);
  487. cRotationDelta.Null();
  488. cRotationCumulative = NeHe::Vector(m_fXRotation, m_fYRotation, m_fZRotation, 0.0f);
  489. return TRUE;
  490. }
  491. if(bLDown==FALSE) { // Button up..
  492. m_bLButtonDown = FALSE;
  493. cRotationDelta.Null();
  494. // Remember global rotation
  495. cRotationCumulative = NeHe::Vector(m_fXRotation, m_fYRotation, m_fZRotation, 0.0f);
  496. m_cMousePoint = CPoint(0,0);
  497. return FALSE;
  498. } else { // Button down
  499. if(m_bLButtonDown==FALSE) { // Click
  500. // Button state has toggled
  501. // *Fresh* mouse down, start trackball
  502. m_bLButtonDown = TRUE;
  503. m_cMousePoint = point;
  504. // Stay at current rotation
  505. cRotationDelta.Null();
  506. cRotationCumulative = NeHe::Vector(m_fXRotation, m_fYRotation, m_fZRotation, 0.0f);
  507. return FALSE;
  508. } else {
  509. // Perform actions below
  510. // ** dragging **
  511. }
  512. }
  513. // Drag
  514. if(m_cMousePoint == point) {
  515. return FALSE;
  516. }
  517. SHORT sCTRL = ::GetAsyncKeyState(VK_CONTROL);
  518. BOOL bCTRLDown = ((sCTRL & 0x8000) != 0);
  519. bCTRLDown = FALSE;
  520. // Dragging state
  521. cRotationDelta.Null();
  522. float xRot, yRot, zRot;
  523. xRot = yRot = zRot = 0.0f;
  524. xRot = (float)(point.y-m_cMousePoint.y)/m_fYDiv;
  525. if(bCTRLDown==FALSE) {
  526. yRot = (float)(point.x-m_cMousePoint.x)/m_fXDiv;
  527. } else {
  528. zRot = (float)(point.x-m_cMousePoint.x)/m_fXDiv;
  529. }
  530. m_fXRotation -= xRot; 
  531. m_fYRotation += yRot; 
  532. m_fZRotation -= zRot; 
  533. // Limit result to 360 degree
  534. m_fXRotation = fmodf(m_fXRotation, 360.0f);
  535. m_fYRotation = fmodf(m_fYRotation, 360.0f);
  536. m_fZRotation = fmodf(m_fZRotation, 360.0f);
  537. cRotationCumulative = NeHe::Vector(m_fXRotation, m_fYRotation, m_fZRotation, 0.0f);
  538. cRotationDelta = NeHe::Vector(xRot, yRot, zRot, 0.0f);
  539. m_cMousePoint = point;
  540. return TRUE;
  541. }