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.

937 lines
28 KiB

  1. //-----------------------------------------------------------------------------
  2. // File: objects.cpp
  3. //
  4. // Desc: Creates command lists for pipe primitive objects
  5. //
  6. // Copyright (c) 1994-2000 Microsoft Corporation
  7. //-----------------------------------------------------------------------------
  8. #include "stdafx.h"
  9. //-----------------------------------------------------------------------------
  10. // Name: OBJECT constructor
  11. // Desc:
  12. //-----------------------------------------------------------------------------
  13. OBJECT::OBJECT( IDirect3DDevice8* pd3dDevice )
  14. {
  15. m_pd3dDevice = pd3dDevice;
  16. m_pVB = NULL;
  17. m_dwNumTriangles = 0;
  18. }
  19. //-----------------------------------------------------------------------------
  20. // Name: OBJECT destructor
  21. // Desc:
  22. //-----------------------------------------------------------------------------
  23. OBJECT::~OBJECT( )
  24. {
  25. SAFE_RELEASE( m_pVB );
  26. }
  27. //-----------------------------------------------------------------------------
  28. // Name: Draw
  29. // Desc: - Draw the object by calling its display list
  30. //-----------------------------------------------------------------------------
  31. void OBJECT::Draw( D3DXMATRIX* pWorldMat )
  32. {
  33. if( m_pVB )
  34. {
  35. m_pd3dDevice->SetTransform( D3DTS_WORLD, pWorldMat );
  36. m_pd3dDevice->SetVertexShader( D3DFVF_VERTEX );
  37. m_pd3dDevice->SetStreamSource( 0, m_pVB, sizeof(D3DVERTEX) );
  38. m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST,
  39. 0, m_dwNumTriangles );
  40. }
  41. }
  42. //-----------------------------------------------------------------------------
  43. // Name: PIPE_OBJECT constructors
  44. // Desc:
  45. //-----------------------------------------------------------------------------
  46. PIPE_OBJECT::PIPE_OBJECT( IDirect3DDevice8* pd3dDevice, OBJECT_BUILD_INFO *pBuildInfo, float len ) : OBJECT(pd3dDevice)
  47. {
  48. Build( pBuildInfo, len, 0.0f, 0.0f );
  49. }
  50. //-----------------------------------------------------------------------------
  51. // Name:
  52. // Desc:
  53. //-----------------------------------------------------------------------------
  54. PIPE_OBJECT::PIPE_OBJECT( IDirect3DDevice8* pd3dDevice, OBJECT_BUILD_INFO *pBuildInfo, float len,
  55. float s_start, float s_end ) : OBJECT(pd3dDevice)
  56. {
  57. Build( pBuildInfo, len, s_start, s_end );
  58. }
  59. //-----------------------------------------------------------------------------
  60. // Name: ELBOW_OBJECT constructors
  61. // Desc:
  62. //-----------------------------------------------------------------------------
  63. ELBOW_OBJECT::ELBOW_OBJECT( IDirect3DDevice8* pd3dDevice, OBJECT_BUILD_INFO *pBuildInfo,
  64. int notch ) : OBJECT(pd3dDevice)
  65. {
  66. Build( pBuildInfo, notch, 0.0f, 0.0f );
  67. }
  68. //-----------------------------------------------------------------------------
  69. // Name:
  70. // Desc:
  71. //-----------------------------------------------------------------------------
  72. ELBOW_OBJECT::ELBOW_OBJECT( IDirect3DDevice8* pd3dDevice, OBJECT_BUILD_INFO *pBuildInfo, int notch, float s_start, float s_end ) : OBJECT(pd3dDevice)
  73. {
  74. Build( pBuildInfo, notch, s_start, s_end );
  75. }
  76. //-----------------------------------------------------------------------------
  77. // Name: BALLJOINT_OBJECT constructor
  78. // Desc:
  79. //-----------------------------------------------------------------------------
  80. BALLJOINT_OBJECT::BALLJOINT_OBJECT( IDirect3DDevice8* pd3dDevice, OBJECT_BUILD_INFO *pBuildInfo,
  81. int notch, float s_start, float s_end ) : OBJECT(pd3dDevice)
  82. {
  83. Build( pBuildInfo, notch, s_start, s_end );
  84. }
  85. //-----------------------------------------------------------------------------
  86. // Name: SPHERE_OBJECT constructors
  87. // Desc:
  88. //-----------------------------------------------------------------------------
  89. SPHERE_OBJECT::SPHERE_OBJECT( IDirect3DDevice8* pd3dDevice, OBJECT_BUILD_INFO *pBuildInfo, float radius ) : OBJECT(pd3dDevice)
  90. {
  91. Build( pBuildInfo, radius, 0.0f, 0.0f );
  92. }
  93. //-----------------------------------------------------------------------------
  94. // Name:
  95. // Desc:
  96. //-----------------------------------------------------------------------------
  97. SPHERE_OBJECT::SPHERE_OBJECT( IDirect3DDevice8* pd3dDevice, OBJECT_BUILD_INFO *pBuildInfo,
  98. float radius, float s_start, float s_end ) : OBJECT(pd3dDevice)
  99. {
  100. Build( pBuildInfo, radius, s_start, s_end );
  101. }
  102. //-----------------------------------------------------------------------------
  103. // Name:
  104. // Desc: rotate circle around x-axis, with edge attached to anchor
  105. //-----------------------------------------------------------------------------
  106. static void TransformCircle( float angle, D3DXVECTOR3 *inPoint, D3DXVECTOR3 *outPoint,
  107. int num, D3DXVECTOR3 *anchor )
  108. {
  109. D3DXMATRIX matrix1, matrix2, matrix3;
  110. int i;
  111. // translate anchor point to origin
  112. D3DXMatrixIdentity( &matrix1 );
  113. D3DXMatrixTranslation( &matrix1, -anchor->x, -anchor->y, -anchor->z );
  114. // rotate by angle, cw around x-axis
  115. D3DXMatrixIdentity( &matrix2 );
  116. D3DXMatrixRotationYawPitchRoll( &matrix2, 0.0f, angle, 0.0f );
  117. // concat these 2
  118. D3DXMatrixMultiply( &matrix3, &matrix1, &matrix2 );
  119. // translate back
  120. D3DXMatrixIdentity( &matrix2 );
  121. D3DXMatrixTranslation( &matrix2, anchor->x, anchor->y, anchor->z );
  122. // concat these 2
  123. D3DXMatrixMultiply( &matrix1, &matrix3, &matrix2 );
  124. // transform all the points, + center
  125. for( i = 0; i < num; i ++, outPoint++, inPoint++ )
  126. {
  127. D3DXVECTOR4 tmp;
  128. D3DXVec3Transform( &tmp, inPoint, &matrix1 );
  129. outPoint->x = tmp.x;
  130. outPoint->y = tmp.y;
  131. outPoint->z = tmp.z;
  132. }
  133. }
  134. //-----------------------------------------------------------------------------
  135. // Name:
  136. // Desc:
  137. //-----------------------------------------------------------------------------
  138. static void CalcNormals( D3DXVECTOR3 *p, D3DXVECTOR3 *n, D3DXVECTOR3 *center,
  139. int num )
  140. {
  141. D3DXVECTOR3 vec;
  142. int i;
  143. for( i = 0; i < num; i ++, n++, p++ )
  144. {
  145. n->x = p->x - center->x;
  146. n->y = p->y - center->y;
  147. n->z = p->z - center->z;
  148. D3DXVec3Normalize( n, n );
  149. }
  150. }
  151. #define CACHE_SIZE 100
  152. //-----------------------------------------------------------------------------
  153. // Name: BuildElbow
  154. // Desc: - builds elbows, by rotating a circle in the y=r plane
  155. // centered at (0,r,-r), CW around the x-axis at anchor pt.
  156. // (r = radius of the circle)
  157. // - rotation is 90.0 degrees, ending at circle in z=0 plane,
  158. // centered at origin.
  159. // - in order to 'mate' texture coords with the cylinders
  160. // generated with glu, we generate 4 elbows, each corresponding
  161. // to the 4 possible CW 90 degree orientations of the start point
  162. // for each circle.
  163. // - We call this start point the 'notch'. If we characterize
  164. // each notch by the axis it points down in the starting and
  165. // ending circles of the elbow, then we get the following axis
  166. // pairs for our 4 notches:
  167. // - +z,+y
  168. // - +x,+x
  169. // - -z,-y
  170. // - -x,-x
  171. // Since the start of the elbow always points down +y, the 4
  172. // start notches give all possible 90.0 degree orientations
  173. // around y-axis.
  174. // - We can keep track of the current 'notch' vector to provide
  175. // proper mating between primitives.
  176. // - Each circle of points is described CW from the start point,
  177. // assuming looking down the +y axis(+y direction).
  178. // - texture 's' starts at 0.0, and goes to 2.0*r/divSize at
  179. // end of the elbow. (Then a short pipe would start with this
  180. // 's', and run it to 1.0).
  181. //-----------------------------------------------------------------------------
  182. void ELBOW_OBJECT::Build( OBJECT_BUILD_INFO *pBuildInfo, int notch,
  183. float s_start, float s_end )
  184. {
  185. int stacks, slices;
  186. float angle, startAng;
  187. int numPoints;
  188. float s_delta;
  189. D3DXVECTOR3 pi[CACHE_SIZE]; // initial row of points + center
  190. D3DXVECTOR3 p0[CACHE_SIZE]; // 2 rows of points
  191. D3DXVECTOR3 p1[CACHE_SIZE];
  192. D3DXVECTOR3 n0[CACHE_SIZE]; // 2 rows of normals
  193. D3DXVECTOR3 n1[CACHE_SIZE];
  194. float tex_t[CACHE_SIZE];// 't' texture coords
  195. float* curTex_t;
  196. float tex_s[2]; // 's' texture coords
  197. D3DXVECTOR3 center; // center of circle
  198. D3DXVECTOR3 anchor; // where circle is anchored
  199. D3DXVECTOR3* pA;
  200. D3DXVECTOR3* pB;
  201. D3DXVECTOR3* nA;
  202. D3DXVECTOR3* nB;
  203. D3DXVECTOR3* pTA;
  204. D3DXVECTOR3* pTB;
  205. D3DXVECTOR3* nTA;
  206. D3DXVECTOR3* nTB;
  207. int i,j;
  208. IPOINT2D* texRep = pBuildInfo->m_texRep;
  209. float radius = pBuildInfo->m_radius;
  210. slices = pBuildInfo->m_nSlices;
  211. stacks = slices / 2;
  212. if (slices >= CACHE_SIZE) slices = CACHE_SIZE-1;
  213. if (stacks >= CACHE_SIZE) stacks = CACHE_SIZE-1;
  214. s_delta = s_end - s_start;
  215. // calculate 't' texture coords
  216. if( texRep )
  217. {
  218. for( i = 0; i <= slices; i ++ )
  219. {
  220. tex_t[i] = (float) i * texRep->y / slices;
  221. }
  222. }
  223. numPoints = slices + 1;
  224. // starting angle increment 90.0 degrees each time
  225. startAng = notch * PI / 2;
  226. // calc initial circle of points for circle centered at 0,r,-r
  227. // points start at (0,r,0), and rotate circle CCW
  228. for( i = 0; i <= slices; i ++ )
  229. {
  230. angle = startAng + (2 * PI * i / slices);
  231. pi[i].x = radius * (float) sin(angle);
  232. pi[i].y = radius;
  233. // translate z by -r, cuz these cos calcs are for circle at origin
  234. pi[i].z = radius * (float) cos(angle) - radius;
  235. }
  236. // center point, tacked onto end of circle of points
  237. pi[i].x = 0.0f;
  238. pi[i].y = radius;
  239. pi[i].z = -radius;
  240. center = pi[i];
  241. // anchor point
  242. anchor.x = anchor.z = 0.0f;
  243. anchor.y = radius;
  244. // calculate initial normals
  245. CalcNormals( pi, n0, &center, numPoints );
  246. // initial 's' texture coordinate
  247. tex_s[0] = s_start;
  248. // setup pointers
  249. pA = pi;
  250. pB = p0;
  251. nA = n0;
  252. nB = n1;
  253. DWORD dwNumQuadStripsPerStack = numPoints - 1;
  254. DWORD dwNumQuadStrips = dwNumQuadStripsPerStack * stacks;
  255. m_dwNumTriangles = dwNumQuadStrips * 2;
  256. DWORD dwNumVertices = m_dwNumTriangles * 3;
  257. if( FAILED( m_pd3dDevice->CreateVertexBuffer( dwNumVertices*sizeof(D3DVERTEX),
  258. D3DUSAGE_WRITEONLY, D3DFVF_VERTEX,
  259. D3DPOOL_MANAGED, &m_pVB ) ) )
  260. return;
  261. D3DVERTEX* vQuad;
  262. D3DVERTEX* vCurQuad;
  263. vQuad = new D3DVERTEX[dwNumVertices];
  264. ZeroMemory( vQuad, sizeof(D3DVERTEX) * dwNumVertices );
  265. vCurQuad = vQuad;
  266. for( i = 1; i <= stacks; i ++ )
  267. {
  268. // ! this angle must be negative, for correct vertex orientation !
  269. angle = - 0.5f * PI * i / stacks;
  270. // transform to get next circle of points + center
  271. TransformCircle( angle, pi, pB, numPoints+1, &anchor );
  272. // calculate normals
  273. center = pB[numPoints];
  274. CalcNormals( pB, nB, &center, numPoints );
  275. // calculate next 's' texture coord
  276. tex_s[1] = (float) s_start + s_delta * i / stacks;
  277. curTex_t = tex_t;
  278. pTA = pA;
  279. pTB = pB;
  280. nTA = nA;
  281. nTB = nB;
  282. for (j = 0; j < numPoints; j++)
  283. {
  284. vCurQuad->p = *pTA++;
  285. vCurQuad->n = *nTA++;
  286. if( texRep )
  287. {
  288. vCurQuad->tu = (float) tex_s[0];
  289. vCurQuad->tv = (float) *curTex_t;
  290. }
  291. vCurQuad++;
  292. vCurQuad->p = *pTB++;
  293. vCurQuad->n = *nTB++;
  294. if( texRep )
  295. {
  296. vCurQuad->tu = (float) tex_s[1];
  297. vCurQuad->tv = (float) *curTex_t++;
  298. }
  299. vCurQuad++;
  300. }
  301. // reset pointers
  302. pA = pB;
  303. nA = nB;
  304. pB = (pB == p0) ? p1 : p0;
  305. nB = (nB == n0) ? n1 : n0;
  306. tex_s[0] = tex_s[1];
  307. }
  308. D3DVERTEX* v;
  309. DWORD dwCurQuad = 0;
  310. DWORD dwVert = 0;
  311. m_pVB->Lock( 0, 0, (BYTE**)&v, 0 );
  312. for (j = 0; j < stacks; j++)
  313. {
  314. for (i = 0; i < numPoints; i++)
  315. {
  316. if( i==0 )
  317. {
  318. dwCurQuad++;
  319. continue;
  320. }
  321. // Vertices 2n-1, 2n, 2n+2, and 2n+1 define quadrilateral n
  322. DWORD dwTemp = dwCurQuad*2-1;
  323. v[dwVert++] = vQuad[dwTemp];
  324. v[dwVert++] = vQuad[dwTemp-1];
  325. v[dwVert++] = vQuad[dwTemp+2];
  326. v[dwVert++] = vQuad[dwTemp-1];
  327. v[dwVert++] = vQuad[dwTemp+1];
  328. v[dwVert++] = vQuad[dwTemp+2];
  329. dwCurQuad++;
  330. }
  331. }
  332. m_pVB->Unlock();
  333. SAFE_DELETE_ARRAY( vQuad );
  334. }
  335. //-----------------------------------------------------------------------------
  336. // Name: BuildBallJoint
  337. // Desc: - These are very similar to the elbows, in that the starting
  338. // and ending positions are almost identical. The difference
  339. // here is that the circles in the sweep describe a sphere as
  340. // they are rotated.
  341. //-----------------------------------------------------------------------------
  342. void BALLJOINT_OBJECT::Build( OBJECT_BUILD_INFO *pBuildInfo, int notch,
  343. float s_start, float s_end )
  344. {
  345. float ballRadius;
  346. float angle, delta_a, startAng, theta;
  347. int numPoints;
  348. float s_delta;
  349. D3DXVECTOR3 pi0[CACHE_SIZE]; // 2 circles of untransformed points
  350. D3DXVECTOR3 pi1[CACHE_SIZE];
  351. D3DXVECTOR3 p0[CACHE_SIZE]; // 2 rows of transformed points
  352. D3DXVECTOR3 p1[CACHE_SIZE];
  353. D3DXVECTOR3 n0[CACHE_SIZE]; // 2 rows of normals
  354. D3DXVECTOR3 n1[CACHE_SIZE];
  355. float r[CACHE_SIZE]; // radii of the circles
  356. float tex_t[CACHE_SIZE];// 't' texture coords
  357. float tex_s[2]; // 's' texture coords
  358. D3DXVECTOR3 center; // center of circle
  359. D3DXVECTOR3 anchor; // where circle is anchored
  360. D3DXVECTOR3 *pA, *pB, *nA, *nB;
  361. float* curTex_t;
  362. D3DXVECTOR3* pTA;
  363. D3DXVECTOR3* pTB;
  364. D3DXVECTOR3* nTA;
  365. D3DXVECTOR3* nTB;
  366. int i, j, k;
  367. int stacks, slices;
  368. IPOINT2D *texRep = pBuildInfo->m_texRep;
  369. float radius = pBuildInfo->m_radius;
  370. slices = pBuildInfo->m_nSlices;
  371. stacks = slices;
  372. if (slices >= CACHE_SIZE) slices = CACHE_SIZE-1;
  373. if (stacks >= CACHE_SIZE) stacks = CACHE_SIZE-1;
  374. // calculate the radii for each circle in the sweep, where
  375. // r[i] = y = sin(angle)/r
  376. angle = PI / 4; // first radius always at 45.0 degrees
  377. delta_a = (PI / 2.0f) / stacks;
  378. ballRadius = ROOT_TWO * radius;
  379. for( i = 0; i <= stacks; i ++, angle += delta_a )
  380. {
  381. r[i] = (float) sin(angle) * ballRadius;
  382. }
  383. // calculate 't' texture coords
  384. for( i = 0; i <= slices; i ++ )
  385. {
  386. tex_t[i] = (float) i * texRep->y / slices;
  387. }
  388. s_delta = s_end - s_start;
  389. numPoints = slices + 1;
  390. // unlike the elbow, the center for the ball joint is constant
  391. center.x = center.y = 0.0f;
  392. center.z = -radius;
  393. // starting angle along circle, increment 90.0 degrees each time
  394. startAng = notch * PI / 2;
  395. // calc initial circle of points for circle centered at 0,r,-r
  396. // points start at (0,r,0), and rotate circle CCW
  397. delta_a = 2 * PI / slices;
  398. for( i = 0, theta = startAng; i <= slices; i ++, theta += delta_a )
  399. {
  400. pi0[i].x = r[0] * (float) sin(theta);
  401. pi0[i].y = radius;
  402. // translate z by -r, cuz these cos calcs are for circle at origin
  403. pi0[i].z = r[0] * (float) cos(theta) - r[0];
  404. }
  405. // anchor point
  406. anchor.x = anchor.z = 0.0f;
  407. anchor.y = radius;
  408. // calculate initial normals
  409. CalcNormals( pi0, n0, &center, numPoints );
  410. // initial 's' texture coordinate
  411. tex_s[0] = s_start;
  412. // setup pointers
  413. pA = pi0; // circles of transformed points
  414. pB = p0;
  415. nA = n0; // circles of transformed normals
  416. nB = n1;
  417. DWORD dwNumQuadStripsPerStack = numPoints - 1;
  418. DWORD dwNumQuadStrips = dwNumQuadStripsPerStack * stacks;
  419. m_dwNumTriangles = dwNumQuadStrips * 2;
  420. DWORD dwNumVertices = m_dwNumTriangles * 3;
  421. if( FAILED( m_pd3dDevice->CreateVertexBuffer( dwNumVertices*sizeof(D3DVERTEX),
  422. D3DUSAGE_WRITEONLY, D3DFVF_VERTEX,
  423. D3DPOOL_MANAGED, &m_pVB ) ) )
  424. return;
  425. D3DVERTEX* vQuad;
  426. D3DVERTEX* vCurQuad;
  427. vQuad = new D3DVERTEX[dwNumVertices];
  428. ZeroMemory( vQuad, sizeof(D3DVERTEX) * dwNumVertices );
  429. vCurQuad = vQuad;
  430. for( i = 1; i <= stacks; i ++ )
  431. {
  432. // ! this angle must be negative, for correct vertex orientation !
  433. angle = - 0.5f * PI * i / stacks;
  434. for( k = 0, theta = startAng; k <= slices; k ++, theta+=delta_a )
  435. {
  436. pi1[k].x = r[i] * (float) sin(theta);
  437. pi1[k].y = radius;
  438. // translate z by -r, cuz calcs are for circle at origin
  439. pi1[k].z = r[i] * (float) cos(theta) - r[i];
  440. }
  441. // transform to get next circle of points + center
  442. TransformCircle( angle, pi1, pB, numPoints, &anchor );
  443. // calculate normals
  444. CalcNormals( pB, nB, &center, numPoints );
  445. // calculate next 's' texture coord
  446. tex_s[1] = (float) s_start + s_delta * i / stacks;
  447. curTex_t = tex_t;
  448. pTA = pA;
  449. pTB = pB;
  450. nTA = nA;
  451. nTB = nB;
  452. for (j = 0; j < numPoints; j++)
  453. {
  454. vCurQuad->p = *pTA++;
  455. vCurQuad->n = *nTA++;
  456. if( texRep )
  457. {
  458. vCurQuad->tu = (float) tex_s[0];
  459. vCurQuad->tv = (float) *curTex_t;
  460. }
  461. vCurQuad++;
  462. vCurQuad->p = *pTB++;
  463. vCurQuad->n = *nTB++;
  464. if( texRep )
  465. {
  466. vCurQuad->tu = (float) tex_s[1];
  467. vCurQuad->tv = (float) *curTex_t++;
  468. }
  469. vCurQuad++;
  470. }
  471. // reset pointers
  472. pA = pB;
  473. nA = nB;
  474. pB = (pB == p0) ? p1 : p0;
  475. nB = (nB == n0) ? n1 : n0;
  476. tex_s[0] = tex_s[1];
  477. }
  478. D3DVERTEX* v;
  479. DWORD dwCurQuad = 0;
  480. DWORD dwVert = 0;
  481. m_pVB->Lock( 0, 0, (BYTE**)&v, 0 );
  482. for (j = 0; j < stacks; j++)
  483. {
  484. for (i = 0; i < numPoints; i++)
  485. {
  486. if( i==0 )
  487. {
  488. dwCurQuad++;
  489. continue;
  490. }
  491. // Vertices 2n-1, 2n, 2n+2, and 2n+1 define quadrilateral n
  492. DWORD dwTemp = dwCurQuad*2-1;
  493. v[dwVert++] = vQuad[dwTemp];
  494. v[dwVert++] = vQuad[dwTemp-1];
  495. v[dwVert++] = vQuad[dwTemp+2];
  496. v[dwVert++] = vQuad[dwTemp-1];
  497. v[dwVert++] = vQuad[dwTemp+1];
  498. v[dwVert++] = vQuad[dwTemp+2];
  499. dwCurQuad++;
  500. }
  501. }
  502. m_pVB->Unlock();
  503. SAFE_DELETE_ARRAY( vQuad );
  504. }
  505. // 'glu' routines
  506. #ifdef _EXTENSIONS_
  507. #define COS cosf
  508. #define SIN sinf
  509. #define SQRT sqrtf
  510. #else
  511. #define COS cos
  512. #define SIN sin
  513. #define SQRT sqrt
  514. #endif
  515. //-----------------------------------------------------------------------------
  516. // Name: BuildCylinder
  517. // Desc:
  518. //-----------------------------------------------------------------------------
  519. void PIPE_OBJECT::Build( OBJECT_BUILD_INFO *pBuildInfo, float length, float s_start,
  520. float s_end )
  521. {
  522. int stacks, slices;
  523. int i,j;
  524. float sinCache[CACHE_SIZE];
  525. float cosCache[CACHE_SIZE];
  526. float sinCache2[CACHE_SIZE];
  527. float cosCache2[CACHE_SIZE];
  528. float angle;
  529. float zNormal;
  530. float s_delta;
  531. float zHigh, zLow;
  532. IPOINT2D *texRep = pBuildInfo->m_texRep;
  533. float radius = pBuildInfo->m_radius;
  534. slices = pBuildInfo->m_nSlices;
  535. stacks = (int) SS_ROUND_UP( (length/pBuildInfo->m_divSize) * (float)slices) ;
  536. if (slices >= CACHE_SIZE) slices = CACHE_SIZE-1;
  537. if (stacks >= CACHE_SIZE) stacks = CACHE_SIZE-1;
  538. zNormal = 0.0f;
  539. s_delta = s_end - s_start;
  540. for (i = 0; i < slices; i++)
  541. {
  542. angle = 2 * PI * i / slices;
  543. sinCache2[i] = (float) SIN(angle);
  544. cosCache2[i] = (float) COS(angle);
  545. sinCache[i] = (float) SIN(angle);
  546. cosCache[i] = (float) COS(angle);
  547. }
  548. sinCache[slices] = sinCache[0];
  549. cosCache[slices] = cosCache[0];
  550. sinCache2[slices] = sinCache2[0];
  551. cosCache2[slices] = cosCache2[0];
  552. DWORD dwNumQuadStripsPerStack = slices;
  553. DWORD dwNumQuadStrips = dwNumQuadStripsPerStack * stacks;
  554. m_dwNumTriangles = dwNumQuadStrips * 2;
  555. DWORD dwNumVertices = m_dwNumTriangles * 3;
  556. if( FAILED( m_pd3dDevice->CreateVertexBuffer( dwNumVertices*sizeof(D3DVERTEX),
  557. D3DUSAGE_WRITEONLY, D3DFVF_VERTEX,
  558. D3DPOOL_MANAGED, &m_pVB ) ) )
  559. return;
  560. D3DVERTEX* vQuad;
  561. D3DVERTEX* vCurQuad;
  562. vQuad = new D3DVERTEX[dwNumVertices];
  563. ZeroMemory( vQuad, sizeof(D3DVERTEX) * dwNumVertices );
  564. vCurQuad = vQuad;
  565. for (j = 0; j < stacks; j++)
  566. {
  567. zLow = j * length / stacks;
  568. zHigh = (j + 1) * length / stacks;
  569. for (i = 0; i <= slices; i++)
  570. {
  571. vCurQuad->p = D3DXVECTOR3( radius * sinCache[i], radius * cosCache[i], zLow );
  572. vCurQuad->n = D3DXVECTOR3( sinCache2[i], cosCache2[i], zNormal );
  573. if( texRep )
  574. {
  575. vCurQuad->tu = (float) s_start + s_delta * j / stacks;
  576. vCurQuad->tv = (float) i * texRep->y / slices;
  577. }
  578. vCurQuad++;
  579. vCurQuad->p = D3DXVECTOR3( radius * sinCache[i], radius * cosCache[i], zHigh );
  580. vCurQuad->n = D3DXVECTOR3( sinCache2[i], cosCache2[i], zNormal );
  581. if( texRep )
  582. {
  583. vCurQuad->tu = (float) s_start + s_delta*(j+1) / stacks;
  584. vCurQuad->tv = (float) i * texRep->y / slices;
  585. }
  586. vCurQuad++;
  587. }
  588. }
  589. D3DVERTEX* v;
  590. DWORD dwCurQuad = 0;
  591. DWORD dwVert = 0;
  592. m_pVB->Lock( 0, 0, (BYTE**)&v, 0 );
  593. for (j = 0; j < stacks; j++)
  594. {
  595. for (i = 0; i <= slices; i++)
  596. {
  597. if( i==0 )
  598. {
  599. dwCurQuad++;
  600. continue;
  601. }
  602. // Vertices 2n-1, 2n, 2n+2, and 2n+1 define quadrilateral n
  603. DWORD dwTemp = dwCurQuad*2-1;
  604. v[dwVert++] = vQuad[dwTemp];
  605. v[dwVert++] = vQuad[dwTemp-1];
  606. v[dwVert++] = vQuad[dwTemp+2];
  607. v[dwVert++] = vQuad[dwTemp-1];
  608. v[dwVert++] = vQuad[dwTemp+1];
  609. v[dwVert++] = vQuad[dwTemp+2];
  610. dwCurQuad++;
  611. }
  612. }
  613. m_pVB->Unlock();
  614. SAFE_DELETE_ARRAY( vQuad );
  615. }
  616. //-----------------------------------------------------------------------------
  617. // Name: pipeSphere
  618. // Desc:
  619. //-----------------------------------------------------------------------------
  620. void SPHERE_OBJECT::Build( OBJECT_BUILD_INFO *pBuildInfo, float radius,
  621. float s_start, float s_end)
  622. {
  623. int i,j;
  624. float sinCache1a[CACHE_SIZE];
  625. float cosCache1a[CACHE_SIZE];
  626. float sinCache2a[CACHE_SIZE];
  627. float cosCache2a[CACHE_SIZE];
  628. float sinCache1b[CACHE_SIZE];
  629. float cosCache1b[CACHE_SIZE];
  630. float sinCache2b[CACHE_SIZE];
  631. float cosCache2b[CACHE_SIZE];
  632. float angle;
  633. float s_delta;
  634. int stacks, slices;
  635. IPOINT2D *texRep = pBuildInfo->m_texRep;
  636. slices = pBuildInfo->m_nSlices;
  637. stacks = slices;
  638. if (slices >= CACHE_SIZE) slices = CACHE_SIZE-1;
  639. if (stacks >= CACHE_SIZE) stacks = CACHE_SIZE-1;
  640. // invert sense of s - it seems the glu sphere is not built similarly
  641. // to the glu cylinder
  642. // (this probably means stacks don't grow along +z - check it out)
  643. s_delta = s_start;
  644. s_start = s_end;
  645. s_end = s_delta;
  646. s_delta = s_end - s_start;
  647. // Cache is the vertex locations cache
  648. // Cache2 is the various normals at the vertices themselves
  649. for (i = 0; i < slices; i++)
  650. {
  651. angle = 2 * PI * i / slices;
  652. sinCache1a[i] = (float) SIN(angle);
  653. cosCache1a[i] = (float) COS(angle);
  654. sinCache2a[i] = sinCache1a[i];
  655. cosCache2a[i] = cosCache1a[i];
  656. }
  657. for (j = 0; j <= stacks; j++)
  658. {
  659. angle = PI * j / stacks;
  660. sinCache2b[j] = (float) SIN(angle);
  661. cosCache2b[j] = (float) COS(angle);
  662. sinCache1b[j] = radius * (float) SIN(angle);
  663. cosCache1b[j] = radius * (float) COS(angle);
  664. }
  665. // Make sure it comes to a point
  666. sinCache1b[0] = 0.0f;
  667. sinCache1b[stacks] = 0.0f;
  668. sinCache1a[slices] = sinCache1a[0];
  669. cosCache1a[slices] = cosCache1a[0];
  670. sinCache2a[slices] = sinCache2a[0];
  671. cosCache2a[slices] = cosCache2a[0];
  672. int start, finish;
  673. float zLow, zHigh;
  674. float sintemp1, sintemp2, sintemp3, sintemp4;
  675. float costemp3, costemp4;
  676. start = 0;
  677. finish = stacks;
  678. DWORD dwNumQuadStripsPerStack = slices;
  679. DWORD dwNumQuadStrips = dwNumQuadStripsPerStack * (finish-start);
  680. m_dwNumTriangles = dwNumQuadStrips * 2;
  681. DWORD dwNumVertices = m_dwNumTriangles * 3;
  682. if( FAILED( m_pd3dDevice->CreateVertexBuffer( dwNumVertices*sizeof(D3DVERTEX),
  683. D3DUSAGE_WRITEONLY, D3DFVF_VERTEX,
  684. D3DPOOL_MANAGED, &m_pVB ) ) )
  685. return;
  686. D3DVERTEX* vQuad;
  687. D3DVERTEX* vCurQuad;
  688. vQuad = new D3DVERTEX[dwNumVertices];
  689. ZeroMemory( vQuad, sizeof(D3DVERTEX) * dwNumVertices );
  690. vCurQuad = vQuad;
  691. for (j = 0; j < stacks; j++)
  692. {
  693. zLow = cosCache1b[j];
  694. zHigh = cosCache1b[j+1];
  695. sintemp1 = sinCache1b[j];
  696. sintemp2 = sinCache1b[j+1];
  697. sintemp3 = sinCache2b[j+1];
  698. costemp3 = cosCache2b[j+1];
  699. sintemp4 = sinCache2b[j];
  700. costemp4 = cosCache2b[j];
  701. for (i = 0; i <= slices; i++)
  702. {
  703. vCurQuad->p = D3DXVECTOR3( sintemp2 * sinCache1a[i], sintemp2 * cosCache1a[i], zHigh );
  704. vCurQuad->n = D3DXVECTOR3( sinCache2a[i] * sintemp3, cosCache2a[i] * sintemp3, costemp3 );
  705. if( texRep )
  706. {
  707. vCurQuad->tu = (float) s_start + s_delta*(j+1) / stacks;
  708. vCurQuad->tv = (float) i * texRep->y / slices;
  709. }
  710. vCurQuad++;
  711. vCurQuad->p = D3DXVECTOR3( sintemp1 * sinCache1a[i], sintemp1 * cosCache1a[i], zLow );
  712. vCurQuad->n = D3DXVECTOR3( sinCache2a[i] * sintemp4, cosCache2a[i] * sintemp4, costemp4 );
  713. if( texRep )
  714. {
  715. vCurQuad->tu = (float) s_start + s_delta * j / stacks;
  716. vCurQuad->tv = (float) i * texRep->y / slices;
  717. }
  718. vCurQuad++;
  719. }
  720. }
  721. D3DVERTEX* v;
  722. DWORD dwCurQuad = 0;
  723. DWORD dwVert = 0;
  724. m_pVB->Lock( 0, 0, (BYTE**)&v, 0 );
  725. for (j = 0; j < stacks; j++)
  726. {
  727. for (i = 0; i <= slices; i++)
  728. {
  729. if( i==0 )
  730. {
  731. dwCurQuad++;
  732. continue;
  733. }
  734. // Vertices 2n-1, 2n, 2n+2, and 2n+1 define quadrilateral n
  735. DWORD dwTemp = dwCurQuad*2-1;
  736. v[dwVert++] = vQuad[dwTemp];
  737. v[dwVert++] = vQuad[dwTemp-1];
  738. v[dwVert++] = vQuad[dwTemp+2];
  739. v[dwVert++] = vQuad[dwTemp-1];
  740. v[dwVert++] = vQuad[dwTemp+1];
  741. v[dwVert++] = vQuad[dwTemp+2];
  742. dwCurQuad++;
  743. }
  744. }
  745. m_pVB->Unlock();
  746. SAFE_DELETE_ARRAY( vQuad );
  747. }