c_viewpt.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923
  1. // c_viewpt.cpp
  2. // A dialog box to allow adjustment of the viewpoint for
  3. // graphics objects. Implemented as a regular window rather
  4. // than as a special dialog box since I want almost all of my
  5. // "controls" to be custom-drawn, and the usual dialog box stuff
  6. // does not seem to help very much.
  7. //
  8. // Copyright (C)/©/¸ Codemist Ltd, 1995-96
  9. /* Signature: 61b86258 08-Jan-1996 */
  10. #ifdef GRAPHICS_WINDOW
  11. #include "cwin.hpp"
  12. // What follows is my default transformation matrix. It is pretty
  13. // arbitrarily chosen & I may want to change it later. I collected the numbers
  14. // by viewing a simple object, selecting a pretty view & dumping the
  15. // transformation matrix I had built.
  16. fourByFour stdView =
  17. {
  18. {0.906307792530088, -0.109381667816302, 0.408217878032017, 0.0},
  19. {0.422618249959983, 0.234569751569506, -0.875426094224625, 0.0},
  20. {0.0, 0.965925816196225, 0.258819082769520, 0.0},
  21. {0.0, 0.0, 0.0, 1.0/700.0}
  22. };
  23. CViewpointWindow::CViewpointWindow()
  24. {
  25. activeButton = NULL;
  26. mouseDrag = 0;
  27. moveObject = 1;
  28. for (int i=0; i<60; i++) buttonPressed[i] = 0;
  29. // I will create my dialog window at a size that increases somewhat as the
  30. // selected screen resolution does, on the hypothesis that people who use high
  31. // resolutions will have physically large monitors and that this will then
  32. // keep the displayed size of the box very roughly constant across systems.
  33. // It will also mean that at higher resolutions the controls have more pixels
  34. // in them so should be clearer and the box as a whole remains big enough
  35. // to see, while with low resolution displays it doe snot take over quite
  36. // all of the screen.
  37. int screenWidth = ::GetSystemMetrics(SM_CXSCREEN);
  38. dlgWidth = 280;
  39. if (screenWidth > 640) dlgWidth = 320;
  40. if (screenWidth > 800) dlgWidth = 360;
  41. if (screenWidth > 1024) dlgWidth = 400;
  42. dlgHeight = (3*dlgWidth)/4;
  43. click = dlgWidth/40;
  44. setArcPoints();
  45. // I will always start with the control box in the top right hand of the
  46. // screen.
  47. CreateEx(0, "AfxWnd", "Graphics Viewpoint",
  48. WS_POPUP | WS_DLGFRAME | WS_OVERLAPPED,
  49. screenWidth-dlgWidth-10, 10, dlgWidth, dlgHeight,
  50. NULL, NULL);
  51. int fontSize = -((dlgWidth+15)/30);
  52. labelFont.CreateFont(fontSize, 0,
  53. 0, 0,
  54. FW_NORMAL, 0, 0, 0, ANSI_CHARSET,
  55. OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  56. DEFAULT_QUALITY, DEFAULT_PITCH+FF_DONTCARE,
  57. "Arial");
  58. fontSize = -((dlgWidth+10)/20);
  59. titleFont.CreateFont(fontSize, 0,
  60. 0, 0,
  61. FW_BOLD, 0, 0, 0, ANSI_CHARSET,
  62. OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  63. DEFAULT_QUALITY, DEFAULT_PITCH+FF_DONTCARE,
  64. "Arial");
  65. memcpy((void *)view1, (void *)stdView, sizeof(stdView));
  66. memcpy((void *)view2, (void *)stdView, sizeof(stdView));
  67. undoCount = undoPoint = 0;
  68. }
  69. virtual CViewpointWindow::~CViewpointWindow()
  70. {
  71. }
  72. BEGIN_MESSAGE_MAP(CViewpointWindow, CWnd)
  73. ON_WM_SETFOCUS()
  74. // ON_WM_KILLFOCUS()
  75. ON_WM_ERASEBKGND()
  76. ON_WM_PAINT()
  77. // ON_WM_CHAR()
  78. // ON_WM_KEYDOWN()
  79. ON_WM_LBUTTONDOWN()
  80. ON_WM_LBUTTONUP()
  81. ON_WM_MOUSEMOVE()
  82. ON_WM_LBUTTONDBLCLK()
  83. END_MESSAGE_MAP()
  84. // Now message handlers
  85. BOOL CViewpointWindow::OnEraseBkgnd(CDC *dc)
  86. {
  87. CBrush backgroundBrush(RGB(255,255,128));
  88. CBrush *oldBrush = dc->SelectObject(&backgroundBrush);
  89. dc->Rectangle(0, 0, dlgWidth, dlgHeight);
  90. dc->SelectObject(oldBrush);
  91. return TRUE;
  92. }
  93. void CViewpointWindow::LText(CDC *dc, int x1, int y, char *s)
  94. {
  95. int n = strlen(s);
  96. dc->TextOut(x1, y, s, n);
  97. }
  98. void CViewpointWindow::CText(CDC *dc, int x1, int x2, int y, char *s)
  99. {
  100. int n = strlen(s);
  101. CSize w = dc->GetTextExtent(s, n);
  102. int slack = (x2 - x1) - w.cx;
  103. dc->TextOut(x1+slack/2, y, s, n);
  104. }
  105. void CViewpointWindow::RText(CDC *dc, int x2, int y, char *s)
  106. {
  107. int n = strlen(s);
  108. CSize w = dc->GetTextExtent(s, n);
  109. dc->TextOut(x2-w.cx, y, s, n);
  110. }
  111. #define B_MID 0
  112. #define B_UP 1
  113. #define B_DOWN 2
  114. #define B_LEFT 3
  115. #define B_RIGHT 4
  116. #define B_RADIO 5
  117. #define B_CLOSE 6
  118. #define B_TEXT 7
  119. #define B_TWIST 8
  120. const ButtonPlace buttonLocations[] =
  121. {
  122. #define mobjC 0
  123. { mobjC, 14, 8, 2, B_RADIO, NULL}, // What moves - eye or object?
  124. #define meyeC 1
  125. { meyeC, 14, 6, 2, B_RADIO, NULL}, // (Radio buttons come first in this list)
  126. #define far3C 2
  127. { far3C, 2, 28, 2, B_LEFT, NULL}, // The perspective FAR/NEAR arrows
  128. #define far2C 3
  129. { far2C, 4, 28, 2, B_LEFT, NULL},
  130. #define far1C 4
  131. { far1C, 6, 28, 2, B_LEFT, NULL},
  132. #define far0C 5
  133. { far0C, 8, 28, 2, B_MID, NULL},
  134. #define near1C 6
  135. { near1C, 10, 28, 2, B_RIGHT, NULL},
  136. #define near2C 7
  137. { near2C, 12, 28, 2, B_RIGHT, NULL},
  138. #define near3C 8
  139. { near3C, 14, 28, 2, B_RIGHT, NULL},
  140. #define smal3C 9
  141. { smal3C, 2, 22, 2, B_LEFT, NULL}, // The image size SMALL/LARGE arrows
  142. #define smal2C 10
  143. {smal2C, 4, 22, 2, B_LEFT, NULL},
  144. #define smal1C 11
  145. {smal1C, 6, 22, 2, B_LEFT, NULL},
  146. #define big0C 12
  147. {big0C, 8, 22, 2, B_MID, NULL},
  148. #define big1C 13
  149. {big1C, 10, 22, 2, B_RIGHT, NULL},
  150. #define big2C 14
  151. {big2C, 12, 22, 2, B_RIGHT, NULL},
  152. #define big3C 15
  153. {big3C, 14, 22, 2, B_RIGHT, NULL},
  154. #define left3C 16
  155. {left3C, 2, 12, 2, B_LEFT, NULL}, // The image position LEFT/RIGHT arrows
  156. #define left2C 17
  157. {left2C, 4, 12, 2, B_LEFT, NULL},
  158. #define left1C 18
  159. {left1C, 6, 12, 2, B_LEFT, NULL},
  160. #define midC 19
  161. {midC, 8, 12, 2, B_MID, NULL},
  162. #define right1C 20
  163. {right1C, 10, 12, 2, B_RIGHT, NULL},
  164. #define right2C 21
  165. {right2C, 12, 12, 2, B_RIGHT, NULL},
  166. #define right3C 22
  167. {right3C, 14, 12, 2, B_RIGHT, NULL},
  168. #define down3C 23
  169. {down3C, 8, 18, 2, B_DOWN, NULL}, // The image position UP/DOWN arrows
  170. #define down2C 24
  171. {down2C, 8, 16, 2, B_DOWN, NULL},
  172. #define down1C 25
  173. {down1C, 8, 14, 2, B_DOWN, NULL},
  174. #define up1C 26
  175. {up1C, 8, 10, 2, B_UP, NULL},
  176. #define up2C 27
  177. {up2C, 8, 8, 2, B_UP, NULL},
  178. #define up3C 28
  179. {up3C, 8, 6, 2, B_UP, NULL},
  180. #define rleft3C 29
  181. {rleft3C, 24, 12, 2, B_LEFT, NULL}, // The rotation turntable-rotate arrows
  182. #define rleft2C 30
  183. {rleft2C, 26, 12, 2, B_LEFT, NULL},
  184. #define rleft1C 31
  185. {rleft1C, 28, 12, 2, B_LEFT, NULL},
  186. #define backC 32
  187. {backC, 30, 12, 2, B_MID, NULL},
  188. #define rrt1C 33
  189. {rrt1C, 32, 12, 2, B_RIGHT, NULL},
  190. #define rrt2C 34
  191. {rrt2C, 34, 12, 2, B_RIGHT, NULL},
  192. #define rrt3C 35
  193. {rrt3C, 36, 12, 2, B_RIGHT, NULL},
  194. #define rdown3C 36
  195. {rdown3C, 30, 18, 2, B_DOWN, NULL}, // Rotation roll forwards/backwards arrows
  196. #define rdown2C 37
  197. {rdown2C, 30, 16, 2, B_DOWN, NULL},
  198. #define rdown1C 38
  199. {rdown1C, 30, 14, 2, B_DOWN, NULL},
  200. #define rup1C 39
  201. {rup1C, 30, 10, 2, B_UP, NULL},
  202. #define rup2C 40
  203. {rup2C, 30, 8, 2, B_UP, NULL},
  204. #define rup3C 41
  205. {rup3C, 30, 6, 2, B_UP, NULL},
  206. #define closeC 42
  207. {closeC, 38, 1, 1, B_CLOSE, NULL},
  208. #define showC 43
  209. {showC, 18, 14, 4, B_TEXT, "show"},
  210. #define undoC 44
  211. {undoC, 18, 18, 4, B_TEXT, "undo"},
  212. #define stdC 45
  213. {stdC, 19, 25, 3, B_TEXT, "Std"},
  214. #define XC 46
  215. {XC, 19, 28, 3, B_TEXT, "X"},
  216. #define YC 47
  217. {YC, 24, 25, 3, B_TEXT, "Y"},
  218. #define ZC 48
  219. {ZC, 24, 28, 3, B_TEXT, "Z"},
  220. #define V1C 49
  221. {V1C, 29, 25, 3, B_TEXT, "V1"},
  222. #define V2C 50
  223. {V2C, 29, 28, 3, B_TEXT, "V2"},
  224. #define SV1C 51
  225. {SV1C, 34, 25, 4, B_TEXT, "set V1"},
  226. #define SV2C 52
  227. {SV2C, 34, 28, 4, B_TEXT, "set V2"},
  228. #define twl3C 53
  229. {twl3C, 1, 0, 0, B_TWIST, NULL},
  230. #define twl2C 54
  231. {twl2C, 1, 1, 0, B_TWIST, NULL},
  232. #define twl1C 55
  233. {twl1C, 1, 2, 0, B_TWIST, NULL},
  234. #define twl0C 56
  235. {twl0C, 1, 3, 0, B_TWIST, NULL},
  236. #define twr1C 57
  237. {twr1C, 1, 4, 0, B_TWIST, NULL},
  238. #define twr2C 58
  239. {twr2C, 1, 5, 0, B_TWIST, NULL},
  240. #define twr3C 59
  241. {twr3C, 1, 6, 0, B_TWIST, NULL},
  242. { 0, 0, 0, 0, 0, NULL}
  243. };
  244. #define X 255
  245. typedef unsigned char two_bytes[2];
  246. typedef two_bytes seven_points[7];
  247. const seven_points buttonShapes[] =
  248. {
  249. {{2,2}, {2,4}, {4,4}, {4,2}, {X,0}, {0,0}, {0,0}}, // mid
  250. {{0,3}, {3,6}, {6,3}, {3,0}, {X,0}, {0,0}, {0,0}}, // mid selected
  251. {{1,1}, {5,1}, {3,5}, {X,0}, {0,0}, {0,0}, {0,0}}, // up
  252. {{2,1}, {2,3}, {1,3}, {3,5}, {5,3}, {4,3}, {4,1}}, // up selected
  253. {{3,1}, {1,5}, {5,5}, {X,0}, {0,0}, {0,0}, {0,0}}, // down
  254. {{3,0}, {5,3}, {4,3}, {4,5}, {2,5}, {2,3}, {1,3}}, // down selected
  255. {{1,3}, {5,1}, {5,5}, {X,0}, {0,0}, {0,0}, {0,0}}, // left
  256. {{0,3}, {3,5}, {3,4}, {5,4}, {5,2}, {3,2}, {3,1}}, // left selected
  257. {{1,1}, {1,5}, {5,3}, {X,0}, {0,0}, {0,0}, {0,0}}, // right
  258. {{1,2}, {1,4}, {3,4}, {3,5}, {5,3}, {3,1}, {3,2}} // right selected
  259. };
  260. CPoint innerArc[8], outerArc[8];
  261. CRect innerRect, outerRect;
  262. CRgn arcRegions[7];
  263. void CViewpointWindow::DrawButton(CDC *dc, const ButtonPlace *pb)
  264. {
  265. const two_bytes *p;
  266. int i;
  267. POINT pp[8];
  268. CRect r;
  269. CPen darkGrayPen(PS_SOLID, 0, RGB(128, 128, 128));
  270. int xx = click*pb->x, yy = click*pb->y;
  271. int width = click*pb->width;
  272. int flavour = 2*pb->flavour + buttonPressed[pb->id];
  273. switch (flavour)
  274. {
  275. default:
  276. p = buttonShapes[flavour];
  277. dc->SelectStockObject(BLACK_PEN);
  278. dc->MoveTo(xx, yy);
  279. dc->LineTo(xx+2*click, yy);
  280. dc->LineTo(xx+2*click, yy-2*click);
  281. dc->MoveTo(xx, yy);
  282. dc->LineTo(xx, yy-2*click);
  283. dc->LineTo(xx+2*click, yy-2*click);
  284. dc->SelectStockObject(NULL_PEN);
  285. for (i=0; i<7 && p[i][0] != X; i++)
  286. { int dx = p[i][0], dy = p[i][1];
  287. if (dx < 3) dx = dx*3;
  288. else if (dx > 3) dx = 2*click-(6-dx)*3;
  289. else dx = click;
  290. if (dy < 3) dy = dy*3;
  291. else if (dy > 3) dy = 2*click-(6-dy)*3;
  292. else dy = click;
  293. pp[i].x = xx + dx;
  294. pp[i].y = yy - dy;
  295. }
  296. dc->SelectStockObject(BLACK_BRUSH);
  297. dc->Polygon(pp, i);
  298. return;
  299. case 2*B_CLOSE+1:
  300. dc->SelectStockObject(GRAY_BRUSH);
  301. dc->Rectangle(xx, yy-click, xx+click+2, yy+2);
  302. case 2*B_CLOSE:
  303. dc->SelectStockObject(BLACK_PEN);
  304. dc->MoveTo(xx, yy);
  305. dc->LineTo(xx+click, yy);
  306. dc->LineTo(xx, yy-click);
  307. dc->LineTo(xx, yy);
  308. dc->LineTo(xx+click, yy-click);
  309. dc->MoveTo(xx, yy-click);
  310. dc->LineTo(xx+click, yy-click);
  311. dc->LineTo(xx+click, yy);
  312. return;
  313. case 2*B_TWIST+1:
  314. dc->SelectStockObject(GRAY_BRUSH);
  315. case 2*B_TWIST:
  316. i = pb->y;
  317. pp[0] = innerArc[i];
  318. pp[1] = innerArc[i+1];
  319. pp[2] = outerArc[i];
  320. dc->Polygon(pp, 3);
  321. pp[0] = innerArc[i+1];
  322. pp[1] = outerArc[i];
  323. pp[2] = outerArc[i+1];
  324. dc->Polygon(pp, 3);
  325. dc->SelectStockObject(BLACK_PEN);
  326. dc->MoveTo(innerArc[i]);
  327. dc->LineTo(outerArc[i]);
  328. dc->MoveTo(innerArc[i+1]);
  329. dc->LineTo(outerArc[i+1]);
  330. dc->Arc(&innerRect, innerArc[i], innerArc[i+1]);
  331. dc->Arc(&outerRect, outerArc[i], outerArc[i+1]);
  332. return;
  333. case 2*B_RADIO+1:
  334. dc->SelectStockObject(GRAY_BRUSH);
  335. dc->Ellipse(xx+click-2*3, yy-click-2*3,
  336. xx+click+2*3, yy-click+2*3);
  337. case 2*B_RADIO:
  338. dc->SelectStockObject(BLACK_BRUSH);
  339. if (pb->id != moveObject)
  340. dc->Ellipse(xx+click-3, yy-click-3,
  341. xx+click+3, yy-click+3);
  342. dc->SelectStockObject(NULL_BRUSH);
  343. dc->SelectStockObject(BLACK_PEN);
  344. dc->Ellipse(xx+click-2*3, yy-click-2*3,
  345. xx+click+2*3, yy-click+2*3);
  346. return;
  347. case 2*B_TEXT+1:
  348. dc->SelectStockObject(BLACK_PEN);
  349. dc->SelectStockObject(NULL_BRUSH);
  350. r.SetRect(xx, yy-2*click, xx+width, yy);
  351. pp[0].x = 3;
  352. pp[0].y = 3;
  353. dc->RoundRect(&r, pp[0]);
  354. dc->SelectObject(&darkGrayPen);
  355. dc->MoveTo(xx+width-2, yy-2*click+1);
  356. dc->LineTo(xx+1, yy-2*click+1);
  357. dc->LineTo(xx+1, yy-2);
  358. CText(dc, xx, xx+width+2, yy-2*click+2, pb->text);
  359. dc->SelectStockObject(BLACK_PEN);
  360. return;
  361. case 2*B_TEXT:
  362. dc->SelectStockObject(BLACK_PEN);
  363. dc->SelectStockObject(NULL_BRUSH);
  364. r.SetRect(xx, yy-2*click, xx+width, yy);
  365. pp[0].x = 3;
  366. pp[0].y = 3;
  367. dc->RoundRect(&r, pp[0]);
  368. dc->SelectStockObject(WHITE_PEN);
  369. dc->MoveTo(xx+width-2, yy-2*click+1);
  370. dc->LineTo(xx+1, yy-2*click+1);
  371. dc->LineTo(xx+1, yy-2);
  372. dc->SelectObject(&darkGrayPen);
  373. dc->LineTo(xx+width-2, yy-2);
  374. dc->LineTo(xx+width-2, yy-2*click+1);
  375. CText(dc, xx, xx+width, yy-2*click, pb->text);
  376. dc->SelectStockObject(BLACK_PEN);
  377. return;
  378. }
  379. }
  380. #undef X
  381. void copyView(fourByFour *dest, fourByFour *src)
  382. {
  383. for (int i=0; i<3; i++)
  384. for (int j=0; j<3; j++) (*dest)[i][j] = (*src)[i][j];
  385. }
  386. void CViewpointWindow::resetXform(int whence)
  387. {
  388. fourByFour *m = &theApp.mainWindow->graphicsWindow->xform;
  389. int i, j;
  390. if (whence != Undo)
  391. { copyView(&undoStack[undoPoint++ & undoMask], m);
  392. if (undoCount != undoMask) undoCount++;
  393. }
  394. switch (whence)
  395. {
  396. case Xaxis: for (i=0; i<3; i++)
  397. for (j=0; j<3; j++) (*m)[i][j] = 0.0;
  398. (*m)[0][1] = (*m)[1][2] = (*m)[2][0] = 1.0;
  399. break;
  400. case Yaxis: for (i=0; i<3; i++)
  401. for (j=0; j<3; j++) (*m)[i][j] = 0.0;
  402. (*m)[0][2] = (*m)[1][0] = (*m)[2][1] = 1.0;
  403. break;
  404. case Zaxis: for (i=0; i<3; i++)
  405. for (j=0; j<3; j++) (*m)[i][j] = 0.0;
  406. (*m)[0][0] = (*m)[1][1] = (*m)[2][2] = 1.0;
  407. break;
  408. case StdView: copyView(m, &stdView);
  409. break;
  410. case View1: copyView(m, &view1);
  411. break;
  412. case View2: copyView(m, &view2);
  413. break;
  414. case Undo: if (undoCount == 0) break;
  415. copyView(m, &undoStack[--undoPoint & undoMask]);
  416. undoCount--;
  417. break;
  418. }
  419. theApp.mainWindow->graphicsWindow->Invalidate();
  420. }
  421. void CViewpointWindow::changeXform(double delta[4][4])
  422. {
  423. double xform1[4][4];
  424. int i, j, k;
  425. copyView(&undoStack[undoPoint++ & undoMask],
  426. &theApp.mainWindow->graphicsWindow->xform);
  427. if (undoCount != undoMask) undoCount++;
  428. for (i=0; i<4; i++)
  429. for (k=0; k<4; k++)
  430. { double w = 0.0;
  431. for (j=0; j<4; j++)
  432. w += theApp.mainWindow->graphicsWindow->xform[i][j]*delta[j][k];
  433. xform1[i][k] = w;
  434. }
  435. for (i=0; i<4; i++)
  436. for (j=0; j<4; j++)
  437. theApp.mainWindow->graphicsWindow->xform[i][j] = xform1[i][j];
  438. theApp.mainWindow->graphicsWindow->Invalidate();
  439. }
  440. const double toRadians = 0.017453292; // pi/180
  441. void CViewpointWindow::rotateXform(int axis, double angle)
  442. {
  443. if (moveObject) angle = -angle;
  444. angle *= toRadians;
  445. double rot[4][4];
  446. for (int i=0; i<4; i++)
  447. for (int j=0; j<4; j++)
  448. rot[i][j] = (i == j) ? 1.0 : 0.0;
  449. double c = cos(angle), s = sin(angle);
  450. switch (axis)
  451. {
  452. case Xaxis:
  453. rot[1][1] = rot[2][2] = c;
  454. rot[1][2] = -s; rot[2][1] = s;
  455. break;
  456. case Yaxis:
  457. rot[0][0] = rot[2][2] = c;
  458. rot[0][2] = -s; rot[2][0] = s;
  459. break;
  460. case Zaxis:
  461. rot[1][1] = rot[0][0] = c;
  462. rot[1][0] = -s; rot[0][1] = s;
  463. break;
  464. }
  465. changeXform(rot);
  466. }
  467. void CViewpointWindow::scaleXform(double factor)
  468. {
  469. double xform1[4][4];
  470. for (int i=0; i<4; i++)
  471. for (int j=0; j<4; j++)
  472. xform1[i][j] = (i == j) ? 1.0 : 0.0;
  473. xform1[3][3] = 1/factor;
  474. changeXform(xform1);
  475. }
  476. void CViewpointWindow::translateXform(double x, double y)
  477. {
  478. double xform1[4][4];
  479. for (int i=0; i<4; i++)
  480. for (int j=0; j<4; j++)
  481. xform1[i][j] = (i == j) ? 1.0 : 0.0;
  482. if (moveObject) x = -x, y = -y;
  483. xform1[3][0] = x;
  484. xform1[3][1] = y;
  485. changeXform(xform1);
  486. }
  487. void CViewpointWindow::ButtonAction(int n)
  488. {
  489. switch (n)
  490. {
  491. case mobjC:
  492. moveObject = 1;
  493. SetControl(&buttonLocations[0], 0);
  494. SetControl(&buttonLocations[1], 0);
  495. return;
  496. case meyeC:
  497. moveObject = 0;
  498. SetControl(&buttonLocations[0], 0);
  499. SetControl(&buttonLocations[1], 0);
  500. return;
  501. case far3C:
  502. theApp.mainWindow->graphicsWindow->perspecDistance *= 1.2*1.2*1.2;
  503. theApp.mainWindow->graphicsWindow->Invalidate();
  504. return;
  505. case far2C:
  506. theApp.mainWindow->graphicsWindow->perspecDistance *= 1.2*1.2;
  507. theApp.mainWindow->graphicsWindow->Invalidate();
  508. return;
  509. case far1C:
  510. theApp.mainWindow->graphicsWindow->perspecDistance *= 1.1;
  511. theApp.mainWindow->graphicsWindow->Invalidate();
  512. return;
  513. case far0C:
  514. theApp.mainWindow->graphicsWindow->perspecDistance = 50000.0;
  515. theApp.mainWindow->graphicsWindow->Invalidate();
  516. return;
  517. case near1C:
  518. theApp.mainWindow->graphicsWindow->perspecDistance /= 1.1;
  519. theApp.mainWindow->graphicsWindow->Invalidate();
  520. return;
  521. case near2C:
  522. theApp.mainWindow->graphicsWindow->perspecDistance /= (1.2*1.2);
  523. theApp.mainWindow->graphicsWindow->Invalidate();
  524. return;
  525. case near3C:
  526. theApp.mainWindow->graphicsWindow->perspecDistance /= (1.2*1.2*1.2);
  527. theApp.mainWindow->graphicsWindow->Invalidate();
  528. return;
  529. case smal3C:
  530. scaleXform(1.0/(1.2*1.2*1.2));
  531. return;
  532. case smal2C:
  533. scaleXform(1.0/(1.2*1.2));
  534. return;
  535. case smal1C:
  536. scaleXform(1.0/1.1);
  537. return;
  538. case big0C:
  539. scaleXform(theApp.mainWindow->graphicsWindow->xform[3][3]*700.0);
  540. return;
  541. case big1C:
  542. scaleXform(1.1);
  543. return;
  544. case big2C:
  545. scaleXform(1.2*1.2);
  546. return;
  547. case big3C:
  548. scaleXform(1.2*1.2*1.2);
  549. return;
  550. case left3C:
  551. translateXform(2500.0, 0.0);
  552. return;
  553. case left2C:
  554. translateXform(500.0, 0.0);
  555. return;
  556. case left1C:
  557. translateXform(100.0, 0.0);
  558. return;
  559. case midC:
  560. translateXform(-theApp.mainWindow->graphicsWindow->xform[0][3],
  561. -theApp.mainWindow->graphicsWindow->xform[1][3]);
  562. return;
  563. case right1C:
  564. translateXform(-100.0, 0.0);
  565. return;
  566. case right2C:
  567. translateXform(-500.0, 0.0);
  568. return;
  569. case right3C:
  570. translateXform(-2500.0, 0.0);
  571. return;
  572. case down3C:
  573. translateXform(0.0, 2500.0);
  574. return;
  575. case down2C:
  576. translateXform(0.0, 500.0);
  577. return;
  578. case down1C:
  579. translateXform(0.0, 100.0);
  580. return;
  581. case up1C:
  582. translateXform(0.0, -100.0);
  583. return;
  584. case up2C:
  585. translateXform(0.0, -500.0);
  586. return;
  587. case up3C:
  588. translateXform(0.0, -2500.0);
  589. return;
  590. case rleft3C:
  591. rotateXform(Yaxis, 22.5);
  592. return;
  593. case rleft2C:
  594. rotateXform(Yaxis, 5.625);
  595. return;
  596. case rleft1C:
  597. rotateXform(Yaxis, 1.125);
  598. return;
  599. case backC:
  600. rotateXform(Yaxis, 180.0);
  601. return;
  602. case rrt1C:
  603. rotateXform(Yaxis, -1.125);
  604. return;
  605. case rrt2C:
  606. rotateXform(Yaxis, -5.625);
  607. return;
  608. case rrt3C:
  609. rotateXform(Yaxis, -22.5);
  610. return;
  611. case rdown3C:
  612. rotateXform(Xaxis, 22.5);
  613. return;
  614. case rdown2C:
  615. rotateXform(Xaxis, 5.625);
  616. return;
  617. case rdown1C:
  618. rotateXform(Xaxis, 1.125);
  619. return;
  620. case rup1C:
  621. rotateXform(Xaxis, -1.125);
  622. return;
  623. case rup2C:
  624. rotateXform(Xaxis, -5.625);
  625. return;
  626. case rup3C:
  627. rotateXform(Xaxis, -22.5);
  628. return;
  629. case closeC:
  630. theApp.mainWindow->graphicsWindow->PostMessage(WM_USER+2, 0, 0);
  631. return;
  632. case showC:
  633. theApp.mainWindow->graphicsWindow->fullRender = 1;
  634. theApp.mainWindow->graphicsWindow->Invalidate();
  635. return;
  636. case undoC:
  637. resetXform(Undo);
  638. return;
  639. case stdC:
  640. resetXform(StdView);
  641. return;
  642. case XC:
  643. resetXform(Xaxis);
  644. return;
  645. case YC:
  646. resetXform(Yaxis);
  647. return;
  648. case ZC:
  649. resetXform(Zaxis);
  650. return;
  651. case V1C:
  652. resetXform(View1);
  653. return;
  654. case V2C:
  655. resetXform(View2);
  656. return;
  657. case SV1C:
  658. memcpy((void *)view1, (void *)theApp.mainWindow->graphicsWindow->xform, sizeof(stdView));
  659. return;
  660. case SV2C:
  661. memcpy((void *)view2, (void *)theApp.mainWindow->graphicsWindow->xform, sizeof(stdView));
  662. return;
  663. case twl3C:
  664. rotateXform(Zaxis, 22.5);
  665. return;
  666. case twl2C:
  667. rotateXform(Zaxis, 5.625);
  668. return;
  669. case twl1C:
  670. rotateXform(Zaxis, 1.125);
  671. return;
  672. case twl0C:
  673. rotateXform(Zaxis, 180.0);
  674. return;
  675. case twr1C:
  676. rotateXform(Zaxis, -1.125);
  677. return;
  678. case twr2C:
  679. rotateXform(Zaxis, -5.625);
  680. return;
  681. case twr3C:
  682. rotateXform(Zaxis, -22.5);
  683. return;
  684. }
  685. }
  686. void CViewpointWindow::setArcPoints()
  687. {
  688. innerRect.SetRect(22*click, 2*click, 40*click, 20*click);
  689. outerRect.SetRect(20*click, 0, 42*click, 22*click);
  690. double a = atan(1/10.0), b, sb, cb, k = (double)click;;
  691. for (int i=0; i<8; i++)
  692. { b = a*(double)(2*i-7);
  693. sb = sin(b);
  694. cb = cos(b);
  695. innerArc[i].x = 31*click + (int)(9.0*k*sb);
  696. innerArc[i].y = 11*click + (int)(9.0*k*cb);
  697. outerArc[i].x = 31*click + (int)(11.0*k*sb);
  698. outerArc[i].y = 11*click + (int)(11.0*k*cb);
  699. }
  700. for (i=0; i<7; i++)
  701. { CPoint pp[4];
  702. pp[0] = innerArc[i]; pp[1] = outerArc[i];
  703. pp[2] = outerArc[i+1]; pp[3] = innerArc[i+1];
  704. arcRegions[i].CreatePolygonRgn(pp, 4, ALTERNATE);
  705. }
  706. }
  707. void CViewpointWindow::OnPaint()
  708. {
  709. CPaintDC dc(this);
  710. dc.SelectStockObject(NULL_BRUSH);
  711. dc.SetBkMode(TRANSPARENT);
  712. dc.SelectObject(&titleFont);
  713. CText(&dc, 2*click, 16*click, click, "Position");
  714. CText(&dc, 24*click, 38*click, click, "Rotation");
  715. dc.SelectObject(&labelFont);
  716. LText(&dc, 2*click, 24*click, "far");
  717. RText(&dc, 16*click, 24*click, "near");
  718. LText(&dc, 2*click, 18*click, "small");
  719. RText(&dc, 16*click, 18*click, "large");
  720. LText(&dc, 2*click, 12*click, "left");
  721. RText(&dc, 16*click, 12*click, "right");
  722. LText(&dc, 10*click+3, 16*click, "down");
  723. LText(&dc, 10*click+3, 4*click,"up");
  724. LText(&dc, 32*click+3, 4*click,"roll");
  725. RText(&dc, 38*click, 12*click, "rotate");
  726. RText(&dc, 38*click, 16*click, "twist");
  727. LText(&dc, 16*click, 6*click, "move object");
  728. LText(&dc, 16*click, 4*click, "move viewpoint");
  729. CBrush backgroundBrush(RGB(255,255,128));
  730. const ButtonPlace *pb = buttonLocations;
  731. while (pb->x != 0)
  732. { dc.SelectObject(&backgroundBrush);
  733. dc.SelectStockObject(NULL_PEN);
  734. switch (pb->flavour)
  735. {
  736. case B_TWIST:
  737. break; // fills in its own background
  738. case B_CLOSE:
  739. dc.Rectangle(click*pb->x, click*(pb->y-1),
  740. click*(pb->x+1), click*pb->y);
  741. break;
  742. default:
  743. dc.Rectangle(click*pb->x, click*(pb->y-2),
  744. click*(pb->x+pb->width), click*pb->y);
  745. break;
  746. }
  747. DrawButton(&dc, pb);
  748. pb++;
  749. }
  750. dc.SelectStockObject(SYSTEM_FONT);
  751. }
  752. void CViewpointWindow::OnSetFocus(CWnd *pOldWnd)
  753. {
  754. SetWindowPos(&wndTop, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW);
  755. }
  756. void CViewpointWindow::OnKillFocus(CWnd *pNewWnd)
  757. {
  758. }
  759. void CViewpointWindow::OnChar(UINT ch, UINT nRepCnt, UINT nFlags)
  760. {
  761. DisplayMsg("Viewpoint Window OnChar");
  762. }
  763. void CViewpointWindow::OnKeyDown(UINT ch, UINT nRepCnt, UINT nFlags)
  764. {
  765. DisplayMsg("Viewpoint Window OnKeyDown");
  766. }
  767. int CViewpointWindow::inButton(const ButtonPlace *b, int x, int y)
  768. {
  769. if (b->flavour == B_TWIST) return arcRegions[b->y].PtInRegion(x, y);
  770. else return (click*b->x <= x && x < click*(b->x+b->width) &&
  771. click*((int)b->y-2) <= y && y < click*b->y);
  772. }
  773. const ButtonPlace *CViewpointWindow::FindControl(int x, int y)
  774. {
  775. const ButtonPlace *b = buttonLocations;
  776. while (b->x != 0)
  777. { if (inButton(b, x, y)) return b;
  778. b++;
  779. }
  780. return NULL;
  781. }
  782. void CViewpointWindow::SetControl(const ButtonPlace *b, int state)
  783. {
  784. buttonPressed[b->id] = state;
  785. CRect r(click*b->x, click*((int)b->y-2),
  786. click*(b->x+b->width), click*b->y);
  787. if (b->flavour == B_TWIST) InvalidateRgn(&arcRegions[b->y], FALSE);
  788. else InvalidateRect(&r, FALSE);
  789. }
  790. void CViewpointWindow::OnLButtonDown(UINT nFlags, CPoint point)
  791. {
  792. SetCapture();
  793. const ButtonPlace *b = FindControl(point.x, point.y);
  794. if (b == NULL)
  795. { mouseDrag = 1;
  796. mouseX = point.x;
  797. mouseY = point.y;
  798. }
  799. else
  800. { activeButton = b;
  801. SetControl(b, 1);
  802. }
  803. }
  804. // If the user double-clicks on the dialog box it will go away. Well, at least
  805. // if the double-click is not on a button.
  806. void CViewpointWindow::OnLButtonDblClk(UINT nFlags, CPoint point)
  807. {
  808. if (FindControl(point.x, point.y) == NULL)
  809. theApp.mainWindow->graphicsWindow->PostMessage(WM_USER+2, 0, 0);
  810. }
  811. void CViewpointWindow::OnLButtonUp(UINT nFlags, CPoint point)
  812. {
  813. ReleaseCapture();
  814. if (mouseDrag)
  815. { mouseDrag = 0;
  816. activeButton = NULL;
  817. return;
  818. }
  819. if (activeButton == NULL) return;
  820. const ButtonPlace *b = activeButton;
  821. activeButton = NULL;
  822. if (inButton(b, point.x, point.y))
  823. { buttonPressed[b->id] = 0;
  824. SetControl(b, 0);
  825. ButtonAction(b->id); // Dispatch to some activity
  826. }
  827. }
  828. void CViewpointWindow::OnMouseMove(UINT nFlags, CPoint point)
  829. {
  830. if (mouseDrag)
  831. { WINDOWPLACEMENT w;
  832. GetWindowPlacement(&w);
  833. w.rcNormalPosition.left += point.x - mouseX;
  834. w.rcNormalPosition.right += point.x - mouseX;
  835. w.rcNormalPosition.top += point.y - mouseY;
  836. w.rcNormalPosition.bottom += point.y - mouseY;
  837. SetWindowPlacement(&w);
  838. return;
  839. }
  840. if (activeButton == NULL) return;
  841. const ButtonPlace *b = activeButton;
  842. if (inButton(b, point.x, point.y))
  843. { if (buttonPressed[b->id] == 0)
  844. { buttonPressed[b->id] = 1;
  845. SetControl(b, 1);
  846. }
  847. }
  848. else if (buttonPressed[b->id])
  849. { buttonPressed[b->id] = 0;
  850. SetControl(b, 0);
  851. }
  852. }
  853. #endif
  854. // end of c_viewpt.cpp