c_viewpt.cpp 28 KB

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