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.

409 lines
12 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 <GL\gl.h>
  13. #include <string.h>
  14. #include <math.h>
  15. #include "ss3dfo.h"
  16. #include "mesh.h"
  17. #define ZERO_EPS 0.00000001
  18. /******************************Public*Routine******************************\
  19. * newMesh
  20. *
  21. * Allocate memory for the mesh structure to accomodate the specified number
  22. * of points and faces.
  23. *
  24. \**************************************************************************/
  25. void newMesh(MESH *mesh, int numFaces, int numPts)
  26. {
  27. mesh->numFaces = 0;
  28. mesh->numPoints = 0;
  29. if (numPts) {
  30. mesh->pts = SaverAlloc((LONG)numPts * (LONG)sizeof(POINT3D));
  31. mesh->norms = SaverAlloc((LONG)numPts * (LONG)sizeof(POINT3D));
  32. }
  33. mesh->faces = SaverAlloc((LONG)numFaces * (LONG)sizeof(MFACE));
  34. }
  35. /******************************Public*Routine******************************\
  36. * delMesh
  37. *
  38. * Delete the allocated portions of the MESH structure.
  39. *
  40. \**************************************************************************/
  41. void delMesh(MESH *mesh)
  42. {
  43. SaverFree(mesh->pts);
  44. SaverFree(mesh->norms);
  45. SaverFree(mesh->faces);
  46. }
  47. /******************************Public*Routine******************************\
  48. * iPtInList
  49. *
  50. * Add a vertex and its normal to the mesh. If the vertex already exists,
  51. * add in the normal to the existing normal (we to accumulate the average
  52. * normal at each vertex). Normalization of the normals is the
  53. * responsibility of the caller.
  54. *
  55. \**************************************************************************/
  56. static int iPtInList(MESH *mesh, POINT3D *p, POINT3D *norm, int start)
  57. {
  58. int i;
  59. POINT3D *pts = mesh->pts + start;
  60. for (i = start; i < mesh->numPoints; i++, pts++)
  61. {
  62. // If the vertices are within ZERO_EPS of each other, then its the same
  63. // vertex.
  64. if ( fabs(pts->x - p->x) < ZERO_EPS &&
  65. fabs(pts->y - p->y) < ZERO_EPS &&
  66. fabs(pts->z - p->z) < ZERO_EPS )
  67. {
  68. mesh->norms[i].x += norm->x;
  69. mesh->norms[i].y += norm->y;
  70. mesh->norms[i].z += norm->z;
  71. return i;
  72. }
  73. }
  74. mesh->pts[i] = *p;
  75. mesh->norms[i] = *norm;
  76. mesh->numPoints++;
  77. return i;
  78. }
  79. /******************************Public*Routine******************************\
  80. * revolveSurface
  81. *
  82. * Takes the set of points in curve and fills the mesh structure with a
  83. * surface of revolution. The surface consists of quads made up of the
  84. * points in curve rotated about the y-axis. The number of increments
  85. * in the revolution is determined by the steps parameter.
  86. *
  87. \**************************************************************************/
  88. #define MAXPREC 40
  89. void revolveSurface(MESH *mesh, POINT3D *curve, int steps)
  90. {
  91. int i;
  92. int j;
  93. int facecount = 0;
  94. double rotation = 0.0;
  95. double rotInc;
  96. double cosVal;
  97. double sinVal;
  98. int stepsSqr;
  99. POINT3D norm;
  100. POINT3D a[MAXPREC + 1];
  101. POINT3D b[MAXPREC + 1];
  102. if (steps > MAXPREC)
  103. steps = MAXPREC;
  104. rotInc = (2.0 * PI) / (double)(steps - 1);
  105. stepsSqr = steps * steps;
  106. newMesh(mesh, stepsSqr, 4 * stepsSqr);
  107. for (j = 0; j < steps; j++, rotation += rotInc) {
  108. cosVal = cos(rotation);
  109. sinVal = sin(rotation);
  110. for (i = 0; i < steps; i++) {
  111. a[i].x = (float) (curve[i].x * cosVal + curve[i].z * sinVal);
  112. a[i].y = (float) (curve[i].y);
  113. a[i].z = (float) (curve[i].z * cosVal - curve[i].x * sinVal);
  114. }
  115. cosVal = cos(rotation + rotInc);
  116. sinVal = sin(rotation + rotInc);
  117. for (i = 0; i < steps; i++) {
  118. b[i].x = (float) (curve[i].x * cosVal + curve[i].z * sinVal);
  119. b[i].y = (float) (curve[i].y);
  120. b[i].z = (float) (curve[i].z * cosVal - curve[i].x * sinVal);
  121. }
  122. for (i = 0; i < (steps - 1); i++) {
  123. ss_calcNorm(&norm, &b[i + 1], &b[i], &a[i]);
  124. if ((norm.x * norm.x) + (norm.y * norm.y) + (norm.z * norm.z) < 0.9)
  125. ss_calcNorm(&norm, &a[i], &a[i+1], &b[i + 1]);
  126. mesh->faces[facecount].material = j & 7;
  127. mesh->faces[facecount].norm = norm;
  128. mesh->faces[facecount].p[0] = iPtInList(mesh, &b[i], &norm, 0);
  129. mesh->faces[facecount].p[1] = iPtInList(mesh, &a[i], &norm, 0);
  130. mesh->faces[facecount].p[2] = iPtInList(mesh, &b[i + 1], &norm, 0);
  131. mesh->faces[facecount].p[3] = iPtInList(mesh, &a[i + 1], &norm, 0);
  132. mesh->numFaces++;
  133. facecount++;
  134. }
  135. }
  136. ss_normalizeNorms(mesh->norms, mesh->numPoints);
  137. }
  138. /******************************Public*Routine******************************\
  139. * updateObject
  140. *
  141. * Takes the mesh structure and converts the data into OpenGL immediate
  142. * mode commands.
  143. *
  144. \**************************************************************************/
  145. void updateObject(MESH *mesh, BOOL bSmooth)
  146. {
  147. int i;
  148. int a, b;
  149. int aOffs, bOffs, cOffs, dOffs;
  150. MFACE *faces;
  151. POINT3D *pp;
  152. POINT3D *pn;
  153. int lastC, lastD;
  154. pp = mesh->pts;
  155. pn = mesh->norms;
  156. glBegin(GL_QUAD_STRIP);
  157. for (i = 0, faces = mesh->faces, lastC = faces->p[0], lastD = faces->p[1];
  158. i < mesh->numFaces; i++, faces++) {
  159. a = faces->p[0];
  160. b = faces->p[1];
  161. if (!bSmooth) {
  162. if ((a != lastC) || (b != lastD)) {
  163. glNormal3fv((GLfloat *)&(faces - 1)->norm);
  164. glVertex3fv((GLfloat *)((char *)pp +
  165. (lastC << 3) + (lastC << 2)));
  166. glVertex3fv((GLfloat *)((char *)pp +
  167. (lastD << 3) + (lastD << 2)));
  168. glEnd();
  169. glBegin(GL_QUAD_STRIP);
  170. }
  171. glNormal3fv((GLfloat *)&faces->norm);
  172. glVertex3fv((GLfloat *)((char *)pp + (a << 3) + (a << 2)));
  173. glVertex3fv((GLfloat *)((char *)pp + (b << 3) + (b << 2)));
  174. } else {
  175. if ((a != lastC) || (b != lastD)) {
  176. cOffs = (lastC << 3) + (lastC << 2);
  177. dOffs = (lastD << 3) + (lastD << 2);
  178. glNormal3fv((GLfloat *)((char *)pn + cOffs));
  179. glVertex3fv((GLfloat *)((char *)pp + cOffs));
  180. glNormal3fv((GLfloat *)((char *)pn + dOffs));
  181. glVertex3fv((GLfloat *)((char *)pp + dOffs));
  182. glEnd();
  183. glBegin(GL_QUAD_STRIP);
  184. }
  185. aOffs = (a << 3) + (a << 2);
  186. bOffs = (b << 3) + (b << 2);
  187. glNormal3fv((GLfloat *)((char *)pn + aOffs));
  188. glVertex3fv((GLfloat *)((char *)pp + aOffs));
  189. glNormal3fv((GLfloat *)((char *)pn + bOffs));
  190. glVertex3fv((GLfloat *)((char *)pp + bOffs));
  191. }
  192. lastC = faces->p[2];
  193. lastD = faces->p[3];
  194. }
  195. if (!bSmooth) {
  196. glNormal3fv((GLfloat *)&(faces - 1)->norm);
  197. glVertex3fv((GLfloat *)((char *)pp + (lastC << 3) + (lastC << 2)));
  198. glVertex3fv((GLfloat *)((char *)pp + (lastD << 3) + (lastD << 2)));
  199. } else {
  200. cOffs = (lastC << 3) + (lastC << 2);
  201. dOffs = (lastD << 3) + (lastD << 2);
  202. glNormal3fv((GLfloat *)((char *)pn + cOffs));
  203. glVertex3fv((GLfloat *)((char *)pp + cOffs));
  204. glNormal3fv((GLfloat *)((char *)pn + dOffs));
  205. glVertex3fv((GLfloat *)((char *)pp + dOffs));
  206. }
  207. glEnd();
  208. }
  209. /******************************Public*Routine******************************\
  210. * updateObject
  211. *
  212. * This is a special case that handles a mesh structure that represents
  213. * a strip that is a 1 high loop.
  214. *
  215. * Takes the mesh structure and converts the data into OpenGL immediate
  216. * mode commands.
  217. *
  218. \**************************************************************************/
  219. void updateObject2(MESH *mesh, BOOL bSmooth)
  220. {
  221. int i;
  222. int a, b;
  223. int aOffs, bOffs, cOffs, dOffs;
  224. MFACE *faces;
  225. POINT3D *pp;
  226. POINT3D *pn;
  227. int lastC, lastD;
  228. pp = mesh->pts;
  229. pn = mesh->norms;
  230. glBegin(GL_QUAD_STRIP);
  231. for (i = 0, faces = mesh->faces, lastC = faces->p[0], lastD = faces->p[1];
  232. i < mesh->numFaces; i++, faces++) {
  233. a = faces->p[0];
  234. b = faces->p[1];
  235. if (!bSmooth) {
  236. glNormal3fv((GLfloat *)&faces->norm);
  237. glVertex3fv((GLfloat *)((char *)pp + (a << 3) + (a << 2)));
  238. glVertex3fv((GLfloat *)((char *)pp + (b << 3) + (b << 2)));
  239. } else {
  240. aOffs = (a << 3) + (a << 2);
  241. bOffs = (b << 3) + (b << 2);
  242. glNormal3fv((GLfloat *)((char *)pn + aOffs));
  243. glVertex3fv((GLfloat *)((char *)pp + aOffs));
  244. glNormal3fv((GLfloat *)((char *)pn + bOffs));
  245. glVertex3fv((GLfloat *)((char *)pp + bOffs));
  246. }
  247. lastC = faces->p[2];
  248. lastD = faces->p[3];
  249. }
  250. if (!bSmooth) {
  251. glNormal3fv((GLfloat *)&(mesh->faces)->norm);
  252. glVertex3fv((GLfloat *)((char *)pp + (lastC << 3) + (lastC << 2)));
  253. glVertex3fv((GLfloat *)((char *)pp + (lastD << 3) + (lastD << 2)));
  254. } else {
  255. cOffs = (lastC << 3) + (lastC << 2);
  256. dOffs = (lastD << 3) + (lastD << 2);
  257. glNormal3fv((GLfloat *)((char *)pn + cOffs));
  258. glVertex3fv((GLfloat *)((char *)pp + cOffs));
  259. glNormal3fv((GLfloat *)((char *)pn + dOffs));
  260. glVertex3fv((GLfloat *)((char *)pp + dOffs));
  261. }
  262. glEnd();
  263. }
  264. /******************************Public*Routine******************************\
  265. * MakeList
  266. *
  267. * Takes the mesh structure and converts the data into OpenGL display
  268. * list.
  269. *
  270. \**************************************************************************/
  271. void MakeList(GLuint listID, MESH *mesh)
  272. {
  273. int i;
  274. int a, b;
  275. int aOffs, bOffs, cOffs, dOffs;
  276. MFACE *faces;
  277. BOOL bSmooth;
  278. POINT3D *pp;
  279. POINT3D *pn;
  280. GLint shadeModel;
  281. int lastC, lastD;
  282. glGetIntegerv(GL_SHADE_MODEL, &shadeModel);
  283. bSmooth = (shadeModel == GL_SMOOTH);
  284. glNewList(listID, GL_COMPILE);
  285. pp = mesh->pts;
  286. pn = mesh->norms;
  287. glBegin(GL_QUAD_STRIP);
  288. for (i = 0, faces = mesh->faces, lastC = faces->p[0], lastD = faces->p[1];
  289. i < mesh->numFaces; i++, faces++) {
  290. a = faces->p[0];
  291. b = faces->p[1];
  292. if (!bSmooth) {
  293. if ((a != lastC) || (b != lastD)) {
  294. glNormal3fv((GLfloat *)&((faces - 1)->norm));
  295. glVertex3fv((GLfloat *)((char *)pp +
  296. (lastC << 3) + (lastC << 2)));
  297. glVertex3fv((GLfloat *)((char *)pp +
  298. (lastD << 3) + (lastD << 2)));
  299. glEnd();
  300. glBegin(GL_QUAD_STRIP);
  301. }
  302. glNormal3fv((GLfloat *)&faces->norm);
  303. glVertex3fv((GLfloat *)((char *)pp + (a << 3) + (a << 2)));
  304. glVertex3fv((GLfloat *)((char *)pp + (b << 3) + (b << 2)));
  305. } else {
  306. if ((a != lastC) || (b != lastD)) {
  307. cOffs = (lastC << 3) + (lastC << 2);
  308. dOffs = (lastD << 3) + (lastD << 2);
  309. glNormal3fv((GLfloat *)((char *)pn + cOffs));
  310. glVertex3fv((GLfloat *)((char *)pp + cOffs));
  311. glNormal3fv((GLfloat *)((char *)pn + dOffs));
  312. glVertex3fv((GLfloat *)((char *)pp + dOffs));
  313. glEnd();
  314. glBegin(GL_QUAD_STRIP);
  315. }
  316. aOffs = (a << 3) + (a << 2);
  317. bOffs = (b << 3) + (b << 2);
  318. glNormal3fv((GLfloat *)((char *)pn + aOffs));
  319. glVertex3fv((GLfloat *)((char *)pp + aOffs));
  320. glNormal3fv((GLfloat *)((char *)pn + bOffs));
  321. glVertex3fv((GLfloat *)((char *)pp + bOffs));
  322. }
  323. lastC = faces->p[2];
  324. lastD = faces->p[3];
  325. }
  326. if (!bSmooth) {
  327. glNormal3fv((GLfloat *)&((faces - 1)->norm));
  328. glVertex3fv((GLfloat *)((char *)pp + (lastC << 3) + (lastC << 2)));
  329. glVertex3fv((GLfloat *)((char *)pp + (lastD << 3) + (lastD << 2)));
  330. } else {
  331. cOffs = (lastC << 3) + (lastC << 2);
  332. dOffs = (lastD << 3) + (lastD << 2);
  333. glNormal3fv((GLfloat *)((char *)pn + cOffs));
  334. glVertex3fv((GLfloat *)((char *)pp + cOffs));
  335. glNormal3fv((GLfloat *)((char *)pn + dOffs));
  336. glVertex3fv((GLfloat *)((char *)pp + dOffs));
  337. }
  338. glEnd();
  339. glEndList();
  340. }