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.

718 lines
22 KiB

  1. //-----------------------------------------------------------------------------
  2. // File: fpipe.cpp
  3. //
  4. // Desc: Flex pipes
  5. //
  6. // All Draw routines start with current xc at the beginning, and create
  7. // a new one at the end. Since it is common to just have 2 xc's for
  8. // each prim, xcCur holds the current xc, and xcEnd is available
  9. // for the draw routine to use as the end xc.
  10. // They also reset xcCur when done
  11. //
  12. // Copyright (c) 1994-2000 Microsoft Corporation
  13. //-----------------------------------------------------------------------------
  14. #include "stdafx.h"
  15. // defCylNotch shows the absolute notch for the default cylinder,
  16. // given a direction (notch is always along +x axis)
  17. static int defCylNotch[NUM_DIRS] =
  18. { MINUS_Z, PLUS_Z, PLUS_X, PLUS_X, PLUS_X, MINUS_X };
  19. static int GetRelativeDir( int lastDir, int notchVec, int newDir );
  20. //-----------------------------------------------------------------------------
  21. // Name: FLEX_PIPE constructor
  22. // Desc:
  23. //-----------------------------------------------------------------------------
  24. FLEX_PIPE::FLEX_PIPE( STATE *pState ) : PIPE( pState )
  25. {
  26. float circ;
  27. // Create an EVAL object
  28. m_nSlices = pState->m_nSlices;
  29. // No XC's yet, they will be allocated at pipe Start()
  30. m_xcCur = m_xcEnd = NULL;
  31. // The EVAL will be used for all pEvals in the pipe, so should be
  32. // set to hold max. possible # of pts for the pipe.
  33. m_pEval = new EVAL( m_pState->m_bUseTexture );
  34. // Determine pipe tesselation
  35. // For now, this is based on global tesselation factor
  36. //mf: maybe clean up this scheme a bit
  37. // Calculate evalDivSize, a reference value for the size of a UxV division.
  38. // This is used later for calculating texture coords.
  39. circ = CIRCUMFERENCE( pState->m_radius );
  40. m_evalDivSize = circ / (float) m_nSlices;
  41. }
  42. //-----------------------------------------------------------------------------
  43. // Name: ~FLEX_PIPE
  44. // Desc:
  45. //-----------------------------------------------------------------------------
  46. FLEX_PIPE::~FLEX_PIPE( )
  47. {
  48. delete m_pEval;
  49. // delete any XC's
  50. if( m_xcCur != NULL )
  51. {
  52. if( m_xcEnd == m_xcCur )
  53. //mf: so far this can't happen...
  54. m_xcEnd = NULL; // xcCur and xcEnd can point to same xc !
  55. delete m_xcCur;
  56. m_xcCur = NULL;
  57. }
  58. if( m_xcEnd != NULL )
  59. {
  60. delete m_xcEnd;
  61. m_xcEnd = NULL;
  62. }
  63. }
  64. //-----------------------------------------------------------------------------
  65. // Name: REGULAR_FLEX_PIPE constructor
  66. // Desc:
  67. //-----------------------------------------------------------------------------
  68. REGULAR_FLEX_PIPE::REGULAR_FLEX_PIPE( STATE *state ) : FLEX_PIPE( state )
  69. {
  70. static float turnFactorRange = 0.1f;
  71. m_type = TYPE_FLEX_REGULAR;
  72. // figure out turning factor range (0 for min bends, 1 for max bends)
  73. #if 1
  74. float avgTurn = CPipesScreensaver::fRand( 0.11f, 0.81f );
  75. // set min and max turn factors, and clamp to 0..1
  76. m_turnFactorMin =
  77. SS_CLAMP_TO_RANGE( avgTurn - turnFactorRange, 0.0f, 1.0f );
  78. m_turnFactorMax =
  79. SS_CLAMP_TO_RANGE( avgTurn + turnFactorRange, 0.0f, 1.0f );
  80. #else
  81. // debug: test max bend
  82. turnFactorMin = turnFactorMax = 1.0f;
  83. #endif
  84. // choose straight weighting
  85. // mf:for now, same as npipe - if stays same, put in pipe
  86. if( !CPipesScreensaver::iRand( 20 ) )
  87. m_weightStraight = CPipesScreensaver::iRand2( MAX_WEIGHT_STRAIGHT/4, MAX_WEIGHT_STRAIGHT );
  88. else
  89. m_weightStraight = CPipesScreensaver::iRand( 4 );
  90. }
  91. //-----------------------------------------------------------------------------
  92. // Name: TURNING_FLEX_PIPE constructor
  93. // Desc:
  94. //-----------------------------------------------------------------------------
  95. TURNING_FLEX_PIPE::TURNING_FLEX_PIPE( STATE *state ) : FLEX_PIPE( state )
  96. {
  97. m_type = TYPE_FLEX_TURNING;
  98. }
  99. //-----------------------------------------------------------------------------
  100. // Name: SetTexIndex
  101. // Desc: Set the texture index for this pipe, and calculate texture state dependent
  102. // on texRep values
  103. //-----------------------------------------------------------------------------
  104. void FLEX_PIPE::SetTexParams( TEXTUREINFO *pTex, IPOINT2D *pTexRep )
  105. {
  106. if( m_pState->m_bUseTexture )
  107. {
  108. /*
  109. float m_tSize;
  110. float circ;
  111. m_tStart = (float) pTexRep->y * 1.0f;
  112. m_tEnd = 0.0f;
  113. // calc height (m_tSize) of one rep of texture around circumference
  114. circ = CIRCUMFERENCE( m_radius );
  115. m_tSize = circ / pTexRep->y;
  116. // now calc corresponding width of the texture using its x/y ratio
  117. m_sLength = m_tSize / pTex->origAspectRatio;
  118. m_sStart = m_sEnd = 0.0f;
  119. */
  120. //mf: this means we are 'standardizing' the texture size and proportions
  121. // on pipe of radius 1.0 for entire program. Might want to recalc this on
  122. // a per-pipe basis ?
  123. }
  124. }
  125. //-----------------------------------------------------------------------------
  126. // Name: ChooseXCProfile
  127. // Desc: Initialize extruded pipe scheme. This uses a randomly constructed
  128. // XC, but it remains constant throughout the pipe
  129. //-----------------------------------------------------------------------------
  130. void FLEX_PIPE::ChooseXCProfile()
  131. {
  132. static float turnFactorRange = 0.1f;
  133. float baseRadius = m_pState->m_radius;
  134. // initialize evaluator elements:
  135. m_pEval->m_numSections = EVAL_XC_CIRC_SECTION_COUNT;
  136. m_pEval->m_uOrder = EVAL_ARC_ORDER;
  137. //mf: watch this - maybe should ROUND_UP uDiv
  138. // set uDiv per section (assumed uDiv multiple of numSections)
  139. m_pEval->m_uDiv = m_nSlices / m_pEval->m_numSections;
  140. // Setup XC's
  141. // The xc profile remains constant throughout in this case,
  142. // so we only need one xc.
  143. // Choose between elliptical or random cross-sections. Since elliptical
  144. // looks a little better, make it more likely
  145. if( CPipesScreensaver::iRand(4) ) // 3/4 of the time
  146. m_xcCur = new ELLIPTICAL_XC( CPipesScreensaver::fRand(1.2f, 2.0f) * baseRadius,
  147. baseRadius );
  148. else
  149. m_xcCur = new RANDOM4ARC_XC( CPipesScreensaver::fRand(1.5f, 2.0f) * baseRadius );
  150. }
  151. //-----------------------------------------------------------------------------
  152. // Name: REGULAR_FLEX_PIPE::Start
  153. // Desc: Does startup of extruded-XC pipe drawing scheme
  154. //-----------------------------------------------------------------------------
  155. void REGULAR_FLEX_PIPE::Start()
  156. {
  157. NODE_ARRAY* nodes = m_pState->m_nodes;
  158. int newDir;
  159. // Set start position
  160. if( !SetStartPos() )
  161. {
  162. m_status = PIPE_OUT_OF_NODES;
  163. return;
  164. }
  165. // set material
  166. ChooseMaterial();
  167. // set XC profile
  168. ChooseXCProfile();
  169. // push matrix with zTrans and scene rotation
  170. // glPushMatrix();
  171. // Translate to current position
  172. TranslateToCurrentPosition();
  173. // set random lastDir
  174. m_lastDir = CPipesScreensaver::iRand( NUM_DIRS );
  175. // get a new node to draw to
  176. newDir = ChooseNewDirection();
  177. if( newDir == DIR_NONE )
  178. {
  179. // draw like one of those tea-pouring thingies...
  180. m_status = PIPE_STUCK;
  181. // glPopMatrix();
  182. return;
  183. }
  184. else
  185. {
  186. m_status = PIPE_ACTIVE;
  187. }
  188. align_plusz( newDir ); // get us pointed in right direction
  189. // draw start cap, which will end right at current node
  190. DrawCap( START_CAP );
  191. // set initial notch vector, which is just the default notch, since
  192. // we didn't have to spin the start cap around z
  193. m_notchVec = defCylNotch[newDir];
  194. m_zTrans = - m_pState->m_view.m_divSize; // distance back from new node
  195. UpdateCurrentPosition( newDir );
  196. m_lastDir = newDir;
  197. }
  198. //-----------------------------------------------------------------------------
  199. // Name: TURNING_FLEX_PIPE::Start
  200. // Desc: Does startup of turning extruded-XC pipe drawing scheme
  201. //-----------------------------------------------------------------------------
  202. void TURNING_FLEX_PIPE::Start( )
  203. {
  204. NODE_ARRAY* nodes = m_pState->m_nodes;
  205. // Set start position
  206. if( !SetStartPos() )
  207. {
  208. m_status = PIPE_OUT_OF_NODES;
  209. return;
  210. }
  211. // Set material
  212. ChooseMaterial();
  213. // Set XC profile
  214. ChooseXCProfile();
  215. // Push matrix with zTrans and scene rotation
  216. // glPushMatrix();
  217. // Translate to current position
  218. TranslateToCurrentPosition();
  219. // lastDir has to be set to something valid, in case we get stuck right
  220. // away, cuz Draw() will be called anyways on next iteration, whereupon
  221. // it finds out it really is stuck, AFTER calling ChooseNewTurnDirection,
  222. // which requires valid lastDir. (mf: fix this)
  223. m_lastDir = CPipesScreensaver::iRand( NUM_DIRS );
  224. // Pick a starting direction by finding a neihgbouring empty node
  225. int newDir = nodes->FindClearestDirection( &m_curPos );
  226. // We don't 'choose' it, or mark it as taken, because ChooseNewDirection
  227. // will always check it anyways
  228. if( newDir == DIR_NONE )
  229. {
  230. // we can't go anywhere
  231. // draw like one of those tea-pouring thingies...
  232. m_status = PIPE_STUCK;
  233. // glPopMatrix();
  234. return;
  235. }
  236. else
  237. {
  238. m_status = PIPE_ACTIVE;
  239. }
  240. align_plusz( newDir ); // get us pointed in right direction
  241. // Draw start cap, which will end right at current node
  242. DrawCap( START_CAP );
  243. // Set initial notch vector, which is just the default notch, since
  244. // we didn't have to spin the start cap around z
  245. m_notchVec = defCylNotch[newDir];
  246. m_zTrans = 0.0f; // right at current node
  247. m_lastDir = newDir;
  248. }
  249. //-----------------------------------------------------------------------------
  250. // Name: REGULAR_FLEX_PIPE::Draw
  251. // Desc: Draws the pipe using a constant random xc that is extruded
  252. //
  253. // Minimum turn radius can vary, since xc is not symmetrical across any
  254. // of its axes. Therefore here we draw using a pipe/elbow sequence, so we
  255. // know what direction we're going in before drawing the elbow. The current
  256. // node is the one we will draw thru next time. Typically, the actual end
  257. // of the pipe is way back of this node, almost at the previous node, due
  258. // to the variable turn radius
  259. //-----------------------------------------------------------------------------
  260. void REGULAR_FLEX_PIPE::Draw()
  261. {
  262. float turnRadius, minTurnRadius;
  263. float pipeLen, maxPipeLen, minPipeLen;
  264. int newDir, relDir;
  265. float maxXCExtent;
  266. NODE_ARRAY* nodes = m_pState->m_nodes;
  267. float divSize = m_pState->m_view.m_divSize;
  268. // get new direction
  269. newDir = ChooseNewDirection();
  270. if( newDir == DIR_NONE )
  271. {
  272. m_status = PIPE_STUCK;
  273. DrawCap( END_CAP );
  274. // glPopMatrix();
  275. return;
  276. }
  277. // draw pipe, and if turning, joint
  278. if( newDir != m_lastDir )
  279. {
  280. // turning! - we have to draw joint
  281. // get relative turn, to figure turn radius
  282. relDir = GetRelativeDir( m_lastDir, m_notchVec, newDir );
  283. minTurnRadius = m_xcCur->MinTurnRadius( relDir );
  284. // now calc maximum straight section we can draw before turning
  285. // zTrans is current pos'n of end of pipe, from current node ??
  286. // zTrans is current pos'n of end of pipe, from last node
  287. maxPipeLen = (-m_zTrans) - minTurnRadius;
  288. // there is also a minimum requirement for the length of the straight
  289. // section, cuz if we turn too soon with a large turn radius, we
  290. // will swing up too close to the next node, and won't be able to
  291. // make one or more of the 4 possible turns from that point
  292. maxXCExtent = m_xcCur->MaxExtent(); // in case need it again
  293. minPipeLen = maxXCExtent - (divSize + m_zTrans);
  294. if( minPipeLen < 0.0f )
  295. minPipeLen = 0.0f;
  296. // Choose length of straight section
  297. // (we are translating from turnFactor to 'straightFactor' here)
  298. pipeLen = minPipeLen +
  299. CPipesScreensaver::fRand( 1.0f - m_turnFactorMax, 1.0f - m_turnFactorMin ) *
  300. (maxPipeLen - minPipeLen);
  301. // turn radius is whatever's left over:
  302. turnRadius = maxPipeLen - pipeLen + minTurnRadius;
  303. // draw straight section
  304. DrawExtrudedXCObject( pipeLen );
  305. m_zTrans += pipeLen; // not necessary for now, since elbow no use
  306. // draw elbow
  307. // this updates axes, notchVec to position at end of elbow
  308. DrawXCElbow( newDir, turnRadius );
  309. m_zTrans = -(divSize - turnRadius); // distance back from node
  310. }
  311. else
  312. {
  313. // no turn
  314. // draw a straight pipe through the current node
  315. // length can vary according to the turnFactors (e.g. for high turn
  316. // factors draw a short pipe, so next turn can be as big as possible)
  317. minPipeLen = -m_zTrans; // brings us just up to last node
  318. maxPipeLen = minPipeLen + divSize - m_xcCur->MaxExtent();
  319. // brings us as close as possible to new node
  320. pipeLen = minPipeLen +
  321. CPipesScreensaver::fRand( 1.0f - m_turnFactorMax, 1.0f - m_turnFactorMin ) *
  322. (maxPipeLen - minPipeLen);
  323. // draw pipe
  324. DrawExtrudedXCObject( pipeLen );
  325. m_zTrans += (-divSize + pipeLen);
  326. }
  327. UpdateCurrentPosition( newDir );
  328. m_lastDir = newDir;
  329. }
  330. //-----------------------------------------------------------------------------
  331. // Name: DrawTurningXCPipe
  332. // Desc: Draws the pipe using only turns
  333. // - Go straight if no turns available
  334. //-----------------------------------------------------------------------------
  335. void TURNING_FLEX_PIPE::Draw()
  336. {
  337. float turnRadius;
  338. int newDir;
  339. NODE_ARRAY *nodes = m_pState->m_nodes;
  340. float divSize = m_pState->m_view.m_divSize;
  341. // get new direction
  342. //mf: pipe may have gotten stuck on Start...(we don't check for this)
  343. newDir = nodes->ChooseNewTurnDirection( &m_curPos, m_lastDir );
  344. if( newDir == DIR_NONE )
  345. {
  346. m_status = PIPE_STUCK;
  347. DrawCap( END_CAP );
  348. // glPopMatrix();
  349. return;
  350. }
  351. if( newDir == DIR_STRAIGHT )
  352. {
  353. // No turns available - draw straight section and hope for turns
  354. // on next iteration
  355. DrawExtrudedXCObject( divSize );
  356. UpdateCurrentPosition( m_lastDir );
  357. // ! we have to mark node as taken for this case, since
  358. // ChooseNewTurnDirection doesn't know whether we're taking the
  359. // straight option or not
  360. nodes->NodeVisited( &m_curPos );
  361. }
  362. else
  363. {
  364. // draw turning pipe
  365. // since xc is always located right at current node, turn radius
  366. // stays constant at one node division
  367. turnRadius = divSize;
  368. DrawXCElbow( newDir, turnRadius );
  369. // (zTrans stays at 0)
  370. // need to update 2 nodes
  371. UpdateCurrentPosition( m_lastDir );
  372. UpdateCurrentPosition( newDir );
  373. m_lastDir = newDir;
  374. }
  375. }
  376. //-----------------------------------------------------------------------------
  377. // Name: DrawXCElbow
  378. // Desc: Draw elbow from current position through new direction
  379. // - Extends current xc around bend
  380. // - Radius of bend is provided - this is distance from xc center to hinge
  381. // point, along newDir. e.g. for 'normal pipes', radius=vc->radius
  382. //-----------------------------------------------------------------------------
  383. void FLEX_PIPE::DrawXCElbow( int newDir, float radius )
  384. {
  385. int relDir; // 'relative' direction of turn
  386. float length;
  387. length = (2.0f * PI * radius) / 4.0f; // average length of elbow
  388. // calc vDiv, texture params based on length
  389. //mf: I think we should improve resolution of elbows - more vDiv's
  390. // could rewrite this fn to take a vDivSize
  391. CalcEvalLengthParams( length );
  392. m_pEval->m_vOrder = EVAL_ARC_ORDER;
  393. // convert absolute dir to relative dir
  394. relDir = GetRelativeDir( m_lastDir, m_notchVec, newDir );
  395. // draw it - call simple bend function
  396. m_pEval->ProcessXCPrimBendSimple( m_xcCur, relDir, radius );
  397. /*
  398. // set transf. matrix to new position by translating/rotating/translating
  399. // ! Based on simple elbow
  400. glTranslatef( 0.0f, 0.0f, radius );
  401. switch( relDir )
  402. {
  403. case PLUS_X:
  404. glRotatef( 90.0f, 0.0f, 1.0f, 0.0f );
  405. break;
  406. case MINUS_X:
  407. glRotatef( -90.0f, 0.0f, 1.0f, 0.0f );
  408. break;
  409. case PLUS_Y:
  410. glRotatef( -90.0f, 1.0f, 0.0f, 0.0f );
  411. break;
  412. case MINUS_Y:
  413. glRotatef( 90.0f, 1.0f, 0.0f, 0.0f );
  414. break;
  415. }
  416. glTranslatef( 0.0f, 0.0f, radius );
  417. */
  418. // update notch vector using old function
  419. m_notchVec = notchTurn[m_lastDir][newDir][m_notchVec];
  420. }
  421. //-----------------------------------------------------------------------------
  422. // Name: DrawExtrudedXCObject
  423. // Desc: Draws object generated by extruding the current xc
  424. // Object starts at xc at origin in z=0 plane, and grows along +z axis
  425. //-----------------------------------------------------------------------------
  426. void FLEX_PIPE::DrawExtrudedXCObject( float length )
  427. {
  428. // calc vDiv, and texture coord stuff based on length
  429. // this also calcs pEval texture ctrl pt arrray now
  430. CalcEvalLengthParams( length );
  431. // we can fill in some more stuff:
  432. m_pEval->m_vOrder = EVAL_CYLINDER_ORDER;
  433. #if 0
  434. // continuity stuff
  435. prim.contStart = prim.contEnd = CONT_1; // geometric continuity
  436. #endif
  437. // draw it
  438. //mf: this fn doesn't really handle continutity for 2 different xc's, so
  439. // may as well pass it one xc
  440. m_pEval->ProcessXCPrimLinear( m_xcCur, m_xcCur, length );
  441. // update state draw axes position
  442. // glTranslatef( 0.0f, 0.0f, length );
  443. }
  444. //-----------------------------------------------------------------------------
  445. // Name: DrawXCCap
  446. // Desc: Cap the start of the pipe
  447. // Needs newDir, so it can orient itself.
  448. // Cap ends at current position with approppriate profile, starts a distance
  449. // 'z' back along newDir.
  450. // Profile is a singularity at start point.
  451. //-----------------------------------------------------------------------------
  452. void FLEX_PIPE::DrawCap( int type )
  453. {
  454. float radius;
  455. XC *xc = m_xcCur;
  456. BOOL bOpening = (type == START_CAP) ? TRUE : FALSE;
  457. float length;
  458. // set radius as average of the bounding box min/max's
  459. radius = ((xc->m_xRight - xc->m_xLeft) + (xc->m_yTop - xc->m_yBottom)) / 4.0f;
  460. length = (2.0f * PI * radius) / 4.0f; // average length of arc
  461. // calc vDiv, and texture coord stuff based on length
  462. CalcEvalLengthParams( length );
  463. // we can fill in some more stuff:
  464. m_pEval->m_vOrder = EVAL_ARC_ORDER;
  465. // draw it
  466. m_pEval->ProcessXCPrimSingularity( xc, radius, bOpening );
  467. }
  468. //-----------------------------------------------------------------------------
  469. // Name: CalcEvalLengthParams
  470. // Desc: Calculate pEval values that depend on the length of the extruded object
  471. // - calculate vDiv, m_sStart, m_sEnd, and the texture control net array
  472. //-----------------------------------------------------------------------------
  473. void FLEX_PIPE::CalcEvalLengthParams( float length )
  474. {
  475. m_pEval->m_vDiv = (int ) SS_ROUND_UP( length / m_evalDivSize );
  476. // calc texture start and end coords
  477. if( m_pState->m_bUseTexture )
  478. {
  479. float s_delta;
  480. // Don't let m_sEnd overflow : it should stay in range (0..1.0)
  481. if( m_sEnd > 1.0f )
  482. m_sEnd -= (int) m_sEnd;
  483. m_sStart = m_sEnd;
  484. s_delta = (length / m_sLength );
  485. m_sEnd = m_sStart + s_delta;
  486. // the texture ctrl point array can be calc'd here - it is always
  487. // a simple 2x2 array for each section
  488. m_pEval->SetTextureControlPoints( m_sStart, m_sEnd, m_tStart, m_tEnd );
  489. }
  490. }
  491. //-----------------------------------------------------------------------------
  492. // Name: relDir
  493. // Desc: this array tells you relative turn
  494. // format: relDir[lastDir][notchVec][newDir]
  495. //-----------------------------------------------------------------------------
  496. static int relDir[NUM_DIRS][NUM_DIRS][NUM_DIRS] =
  497. {
  498. // +x -x +y -y +z -z (newDir)
  499. // lastDir = +x
  500. iXX, iXX, iXX, iXX, iXX, iXX,
  501. iXX, iXX, iXX, iXX, iXX, iXX,
  502. iXX, iXX, PLUS_X, MINUS_X,PLUS_Y, MINUS_Y,
  503. iXX, iXX, MINUS_X,PLUS_X, MINUS_Y,PLUS_Y,
  504. iXX, iXX, MINUS_Y,PLUS_Y, PLUS_X, MINUS_X,
  505. iXX, iXX, PLUS_Y, MINUS_Y,MINUS_X,PLUS_X,
  506. // lastDir = -x
  507. iXX, iXX, iXX, iXX, iXX, iXX,
  508. iXX, iXX, iXX, iXX, iXX, iXX,
  509. iXX, iXX, PLUS_X, MINUS_X,MINUS_Y,PLUS_Y,
  510. iXX, iXX, MINUS_X,PLUS_X, PLUS_Y, MINUS_Y,
  511. iXX, iXX, PLUS_Y, MINUS_Y,PLUS_X, MINUS_X,
  512. iXX, iXX, MINUS_Y,PLUS_Y, MINUS_X,PLUS_X,
  513. // lastDir = +y
  514. PLUS_X, MINUS_X,iXX, iXX, MINUS_Y,PLUS_Y,
  515. MINUS_X,PLUS_X, iXX, iXX, PLUS_Y, MINUS_Y,
  516. iXX, iXX, iXX, iXX, iXX, iXX,
  517. iXX, iXX, iXX, iXX, iXX, iXX,
  518. PLUS_Y, MINUS_Y,iXX, iXX, PLUS_X, MINUS_X,
  519. MINUS_Y,PLUS_Y, iXX, iXX, MINUS_X,PLUS_X,
  520. // lastDir = -y
  521. PLUS_X, MINUS_X,iXX, iXX, PLUS_Y, MINUS_Y,
  522. MINUS_X,PLUS_X, iXX, iXX, MINUS_Y,PLUS_Y,
  523. iXX, iXX, iXX, iXX, iXX, iXX,
  524. iXX, iXX, iXX, iXX, iXX, iXX,
  525. MINUS_Y,PLUS_Y, iXX, iXX, PLUS_X, MINUS_X,
  526. PLUS_Y, MINUS_Y,iXX, iXX, MINUS_X,PLUS_X,
  527. // lastDir = +z
  528. PLUS_X, MINUS_X,PLUS_Y, MINUS_Y,iXX, iXX,
  529. MINUS_X,PLUS_X, MINUS_Y,PLUS_Y, iXX, iXX,
  530. MINUS_Y,PLUS_Y, PLUS_X, MINUS_X,iXX, iXX,
  531. PLUS_Y, MINUS_Y,MINUS_X,PLUS_X, iXX, iXX,
  532. iXX, iXX, iXX, iXX, iXX, iXX,
  533. iXX, iXX, iXX, iXX, iXX, iXX,
  534. // lastDir = -z
  535. PLUS_X, MINUS_X,MINUS_Y,PLUS_Y, iXX, iXX,
  536. MINUS_X,PLUS_X, PLUS_Y, MINUS_Y,iXX, iXX,
  537. PLUS_Y, MINUS_Y,PLUS_X, MINUS_X,iXX, iXX,
  538. MINUS_Y,PLUS_Y, MINUS_X,PLUS_X, iXX, iXX,
  539. iXX, iXX, iXX, iXX, iXX, iXX,
  540. iXX, iXX, iXX, iXX, iXX, iXX
  541. };
  542. //-----------------------------------------------------------------------------
  543. // Name: GetRelativeDir
  544. // Desc: Calculates relative direction of turn from lastDir, notchVec, newDir
  545. // - Use look up table for now.
  546. // - Relative direction is from xy-plane, and can be +x,-x,+y,-y
  547. // - In current orientation, +z is along lastDir, +x along notchVec
  548. //-----------------------------------------------------------------------------
  549. static int GetRelativeDir( int lastDir, int notchVec, int newDir )
  550. {
  551. return( relDir[lastDir][notchVec][newDir] );
  552. }