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.

497 lines
12 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: xc.cxx
  3. *
  4. * Cross-section (xc) object stuff
  5. *
  6. * Copyright (c) 1995 Microsoft Corporation
  7. *
  8. \**************************************************************************/
  9. #include <stdio.h>
  10. #include <string.h>
  11. #include <stdlib.h>
  12. #include <math.h>
  13. #include <sys/types.h>
  14. #include <time.h>
  15. #include <windows.h>
  16. #include <GL/gl.h>
  17. #include <GL/glu.h>
  18. #include <GL/glaux.h>
  19. #include <float.h>
  20. #include "sscommon.h"
  21. #include "sspipes.h"
  22. #include "eval.h"
  23. #include "xc.h"
  24. /**************************************************************************\
  25. * XC::CalcArcACValues90
  26. *
  27. * Calculate arc control points for a 90 degree rotation of an xc
  28. *
  29. * Arc is a quarter-circle
  30. * - 90 degree is much easier, so we special case it
  31. * - radius is distance from xc-origin to hinge of turn
  32. *
  33. * History
  34. * July 28, 95 : [marcfo]
  35. * - Wrote it
  36. *
  37. \**************************************************************************/
  38. void
  39. XC::CalcArcACValues90( int dir, float radius, float *acPts )
  40. {
  41. int i;
  42. float sign;
  43. int offset;
  44. float *ppts = (float *) pts;
  45. // 1) calc 'r' values for each point (4 turn possibilities/point). From
  46. // this can determine ac, which is extrusion of point from xc face
  47. switch( dir ) {
  48. case PLUS_X:
  49. offset = 0;
  50. sign = -1.0f;
  51. break;
  52. case MINUS_X:
  53. offset = 0;
  54. sign = 1.0f;
  55. break;
  56. case PLUS_Y:
  57. offset = 1;
  58. sign = -1.0f;
  59. break;
  60. case MINUS_Y:
  61. offset = 1;
  62. sign = 1.0f;
  63. break;
  64. }
  65. for( i = 0; i < numPts; i++, ppts+=2, acPts++ ) {
  66. *acPts = EVAL_CIRC_ARC_CONTROL * (radius + (sign * ppts[offset]));
  67. }
  68. // replicate !
  69. *acPts = *(acPts - numPts);
  70. }
  71. /**************************************************************************\
  72. * XC::CalcArcACValuesByDistance
  73. *
  74. * Use the distance of each xc point from the xc origin, as the radius for
  75. * an arc control value.
  76. *
  77. * History
  78. * July 29, 95 : [marcfo]
  79. * - Wrote it
  80. *
  81. \**************************************************************************/
  82. void
  83. XC::CalcArcACValuesByDistance( float *acPts )
  84. {
  85. int i;
  86. float r;
  87. POINT2D *ppts = pts;
  88. for( i = 0; i < numPts; i++, ppts++ ) {
  89. r = (float) sqrt( ppts->x*ppts->x + ppts->y*ppts->y );
  90. *acPts++ = EVAL_CIRC_ARC_CONTROL * r;
  91. }
  92. // replicate !
  93. *acPts = *(acPts - numPts);
  94. }
  95. /**************************************************************************\
  96. * ELLIPTICAL_XC::SetControlPoints
  97. *
  98. * Set the 12 control points for a circle at origin in z=0 plane
  99. *
  100. * Points go CCW from +x
  101. *
  102. * History
  103. * July 24, 95 : [marcfo]
  104. * - Wrote it
  105. * - 10/18/95 [marcfo] : Convert to C++
  106. *
  107. \**************************************************************************/
  108. void
  109. ELLIPTICAL_XC::SetControlPoints( GLfloat r1, GLfloat r2 )
  110. {
  111. GLfloat ac1, ac2;
  112. ac1 = EVAL_CIRC_ARC_CONTROL * r2;
  113. ac2 = EVAL_CIRC_ARC_CONTROL * r1;
  114. // create 12-pt. set CCW from +x
  115. // last 2 points of right triplet
  116. pts[0].x = r1;
  117. pts[0].y = 0.0f;
  118. pts[1].x = r1;
  119. pts[1].y = ac1;
  120. // top triplet
  121. pts[2].x = ac2;
  122. pts[2].y = r2;
  123. pts[3].x = 0.0f;
  124. pts[3].y = r2;
  125. pts[4].x = -ac2;
  126. pts[4].y = r2;
  127. // left triplet
  128. pts[5].x = -r1;
  129. pts[5].y = ac1;
  130. pts[6].x = -r1;
  131. pts[6].y = 0.0f;
  132. pts[7].x = -r1;
  133. pts[7].y = -ac1;
  134. // bottom triplet
  135. pts[8].x = -ac2;
  136. pts[8].y = -r2;
  137. pts[9].x = 0.0f;
  138. pts[9].y = -r2;
  139. pts[10].x = ac2;
  140. pts[10].y = -r2;
  141. // first point of first triplet
  142. pts[11].x = r1;
  143. pts[11].y = -ac1;
  144. }
  145. /**************************************************************************\
  146. * RANDOM4ARC_XC::SetControlPoints
  147. *
  148. * Set random control points for xc
  149. * Points go CCW from +x
  150. *
  151. * History
  152. * July 30, 95 : [marcfo]
  153. * - Wrote it
  154. * - 10/18/95 [marcfo] : Convert to C++
  155. *
  156. \**************************************************************************/
  157. void
  158. RANDOM4ARC_XC::SetControlPoints( float radius )
  159. {
  160. int i;
  161. GLfloat r[4];
  162. float rMin = 0.5f * radius;
  163. float distx, disty;
  164. // figure the radius of each side first
  165. for( i = 0; i < 4; i ++ )
  166. r[i] = ss_fRand( rMin, radius );
  167. // The 4 r's now describe a box around the origin - this restricts stuff
  168. // Now need to select a point along each edge of the box as the joining
  169. // points for each arc (join points are at indices 0,3,6,9)
  170. pts[0].x = r[RIGHT];
  171. pts[3].y = r[TOP];
  172. pts[6].x = -r[LEFT];
  173. pts[9].y = -r[BOTTOM];
  174. // quarter of distance between edges
  175. disty = (r[TOP] - -r[BOTTOM]) / 4.0f;
  176. distx = (r[RIGHT] - -r[LEFT]) / 4.0f;
  177. // uh, put'em somwhere in the middle half of each side
  178. pts[0].y = ss_fRand( -r[BOTTOM] + disty, r[TOP] - disty );
  179. pts[6].y = ss_fRand( -r[BOTTOM] + disty, r[TOP] - disty );
  180. pts[3].x = ss_fRand( -r[LEFT] + distx, r[RIGHT] - distx );
  181. pts[9].x = ss_fRand( -r[LEFT] + distx, r[RIGHT] - distx );
  182. // now can calc ac's
  183. // easy part first:
  184. pts[1].x = pts[11].x = pts[0].x;
  185. pts[2].y = pts[4].y = pts[3].y;
  186. pts[5].x = pts[7].x = pts[6].x;
  187. pts[8].y = pts[10].y = pts[9].y;
  188. // right side ac's
  189. disty = (r[TOP] - pts[0].y) / 4.0f;
  190. pts[1].y = ss_fRand( pts[0].y + disty, r[TOP] );
  191. disty = (pts[0].y - -r[BOTTOM]) / 4.0f;
  192. pts[11].y = ss_fRand( -r[BOTTOM], pts[0].y - disty );
  193. // left side ac's
  194. disty = (r[TOP] - pts[6].y) / 4.0f;
  195. pts[5].y = ss_fRand( pts[6].y + disty, r[TOP]);
  196. disty = (pts[6].y - -r[BOTTOM]) / 4.0f;
  197. pts[7].y = ss_fRand( -r[BOTTOM], pts[6].y - disty );
  198. // top ac's
  199. distx = (r[RIGHT] - pts[3].x) / 4.0f;
  200. pts[2].x = ss_fRand( pts[3].x + distx, r[RIGHT] );
  201. distx = (pts[3].x - -r[LEFT]) / 4.0f;
  202. pts[4].x = ss_fRand( -r[LEFT], pts[3].x - distx );
  203. // bottom ac's
  204. distx = (r[RIGHT] - pts[9].x) / 4.0f;
  205. pts[10].x = ss_fRand( pts[9].x + distx, r[RIGHT] );
  206. distx = (pts[9].x - -r[LEFT]) / 4.0f;
  207. pts[8].x = ss_fRand( -r[LEFT], pts[9].x - distx );
  208. }
  209. /**************************************************************************\
  210. * ConvertPtsZ
  211. *
  212. * Convert the 2D pts in an xc, to 3D pts in point buffer, with z.
  213. *
  214. * Also replicate the last point.
  215. *
  216. * July 28, 95 : [marcfo]
  217. * - Wrote it
  218. *
  219. \**************************************************************************/
  220. void
  221. XC::ConvertPtsZ( POINT3D *newpts, float z )
  222. {
  223. int i;
  224. POINT2D *xcPts = pts;
  225. for( i = 0; i < numPts; i++, newpts++ ) {
  226. *( (POINT2D *) newpts ) = *xcPts++;
  227. newpts->z = z;
  228. }
  229. *newpts = *(newpts - numPts);
  230. }
  231. /**************************************************************************\
  232. * XC::CalcBoundingBox
  233. *
  234. * Calculate bounding box in x/y plane for xc
  235. *
  236. * July 28, 95 : [marcfo]
  237. * - Wrote it
  238. *
  239. \**************************************************************************/
  240. void
  241. XC::CalcBoundingBox( )
  242. {
  243. POINT2D *ppts = pts;
  244. int i;
  245. float xMin, xMax, yMax, yMin;
  246. // initialize to really insane numbers
  247. xMax = yMax = -FLT_MAX;
  248. xMin = yMin = FLT_MAX;
  249. // compare with rest of points
  250. for( i = 0; i < numPts; i ++, ppts++ ) {
  251. if( ppts->x < xMin )
  252. xMin = ppts->x;
  253. else if( ppts->x > xMax )
  254. xMax = ppts->x;
  255. if( ppts->y < yMin )
  256. yMin = ppts->y;
  257. else if( ppts->y > yMax )
  258. yMax = ppts->y;
  259. }
  260. xLeft = xMin;
  261. xRight = xMax;
  262. yBottom = yMin;
  263. yTop = yMax;
  264. }
  265. /**************************************************************************\
  266. *
  267. * MinTurnRadius
  268. *
  269. * Get minimum radius for the xc to turn in given direction.
  270. *
  271. * If the turn radius is less than this minimum, then primitive will 'fold'
  272. * over itself at the inside of the turn, creating ugliness.
  273. *
  274. * History
  275. * July 27, 95 : [marcfo]
  276. * - Wrote it
  277. *
  278. \**************************************************************************/
  279. float
  280. XC::MinTurnRadius( int relDir )
  281. {
  282. //mf: for now, assume xRight, yTop positive, xLeft, yBottom negative
  283. // otherwise, might want to consider 'negative'radius
  284. switch( relDir ) {
  285. case PLUS_X:
  286. return( xRight );
  287. case MINUS_X:
  288. return( - xLeft );
  289. case PLUS_Y:
  290. return( yTop );
  291. case MINUS_Y:
  292. return( - yBottom );
  293. default:
  294. return(0.0f);
  295. }
  296. }
  297. /**************************************************************************\
  298. *
  299. * XC::MaxExtent
  300. *
  301. * Get maximum extent of the xc in x and y
  302. *
  303. * History
  304. * Aug. 1, 95 : [marcfo]
  305. * - Wrote it
  306. *
  307. \**************************************************************************/
  308. float
  309. XC::MaxExtent( )
  310. {
  311. float max;
  312. max = xRight;
  313. if( yTop > max )
  314. max = yTop;
  315. if( -xLeft > max )
  316. max = -xLeft;
  317. if( -yBottom > max )
  318. max = -yBottom;
  319. return max;
  320. }
  321. /**************************************************************************\
  322. *
  323. * XC::Scale
  324. *
  325. * Scale an XC's points and extents by supplied scale value
  326. *
  327. \**************************************************************************/
  328. void
  329. XC::Scale( float scale )
  330. {
  331. int i;
  332. POINT2D *ppts = pts;
  333. for( i = 0; i < numPts; i ++, ppts++ ) {
  334. ppts->x *= scale;
  335. ppts->y *= scale;
  336. }
  337. xLeft *= scale;
  338. xRight *= scale;
  339. yBottom *= scale;
  340. yTop *= scale;
  341. }
  342. /**************************************************************************\
  343. * ~XC::XC
  344. *
  345. * Destructor
  346. *
  347. \**************************************************************************/
  348. XC::~XC()
  349. {
  350. if( pts )
  351. LocalFree( pts );
  352. }
  353. /**************************************************************************\
  354. * XC::XC
  355. *
  356. * Constructor
  357. *
  358. * - Allocates point buffer for the xc
  359. *
  360. \**************************************************************************/
  361. XC::XC( int nPts )
  362. {
  363. numPts = nPts;
  364. pts = (POINT2D *) LocalAlloc( LMEM_FIXED, numPts * sizeof(POINT2D) );
  365. SS_ASSERT( pts != 0, "XC constructor\n" );
  366. }
  367. #if 0
  368. /**************************************************************************\
  369. * XC::XC
  370. *
  371. * Constructor
  372. *
  373. * - Copies data from another XC
  374. *
  375. \**************************************************************************/
  376. //mf: couldn't get calling this to work (compile time)
  377. XC::XC( const XC& xc )
  378. {
  379. numPts = xc.numPts;
  380. pts = (POINT2D *) LocalAlloc( LMEM_FIXED, numPts * sizeof(POINT2D) );
  381. SS_ASSERT( pts != 0, "XC constructor\n" );
  382. RtlCopyMemory( pts, xc.pts, numPts * sizeof(POINT2D) );
  383. xLeft = xc.xLeft;
  384. xRight = xc.xRight;
  385. yBottom = xc.yBottom;
  386. yTop = xc.yTop;
  387. }
  388. #endif
  389. XC::XC( XC *xc )
  390. {
  391. numPts = xc->numPts;
  392. pts = (POINT2D *) LocalAlloc( LMEM_FIXED, numPts * sizeof(POINT2D) );
  393. SS_ASSERT( pts != 0, "XC constructor\n" );
  394. RtlCopyMemory( pts, xc->pts, numPts * sizeof(POINT2D) );
  395. xLeft = xc->xLeft;
  396. xRight = xc->xRight;
  397. yBottom = xc->yBottom;
  398. yTop = xc->yTop;
  399. }
  400. /**************************************************************************\
  401. *
  402. * ELLIPTICAL_XC::ELLIPTICALXC
  403. *
  404. * Elliptical XC constructor
  405. * These have 4 sections of 4 pts each, with pts shared between sections.
  406. *
  407. \**************************************************************************/
  408. ELLIPTICAL_XC::ELLIPTICAL_XC( float r1, float r2 )
  409. // initialize base XC with numPts
  410. : XC( (int) EVAL_XC_CIRC_SECTION_COUNT * (EVAL_ARC_ORDER - 1))
  411. {
  412. SetControlPoints( r1, r2 );
  413. CalcBoundingBox( );
  414. }
  415. /**************************************************************************\
  416. *
  417. * RANDOM4ARC_XC::RANDOM4ARC_XC
  418. *
  419. * Random 4-arc XC constructor
  420. * The bounding box is 2*r each side
  421. * These have 4 sections of 4 pts each, with pts shared between sections.
  422. *
  423. \**************************************************************************/
  424. RANDOM4ARC_XC::RANDOM4ARC_XC( float r )
  425. // initialize base XC with numPts
  426. : XC( (int) EVAL_XC_CIRC_SECTION_COUNT * (EVAL_ARC_ORDER - 1))
  427. {
  428. SetControlPoints( r );
  429. CalcBoundingBox( );
  430. }