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.

564 lines
15 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: eval.cxx
  3. *
  4. * Evaluator stuff
  5. *
  6. * Copyright (c) 1994 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 "sscommon.h"
  20. #include "sspipes.h"
  21. #include "eval.h"
  22. //#define EVAL_DBG 1
  23. typedef enum {
  24. X_PLANE = 0,
  25. Y_PLANE,
  26. Z_PLANE
  27. };
  28. #define EVAL_VSIZE 3 // vertex size in floats
  29. #define TMAJOR_ORDER 2
  30. #define TMINOR_ORDER 2
  31. #define VDIM 3
  32. #define TDIM 2
  33. //forwards
  34. #if EVAL_DBG
  35. static void DrawPoints( int num, POINT3D *pts );
  36. #endif
  37. static void RotatePointSet( POINT3D *inPts, int numPts, float angle, int dir,
  38. float radius, POINT3D *outPts );
  39. static void ExtrudePointSetDir( POINT3D *inPts, int numPts, float *acPts,
  40. int dir, POINT3D *outPts );
  41. /**************************************************************************\
  42. * EVAL
  43. *
  44. * Evaluator constructor
  45. *
  46. \**************************************************************************/
  47. EVAL::EVAL( BOOL bTex )
  48. {
  49. bTexture = bTex;
  50. // Allocate points buffer
  51. //mf: might want to use less than max in some cases
  52. int size = MAX_USECTIONS * MAX_UORDER * MAX_VORDER * sizeof(POINT3D);
  53. pts = (POINT3D *) LocalAlloc( LMEM_FIXED, size );
  54. SS_ASSERT( pts != NULL, "EVAL constructor\n" );
  55. // Alloc texture points buffer
  56. if( bTexture ) {
  57. size = MAX_USECTIONS * TEX_ORDER * TEX_ORDER * sizeof(TEX_POINT2D);
  58. texPts = (TEX_POINT2D *) LocalAlloc( LMEM_FIXED, size );
  59. SS_ASSERT( texPts != NULL, "EVAL constructor\n" );
  60. }
  61. ResetEvaluator( bTexture );
  62. }
  63. /**************************************************************************\
  64. * ~EVAL
  65. *
  66. * Evaluator destructor
  67. *
  68. * Frees up memory
  69. *
  70. \**************************************************************************/
  71. EVAL::~EVAL( )
  72. {
  73. LocalFree( pts );
  74. if( bTexture )
  75. LocalFree( texPts );
  76. }
  77. /**************************************************************************\
  78. * Reset
  79. *
  80. * Reset evaluator to generate 3d vertices and vertex normals
  81. *
  82. \**************************************************************************/
  83. void
  84. ResetEvaluator( BOOL bTexture )
  85. {
  86. if( bTexture ) {
  87. glEnable( GL_MAP2_TEXTURE_COORD_2 );
  88. }
  89. glEnable( GL_MAP2_VERTEX_3 );
  90. glEnable( GL_AUTO_NORMAL );
  91. glFrontFace( GL_CW ); // cuz
  92. //mf: !!! if mixing Normal and Flex, have to watch out for this, cuz normal
  93. // needs CCW
  94. }
  95. /**************************************************************************\
  96. * SetTextureControlPoints
  97. *
  98. * Set texture control point net
  99. *
  100. * This sets up 'numSections' sets of texture coordinate control points, based
  101. * on starting and ending s and t values.
  102. *
  103. * s coords run along pipe direction, t coords run around circumference
  104. *
  105. * History
  106. * July 17, 95 : [marcfo]
  107. * - Wrote it
  108. *
  109. \**************************************************************************/
  110. void
  111. EVAL::SetTextureControlPoints( float s_start, float s_end,
  112. float t_start, float t_end )
  113. {
  114. int i;
  115. TEX_POINT2D *ptexPts = texPts;
  116. GLfloat t_delta = (t_end - t_start) / numSections;
  117. GLfloat t = t_start;
  118. // calc ctrl pts for each quadrant
  119. for( i = 0; i < numSections; i++, ptexPts += (TDIM*TDIM) ) {
  120. // s, t coords
  121. ptexPts[0].t = ptexPts[2].t = t;
  122. t += t_delta;
  123. ptexPts[1].t = ptexPts[3].t = t;
  124. ptexPts[0].s = ptexPts[1].s = s_start;
  125. ptexPts[2].s = ptexPts[3].s = s_end;
  126. }
  127. }
  128. /**************************************************************************\
  129. * SetVertexCtrlPtsXCTranslate
  130. *
  131. * Builds 3D control eval control net from 2 xcObjs displaced along the
  132. * z-axis by 'length'.
  133. *
  134. * First xc used to generate points in z=0 plane.
  135. * Second xc generates points in z=length plane.
  136. * ! Replicates the last point around each u.
  137. *
  138. * July 27, 95 : [marcfo]
  139. * - Wrote it
  140. *
  141. \**************************************************************************/
  142. void
  143. EVAL::SetVertexCtrlPtsXCTranslate( POINT3D *pts, float length,
  144. XC *xcStart, XC *xcEnd )
  145. {
  146. int i;
  147. POINT2D *ptsStart, *ptsEnd;
  148. POINT3D *pts1, *pts2;
  149. int numPts = xcStart->numPts;
  150. numPts++; // due to last point replication
  151. ptsStart = xcStart->pts;
  152. ptsEnd = xcEnd->pts;
  153. pts1 = pts;
  154. pts2 = pts + numPts;
  155. for( i = 0; i < (numPts-1); i++, pts1++, pts2++ ) {
  156. // copy over x,y from each xc
  157. *( (POINT2D *) pts1) = *ptsStart++;
  158. *( (POINT2D *) pts2) = *ptsEnd++;
  159. // set z for each
  160. pts1->z = 0.0f;
  161. pts2->z = length;
  162. }
  163. // Replicate last point in each u-band
  164. *pts1 = *pts;
  165. *pts2 = *(pts + numPts);
  166. }
  167. /**************************************************************************\
  168. * ProcessXCPrimLinear
  169. *
  170. * Processes a prim according to evaluator data
  171. *
  172. * - Only valid for colinear xc's (along z)
  173. * - XC's may be identical (extrusion). If not identical, may have
  174. * discontinuities at each end.
  175. * - Converts 2D XC pts to 3D pts
  176. *
  177. * July 27, 95 : [marcfo]
  178. * - Wrote it
  179. *
  180. \**************************************************************************/
  181. void
  182. EVAL::ProcessXCPrimLinear( XC *xcStart, XC *xcEnd, float length )
  183. {
  184. if( length <= 0.0f )
  185. // nuttin' to do
  186. return;
  187. // Build a vertex control net from 2 xcObj's a distance 'length' apart
  188. // this will displace the end xcObj a distance 'length' down the z-axis
  189. SetVertexCtrlPtsXCTranslate( pts, length, xcStart, xcEnd );
  190. Evaluate( );
  191. }
  192. /**************************************************************************\
  193. * ProcessXCPrimBendSimple
  194. *
  195. * Processes a prim by bending along dir from xcCur
  196. *
  197. * - dir is relative from xc in x-y plane
  198. * - adds C2 continuity at ends
  199. *
  200. * July 27, 95 : [marcfo]
  201. * - Wrote it
  202. *
  203. \**************************************************************************/
  204. void
  205. EVAL::ProcessXCPrimBendSimple( XC *xcCur, int dir, float radius )
  206. {
  207. POINT3D *ptsSrc, *ptsDst;
  208. static float acPts[MAX_XC_PTS+1];
  209. int ptSetStride = xcCur->numPts + 1; // pt stride for output pts buffer
  210. // We will be creating 4 cross-sectional control point sets here.
  211. // Convert 2D pts in xcCur to 3D pts at z=0 for 1st point set
  212. xcCur->ConvertPtsZ( pts, 0.0f );
  213. // Calc 4th point set by rotating 1st set as per dir
  214. ptsDst = pts + 3*ptSetStride;
  215. RotatePointSet( pts, ptSetStride, 90.0f, dir, radius, ptsDst );
  216. // angles != 90, hard, cuz not easy to extrude 3rd set from 4th
  217. // Next, have to figure out ac values. Need to extend each xc's points
  218. // into bend to generate ac net. For circular bend (and later for general
  219. // case elliptical bend), need to know ac distance from xc for each point.
  220. // This is based on the point's turn radius - a function of its distance
  221. // from the 'hinge' of the turn.
  222. // Can take advantage of symmetry here. Figure for one xc, good for 2nd.
  223. // This assumes 90 deg turn. (also,last point replicated)
  224. xcCur->CalcArcACValues90( dir, radius, acPts );
  225. // 2) extrude each point's ac from xcCur (extrusion in +z)
  226. // apply values to 1st to get 2nd
  227. // MINUS_Z, cuz subtracts *back* from dir
  228. ExtrudePointSetDir( pts, ptSetStride, acPts, MINUS_Z,
  229. pts + ptSetStride );
  230. // 3) extrude each point's ac from xcEnd (extrusion in -dir)
  231. ptsSrc = pts + 3*ptSetStride;
  232. ptsDst = pts + 2*ptSetStride;
  233. ExtrudePointSetDir( ptsSrc, ptSetStride, acPts, dir, ptsDst );
  234. Evaluate();
  235. }
  236. /**************************************************************************\
  237. * eval_ProcessXCPrimSingularity
  238. *
  239. * Processes a prim by joining singularity to an xc
  240. *
  241. * - Used for closing or opening the pipe
  242. * - If bOpening is true, starts with singularity, otherwise ends with one
  243. * - the xc side is always in z=0 plane
  244. * - singularity side is radius on either side of xc
  245. * - adds C2 continuity at ends (perpendicular to +z at singularity end)
  246. *
  247. * July 29, 95 : [marcfo]
  248. * - Wrote it
  249. *
  250. \**************************************************************************/
  251. void
  252. EVAL::ProcessXCPrimSingularity( XC *xcCur, float length, BOOL bOpening )
  253. {
  254. POINT3D *ptsSing, *ptsXC;
  255. static float acPts[MAX_XC_PTS+1];
  256. float zSing; // z-value at singularity
  257. int ptSetStride = xcCur->numPts + 1; // pt stride for output pts buffer
  258. int i;
  259. XC xcSing(xcCur);
  260. // create singularity xc - which is an extremely scaled-down version
  261. // of xcCur (this prevents any end-artifacts, unless of course we were
  262. // to zoom it ultra-large).
  263. xcSing.Scale( .0005f );
  264. // We will be creating 4 cross-sectional control point sets here.
  265. // mf: 4 is like hard coded; what about for different xc component levels ?
  266. if( bOpening ) {
  267. ptsSing = pts;
  268. ptsXC = pts + 3*ptSetStride;
  269. } else {
  270. ptsSing = pts + 3*ptSetStride;
  271. ptsXC = pts;
  272. }
  273. // Convert 2D pts in xcCur to 3D pts at 'xc' point set
  274. xcCur->ConvertPtsZ( ptsXC, 0.0f );
  275. // Set z-value for singularity point set
  276. zSing = bOpening ? -length : length;
  277. xcSing.ConvertPtsZ( ptsSing, zSing );
  278. // The arc control for each point is based on a radius value that is
  279. // each xc point's distance from the xc center
  280. xcCur->CalcArcACValuesByDistance( acPts );
  281. // Calculate point set near xc
  282. if( bOpening )
  283. ExtrudePointSetDir( ptsXC, ptSetStride, acPts, PLUS_Z,
  284. ptsXC - ptSetStride );
  285. else
  286. ExtrudePointSetDir( ptsXC, ptSetStride, acPts, MINUS_Z,
  287. ptsXC + ptSetStride );
  288. // Point set near singularity is harder, as the points must generate
  289. // a curve between the singularity and each xc point
  290. // No, easier, just scale each point by universal arc controller !
  291. POINT3D *ptsDst = pts;
  292. ptsDst = bOpening ? ptsSing + ptSetStride : ptsSing - ptSetStride;
  293. for( i = 0; i < ptSetStride; i ++, ptsDst++ ) {
  294. ptsDst->x = EVAL_CIRC_ARC_CONTROL * ptsXC[i].x;
  295. ptsDst->y = EVAL_CIRC_ARC_CONTROL * ptsXC[i].y;
  296. ptsDst->z = zSing;
  297. }
  298. Evaluate();
  299. }
  300. /**************************************************************************\
  301. * Evaluate
  302. *
  303. * Evaluates the EVAL object
  304. *
  305. * - There may be 1 or more lengthwise sections around an xc
  306. * - u is minor, v major
  307. * - u,t run around circumference, v,s lengthwise
  308. * - Texture maps are 2x2 for each section
  309. * - ! uDiv is per section !
  310. *
  311. * History
  312. * July 21, 95 : [marcfo]
  313. * - Wrote it
  314. *
  315. \**************************************************************************/
  316. void
  317. EVAL::Evaluate( )
  318. {
  319. int i;
  320. POINT3D *ppts = pts;
  321. TEX_POINT2D *ptexPts = texPts;
  322. // total # pts in cross-section:
  323. int xcPointCount = (uOrder-1)*numSections + 1;
  324. for( i = 0; i < numSections; i ++,
  325. ppts += (uOrder-1),
  326. ptexPts += (TEX_ORDER*TEX_ORDER) ) {
  327. // map texture coords
  328. if( bTexture ) {
  329. glMap2f(GL_MAP2_TEXTURE_COORD_2,
  330. 0.0f, 1.0f, TDIM, TEX_ORDER,
  331. 0.0f, 1.0f, TEX_ORDER*TDIM, TEX_ORDER,
  332. (GLfloat *) ptexPts );
  333. }
  334. // map vertices
  335. glMap2f(GL_MAP2_VERTEX_3,
  336. 0.0f, 1.0f, VDIM, uOrder,
  337. 0.0f, 1.0f, xcPointCount*VDIM, vOrder,
  338. (GLfloat *) ppts );
  339. // evaluate
  340. glMapGrid2f(uDiv, 0.0f, 1.0f, vDiv, 0.0f, 1.0f);
  341. glEvalMesh2( GL_FILL, 0, uDiv, 0, vDiv);
  342. }
  343. }
  344. #if EVAL_DBG
  345. /**************************************************************************\
  346. * DrawPoints
  347. *
  348. * draw control points
  349. *
  350. \**************************************************************************/
  351. static
  352. void DrawPoints( int num, POINT3D *pts )
  353. {
  354. GLint i;
  355. // draw green pts for now
  356. glColor3f(0.0f, 1.0f, 0.0f);
  357. glPointSize(2);
  358. glBegin(GL_POINTS);
  359. for (i = 0; i < num; i++, pts++) {
  360. glVertex3fv( (GLfloat *) pts );
  361. }
  362. glEnd();
  363. }
  364. #endif
  365. /**************************************************************************\
  366. * ExtrudePointSetDir
  367. *
  368. * Extrude a point set back from the current direction
  369. *
  370. * Generates C2 continuity at the supplied point set xc, by generating another
  371. * point set back of the first, using supplied subtraction values.
  372. *
  373. * July 28, 95 : [marcfo]
  374. * - Wrote it
  375. *
  376. \**************************************************************************/
  377. static void
  378. ExtrudePointSetDir( POINT3D *inPts, int numPts, float *acPts, int dir,
  379. POINT3D *outPts )
  380. {
  381. int i;
  382. float sign;
  383. int offset;
  384. switch( dir ) {
  385. case PLUS_X:
  386. offset = 0;
  387. sign = -1.0f;
  388. break;
  389. case MINUS_X:
  390. offset = 0;
  391. sign = 1.0f;
  392. break;
  393. case PLUS_Y:
  394. offset = 1;
  395. sign = -1.0f;
  396. break;
  397. case MINUS_Y:
  398. offset = 1;
  399. sign = 1.0f;
  400. break;
  401. case PLUS_Z:
  402. offset = 2;
  403. sign = -1.0f;
  404. break;
  405. case MINUS_Z:
  406. offset = 2;
  407. sign = 1.0f;
  408. break;
  409. }
  410. for( i = 0; i < numPts; i++, inPts++, outPts++, acPts++ ) {
  411. *outPts = *inPts;
  412. ((float *)outPts)[offset] = ((float *)inPts)[offset] + (sign * (*acPts));
  413. }
  414. }
  415. /**************************************************************************\
  416. * RotatePointSet
  417. *
  418. * Rotate point set by angle, according to dir and radius
  419. *
  420. * - Put points in supplied outPts buffer
  421. *
  422. * July 28, 95 : [marcfo]
  423. * - Wrote it
  424. *
  425. \**************************************************************************/
  426. static void
  427. RotatePointSet( POINT3D *inPts, int numPts, float angle, int dir,
  428. float radius, POINT3D *outPts )
  429. {
  430. MATRIX matrix1, matrix2, matrix3;
  431. int i;
  432. POINT3D rot = {0.0f};
  433. POINT3D anchor = {0.0f};
  434. /* dir rot
  435. +x 90 y
  436. -x -90 y
  437. +y -90 x
  438. -y 90 x
  439. */
  440. // convert angle to radians
  441. //mf: as noted in objects.c, we have to take negative angle to make
  442. // it work in familiar 'CCW rotation is positive' mode. The ss_* rotate
  443. // routines must work in the 'CW is +'ve' mode, as axis pointing at you.
  444. angle = SS_DEG_TO_RAD(-angle);
  445. // set axis rotation and anchor point
  446. switch( dir ) {
  447. case PLUS_X:
  448. rot.y = angle;
  449. anchor.x = radius;
  450. break;
  451. case MINUS_X:
  452. rot.y = -angle;
  453. anchor.x = -radius;
  454. break;
  455. case PLUS_Y:
  456. rot.x = -angle;
  457. anchor.y = radius;
  458. break;
  459. case MINUS_Y:
  460. rot.x = angle;
  461. anchor.y = -radius;
  462. break;
  463. }
  464. // translate anchor point to origin
  465. ss_matrixIdent( &matrix1 );
  466. ss_matrixTranslate( &matrix1, -anchor.x, -anchor.y, -anchor.z );
  467. // rotate
  468. ss_matrixIdent( &matrix2 );
  469. ss_matrixRotate( &matrix2, (double) rot.x, rot.y, rot.z );
  470. // concat these 2
  471. ss_matrixMult( &matrix3, &matrix2, &matrix1 );
  472. // translate back
  473. ss_matrixIdent( &matrix2 );
  474. ss_matrixTranslate( &matrix2, anchor.x, anchor.y, anchor.z );
  475. // concat these 2
  476. ss_matrixMult( &matrix1, &matrix2, &matrix3 );
  477. for( i = 0; i < numPts; i ++, outPts++, inPts++ ) {
  478. ss_xformPoint( outPts, inPts, &matrix1 );
  479. }
  480. }