Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

427 lines
12 KiB

  1. //-----------------------------------------------------------------------------
  2. // File: xc.cpp
  3. //
  4. // Desc: Cross-section (xc) object stuff
  5. //
  6. // Copyright (c) 1995-2000 Microsoft Corporation
  7. //-----------------------------------------------------------------------------
  8. #include "stdafx.h"
  9. //-----------------------------------------------------------------------------
  10. // Name: XC::CalcArcACValues90
  11. // Desc: Calculate arc control points for a 90 degree rotation of an xc
  12. //
  13. // Arc is a quarter-circle
  14. // - 90 degree is much easier, so we special case it
  15. // radius is distance from xc-origin to hinge of turn
  16. //-----------------------------------------------------------------------------
  17. void XC::CalcArcACValues90( int dir, float radius, float *acPts )
  18. {
  19. int i;
  20. float sign;
  21. int offset;
  22. float* ppts = (float *) m_pts;
  23. // 1) calc 'r' values for each point (4 turn possibilities/point). From
  24. // this can determine ac, which is extrusion of point from xc face
  25. switch( dir )
  26. {
  27. case PLUS_X:
  28. offset = 0;
  29. sign = -1.0f;
  30. break;
  31. case MINUS_X:
  32. offset = 0;
  33. sign = 1.0f;
  34. break;
  35. case PLUS_Y:
  36. offset = 1;
  37. sign = -1.0f;
  38. break;
  39. case MINUS_Y:
  40. offset = 1;
  41. sign = 1.0f;
  42. break;
  43. }
  44. for( i = 0; i < m_numPts; i++, ppts+=2, acPts++ )
  45. {
  46. *acPts = EVAL_CIRC_ARC_CONTROL * (radius + (sign * ppts[offset]));
  47. }
  48. // replicate !
  49. *acPts = *(acPts - m_numPts);
  50. }
  51. //-----------------------------------------------------------------------------
  52. // Name: XC::CalcArcACValuesByDistance
  53. // Desc: Use the distance of each xc point from the xc origin, as the radius for
  54. // an arc control value.
  55. //-----------------------------------------------------------------------------
  56. void XC::CalcArcACValuesByDistance( float *acPts )
  57. {
  58. int i;
  59. float r;
  60. D3DXVECTOR2* ppts = m_pts;
  61. for( i = 0; i < m_numPts; i++, ppts++ )
  62. {
  63. r = (float) sqrt( ppts->x*ppts->x + ppts->y*ppts->y );
  64. *acPts++ = EVAL_CIRC_ARC_CONTROL * r;
  65. }
  66. // replicate !
  67. *acPts = *(acPts - m_numPts);
  68. }
  69. //-----------------------------------------------------------------------------
  70. // Name: ELLIPTICAL_XC::SetControlPoints
  71. // Desc: Set the 12 control points for a circle at origin in z=0 plane
  72. //-----------------------------------------------------------------------------
  73. void ELLIPTICAL_XC::SetControlPoints( float r1, float r2 )
  74. {
  75. float ac1, ac2;
  76. ac1 = EVAL_CIRC_ARC_CONTROL * r2;
  77. ac2 = EVAL_CIRC_ARC_CONTROL * r1;
  78. // create 12-pt. set CCW from +x
  79. // last 2 points of right triplet
  80. m_pts[0].x = r1;
  81. m_pts[0].y = 0.0f;
  82. m_pts[1].x = r1;
  83. m_pts[1].y = ac1;
  84. // top triplet
  85. m_pts[2].x = ac2;
  86. m_pts[2].y = r2;
  87. m_pts[3].x = 0.0f;
  88. m_pts[3].y = r2;
  89. m_pts[4].x = -ac2;
  90. m_pts[4].y = r2;
  91. // left triplet
  92. m_pts[5].x = -r1;
  93. m_pts[5].y = ac1;
  94. m_pts[6].x = -r1;
  95. m_pts[6].y = 0.0f;
  96. m_pts[7].x = -r1;
  97. m_pts[7].y = -ac1;
  98. // bottom triplet
  99. m_pts[8].x = -ac2;
  100. m_pts[8].y = -r2;
  101. m_pts[9].x = 0.0f;
  102. m_pts[9].y = -r2;
  103. m_pts[10].x = ac2;
  104. m_pts[10].y = -r2;
  105. // first point of first triplet
  106. m_pts[11].x = r1;
  107. m_pts[11].y = -ac1;
  108. }
  109. //-----------------------------------------------------------------------------
  110. // Name: RANDOM4ARC_XC::SetControlPoints
  111. // Desc: Set random control points for xc
  112. // Points go CCW from +x
  113. //-----------------------------------------------------------------------------
  114. void RANDOM4ARC_XC::SetControlPoints( float radius )
  115. {
  116. int i;
  117. float r[4];
  118. float rMin = 0.5f * radius;
  119. float distx, disty;
  120. // figure the radius of each side first
  121. for( i = 0; i < 4; i ++ )
  122. r[i] = CPipesScreensaver::fRand( rMin, radius );
  123. // The 4 r's now describe a box around the origin - this restricts stuff
  124. // Now need to select a point along each edge of the box as the joining
  125. // points for each arc (join points are at indices 0,3,6,9)
  126. m_pts[0].x = r[RIGHT];
  127. m_pts[3].y = r[TOP];
  128. m_pts[6].x = -r[LEFT];
  129. m_pts[9].y = -r[BOTTOM];
  130. // quarter of distance between edges
  131. disty = (r[TOP] - -r[BOTTOM]) / 4.0f;
  132. distx = (r[RIGHT] - -r[LEFT]) / 4.0f;
  133. // uh, put'em somwhere in the middle half of each side
  134. m_pts[0].y = CPipesScreensaver::fRand( -r[BOTTOM] + disty, r[TOP] - disty );
  135. m_pts[6].y = CPipesScreensaver::fRand( -r[BOTTOM] + disty, r[TOP] - disty );
  136. m_pts[3].x = CPipesScreensaver::fRand( -r[LEFT] + distx, r[RIGHT] - distx );
  137. m_pts[9].x = CPipesScreensaver::fRand( -r[LEFT] + distx, r[RIGHT] - distx );
  138. // now can calc ac's
  139. // easy part first:
  140. m_pts[1].x = m_pts[11].x = m_pts[0].x;
  141. m_pts[2].y = m_pts[4].y = m_pts[3].y;
  142. m_pts[5].x = m_pts[7].x = m_pts[6].x;
  143. m_pts[8].y = m_pts[10].y = m_pts[9].y;
  144. // right side ac's
  145. disty = (r[TOP] - m_pts[0].y) / 4.0f;
  146. m_pts[1].y = CPipesScreensaver::fRand( m_pts[0].y + disty, r[TOP] );
  147. disty = (m_pts[0].y - -r[BOTTOM]) / 4.0f;
  148. m_pts[11].y = CPipesScreensaver::fRand( -r[BOTTOM], m_pts[0].y - disty );
  149. // left side ac's
  150. disty = (r[TOP] - m_pts[6].y) / 4.0f;
  151. m_pts[5].y = CPipesScreensaver::fRand( m_pts[6].y + disty, r[TOP]);
  152. disty = (m_pts[6].y - -r[BOTTOM]) / 4.0f;
  153. m_pts[7].y = CPipesScreensaver::fRand( -r[BOTTOM], m_pts[6].y - disty );
  154. // top ac's
  155. distx = (r[RIGHT] - m_pts[3].x) / 4.0f;
  156. m_pts[2].x = CPipesScreensaver::fRand( m_pts[3].x + distx, r[RIGHT] );
  157. distx = (m_pts[3].x - -r[LEFT]) / 4.0f;
  158. m_pts[4].x = CPipesScreensaver::fRand( -r[LEFT], m_pts[3].x - distx );
  159. // bottom ac's
  160. distx = (r[RIGHT] - m_pts[9].x) / 4.0f;
  161. m_pts[10].x = CPipesScreensaver::fRand( m_pts[9].x + distx, r[RIGHT] );
  162. distx = (m_pts[9].x - -r[LEFT]) / 4.0f;
  163. m_pts[8].x = CPipesScreensaver::fRand( -r[LEFT], m_pts[9].x - distx );
  164. }
  165. //-----------------------------------------------------------------------------
  166. // Name: ConvertPtsZ
  167. // Desc: Convert the 2D pts in an xc, to 3D pts in point buffer, with z.
  168. //
  169. // Also replicate the last point.
  170. //-----------------------------------------------------------------------------
  171. void XC::ConvertPtsZ( D3DXVECTOR3 *newpts, float z )
  172. {
  173. int i;
  174. D3DXVECTOR2* xcPts = m_pts;
  175. for( i = 0; i < m_numPts; i++, newpts++ )
  176. {
  177. *( (D3DXVECTOR2 *) newpts ) = *xcPts++;
  178. newpts->z = z;
  179. }
  180. *newpts = *(newpts - m_numPts);
  181. }
  182. //-----------------------------------------------------------------------------
  183. // Name: XC::CalcBoundingBox
  184. // Desc: Calculate bounding box in x/y plane for xc
  185. //-----------------------------------------------------------------------------
  186. void XC::CalcBoundingBox( )
  187. {
  188. D3DXVECTOR2* ppts = m_pts;
  189. int i;
  190. float xMin, xMax, yMax, yMin;
  191. // initialize to really insane numbers
  192. xMax = yMax = -FLT_MAX;
  193. xMin = yMin = FLT_MAX;
  194. // compare with rest of points
  195. for( i = 0; i < m_numPts; i ++, ppts++ )
  196. {
  197. if( ppts->x < xMin )
  198. xMin = ppts->x;
  199. else if( ppts->x > xMax )
  200. xMax = ppts->x;
  201. if( ppts->y < yMin )
  202. yMin = ppts->y;
  203. else if( ppts->y > yMax )
  204. yMax = ppts->y;
  205. }
  206. m_xLeft = xMin;
  207. m_xRight = xMax;
  208. m_yBottom = yMin;
  209. m_yTop = yMax;
  210. }
  211. //-----------------------------------------------------------------------------
  212. // Name: MinTurnRadius
  213. // Desc: Get minimum radius for the xc to turn in given direction.
  214. //
  215. // If the turn radius is less than this minimum, then primitive will 'fold'
  216. // over itself at the inside of the turn, creating ugliness.
  217. //-----------------------------------------------------------------------------
  218. float XC::MinTurnRadius( int relDir )
  219. {
  220. // For now, assume xRight, yTop positive, xLeft, yBottom negative
  221. // otherwise, might want to consider 'negative'radius
  222. switch( relDir )
  223. {
  224. case PLUS_X:
  225. return( m_xRight );
  226. case MINUS_X:
  227. return( - m_xLeft );
  228. case PLUS_Y:
  229. return( m_yTop );
  230. case MINUS_Y:
  231. return( - m_yBottom );
  232. default:
  233. return(0.0f);
  234. }
  235. }
  236. //-----------------------------------------------------------------------------
  237. // Name: XC::MaxExtent
  238. // Desc: Get maximum extent of the xc in x and y
  239. //-----------------------------------------------------------------------------
  240. float XC::MaxExtent( )
  241. {
  242. float max;
  243. max = m_xRight;
  244. if( m_yTop > max )
  245. max = m_yTop;
  246. if( -m_xLeft > max )
  247. max = -m_xLeft;
  248. if( -m_yBottom > max )
  249. max = -m_yBottom;
  250. return max;
  251. }
  252. //-----------------------------------------------------------------------------
  253. // Name: XC::Scale
  254. // Desc: Scale an XC's points and extents by supplied scale value
  255. //-----------------------------------------------------------------------------
  256. void XC::Scale( float scale )
  257. {
  258. int i;
  259. D3DXVECTOR2* ppts = m_pts;
  260. if( ppts == NULL )
  261. return;
  262. for( i = 0; i < m_numPts; i ++, ppts++ )
  263. {
  264. ppts->x *= scale;
  265. ppts->y *= scale;
  266. }
  267. m_xLeft *= scale;
  268. m_xRight *= scale;
  269. m_yBottom *= scale;
  270. m_yTop *= scale;
  271. }
  272. //-----------------------------------------------------------------------------
  273. // Name: ~XC::XC
  274. // Desc: Destructor
  275. //-----------------------------------------------------------------------------
  276. XC::~XC()
  277. {
  278. if( m_pts )
  279. LocalFree( m_pts );
  280. }
  281. //-----------------------------------------------------------------------------
  282. // Name: XC::XC
  283. // Desc: Constructor
  284. // Allocates point buffer for the xc
  285. //-----------------------------------------------------------------------------
  286. XC::XC( int nPts )
  287. {
  288. m_numPts = nPts;
  289. m_pts = (D3DXVECTOR2 *) LocalAlloc( LMEM_FIXED, m_numPts * sizeof(D3DXVECTOR2) );
  290. assert( m_pts != 0 && "XC constructor\n" );
  291. }
  292. //-----------------------------------------------------------------------------
  293. // Name: XC::XC
  294. // Desc: Constructor
  295. // Allocates point buffer for the xc from another XC
  296. //-----------------------------------------------------------------------------
  297. XC::XC( XC *xc )
  298. {
  299. m_numPts = xc->m_numPts;
  300. m_pts = (D3DXVECTOR2 *) LocalAlloc( LMEM_FIXED, m_numPts * sizeof(D3DXVECTOR2) );
  301. assert( m_pts != 0 && "XC constructor\n" );
  302. if( m_pts != NULL )
  303. RtlCopyMemory( m_pts, xc->m_pts, m_numPts * sizeof(D3DXVECTOR2) );
  304. m_xLeft = xc->m_xLeft;
  305. m_xRight = xc->m_xRight;
  306. m_yBottom = xc->m_yBottom;
  307. m_yTop = xc->m_yTop;
  308. }
  309. //-----------------------------------------------------------------------------
  310. // Name: ELLIPTICAL_XC::ELLIPTICALXC
  311. // Desc: Elliptical XC constructor
  312. // These have 4 sections of 4 pts each, with pts shared between sections.
  313. //-----------------------------------------------------------------------------
  314. ELLIPTICAL_XC::ELLIPTICAL_XC( float r1, float r2 )
  315. // initialize base XC with numPts
  316. : XC( (int) EVAL_XC_CIRC_SECTION_COUNT * (EVAL_ARC_ORDER - 1))
  317. {
  318. SetControlPoints( r1, r2 );
  319. CalcBoundingBox( );
  320. }
  321. //-----------------------------------------------------------------------------
  322. // Name: RANDOM4ARC_XC::RANDOM4ARC_XC
  323. // Desc: Random 4-arc XC constructor
  324. // The bounding box is 2*r each side
  325. // These have 4 sections of 4 pts each, with pts shared between sections.
  326. //-----------------------------------------------------------------------------
  327. RANDOM4ARC_XC::RANDOM4ARC_XC( float r )
  328. // initialize base XC with numPts
  329. : XC( (int) EVAL_XC_CIRC_SECTION_COUNT * (EVAL_ARC_ORDER - 1))
  330. {
  331. SetControlPoints( r );
  332. CalcBoundingBox( );
  333. }