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.

302 lines
8.6 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: mesh.c
  3. *
  4. * Routines to create a mesh representation of a 3D object and to turn it
  5. * into an OpenGL description.
  6. *
  7. * Copyright (c) 1994 Microsoft Corporation
  8. *
  9. \**************************************************************************/
  10. #include <stdlib.h>
  11. #include <windows.h>
  12. #include <D3DX8.h>
  13. #include <string.h>
  14. #include <math.h>
  15. #include <d3dx8.h>
  16. #include "D3DSaver.h"
  17. #include "FlyingObjects.h"
  18. #include "mesh.h"
  19. #define ZERO_EPS 0.00000001
  20. /******************************Public*Routine******************************\
  21. * newMesh
  22. *
  23. * Allocate memory for the mesh structure to accomodate the specified number
  24. * of points and faces.
  25. *
  26. \**************************************************************************/
  27. BOOL newMesh(MESH *mesh, int numFaces, int numPts)
  28. {
  29. mesh->numFaces = 0;
  30. mesh->numPoints = 0;
  31. if (numPts) {
  32. mesh->pts = (POINT3D*)SaverAlloc((LONG)numPts * (LONG)sizeof(POINT3D));
  33. if( mesh->pts == NULL )
  34. return FALSE;
  35. mesh->norms = (POINT3D*)SaverAlloc((LONG)numPts * (LONG)sizeof(POINT3D));
  36. if( mesh->norms == NULL )
  37. return FALSE;
  38. }
  39. mesh->faces = (MFACE*)SaverAlloc((LONG)numFaces * (LONG)sizeof(MFACE));
  40. if (mesh->faces == NULL )
  41. return FALSE;
  42. return TRUE;
  43. }
  44. /******************************Public*Routine******************************\
  45. * delMesh
  46. *
  47. * Delete the allocated portions of the MESH structure.
  48. *
  49. \**************************************************************************/
  50. void delMesh(MESH *mesh)
  51. {
  52. SaverFree(mesh->pts);
  53. SaverFree(mesh->norms);
  54. SaverFree(mesh->faces);
  55. }
  56. /******************************Public*Routine******************************\
  57. * iPtInList
  58. *
  59. * Add a vertex and its normal to the mesh. If the vertex already exists,
  60. * add in the normal to the existing normal (we to accumulate the average
  61. * normal at each vertex). Normalization of the normals is the
  62. * responsibility of the caller.
  63. *
  64. \**************************************************************************/
  65. static int iPtInList(MESH *mesh, POINT3D *p, POINT3D *norm, int start)
  66. {
  67. int i;
  68. POINT3D *pts = mesh->pts + start;
  69. for (i = start; i < mesh->numPoints; i++, pts++)
  70. {
  71. // If the vertices are within ZERO_EPS of each other, then its the same
  72. // vertex.
  73. if ( fabs(pts->x - p->x) < ZERO_EPS &&
  74. fabs(pts->y - p->y) < ZERO_EPS &&
  75. fabs(pts->z - p->z) < ZERO_EPS )
  76. {
  77. mesh->norms[i].x += norm->x;
  78. mesh->norms[i].y += norm->y;
  79. mesh->norms[i].z += norm->z;
  80. return i;
  81. }
  82. }
  83. mesh->pts[i] = *p;
  84. mesh->norms[i] = *norm;
  85. mesh->numPoints++;
  86. return i;
  87. }
  88. /******************************Public*Routine******************************\
  89. * revolveSurface
  90. *
  91. * Takes the set of points in curve and fills the mesh structure with a
  92. * surface of revolution. The surface consists of quads made up of the
  93. * points in curve rotated about the y-axis. The number of increments
  94. * in the revolution is determined by the steps parameter.
  95. *
  96. \**************************************************************************/
  97. #define MAXPREC 40
  98. void revolveSurface(MESH *mesh, POINT3D *curve, int steps)
  99. {
  100. int i;
  101. int j;
  102. int facecount = 0;
  103. double rotation = 0.0;
  104. double rotInc;
  105. double cosVal;
  106. double sinVal;
  107. int stepsSqr;
  108. POINT3D norm;
  109. POINT3D a[MAXPREC + 1];
  110. POINT3D b[MAXPREC + 1];
  111. if (steps > MAXPREC)
  112. steps = MAXPREC;
  113. rotInc = (2.0 * PI) / (double)(steps - 1);
  114. stepsSqr = steps * steps;
  115. newMesh(mesh, stepsSqr, 4 * stepsSqr);
  116. for (j = 0; j < steps; j++, rotation += rotInc) {
  117. cosVal = cos(rotation);
  118. sinVal = sin(rotation);
  119. for (i = 0; i < steps; i++) {
  120. a[i].x = (float) (curve[i].x * cosVal + curve[i].z * sinVal);
  121. a[i].y = (float) (curve[i].y);
  122. a[i].z = (float) (curve[i].z * cosVal - curve[i].x * sinVal);
  123. }
  124. cosVal = cos(rotation + rotInc);
  125. sinVal = sin(rotation + rotInc);
  126. for (i = 0; i < steps; i++) {
  127. b[i].x = (float) (curve[i].x * cosVal + curve[i].z * sinVal);
  128. b[i].y = (float) (curve[i].y);
  129. b[i].z = (float) (curve[i].z * cosVal - curve[i].x * sinVal);
  130. }
  131. for (i = 0; i < (steps - 1); i++) {
  132. ss_calcNorm(&norm, &b[i + 1], &b[i], &a[i]);
  133. if ((norm.x * norm.x) + (norm.y * norm.y) + (norm.z * norm.z) < 0.9)
  134. ss_calcNorm(&norm, &a[i], &a[i+1], &b[i + 1]);
  135. mesh->faces[facecount].material = j & 7;
  136. mesh->faces[facecount].norm = norm;
  137. mesh->faces[facecount].p[0] = iPtInList(mesh, &b[i], &norm, 0);
  138. mesh->faces[facecount].p[1] = iPtInList(mesh, &a[i], &norm, 0);
  139. mesh->faces[facecount].p[2] = iPtInList(mesh, &b[i + 1], &norm, 0);
  140. mesh->faces[facecount].p[3] = iPtInList(mesh, &a[i + 1], &norm, 0);
  141. mesh->numFaces++;
  142. facecount++;
  143. }
  144. }
  145. ss_normalizeNorms(mesh->norms, mesh->numPoints);
  146. }
  147. HRESULT RenderMesh3( MESH* pMesh, BOOL bSmooth )
  148. {
  149. HRESULT hr;
  150. INT numPrims = 0;
  151. INT numIndices = 0;
  152. INT numVertices = 0;
  153. WORD iVertexA, iVertexB, iVertexC, iVertexD;
  154. INT a,b,c,d;
  155. MFACE *faces;
  156. m_pd3dDevice->SetVertexShader( D3DFVF_MYVERTEX );
  157. WORD* i;
  158. MYVERTEX* v;
  159. hr = m_pVB->Lock( 0, 0, (BYTE**)&v, 0 );
  160. hr = m_pIB->Lock( 0, MAX_INDICES, (BYTE**)&i, 0 );
  161. faces = pMesh->faces;
  162. for( int iFace = 0; iFace < pMesh->numFaces; iFace++ )
  163. {
  164. a = faces[iFace].p[0];
  165. b = faces[iFace].p[1];
  166. c = faces[iFace].p[2];
  167. d = faces[iFace].p[3];
  168. v[numVertices].p = pMesh->pts[a];
  169. v[numVertices].n = bSmooth ? pMesh->norms[a] : faces[iFace].norm;
  170. iVertexA = numVertices++;
  171. v[numVertices].p = pMesh->pts[b];
  172. v[numVertices].n = bSmooth ? pMesh->norms[b] : faces[iFace].norm;
  173. iVertexB = numVertices++;
  174. v[numVertices].p = pMesh->pts[c];
  175. v[numVertices].n = bSmooth ? pMesh->norms[c] : faces[iFace].norm;
  176. iVertexC = numVertices++;
  177. v[numVertices].p = pMesh->pts[d];
  178. v[numVertices].n = bSmooth ? pMesh->norms[d] : faces[iFace].norm;
  179. iVertexD = numVertices++;
  180. i[numIndices++] = iVertexA;
  181. i[numIndices++] = iVertexB;
  182. i[numIndices++] = iVertexC;
  183. numPrims++;
  184. i[numIndices++] = iVertexC;
  185. i[numIndices++] = iVertexB;
  186. i[numIndices++] = iVertexD;
  187. numPrims++;
  188. }
  189. hr = m_pVB->Unlock();
  190. hr = m_pIB->Unlock();
  191. hr = m_pd3dDevice->SetStreamSource( 0, m_pVB, sizeof(MYVERTEX) );
  192. hr = m_pd3dDevice->SetIndices( m_pIB, 0 );
  193. hr = m_pd3dDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, numVertices,
  194. 0, numPrims );
  195. return hr;
  196. }
  197. HRESULT RenderMesh3Backsides( MESH* pMesh, BOOL bSmooth )
  198. {
  199. HRESULT hr;
  200. INT numPrims = 0;
  201. INT numIndices = 0;
  202. INT numVertices = 0;
  203. WORD iVertexA, iVertexB, iVertexC, iVertexD;
  204. INT a,b,c,d;
  205. MFACE *faces;
  206. m_pd3dDevice->SetVertexShader( D3DFVF_MYVERTEX );
  207. WORD* i;
  208. MYVERTEX* v;
  209. hr = m_pVB->Lock( 0, 0, (BYTE**)&v, 0 );
  210. hr = m_pIB->Lock( 0, MAX_INDICES, (BYTE**)&i, 0 );
  211. faces = pMesh->faces;
  212. for( int iFace = 0; iFace < pMesh->numFaces; iFace++ )
  213. {
  214. a = faces[iFace].p[0];
  215. b = faces[iFace].p[1];
  216. c = faces[iFace].p[2];
  217. d = faces[iFace].p[3];
  218. v[numVertices].p = pMesh->pts[a];
  219. v[numVertices].n = bSmooth ? -pMesh->norms[a] : -faces[iFace].norm;
  220. iVertexA = numVertices++;
  221. v[numVertices].p = pMesh->pts[b];
  222. v[numVertices].n = bSmooth ? -pMesh->norms[b] : -faces[iFace].norm;
  223. iVertexB = numVertices++;
  224. v[numVertices].p = pMesh->pts[c];
  225. v[numVertices].n = bSmooth ? -pMesh->norms[c] : -faces[iFace].norm;
  226. iVertexC = numVertices++;
  227. v[numVertices].p = pMesh->pts[d];
  228. v[numVertices].n = bSmooth ? -pMesh->norms[d] : -faces[iFace].norm;
  229. iVertexD = numVertices++;
  230. i[numIndices++] = iVertexB;
  231. i[numIndices++] = iVertexA;
  232. i[numIndices++] = iVertexC;
  233. numPrims++;
  234. i[numIndices++] = iVertexB;
  235. i[numIndices++] = iVertexC;
  236. i[numIndices++] = iVertexD;
  237. numPrims++;
  238. }
  239. hr = m_pVB->Unlock();
  240. hr = m_pIB->Unlock();
  241. hr = m_pd3dDevice->SetStreamSource( 0, m_pVB, sizeof(MYVERTEX) );
  242. hr = m_pd3dDevice->SetIndices( m_pIB, 0 );
  243. hr = m_pd3dDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, numVertices,
  244. 0, numPrims );
  245. return hr;
  246. }