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.

415 lines
12 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: nff.c
  3. *
  4. * Parse the Neutral File Format (.NFF) by Eric Haines of 3D/Eye Inc.
  5. *
  6. * Documentation on NFF available from a varity of sources including:
  7. *
  8. * Eric Haines, 3D/Eye Inc., 2359 N. Triphammer Rd., Ithaca, NY, 14850,
  9. * erich@eye.com.
  10. *
  11. * Murray, J. D. and van Ryper, W., _Encyclopedia of Graphics File Formats_,
  12. * O'Reilly & Associates, 1994, pp. 471-478.
  13. *
  14. * Created: 14-Mar-1995 23:26:34
  15. * Author: Gilman Wong [gilmanw]
  16. *
  17. * Copyright (c) 1995 Microsoft Corporation
  18. *
  19. \**************************************************************************/
  20. #include <windows.h>
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <ctype.h>
  24. #include <math.h>
  25. #include "global.h"
  26. #include "nff.h"
  27. #define STATIC
  28. typedef struct tagNFFPRIV
  29. {
  30. BOOL bInList; // TRUE while compiling display list
  31. BOOL bKayHack; // support for the 'k' backface color hack
  32. } NFFPRIV;
  33. GLint maxLights;
  34. STATIC void parseNffFile(SCENE *, LPTSTR);
  35. STATIC void DoDisplayList(SCENE *);
  36. STATIC void EndDisplayList(SCENE *);
  37. STATIC void parseNffViewpoint(SCENE *scene, FILE *file, char *ach, int n);
  38. STATIC void parseNffBackground(SCENE *scene, FILE *file, char *ach, int n);
  39. STATIC void parseNffLight(SCENE *scene, FILE *file, char *ach, int n);
  40. STATIC void parseNffColor(SCENE *scene, FILE *file, char *ach, int n, GLenum matSide);
  41. STATIC void parseNffCone(SCENE *scene, FILE *file, char *ach, int n);
  42. STATIC void parseNffSphere(SCENE *scene, FILE *file, char *ach, int n);
  43. STATIC void parseNffPolygon(SCENE *scene, FILE *file, char *ach, int n);
  44. STATIC void parseNffPolygonPatch(SCENE *scene, FILE *file, char *ach, int n);
  45. SCENE *NffOpenScene(LPTSTR lpstr)
  46. {
  47. SCENE *scene;
  48. scene = (SCENE *) LocalAlloc(LMEM_FIXED, sizeof(SCENE) + sizeof(NFFPRIV));
  49. if (scene)
  50. {
  51. NFFPRIV *nffPriv = (NFFPRIV *) (scene + 1);
  52. glGetIntegerv(GL_MAX_LIGHTS, &maxLights);
  53. scene->xyzFrom.x = 0.0;
  54. scene->xyzFrom.y = 0.0;
  55. scene->xyzFrom.z = 5.0;
  56. scene->xyzAt.x = 0.0;
  57. scene->xyzAt.y = 0.0;
  58. scene->xyzAt.z = 0.0;
  59. scene->xyzUp.x = 0.0;
  60. scene->xyzUp.y = 1.0;
  61. scene->xyzUp.z = 0.0;
  62. scene->ViewAngle = 45.0f;
  63. scene->Hither = 0.1f;
  64. scene->Yon = 1000000000.0f; // always "infinity" for NFF
  65. scene->AspectRatio = 1.0f; // always 1.0 for NFF
  66. scene->szWindow.cx = 300;
  67. scene->szWindow.cy = 300;
  68. scene->rgbaClear.r = (GLfloat) 0.0; // default is black
  69. scene->rgbaClear.g = (GLfloat) 0.0;
  70. scene->rgbaClear.b = (GLfloat) 0.0;
  71. scene->rgbaClear.a = (GLfloat) 1.0;
  72. scene->Lights.count = 0;
  73. scene->Lights.listBase = 1;
  74. scene->Objects.count = 1;
  75. scene->Objects.listBase = maxLights + 1;
  76. scene->pvData = (VOID *) nffPriv;
  77. nffPriv->bInList = FALSE;
  78. nffPriv->bKayHack = FALSE;
  79. LBprintf("================================");
  80. LBprintf("Parsing NFF file, please wait...");
  81. LBprintf("================================");
  82. parseNffFile(scene, lpstr);
  83. LBprintf("Here we go!");
  84. }
  85. else
  86. {
  87. LBprintf("NffOpenScene: memory allocation failure");
  88. }
  89. return scene;
  90. }
  91. STATIC void parseNffFile(SCENE *scene, LPTSTR lpstr)
  92. {
  93. FILE *file;
  94. char ach[512];
  95. char achToken[5];
  96. file = fopen(lpstr, "r");
  97. if (file)
  98. {
  99. BOOL bKeepGoing = TRUE;
  100. do
  101. {
  102. if (fgets(ach, 512, file) != NULL)
  103. {
  104. switch(ach[0])
  105. {
  106. case 'v':
  107. case 'V':
  108. parseNffViewpoint(scene, file, ach, 512);
  109. break;
  110. case 'b':
  111. case 'B':
  112. parseNffBackground(scene, file, ach, 512);
  113. break;
  114. case 'l':
  115. case 'L':
  116. parseNffLight(scene, file, ach, 512);
  117. break;
  118. case 'f':
  119. case 'F':
  120. if (((NFFPRIV *)scene->pvData)->bKayHack)
  121. parseNffColor(scene, file, ach, 512, GL_FRONT);
  122. else
  123. parseNffColor(scene, file, ach, 512, GL_FRONT_AND_BACK);
  124. break;
  125. case 'k':
  126. case 'K':
  127. parseNffColor(scene, file, ach, 512, GL_BACK);
  128. ((NFFPRIV *)scene->pvData)->bKayHack = TRUE;
  129. break;
  130. case 'c':
  131. case 'C':
  132. parseNffCone(scene, file, ach, 512);
  133. break;
  134. case 's':
  135. case 'S':
  136. parseNffSphere(scene, file, ach, 512);
  137. break;
  138. case 'p':
  139. case 'P':
  140. if ((ach[1] == 'p') || (ach[1] == 'P'))
  141. parseNffPolygonPatch(scene, file, ach, 512);
  142. else
  143. parseNffPolygon(scene, file, ach, 512);
  144. break;
  145. case '#':
  146. LBprintf(ach);
  147. break;
  148. default:
  149. LBprintf("unknown: %s", ach);
  150. break;
  151. }
  152. }
  153. else
  154. {
  155. bKeepGoing = FALSE;
  156. //LBprintf("possible EOF");
  157. }
  158. } while (bKeepGoing || !feof(file));
  159. fclose(file);
  160. EndDisplayList(scene);
  161. }
  162. else
  163. {
  164. LBprintf("fopen failed %s", lpstr);
  165. LBprintf("USAGE: viewer [NFF filename].NFF");
  166. }
  167. }
  168. STATIC void DoDisplayList(SCENE *scene)
  169. {
  170. if (!((NFFPRIV *)scene->pvData)->bInList)
  171. {
  172. ((NFFPRIV *)scene->pvData)->bInList = TRUE;
  173. glNewList(scene->Objects.listBase, GL_COMPILE);
  174. //LBprintf("BEGIN DISPLAY LIST");
  175. }
  176. }
  177. STATIC void EndDisplayList(SCENE *scene)
  178. {
  179. if (((NFFPRIV *)scene->pvData)->bInList)
  180. {
  181. ((NFFPRIV *)scene->pvData)->bInList = FALSE;
  182. glEndList();
  183. //LBprintf("END DISPLAY LIST");
  184. }
  185. }
  186. STATIC void parseNffViewpoint(SCENE *scene, FILE *file, char *ach, int n)
  187. {
  188. if (((NFFPRIV *)scene->pvData)->bInList)
  189. LBprintf("NFF error: setting viewpoint too late");
  190. fgets(ach, n, file);
  191. sscanf(ach, "from %g %g %g", &scene->xyzFrom.x, &scene->xyzFrom.y, &scene->xyzFrom.z);
  192. fgets(ach, n, file);
  193. sscanf(ach, "at %g %g %g", &scene->xyzAt.x, &scene->xyzAt.y, &scene->xyzAt.z);
  194. fgets(ach, n, file);
  195. sscanf(ach, "up %g %g %g", &scene->xyzUp.x, &scene->xyzUp.y, &scene->xyzUp.z);
  196. fgets(ach, n, file);
  197. sscanf(ach, "angle %g", &scene->ViewAngle);
  198. fgets(ach, n, file);
  199. //!!!dbug -- possible front plane clipping problem; should calculate the
  200. //!!! bounding sphere and use this to set near plane, but for now
  201. //!!! set it to zero
  202. //sscanf(ach, "hither %g", &scene->Hither);
  203. scene->Hither = 0.001f;
  204. fgets(ach, n, file);
  205. sscanf(ach, "resolution %ld %ld", &scene->szWindow.cx, &scene->szWindow.cy);
  206. // Estimate the yon plane as 2.5 times the distance from eye to object.
  207. scene->Yon = ((scene->xyzAt.x - scene->xyzFrom.x) * (scene->xyzAt.x - scene->xyzFrom.x)) +
  208. ((scene->xyzAt.y - scene->xyzFrom.y) * (scene->xyzAt.y - scene->xyzFrom.y)) +
  209. ((scene->xyzAt.z - scene->xyzFrom.z) * (scene->xyzAt.z - scene->xyzFrom.z));
  210. scene->Yon = sqrt(scene->Yon) * 2.5f;
  211. #if 0
  212. LBprintf("Viewpoint");
  213. LBprintf("from %g %g %g", scene->xyzFrom.x, scene->xyzFrom.y, scene->xyzFrom.z);
  214. LBprintf("at %g %g %g", scene->xyzAt.x, scene->xyzAt.y, scene->xyzAt.z);
  215. LBprintf("up %g %g %g", scene->xyzUp.x, scene->xyzUp.y, scene->xyzUp.z);
  216. LBprintf("angle %g", scene->ViewAngle);
  217. LBprintf("hither %g", scene->Hither);
  218. LBprintf("resolution %ld %ld", scene->szWindow.cx, scene->szWindow.cy);
  219. LBprintf("yon (estimate) %g", scene->Yon);
  220. #endif
  221. }
  222. STATIC void parseNffBackground(SCENE *scene, FILE *file, char *ach, int n)
  223. {
  224. if (((NFFPRIV *)scene->pvData)->bInList)
  225. LBprintf("NFF error: setting background color too late");
  226. //LBprintf(ach);
  227. sscanf(ach, "b %g %g %g", &scene->rgbaClear.r, &scene->rgbaClear.g, &scene->rgbaClear.b);
  228. }
  229. STATIC void parseNffLight(SCENE *scene, FILE *file, char *ach, int n)
  230. {
  231. GLfloat xyz[3];
  232. GLfloat rgb[4] = {1.0f, 1.0f, 1.0f, 1.0f};
  233. //!!! specular light should be the same as diffuse
  234. //static GLfloat lightSpecular[4] = {1.0f, 1.0f, 1.0f, 1.0f};
  235. if (((NFFPRIV *)scene->pvData)->bInList)
  236. LBprintf("NFF error: setting lights too late");
  237. sscanf(ach, "l %g %g %g %g %g %g", &xyz[0], &xyz[1], &xyz[2]
  238. , &rgb[0], &rgb[1], &rgb[2]);
  239. if (scene->Lights.count < (maxLights + 1))
  240. {
  241. glNewList(scene->Lights.listBase + scene->Lights.count, GL_COMPILE);
  242. glLightfv(GL_LIGHT0 + scene->Lights.count, GL_POSITION, xyz);
  243. glLightfv(GL_LIGHT0 + scene->Lights.count, GL_DIFFUSE, rgb);
  244. glLightfv(GL_LIGHT0 + scene->Lights.count, GL_SPECULAR, rgb);
  245. glEndList();
  246. scene->Lights.count++;
  247. }
  248. }
  249. STATIC void parseNffColor(SCENE *scene, FILE *file, char *ach, int n, GLenum matSide)
  250. {
  251. GLfloat rgb[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
  252. GLfloat Kd, Ks, Shine, Trans, Refract;
  253. GLfloat lightSpecular[4] = {1.0f, 1.0f, 1.0f, 1.0f};
  254. DoDisplayList(scene);
  255. if (matSide == GL_BACK)
  256. sscanf(ach, "k %g %g %g %g %g %g %g %g", &rgb[0], &rgb[1], &rgb[2],
  257. &Kd, &Ks, &Shine,
  258. &Trans, &Refract);
  259. else
  260. sscanf(ach, "f %g %g %g %g %g %g %g %g", &rgb[0], &rgb[1], &rgb[2],
  261. &Kd, &Ks, &Shine,
  262. &Trans, &Refract);
  263. rgb[0] *= Kd; rgb[1] *= Kd; rgb[2] *= Kd;
  264. lightSpecular[0] *= Ks; lightSpecular[1] *= Ks; lightSpecular[2] *= Ks;
  265. glMaterialfv(matSide, GL_SPECULAR, lightSpecular);
  266. glMaterialfv(matSide, GL_AMBIENT_AND_DIFFUSE, rgb);
  267. glMaterialfv(matSide, GL_SHININESS, (GLfloat *) &Shine);
  268. }
  269. STATIC void parseNffCone(SCENE *scene, FILE *file, char *ach, int n)
  270. {
  271. GLfloat xBase, yBase, zBase, rBase;
  272. GLfloat xApex, yApex, zApex, rApex;
  273. DoDisplayList(scene);
  274. LBprintf("*** Cylinder not implemented yet!");
  275. fgets(ach, n, file);
  276. sscanf(ach, "%g %g %g %g", &xBase, &yBase, &zBase, &rBase);
  277. fgets(ach, n, file);
  278. sscanf(ach, "%g %g %g %g", &xApex, &yApex, &zApex, &rApex);
  279. LBprintf(" base %g %g %g %g", xBase, yBase, zBase, rBase);
  280. LBprintf(" apex %g %g %g %g", xApex, yApex, zApex, rApex);
  281. }
  282. STATIC void parseNffSphere(SCENE *scene, FILE *file, char *ach, int n)
  283. {
  284. GLfloat x, y, z, r;
  285. DoDisplayList(scene);
  286. LBprintf("*** Sphere not implemented yet!");
  287. sscanf(ach, "%g %g %g %g", &x, &y, &z, &r);
  288. LBprintf(" %g %g %g %g", x, y, z, r);
  289. }
  290. STATIC void parseNffPolygon(SCENE *scene, FILE *file, char *ach, int n)
  291. {
  292. GLuint i, numVert;
  293. GLfloat *aVerts, *pVert;
  294. GLfloat aNorm[3];
  295. DoDisplayList(scene);
  296. sscanf(ach, "p %ld", &numVert);
  297. aVerts = (GLfloat *) LocalAlloc(LMEM_FIXED, sizeof(GLfloat) * numVert * 3);
  298. if (aVerts)
  299. {
  300. for ( i = 0, pVert = aVerts; i < numVert; i++, pVert+=3 )
  301. {
  302. fgets(ach, n, file);
  303. sscanf(ach, "%g %g %g", &pVert[0], &pVert[1], &pVert[2]);
  304. }
  305. calcNorm(aNorm, &aVerts[0], &aVerts[3], &aVerts[6]);
  306. glBegin(numVert == 3 ? GL_TRIANGLES :
  307. numVert == 4 ? GL_QUADS :
  308. GL_POLYGON);
  309. {
  310. glNormal3fv(aNorm);
  311. for ( i = 0, pVert = aVerts; i < numVert; i++, pVert+=3 )
  312. glVertex3fv(pVert);
  313. }
  314. glEnd();
  315. LocalFree(pVert);
  316. }
  317. }
  318. STATIC void parseNffPolygonPatch(SCENE *scene, FILE *file, char *ach, int n)
  319. {
  320. GLfloat x, y, z;
  321. GLfloat nx, ny, nz;
  322. GLuint count;
  323. DoDisplayList(scene);
  324. sscanf(ach, "pp %ld", &count);
  325. glBegin(count == 3 ? GL_TRIANGLES :
  326. count == 4 ? GL_QUADS :
  327. GL_POLYGON);
  328. for ( ; count; count--)
  329. {
  330. fgets(ach, n, file);
  331. sscanf(ach, "%g %g %g %g %g %g", &x, &y, &z, &nx, &ny, &nz);
  332. glNormal3f(nx, ny, nz);
  333. glVertex3f(x, y, z);
  334. }
  335. glEnd();
  336. }