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.

473 lines
14 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: npipe.cxx
  3. *
  4. * Normal pipes code
  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 <sys/timeb.h>
  15. #include <time.h>
  16. #include <windows.h>
  17. #include "sspipes.h"
  18. #include "npipe.h"
  19. #include "state.h"
  20. static void align_notch( int newDir, int notch );
  21. static void align_plusy( int oldDir, int newDir );
  22. // defCylNotch shows where the notch for the default cylinder will be,
  23. // in absolute coords, once we do an align_plusz
  24. static GLint defCylNotch[NUM_DIRS] =
  25. { PLUS_Y, PLUS_Y, MINUS_Z, PLUS_Z, PLUS_Y, PLUS_Y };
  26. /**************************************************************************\
  27. * NORMAL_PIPE constructor
  28. *
  29. *
  30. \**************************************************************************/
  31. NORMAL_PIPE::NORMAL_PIPE( STATE *pState )
  32. : PIPE( pState )
  33. {
  34. int choice;
  35. type = TYPE_NORMAL;
  36. pNState = pState->pNState;
  37. // choose weighting of going straight
  38. if( ! ss_iRand( 20 ) )
  39. weightStraight = ss_iRand2( MAX_WEIGHT_STRAIGHT/4, MAX_WEIGHT_STRAIGHT );
  40. else
  41. weightStraight = 1 + ss_iRand( 4 );
  42. }
  43. /**************************************************************************\
  44. * Start
  45. *
  46. * Start drawing a new normal pipe
  47. *
  48. * - Draw a start cap and short pipe in new direction
  49. *
  50. * History
  51. * July 27, 95 : [marcfo]
  52. * - Wrote it
  53. *
  54. \**************************************************************************/
  55. void
  56. NORMAL_PIPE::Start( )
  57. {
  58. int newDir;
  59. // Set start position
  60. if( !SetStartPos() ) {
  61. status = PIPE_OUT_OF_NODES;
  62. return;
  63. }
  64. // set a material
  65. ChooseMaterial();
  66. // push matrix that has initial zTrans and rotation
  67. glPushMatrix();
  68. // Translate to current position
  69. TranslateToCurrentPosition();
  70. // Pick a random lastDir
  71. lastDir = ss_iRand( NUM_DIRS );
  72. newDir = ChooseNewDirection();
  73. if( newDir == DIR_NONE ) {
  74. // pipe is stuck at the start node, draw something
  75. status = PIPE_STUCK;
  76. DrawTeapot();
  77. glPopMatrix();
  78. return;
  79. } else
  80. status = PIPE_ACTIVE;
  81. // set initial notch vector
  82. notchVec = defCylNotch[newDir];
  83. DrawStartCap( newDir );
  84. // move ahead 1.0*r to draw pipe
  85. glTranslatef( 0.0f, 0.0f, radius );
  86. // draw short pipe
  87. align_notch( newDir, notchVec );
  88. pNState->shortPipe->Draw();
  89. glPopMatrix();
  90. UpdateCurrentPosition( newDir );
  91. lastDir = newDir;
  92. }
  93. /**************************************************************************\
  94. * Draw
  95. *
  96. * - if turning, draws a joint and a short cylinder, otherwise
  97. * draws a long cylinder.
  98. * - the 'current node' is set as the one we draw thru the NEXT
  99. * time around.
  100. *
  101. \**************************************************************************/
  102. void
  103. NORMAL_PIPE::Draw()
  104. {
  105. int newDir;
  106. newDir = ChooseNewDirection();
  107. if( newDir == DIR_NONE ) { // no empty nodes - nowhere to go
  108. DrawEndCap();
  109. status = PIPE_STUCK;
  110. return;
  111. }
  112. // push matrix that has initial zTrans and rotation
  113. glPushMatrix();
  114. // Translate to current position
  115. TranslateToCurrentPosition();
  116. // draw joint if necessary, and pipe
  117. if( newDir != lastDir ) { // turning! - we have to draw joint
  118. DrawJoint( newDir );
  119. // draw short pipe
  120. align_notch( newDir, notchVec );
  121. pNState->shortPipe->Draw();
  122. }
  123. else { // no turn
  124. // draw long pipe, from point 1.0*r back
  125. align_plusz( newDir );
  126. align_notch( newDir, notchVec );
  127. glTranslatef( 0.0f, 0.0f, -radius );
  128. pNState->longPipe->Draw();
  129. }
  130. glPopMatrix();
  131. UpdateCurrentPosition( newDir );
  132. lastDir = newDir;
  133. }
  134. /**************************************************************************\
  135. * DrawStartCap
  136. *
  137. * Cap the start of the pipe with a ball
  138. *
  139. * History
  140. * July 4, 95 : [marcfo]
  141. * - Wrote it
  142. *
  143. \**************************************************************************/
  144. void
  145. NORMAL_PIPE::DrawStartCap( int newDir )
  146. {
  147. if( bTexture ) {
  148. align_plusz( newDir );
  149. pNState->ballCap->Draw();
  150. }
  151. else {
  152. // draw big ball in default orientation
  153. pNState->bigBall->Draw();
  154. align_plusz( newDir );
  155. }
  156. }
  157. /**************************************************************************\
  158. * DrawEndCap():
  159. *
  160. * - Draws a ball, used to cap end of a pipe
  161. *
  162. \**************************************************************************/
  163. void
  164. NORMAL_PIPE::DrawEndCap( )
  165. {
  166. glPushMatrix();
  167. // Translate to current position
  168. TranslateToCurrentPosition();
  169. if( bTexture ) {
  170. glPushMatrix();
  171. align_plusz( lastDir );
  172. align_notch( lastDir, notchVec );
  173. pNState->ballCap->Draw();
  174. glPopMatrix();
  175. }
  176. else
  177. pNState->bigBall->Draw();
  178. glPopMatrix();
  179. }
  180. /**************************************************************************\
  181. * ChooseElbow
  182. *
  183. * - Decides which elbow to draw
  184. * - The beginning of each elbow is aligned along +y, and we have
  185. * to choose the one with the notch in correct position
  186. * - The 'primary' start notch (elbow[0]) is in same direction as
  187. * newDir, and successive elbows rotate this notch CCW around +y
  188. *
  189. \**************************************************************************/
  190. // this array supplies the sequence of elbow notch vectors, given
  191. // oldDir and newDir (0's are don't cares)
  192. // it is also used to determine the ending notch of an elbow
  193. static GLint notchElbDir[NUM_DIRS][NUM_DIRS][4] = {
  194. // oldDir = +x
  195. iXX, iXX, iXX, iXX,
  196. iXX, iXX, iXX, iXX,
  197. PLUS_Y, MINUS_Z, MINUS_Y, PLUS_Z,
  198. MINUS_Y, PLUS_Z, PLUS_Y, MINUS_Z,
  199. PLUS_Z, PLUS_Y, MINUS_Z, MINUS_Y,
  200. MINUS_Z, MINUS_Y, PLUS_Z, PLUS_Y,
  201. // oldDir = -x
  202. iXX, iXX, iXX, iXX,
  203. iXX, iXX, iXX, iXX,
  204. PLUS_Y, PLUS_Z, MINUS_Y, MINUS_Z,
  205. MINUS_Y, MINUS_Z, PLUS_Y, PLUS_Z,
  206. PLUS_Z, MINUS_Y, MINUS_Z, PLUS_Y,
  207. MINUS_Z, PLUS_Y, PLUS_Z, MINUS_Y,
  208. // oldDir = +y
  209. PLUS_X, PLUS_Z, MINUS_X, MINUS_Z,
  210. MINUS_X, MINUS_Z, PLUS_X, PLUS_Z,
  211. iXX, iXX, iXX, iXX,
  212. iXX, iXX, iXX, iXX,
  213. PLUS_Z, MINUS_X, MINUS_Z, PLUS_X,
  214. MINUS_Z, PLUS_X, PLUS_Z, MINUS_X,
  215. // oldDir = -y
  216. PLUS_X, MINUS_Z, MINUS_X, PLUS_Z,
  217. MINUS_X, PLUS_Z, PLUS_X, MINUS_Z,
  218. iXX, iXX, iXX, iXX,
  219. iXX, iXX, iXX, iXX,
  220. PLUS_Z, PLUS_X, MINUS_Z, MINUS_X,
  221. MINUS_Z, MINUS_X, PLUS_Z, PLUS_X,
  222. // oldDir = +z
  223. PLUS_X, MINUS_Y, MINUS_X, PLUS_Y,
  224. MINUS_X, PLUS_Y, PLUS_X, MINUS_Y,
  225. PLUS_Y, PLUS_X, MINUS_Y, MINUS_X,
  226. MINUS_Y, MINUS_X, PLUS_Y, PLUS_X,
  227. iXX, iXX, iXX, iXX,
  228. iXX, iXX, iXX, iXX,
  229. // oldDir = -z
  230. PLUS_X, PLUS_Y, MINUS_X, MINUS_Y,
  231. MINUS_X, MINUS_Y, PLUS_X, PLUS_Y,
  232. PLUS_Y, MINUS_X, MINUS_Y, PLUS_X,
  233. MINUS_Y, PLUS_X, PLUS_Y, MINUS_X,
  234. iXX, iXX, iXX, iXX,
  235. iXX, iXX, iXX, iXX
  236. };
  237. GLint
  238. NORMAL_PIPE::ChooseElbow( int oldDir, int newDir )
  239. {
  240. int i;
  241. // precomputed table supplies correct elbow orientation
  242. for( i = 0; i < 4; i ++ ) {
  243. if( notchElbDir[oldDir][newDir][i] == notchVec )
  244. return i;
  245. }
  246. // we shouldn't arrive here
  247. return -1;
  248. }
  249. /**************************************************************************\
  250. * DrawJoint
  251. *
  252. * Draw a joint between 2 pipes
  253. *
  254. * History
  255. * Apr. 28, 95 : [marcfo]
  256. * - Wrote it
  257. *
  258. \**************************************************************************/
  259. void
  260. NORMAL_PIPE::DrawJoint( int newDir )
  261. {
  262. int jointType;
  263. int iBend;
  264. jointType = pNState->ChooseJointType();
  265. #if PIPES_DEBUG
  266. if( newDir == oppositeDir[lastDir] )
  267. printf( "Warning: opposite dir chosen!\n" );
  268. #endif
  269. switch( jointType ) {
  270. case BALL_JOINT:
  271. if( bTexture ) {
  272. // use special texture-friendly ballJoints
  273. align_plusz( newDir );
  274. glPushMatrix();
  275. align_plusy( lastDir, newDir );
  276. // translate forward 1.0*r along +z to get set for drawing elbow
  277. glTranslatef( 0.0f, 0.0f, radius );
  278. // decide which elbow orientation to use
  279. iBend = ChooseElbow( lastDir, newDir );
  280. pNState->ballJoints[iBend]->Draw();
  281. glPopMatrix();
  282. }
  283. else {
  284. // draw big ball in default orientation
  285. pNState->bigBall->Draw();
  286. align_plusz( newDir );
  287. }
  288. // move ahead 1.0*r to draw pipe
  289. glTranslatef( 0.0f, 0.0f, radius );
  290. break;
  291. case ELBOW_JOINT:
  292. align_plusz( newDir );
  293. // the align_plusy() here will mess up our notch calcs, so
  294. // we push-pop
  295. glPushMatrix();
  296. align_plusy( lastDir, newDir );
  297. // translate forward 1.0*r along +z to get set for drawing elbow
  298. glTranslatef( 0.0f, 0.0f, radius );
  299. // decide which elbow orientation to use
  300. iBend = ChooseElbow( lastDir, newDir );
  301. if( iBend == -1 ) {
  302. #if PIPES_DEBUG
  303. printf( "ChooseElbow() screwed up\n" );
  304. #endif
  305. iBend = 0; // recover
  306. }
  307. pNState->elbows[iBend]->Draw();
  308. glPopMatrix();
  309. glTranslatef( 0.0f, 0.0f, radius );
  310. break;
  311. default:
  312. // Horrors! It's the teapot!
  313. DrawTeapot();
  314. align_plusz( newDir );
  315. // move ahead 1.0*r to draw pipe
  316. glTranslatef( 0.0f, 0.0f, radius );
  317. }
  318. // update the current notch vector
  319. notchVec = notchTurn[lastDir][newDir][notchVec];
  320. #if PIPES_DEBUG
  321. if( notchVec == iXX )
  322. printf( "notchTurn gave bad value\n" );
  323. #endif
  324. }
  325. /**************************************************************************\
  326. * Geometry functions
  327. \**************************************************************************/
  328. static float RotZ[NUM_DIRS][NUM_DIRS] = {
  329. 0.0f, 0.0f, 90.0f, 90.0f, 90.0f, -90.0f,
  330. 0.0f, 0.0f, -90.0f, -90.0f, -90.0f, 90.0f,
  331. 180.0f, 180.0f, 0.0f, 0.0f, 180.0f, 180.0f,
  332. 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
  333. -90.0f, 90.0f, 0.0f, 180.0f, 0.0f, 0.0f,
  334. 90.0f, -90.0f, 180.0f, 0.0f, 0.0f, 0.0f };
  335. /*-----------------------------------------------------------------------
  336. | |
  337. | align_plusy( int lastDir, int newDir ) |
  338. | - Assuming +z axis is already aligned with newDir, align |
  339. | +y axis BACK along lastDir |
  340. | |
  341. -----------------------------------------------------------------------*/
  342. static void
  343. align_plusy( int oldDir, int newDir )
  344. {
  345. GLfloat rotz;
  346. rotz = RotZ[oldDir][newDir];
  347. glRotatef( rotz, 0.0f, 0.0f, 1.0f );
  348. }
  349. // given a dir, determine how much to rotate cylinder around z to match notches
  350. // format is [newDir][notchVec]
  351. static GLfloat alignNotchRot[NUM_DIRS][NUM_DIRS] = {
  352. fXX, fXX, 0.0f, 180.0f, 90.0f, -90.0f,
  353. fXX, fXX, 0.0f, 180.0f, -90.0f, 90.0f,
  354. -90.0f, 90.0f, fXX, fXX, 180.0f, 0.0f,
  355. -90.0f, 90.0f, fXX, fXX, 0.0f, 180.0f,
  356. -90.0f, 90.0f, 0.0f, 180.0f, fXX, fXX,
  357. 90.0f, -90.0f, 0.0f, 180.0f, fXX, fXX
  358. };
  359. /*-----------------------------------------------------------------------
  360. | |
  361. | align_notch( int newDir ) |
  362. | - a cylinder is notched, and we have to line this up |
  363. | with the previous primitive's notch which is maintained as |
  364. | notchVec. |
  365. | - this adds a rotation around z to achieve this |
  366. | |
  367. -----------------------------------------------------------------------*/
  368. static void
  369. align_notch( int newDir, int notch )
  370. {
  371. GLfloat rotz;
  372. GLint curNotch;
  373. // figure out where notch is presently after +z alignment
  374. curNotch = defCylNotch[newDir];
  375. // (don't need this now we have lut)
  376. // look up rotation value in table
  377. rotz = alignNotchRot[newDir][notch];
  378. #if PIPES_DEBUG
  379. if( rotz == fXX ) {
  380. printf( "align_notch(): unexpected value\n" );
  381. return;
  382. }
  383. #endif
  384. if( rotz != 0.0f )
  385. glRotatef( rotz, 0.0f, 0.0f, 1.0f );
  386. }