SplineTestView.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. // SplineTestView.cpp : implementation of the CSplineTestView class
  19. //
  20. #include "stdafx.h"
  21. #include "SplineTest.h"
  22. #include "SplineTestDoc.h"
  23. #include "SplineTestView.h"
  24. #include "curve.h"
  25. #include "hermitespline.h"
  26. #include "catmullromspline.h"
  27. #include "cardinalspline.h"
  28. #include "tcbspline.h"
  29. #ifdef _DEBUG
  30. #define new DEBUG_NEW
  31. #undef THIS_FILE
  32. static char THIS_FILE[] = __FILE__;
  33. #endif
  34. const float MIN_X = -10.0f;
  35. const float MIN_Y = -10.0f;
  36. const float MIN_Z = -10.0f;
  37. const float MAX_X = 10.0f;
  38. const float MAX_Y = 10.0f;
  39. const float MAX_Z = 10.0f;
  40. /////////////////////////////////////////////////////////////////////////////
  41. // CSplineTestView
  42. IMPLEMENT_DYNCREATE(CSplineTestView, CView)
  43. BEGIN_MESSAGE_MAP(CSplineTestView, CView)
  44. //{{AFX_MSG_MAP(CSplineTestView)
  45. ON_WM_LBUTTONDOWN()
  46. ON_WM_LBUTTONUP()
  47. ON_WM_MOUSEMOVE()
  48. ON_WM_RBUTTONUP()
  49. //}}AFX_MSG_MAP
  50. END_MESSAGE_MAP()
  51. /////////////////////////////////////////////////////////////////////////////
  52. // CSplineTestView construction/destruction
  53. CSplineTestView::CSplineTestView()
  54. {
  55. DrawTangents = false;
  56. }
  57. CSplineTestView::~CSplineTestView()
  58. {
  59. }
  60. BOOL CSplineTestView::PreCreateWindow(CREATESTRUCT& cs)
  61. {
  62. // TODO: Modify the Window class or styles here by modifying
  63. // the CREATESTRUCT cs
  64. return CView::PreCreateWindow(cs);
  65. }
  66. /////////////////////////////////////////////////////////////////////////////
  67. // CSplineTestView drawing
  68. void CSplineTestView::OnDraw(CDC* pDC)
  69. {
  70. CSplineTestDoc* pDoc = GetDocument();
  71. ASSERT_VALID(pDoc);
  72. Curve3DClass * curve = pDoc->Get_Curve();
  73. if (curve == NULL) return;
  74. Vector3 pt;
  75. int x,y;
  76. // draw coordinate axes
  77. CPen blackpen;
  78. blackpen.CreatePen(PS_DASH,1,RGB(0,0,0));
  79. pDC->SelectObject(&blackpen);
  80. Map_Point(Vector3(0,10,0),&x,&y);
  81. pDC->MoveTo(x,y);
  82. Map_Point(Vector3(0,-10,0),&x,&y);
  83. pDC->LineTo(x,y);
  84. Map_Point(Vector3(10,0,0),&x,&y);
  85. pDC->MoveTo(x,y);
  86. Map_Point(Vector3(-10,0,0),&x,&y);
  87. pDC->LineTo(x,y);
  88. // draw the spline
  89. CPen greenpen;
  90. greenpen.CreatePen(PS_SOLID,2,RGB(0,255,0));
  91. pDC->SelectObject(&greenpen);
  92. if (curve->Key_Count() >= 2) {
  93. float t0 = curve->Get_Start_Time();
  94. float t1 = curve->Get_End_Time();
  95. float dt = (t1 - t0) / 500.0f;
  96. curve->Evaluate(t0,&pt);
  97. Map_Point(pt,&x,&y);
  98. pDC->MoveTo(x,y);
  99. for (float t=t0; t<t1; t+=dt) {
  100. curve->Evaluate(t,&pt);
  101. Map_Point(pt,&x,&y);
  102. pDC->LineTo(x,y);
  103. }
  104. }
  105. // draw the control points
  106. for (int pi=0; pi<curve->Key_Count(); pi++) {
  107. curve->Get_Key(pi,&pt,NULL);
  108. Map_Point(pt,&x,&y);
  109. pDC->FillSolidRect(x-2,y-2,4,4, RGB(255,0,0));
  110. }
  111. // draw the tangents
  112. if ((DrawTangents) && (pDoc->Get_Curve_Type() > CSplineTestDoc::LINEAR)) {
  113. HermiteSpline3DClass * spline = (HermiteSpline3DClass *)curve;
  114. CPen blackpen;
  115. blackpen.CreatePen(PS_SOLID,1,RGB(0,0,0));
  116. pDC->SelectObject(&blackpen);
  117. for (int pi=0; pi<spline->Key_Count(); pi++) {
  118. int cx,cy;
  119. spline->Get_Key(pi,&pt,NULL);
  120. Map_Point(pt,&cx,&cy);
  121. Vector3 in,out;
  122. spline->Get_Tangents(pi,&in,&out);
  123. Map_Point(pt-in,&x,&y);
  124. pDC->MoveTo(cx,cy);
  125. pDC->LineTo(x,y);
  126. Map_Point(pt+out,&x,&y);
  127. pDC->MoveTo(cx,cy);
  128. pDC->LineTo(x,y);
  129. }
  130. }
  131. }
  132. void CSplineTestView::Map_Point(const Vector3 & point,int * set_x,int * set_y)
  133. {
  134. RECT rect;
  135. GetClientRect(&rect);
  136. float nx,ny;
  137. nx = (point.X - MIN_X) / (MAX_X - MIN_X);
  138. ny = (point.Y - MIN_Y) / (MAX_Y - MIN_Y);
  139. *set_x = (float)(rect.right - rect.left) * nx + rect.left;
  140. *set_y = (float)(rect.top - rect.bottom) * ny + rect.bottom;
  141. }
  142. void CSplineTestView::Un_Map_Point(int x,int y,Vector3 * set_point)
  143. {
  144. RECT rect;
  145. GetClientRect(&rect);
  146. float nx,ny;
  147. nx = (float)(x - rect.left) / (float)(rect.right - rect.left);
  148. ny = (float)(y - rect.bottom) / (float)(rect.top - rect.bottom);
  149. set_point->X = MIN_X + (MAX_X - MIN_X) * nx;
  150. set_point->Y = MIN_Y + (MAX_Y - MIN_Y) * ny;
  151. set_point->Z = 0.0f;
  152. *set_point = Clamp_Point(*set_point);
  153. }
  154. /////////////////////////////////////////////////////////////////////////////
  155. // CSplineTestView diagnostics
  156. #ifdef _DEBUG
  157. void CSplineTestView::AssertValid() const
  158. {
  159. CView::AssertValid();
  160. }
  161. void CSplineTestView::Dump(CDumpContext& dc) const
  162. {
  163. CView::Dump(dc);
  164. }
  165. CSplineTestDoc* CSplineTestView::GetDocument() // non-debug version is inline
  166. {
  167. ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CSplineTestDoc)));
  168. return (CSplineTestDoc*)m_pDocument;
  169. }
  170. #endif //_DEBUG
  171. /////////////////////////////////////////////////////////////////////////////
  172. // CSplineTestView message handlers
  173. void CSplineTestView::OnLButtonDown(UINT nFlags, CPoint point)
  174. {
  175. CSplineTestDoc* pDoc = GetDocument();
  176. if (pDoc) {
  177. // map the point
  178. Vector3 pt;
  179. Un_Map_Point(point.x,point.y,&pt);
  180. // try to go into drag mode
  181. bool gotone = pDoc->Grab_Point(pt);
  182. if (gotone) {
  183. ::SetCapture(m_hWnd);
  184. }
  185. }
  186. CView::OnLButtonDown(nFlags, point);
  187. }
  188. void CSplineTestView::OnLButtonUp(UINT nFlags, CPoint point)
  189. {
  190. // were we dragging something? if so release it
  191. // otherwise add a point to the curve
  192. CSplineTestDoc* pDoc = GetDocument();
  193. if (pDoc != NULL) {
  194. if (pDoc->Is_Dragging()) {
  195. pDoc->Release_Point();
  196. ::ReleaseCapture();
  197. } else {
  198. Vector3 pt;
  199. Un_Map_Point(point.x,point.y,&pt);
  200. pDoc->Add_Point(pt);
  201. }
  202. }
  203. CView::OnLButtonUp(nFlags, point);
  204. }
  205. void CSplineTestView::OnMouseMove(UINT nFlags, CPoint point)
  206. {
  207. CSplineTestDoc* pDoc = GetDocument();
  208. // are we dragging?
  209. // if so tell the doc where the point should go
  210. if (pDoc && pDoc->Is_Dragging()) {
  211. Vector3 pt;
  212. Un_Map_Point(point.x,point.y,&pt);
  213. pDoc->Drag_Point(pt);
  214. }
  215. CView::OnMouseMove(nFlags, point);
  216. }
  217. void CSplineTestView::OnRButtonUp(UINT nFlags, CPoint point)
  218. {
  219. Vector3 pt;
  220. Un_Map_Point(point.x,point.y,&pt);
  221. CSplineTestDoc* pDoc = GetDocument();
  222. if (pDoc) {
  223. pDoc->Edit_Point(pt);
  224. }
  225. CView::OnRButtonUp(nFlags, point);
  226. }
  227. Vector3 CSplineTestView::Clamp_Point(const Vector3 & input)
  228. {
  229. Vector3 output = input;
  230. if (output.X < MIN_X) output.X = MIN_X;
  231. if (output.Y < MIN_Y) output.Y = MIN_Y;
  232. if (output.Z < MIN_Z) output.Z = MIN_Z;
  233. if (output.X > MAX_X) output.X = MAX_X;
  234. if (output.Y > MAX_Y) output.Y = MAX_Y;
  235. if (output.Z > MAX_Z) output.Z = MAX_Z;
  236. return output;
  237. }
  238. void CSplineTestView::Enable_Draw_Tangents(bool onoff)
  239. {
  240. DrawTangents = onoff;
  241. CSplineTestDoc* pDoc = GetDocument();
  242. if (pDoc) {
  243. pDoc->UpdateAllViews(NULL);
  244. }
  245. }
  246. bool CSplineTestView::Is_Draw_Tangents_Enabled(void)
  247. {
  248. return DrawTangents;
  249. }