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.

631 lines
17 KiB

  1. #include "precomp.h"
  2. #pragma hdrstop
  3. #include "cpmesh.h"
  4. #include "pmerrors.h"
  5. #include "fileio.h"
  6. float (* vdata)[3];
  7. static GLuint LoadTexture (char* file)
  8. {
  9. return 0;
  10. }
  11. const short PM_MAX_TEX_STRING_LEN = 1024; // Enforced by the spec.
  12. /*
  13. * This function currently only works on external files, not on URLs.
  14. * It can only load .pmx files and not PM records embedded in X files.
  15. * Hence the "pmname" argument is ignored.
  16. * It only supports synchronous loads so pPMeshLoadCB is ignored
  17. * !!Currently no memory cleanup occurs on error. Must add code to do so.
  18. * Could use a local win32 heap!!
  19. * See \\anujg\docs\"Progressive Mesh file format.doc" for details on the
  20. * file format
  21. */
  22. /*
  23. * The concept of Materials:
  24. * 1) Materials can be "looked up", i.e. textures
  25. * 2) Computed using a API specific lighting equation. (pure mat)
  26. * 3) Both of above combined. (Modulated/Lit textures)
  27. */
  28. STDMETHODIMP CPMeshGL::Load(const TCHAR* const url,
  29. const TCHAR* const pmname,
  30. DWORD* const minvert,
  31. DWORD* const maxvert,
  32. LPPMESHLOADCB pPMeshLoadCB)
  33. {
  34. DWORD i, k;
  35. WORD j, ftCurveSize, fmCurveSize;
  36. DWORD vAttr, wAttr, fAttr, mAttr, sAttr;
  37. DWORD mOffset, vOffset, wOffset, fOffset;
  38. DWORD& maxVert = *maxvert;
  39. DWORD& minVert = *minvert;
  40. HRESULT hr;
  41. DWORD vsplit_offset, bmesh_offset;
  42. // Estimated number of faces and wedges in the mesh with maxvert vertices
  43. DWORD nFacePredict=0, nWedgePredict=0;
  44. // A curve is approximated by an array of pairs {(x,y), (x,y),...}
  45. typedef struct crvpnt{
  46. DWORD x;
  47. float y;
  48. } *CURVE;
  49. CURVE *ftcurves, *fmcurves; // An array of curves
  50. ifstream is(url);
  51. if (!is)
  52. return PM_E_FOPENERROR;
  53. is.setmode(filebuf::binary);
  54. #ifdef __DUMP_DATA
  55. ofstream dump("dump.pmx");
  56. if (!dump)
  57. return PM_E_FOPENERROR;
  58. dump.setmode(filebuf::text);
  59. #endif //__DUMP_DATA
  60. /*
  61. * Read PMesh Header
  62. */
  63. read_DWORD(is, m_maxVertices);
  64. #ifdef __MAT_PREALLOC_OPTIMIZATION
  65. maxVert = min(maxVert, m_maxVertices);
  66. #else
  67. maxVert = m_maxVertices;
  68. #endif //__MAT_PREALLOC_OPTIMIZATION
  69. *maxvert = maxVert;
  70. read_DWORD(is, m_maxWedges);
  71. read_DWORD(is, m_maxFaces);
  72. read_DWORD(is, m_maxMaterials);
  73. read_DWORD(is, m_maxTextures);
  74. #ifdef __DUMP_DATA
  75. dump << "\nMaxVert = " << m_maxVertices;
  76. dump << "\nMaxWedges = " << m_maxWedges;
  77. dump << "\nMaxFaces = " << m_maxFaces;
  78. dump << "\nMaxMat = " << m_maxMaterials;
  79. dump << "\nMaxTex = " << m_maxTextures;
  80. #endif //__DUMP_DATA
  81. /*
  82. * Max Valence
  83. */
  84. read_DWORD(is, i);
  85. if (i > 65535)
  86. return PM_E_BADVALENCE;
  87. #ifdef __DUMP_DATA
  88. dump << "\nMaxValence = " << i;
  89. #endif //__DUMP_DATA
  90. /*
  91. * Normal Encoding
  92. */
  93. read_WORD(is, j);
  94. if (((j & NORM_MASK) != NORM_EXPLICIT) || ((j & TEX_MASK) != TEX_EXPLICIT))
  95. return PM_E_BADWEDGEDATA;
  96. #ifdef __DUMP_DATA
  97. dump << "\nNormal Encoding = " << j;
  98. #endif //__DUMP_DATA
  99. /*
  100. * Integer Encoding
  101. */
  102. read_WORD(is, j); // integer encoding type
  103. if (j != INTC_MAX)
  104. return PM_E_BADINTCODE;
  105. #ifdef __DUMP_DATA
  106. dump << "\nInteger Encoding = " << j;
  107. #endif //__DUMP_DATA
  108. /*
  109. * Sizes of various user defined attributes
  110. */
  111. read_DWORD(is, vAttr); // Vertex attributes
  112. read_DWORD(is, wAttr); // Wedge attributes
  113. read_DWORD(is, fAttr); // Face attributes
  114. read_DWORD(is, mAttr); // Material attributes
  115. read_DWORD(is, sAttr); // VSplit attributes
  116. #ifdef __DUMP_DATA
  117. dump << "\n\nUser defined attribute sizes:";
  118. dump << "\nVertex: " << vAttr;
  119. dump << "\nWedge: " << wAttr;
  120. dump << "\nFace: " << fAttr;
  121. dump << "\nMaterial: " << mAttr;
  122. dump << "\nVSplit: " << sAttr;
  123. #endif //__DUMP_DATA
  124. /*
  125. * Allocate material and texture related tables
  126. */
  127. WORD *matcnt = new WORD [m_maxMaterials];
  128. #ifdef __MATPOS_IS_A_PTR
  129. GLface **matpos = new GLface* [m_maxMaterials];
  130. #else
  131. WORD *matpos = new WORD [m_maxMaterials];
  132. #endif
  133. GLmaterial *matArray = new GLmaterial [m_maxMaterials];
  134. if (!matArray || !matcnt || !matpos)
  135. {
  136. return E_OUTOFMEMORY;
  137. }
  138. else
  139. {
  140. m_matArray = matArray;
  141. m_matcnt = matcnt;
  142. m_matpos = matpos;
  143. }
  144. #ifdef __MATPOS_IS_A_PTR
  145. /*
  146. * Allocate the vertex and normal arrays.
  147. */
  148. GLvertex *varray = new GLvertex [m_maxWedges];
  149. GLnormal *narray = new GLnormal [m_maxWedges];
  150. GLtexCoord *tarray = new GLtexCoord [m_maxWedges];
  151. WORD *wedgelist = new WORD [m_maxWedges];
  152. WORD (*fnei)[3] = new WORD [m_maxFaces][3];
  153. GLface *farray = new GLface [m_maxFaces];
  154. if (!farray || !varray || !narray || !tarray || !wedgelist || !fnei)
  155. {
  156. return E_OUTOFMEMORY;
  157. }
  158. else
  159. {
  160. m_varray = varray;
  161. m_narray = narray;
  162. m_tarray = tarray;
  163. m_farray = farray;
  164. m_wedgelist = wedgelist;
  165. m_fnei = fnei;
  166. }
  167. #endif
  168. /*
  169. * Read face-texture curve
  170. */
  171. read_WORD(is, ftCurveSize); // Size of face-texture curve
  172. #ifdef __DUMP_DATA
  173. dump << "\n\nFace-texture curve:";
  174. dump << "\nFT-curve size: " << ftCurveSize;
  175. #endif //__DUMP_DATA
  176. ftcurves = new CURVE[m_maxTextures]; // A curve for each texture
  177. DWORD* ftmax = new DWORD[m_maxTextures];
  178. if (!ftcurves || !ftmax)
  179. return E_OUTOFMEMORY;
  180. for (k=0; k<m_maxTextures; ++k)
  181. {
  182. ftcurves[k] = new crvpnt[ftCurveSize];
  183. if (!ftcurves[k])
  184. return E_OUTOFMEMORY;
  185. read_DWORD(is,ftmax[k]); // Total faces of tex k in fully detailed
  186. // mesh
  187. #ifdef __DUMP_DATA
  188. dump << "\n\nTotal faces of tex " << k << " in fully detailed mesh: ";
  189. dump << ftmax[k];
  190. #endif //__DUMP_DATA
  191. for (i=0; i<ftCurveSize; ++i)
  192. {
  193. read_DWORD(is, ftcurves[k][i].x); // vertex(i) of ftcurve of
  194. // texture k.
  195. read_float(is, ftcurves[k][i].y); // faces of tex k when total
  196. // vert in mesh = vertex(i).
  197. #ifdef __DUMP_DATA
  198. dump << "\n (" << ftcurves[k][i].x << ", " << ftcurves[k][i].y << ")";
  199. #endif //__DUMP_DATA
  200. }
  201. }
  202. #ifdef __TEX_PREALLOC_OPTIMIZATION
  203. for (k=0; k<m_maxTextures; ++k)
  204. {
  205. for (i=0; i<ftCurveSize; ++i)
  206. {
  207. if (ftcurves[k][i].x == maxVert)
  208. {
  209. m_texcnt[k] = WORD(ftcurves[k][i].y + 0.5);
  210. m_texcnt[k] = WORD(min(m_texcnt[k], ftmax[k]));
  211. break;
  212. }
  213. else if (ftcurves[k][i].x > maxVert)
  214. {
  215. m_texcnt[k] = WORD(ftcurves[k][i-1].y +
  216. (maxVert - ftcurves[k][i-1].x) *
  217. (ftcurves[k][i].y - ftcurves[k][i-1].y) /
  218. (ftcurves[k][i].x - ftcurves[k][i-1].x));
  219. m_texcnt[k] = WORD(min(m_texcnt[k], ftmax[k]));
  220. break;
  221. }
  222. }
  223. nFacePredict += m_texcnt[k];
  224. delete [] ftcurves[k];
  225. }
  226. delete [] ftcurves;
  227. delete [] ftmax;
  228. /*
  229. * Convert m_texcnt to array of offsets into the prim buf where faces of
  230. * that texture need to be stored.
  231. */
  232. m_texpos[0] = 0;
  233. for (i=1; i<m_maxTextures; ++i)
  234. m_texpos[i] = WORD(m_texpos[i-1] + m_texcnt[i-1] +
  235. TEXTUREGAP/sizeof(D3DTRIANGLE));
  236. #else
  237. delete [] ftcurves;
  238. delete [] ftmax;
  239. #endif __TEX_PREALLOC_OPTIMIZATION
  240. /*
  241. * Read face-material curve
  242. */
  243. read_WORD(is,fmCurveSize); // Size of face-material curve
  244. #ifdef __DUMP_DATA
  245. dump << "\n\nFace-material curve:";
  246. dump << "\nFM-curve size: " << fmCurveSize;
  247. #endif //__DUMP_DATA
  248. fmcurves = new CURVE[m_maxMaterials];
  249. DWORD* fmmax = new DWORD[m_maxMaterials];
  250. if (!fmcurves || !fmmax)
  251. return E_OUTOFMEMORY;
  252. for (k=0; k<m_maxMaterials; ++k)
  253. {
  254. fmcurves[k] = new crvpnt [fmCurveSize];
  255. if (!fmcurves[k])
  256. return E_OUTOFMEMORY;
  257. read_DWORD(is,fmmax[k]); // Total faces of material k in fully
  258. // detailed mesh
  259. #ifdef __DUMP_DATA
  260. dump << "\n\nTotal faces of mat " << k << " in fully detailed mesh: ";
  261. dump << fmmax[k];
  262. #endif //__DUMP_DATA
  263. for (i=0; i<fmCurveSize; ++i)
  264. {
  265. read_DWORD(is,fmcurves[k][i].x); // vertex(i) of fmcurve of
  266. // material k
  267. read_float(is,fmcurves[k][i].y); // faces of mat k when total
  268. // vert in mesh = vertex(i)
  269. #ifdef __DUMP_DATA
  270. dump << "\n (" << fmcurves[k][i].x << ", " << fmcurves[k][i].y << ")";
  271. #endif //__DUMP_DATA
  272. }
  273. }
  274. #ifdef __MAT_PREALLOC_OPTIMIZATION
  275. for (k=0; k<m_maxMaterials; ++k)
  276. {
  277. for (i=0; i<fmCurveSize; ++i)
  278. {
  279. if (fmcurves[k][i].x == maxVert)
  280. {
  281. matcnt[k] = WORD(fmcurves[k][i].y + 0.5);
  282. matcnt[k] = WORD(min(matcnt[k], fmmax[k]));
  283. break;
  284. }
  285. else if (fmcurves[k][i].x > maxVert)
  286. {
  287. matcnt[k] = WORD(fmcurves[k][i-1].y + (maxVert -
  288. fmcurves[k][i-1].x) *
  289. (fmcurves[k][i].y - fmcurves[k][i-1].y) /
  290. (fmcurves[k][i].x - fmcurves[k][i-1].x));
  291. matcnt[k] = WORD(min(matcnt[k], fmmax[k]));
  292. break;
  293. }
  294. }
  295. nFacePredict += matcnt[k];
  296. delete [] fmcurves[k];
  297. }
  298. delete [] fmcurves;
  299. delete [] fmmax;
  300. #else //__MAT_PREALLOC_OPTIMIZATION
  301. /*
  302. * Convert m_matcnt to array of offsets into the face buf where faces of
  303. * that material need to be stored.
  304. */
  305. #ifdef __MATPOS_IS_A_PTR
  306. matpos[0] = farray;
  307. int cnt = 0;
  308. for (i=1; i<m_maxMaterials; ++i)
  309. {
  310. matpos[i] = &(farray[cnt + fmmax[i-1]]);
  311. cnt += fmmax[i-1];
  312. }
  313. #else
  314. matpos[0] = 0;
  315. for (i=1; i<m_maxMaterials; ++i)
  316. {
  317. matpos[i] = matpos[i-1] + fmmax[i-1];
  318. }
  319. #endif
  320. delete [] fmcurves;
  321. delete [] fmmax;
  322. #endif //__MAT_PREALLOC_OPTIMIZATION
  323. read_DWORD(is,vsplit_offset); // offset to vsplit array from end of
  324. // the Base mesh
  325. read_DWORD(is,bmesh_offset); // offset from here to start of base mesh
  326. #ifdef __DUMP_DATA
  327. dump << "\n\nVSplit offset from BaseMesh: " << vsplit_offset;
  328. dump << "\n\nBaseMesh offset from here: " << bmesh_offset;
  329. #endif //__DUMP_DATA
  330. #ifndef __MATPOS_IS_A_PTR
  331. /*
  332. * Allocate the vertex and normal arrays.
  333. */
  334. GLvertex *varray = new GLvertex [m_maxWedges];
  335. GLnormal *narray = new GLnormal [m_maxWedges];
  336. GLtexCoord *tarray = new GLtexCoord [m_maxWedges];
  337. WORD *wedgelist = new WORD [m_maxWedges];
  338. WORD (*fnei)[3] = new WORD [m_maxFaces][3];
  339. GLface *farray = new GLface [m_maxFaces];
  340. WORD *facemap = new WORD [m_maxFaces];
  341. if (!farray || !varray || !narray || !tarray || !wedgelist || !fnei
  342. || !facemap)
  343. {
  344. return E_OUTOFMEMORY;
  345. }
  346. else
  347. {
  348. m_varray = varray;
  349. m_narray = narray;
  350. m_tarray = tarray;
  351. m_farray = farray;
  352. m_wedgelist = wedgelist;
  353. m_fnei = fnei;
  354. m_facemap = facemap;
  355. }
  356. #endif
  357. /*
  358. * Read Base Mesh Header
  359. */
  360. if (bmesh_offset)
  361. skip_bytes(is,bmesh_offset); // jump to start of base mesh.
  362. read_DWORD(is,m_baseVertices);
  363. #ifdef __MAT_PREALLOC_OPTIMIZATION
  364. minVert = max(minVert, m_baseVertices);
  365. #else
  366. minVert = m_baseVertices;
  367. #endif //__MAT_PREALLOC_OPTIMIZATION
  368. *minvert = minVert;
  369. m_numVerts = m_baseVertices;
  370. read_DWORD(is,m_baseWedges);
  371. m_numWedges = m_baseWedges;
  372. read_DWORD(is,m_baseFaces);
  373. m_numFaces = m_baseFaces;
  374. read_DWORD(is,i); // max materials
  375. if (i != m_maxMaterials)
  376. return PM_E_MATCNT_MISMATCH;
  377. else
  378. m_numMaterials = i;
  379. read_DWORD(is,mOffset); // Offset to mat array
  380. read_DWORD(is,vOffset); // Offset to vertex array
  381. read_DWORD(is,wOffset); // Offset to wedge array
  382. read_DWORD(is,fOffset); // Offset to face array
  383. #ifdef __DUMP_DATA
  384. dump << "\n\n# of baseVerts: " << m_baseVertices;
  385. dump << "\n# of baseWedges: " << m_baseWedges;
  386. dump << "\n# of baseFaces: " << m_baseFaces;
  387. dump << "\n\nOffset to MatArray: " << mOffset;
  388. dump << "\nOffset to Vertex Array: " << vOffset;
  389. dump << "\nOffset to Wedge Array: " << wOffset;
  390. dump << "\nOffset to Face Array: " << fOffset;
  391. #endif //__DUMP_DATA
  392. /*
  393. * Read Materials
  394. */
  395. j = 0; // texture count
  396. if (mOffset)
  397. skip_bytes(is, mOffset);
  398. for (i=0; i<m_maxMaterials; ++i)
  399. {
  400. char texname[PM_MAX_TEX_STRING_LEN];
  401. matArray[i].ambient.r =
  402. matArray[i].ambient.g =
  403. matArray[i].ambient.b =
  404. matArray[i].ambient.a = 0.0f;
  405. matcnt[i] = (WORD) 0;
  406. read_float(is, matArray[i].diffuse.r);
  407. read_float(is, matArray[i].diffuse.g);
  408. read_float(is, matArray[i].diffuse.b);
  409. read_float(is, matArray[i].diffuse.a);
  410. read_float(is, matArray[i].shininess);
  411. read_float(is, matArray[i].specular.r);
  412. read_float(is, matArray[i].specular.g);
  413. read_float(is, matArray[i].specular.b);
  414. read_float(is, matArray[i].specular.a);
  415. read_float(is, matArray[i].emissive.r);
  416. read_float(is, matArray[i].emissive.g);
  417. read_float(is, matArray[i].emissive.b);
  418. read_float(is, matArray[i].emissive.a);
  419. is.getline(texname, 1024, '\0');
  420. if (texname[0])
  421. {
  422. j++;
  423. matArray[i].texObj = LoadTexture (texname);
  424. }
  425. else
  426. {
  427. matArray[i].texObj = 0;
  428. }
  429. }
  430. /*
  431. * Read base-mesh faces
  432. */
  433. if (fOffset)
  434. skip_bytes(is, fOffset);
  435. for (i=0; i<m_baseFaces; ++i)
  436. {
  437. DWORD w;
  438. WORD matid;
  439. read_WORD(is, matid);
  440. for (int j=0; j<3; ++j)
  441. {
  442. read_DWORD(is, w);
  443. #ifdef __MATPOS_IS_A_PTR
  444. (matpos[matid][matcnt[matid]]).w[j] = (WORD)w;
  445. #else
  446. (farray[matpos[matid] + matcnt[matid]]).w[j] = (WORD)w;
  447. #endif
  448. facemap[i] = matpos[matid] + matcnt[matid];
  449. }
  450. matcnt[matid]++;
  451. }
  452. /*
  453. * Read base-mesh wedges
  454. */
  455. if (wOffset)
  456. skip_bytes(is, wOffset);
  457. long* vidx_arr = new long[m_baseVertices];
  458. if (!vidx_arr)
  459. return E_OUTOFMEMORY;
  460. memset(vidx_arr, -1, sizeof(long) * m_baseVertices);
  461. for (i=0; i<m_baseWedges; ++i)
  462. {
  463. DWORD vidx;
  464. read_DWORD(is, vidx);
  465. #ifdef _DEBUG
  466. if (vidx >= m_baseVertices)
  467. return -1;
  468. #endif
  469. if (vidx_arr[vidx] < 0)
  470. {
  471. /*
  472. * New vertex, create entry and initialize the wedge list
  473. */
  474. vidx_arr[vidx] = i;
  475. wedgelist[i] = WORD(i); // create circular list with one entry
  476. }
  477. else
  478. {
  479. /*
  480. * Another wedge uses existing vertex, add new wedge to the
  481. * existing wedge list.
  482. */
  483. wedgelist[i] = wedgelist[vidx_arr[vidx]];
  484. wedgelist[vidx_arr[vidx]] = WORD(i);
  485. }
  486. read_float(is, narray[i].x);
  487. read_float(is, narray[i].y);
  488. read_float(is, narray[i].z);
  489. read_float(is, tarray[i].s);
  490. read_float(is, tarray[i].t);
  491. }
  492. /*
  493. * Read base-mesh vertices
  494. */
  495. if (vOffset)
  496. skip_bytes(is, vOffset);
  497. for (i=0; i<m_baseVertices; ++i)
  498. {
  499. float x, y, z;
  500. read_float(is, x);
  501. read_float(is, y);
  502. read_float(is, z);
  503. /*
  504. * Loop thru all wedges that share the vertex
  505. * and fill in coordinates.
  506. */
  507. WORD start = j = WORD(vidx_arr[i]);
  508. do
  509. {
  510. varray[j].x = x;
  511. varray[j].y = y;
  512. varray[j].z = z;
  513. }
  514. while ((j=wedgelist[j]) != start);
  515. }
  516. delete [] vidx_arr;
  517. #ifdef __DUMP_DATA
  518. Print (dump);
  519. #endif //__DUMP_DATA
  520. /*
  521. * Compute adjacency before we apply any vsplits
  522. */
  523. ComputeAdjacency();
  524. /*
  525. * Read Vsplit records
  526. */
  527. m_vsarr = new VsplitArray(maxVert - minVert);
  528. for (i=0; i<maxVert-m_baseVertices; ++i)
  529. {
  530. /*
  531. * Keep applying vsplits till base mesh is refined to have
  532. * minVert vertices.
  533. */
  534. if (i + m_baseVertices < minVert)
  535. {
  536. Vsplit vs;
  537. vs.read(is);
  538. apply_vsplit(vs);
  539. // Update m_base* members
  540. }
  541. else // Read the rest in the Vsplit array
  542. {
  543. m_vsarr->elem(i + m_baseVertices - minVert).read(is);
  544. }
  545. }
  546. #ifdef __DUMP_DATA
  547. m_vsarr->write(dump);
  548. #endif //__DUMP_DATA
  549. m_currPos = 0;
  550. return S_OK;
  551. }