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.

1526 lines
38 KiB

  1. /**
  2. ** File : aglmesh.cxx
  3. ** Description: Implementations of CAugGlMesh class
  4. **/
  5. #include "precomp.h"
  6. #pragma hdrstop
  7. #include "array.h"
  8. #include "aglmesh.h"
  9. #include "pmerrors.h"
  10. #include <math.h>
  11. void interp(GLwedgeAttrib& a, const GLwedgeAttrib& a1,
  12. const GLwedgeAttrib& a2, float f1, float f2);
  13. /**************************************************************************/
  14. /*
  15. * CAugGlMesh: Constructor
  16. */
  17. CAugGlMesh::CAugGlMesh() : CSimpGlMesh ()
  18. {
  19. //Dynamically allocated arrays
  20. m_fnei = NULL;
  21. m_facemap = NULL;
  22. }
  23. /*
  24. * CAugGlMesh: Destructor
  25. */
  26. CAugGlMesh::~CAugGlMesh()
  27. {
  28. delete [] m_fnei;
  29. delete [] m_facemap;
  30. }
  31. PHASHENTRY* hashtable;
  32. PHASHENTRY hashentries;
  33. int freeptr, maxptr;
  34. void CAugGlMesh::HashAdd(WORD va, WORD vb, WORD f)
  35. {
  36. #ifdef _DEBUG
  37. if (va > m_numWedges || va < 0)
  38. throw CHashOvrflw();
  39. #endif
  40. for (PHASHENTRY* t = &(hashtable[va]); *t; t = &((*t)->next));
  41. PHASHENTRY p = &(hashentries[freeptr++]);
  42. p->f = f;
  43. p->v2 = vb;
  44. p->next = NULL;
  45. *t=p;
  46. }
  47. WORD CAugGlMesh::HashFind(WORD va, WORD vb)
  48. {
  49. #ifdef _DEBUG
  50. if (va > m_baseWedges || va < 0)
  51. throw CHashOvrflw();
  52. #endif
  53. for (PHASHENTRY* t = &(hashtable[va]); *t; t = &((*t)->next))
  54. {
  55. if ((*t)->v2 == vb)
  56. {
  57. return (*t)->f;
  58. }
  59. }
  60. return USHRT_MAX;
  61. }
  62. void CAugGlMesh::ComputeAdjacency(void)
  63. {
  64. freeptr = 0;
  65. maxptr = m_numFaces*3;
  66. hashtable = new PHASHENTRY[m_numWedges];
  67. // An entry for each 3 edges of each face in base mesh
  68. hashentries = new hashentry[maxptr];
  69. if (!hashtable)
  70. throw CExNewFailed();
  71. memset(hashtable, 0, sizeof(PHASHENTRY)*m_numWedges);
  72. /*
  73. * For each group of faces
  74. */
  75. for(int i=0; i < (int)m_numMaterials; ++i)
  76. {
  77. /*
  78. * For each face in the group
  79. */
  80. for (int k=m_matpos[i]; k<(m_matpos[i]+m_matcnt[i]); ++k)
  81. {
  82. int v1 = FindVertexIndex((m_farray[k]).w[0]);
  83. int v2 = FindVertexIndex((m_farray[k]).w[1]);
  84. int v3 = FindVertexIndex((m_farray[k]).w[2]);
  85. HashAdd(v1,v2,k);
  86. HashAdd(v2,v3,k);
  87. HashAdd(v3,v1,k);
  88. }
  89. }
  90. #ifdef _DEBUG
  91. if (freeptr > maxptr)
  92. throw CHashOvrflw();
  93. #endif
  94. /*
  95. * For each group of faces
  96. */
  97. for(i=0; i < (int)m_numMaterials; ++i)
  98. {
  99. /*
  100. * For each face in the group
  101. */
  102. for (int k=m_matpos[i]; k<(m_matpos[i]+m_matcnt[i]); ++k)
  103. {
  104. int v1 = FindVertexIndex((m_farray[k]).w[0]);
  105. int v2 = FindVertexIndex((m_farray[k]).w[1]);
  106. int v3 = FindVertexIndex((m_farray[k]).w[2]);
  107. m_fnei[k][0] = HashFind(v3,v2);
  108. m_fnei[k][1] = HashFind(v1,v3);
  109. m_fnei[k][2] = HashFind(v2,v1);
  110. }
  111. }
  112. delete [] hashtable;
  113. delete [] hashentries;
  114. }
  115. // note: vspl is modified!
  116. void CAugGlMesh::apply_vsplit(Vsplit& vspl)
  117. {
  118. const BOOL isl = TRUE;
  119. BOOL isr = vspl.vlr_offset1 > 1;
  120. HRESULT hr;
  121. /*
  122. * Get vertices, faces, and wedges in the neigbhorhood of the split.
  123. * Look at the diagram in mesh.vld for more information about the
  124. * meanings of various variables.
  125. */
  126. WORD vs;
  127. WORD code=vspl.code;
  128. int ii=(code&Vsplit::II_MASK)>>Vsplit::II_SHIFT;
  129. WORD flccw, flclw; // either (not both) may be UNDEF
  130. WORD frccw, frclw; // either (or both) may be UNDEF
  131. WORD wlccw, wlclw, wrccw, wrclw; // ==UNDEF if faces do not exist
  132. int jlccw, jlclw, jrccw, jrclw; // only defined if faces exist
  133. int jlclw2;
  134. WORD flmatid, frmatid;
  135. GLvertex glvs, glvt; // vertices vs and vt
  136. PArray<WORD*,10> ar_pwedges;
  137. /*
  138. * 1) Gather all the wedges surrounding Vs into ar_pwedges array
  139. * -------------------------------------------------------------
  140. */
  141. if (vspl.vlr_offset1 == 0)
  142. {
  143. /*
  144. * Extremely rare case when flclw does not exist.
  145. */
  146. flclw = UNDEF;
  147. wlclw = UNDEF;
  148. if (vspl.modified)
  149. {
  150. flccw = vspl.flclw;
  151. }
  152. else
  153. {
  154. flccw = WORD(m_facemap[WORD(vspl.flclw)]);
  155. vspl.flclw = flccw;
  156. vspl.modified = TRUE;
  157. }
  158. int vs_index = (code & Vsplit::VSINDEX_MASK)>>Vsplit::VSINDEX_SHIFT;
  159. jlccw = vs_index;
  160. wlccw = m_farray[flccw].w[jlccw];
  161. vs = FindVertexIndex(wlccw);
  162. frccw = frclw = wrccw = wrclw = UNDEF;
  163. }
  164. else
  165. {
  166. if (vspl.modified)
  167. {
  168. flclw = vspl.flclw;
  169. }
  170. else
  171. {
  172. flclw = WORD(m_facemap[WORD(vspl.flclw)]);
  173. vspl.flclw = flclw;
  174. vspl.modified = TRUE;
  175. }
  176. //flclw = WORD(m_facemap[WORD(vspl.flclw)]);
  177. int vs_index = (code&Vsplit::VSINDEX_MASK)>>Vsplit::VSINDEX_SHIFT;
  178. jlclw = vs_index; //The vs's index
  179. jlclw2 = (jlclw + 2)%3; //The vl's index
  180. WORD* pwlclw = &(m_farray[flclw].w[jlclw]);
  181. wlclw = *pwlclw;
  182. vs = FindVertexIndex (wlclw);
  183. flccw = m_fnei[flclw][(jlclw+1)%3];
  184. if (flccw == UNDEF)
  185. {
  186. wlccw = UNDEF;
  187. }
  188. else
  189. {
  190. gather_vf_jw(vs, flccw, jlccw, wlccw);
  191. }
  192. if (!isr)
  193. {
  194. frccw = frclw = wrccw = wrclw = UNDEF;
  195. ar_pwedges += pwlclw;
  196. /*
  197. * Rotate around and record all wedges CLW from wlclw.
  198. */
  199. int j0 = jlclw, j2 = jlclw2;
  200. WORD f = flclw;
  201. for (;;)
  202. {
  203. f = m_fnei[f][j2];
  204. if (f == UNDEF) break;
  205. WORD* pw;
  206. gather_vf_j0j2pw (vs, f, j0, j2, pw);
  207. ar_pwedges += pw;
  208. }
  209. }
  210. else
  211. {
  212. ar_pwedges.init (vspl.vlr_offset1 - 1);
  213. ar_pwedges[0] = pwlclw;
  214. /*
  215. * Rotate around the first vlr_offset-1 faces.
  216. */
  217. int j0 = jlclw, j2 = jlclw2;
  218. WORD f = flclw;
  219. for(int count=0; count < vspl.vlr_offset1-2; ++count)
  220. {
  221. f = m_fnei[f][j2];
  222. WORD* pw;
  223. gather_vf_j0j2pw (vs, f, j0, j2, pw);
  224. ar_pwedges[count+1] = pw;
  225. }
  226. frccw=f;
  227. /*
  228. * On the last face, find adjacent faces.
  229. */
  230. jrccw = j0;
  231. wrccw = m_farray[frccw].w[jrccw];
  232. frclw = m_fnei[frccw][j2];
  233. if (frclw==UNDEF)
  234. {
  235. wrclw=UNDEF;
  236. }
  237. else
  238. {
  239. gather_vf_jw(vs,frclw,jrclw,wrclw);
  240. }
  241. }
  242. }
  243. /*
  244. * 2) Obtain the matIDs of the two new faces generated by applying vsplit.
  245. * -----------------------------------------------------------------------
  246. * ?? could use L_MASK instead of ii for prediction instead.
  247. * face_prediction() is the shady part.
  248. */
  249. if (code & Vsplit::FLN_MASK)
  250. {
  251. flmatid = vspl.fl_matid;
  252. }
  253. else
  254. {
  255. flmatid = MatidOfFace(face_prediction(flclw,flccw,ii));
  256. // save computed value for undo_vsplit and future vsplits
  257. vspl.fl_matid = flmatid;
  258. vspl.code |= Vsplit::FLN_MASK;
  259. }
  260. if (isr)
  261. {
  262. if (code&Vsplit::FRN_MASK)
  263. frmatid = vspl.fr_matid;
  264. else
  265. {
  266. frmatid = MatidOfFace(face_prediction(frccw,frclw,ii));
  267. // save computed value for undo_vsplit and future vsplits
  268. vspl.fr_matid = frmatid;
  269. vspl.code|=Vsplit::FRN_MASK;
  270. }
  271. }
  272. /*
  273. * 3) Compute new coordinates of vt and vs (calc coordinates).
  274. * -----------------------------------------------------------
  275. */
  276. switch (ii)
  277. {
  278. case 2:
  279. glvt.x = m_varray[vs].x + vspl.vad_large[0];
  280. glvt.y = m_varray[vs].y + vspl.vad_large[1];
  281. glvt.z = m_varray[vs].z + vspl.vad_large[2];
  282. glvs.x = m_varray[vs].x + vspl.vad_small[0];
  283. glvs.y = m_varray[vs].y + vspl.vad_small[1];
  284. glvs.z = m_varray[vs].z + vspl.vad_small[2];
  285. break;
  286. case 0:
  287. glvt.x = m_varray[vs].x + vspl.vad_small[0];
  288. glvt.y = m_varray[vs].y + vspl.vad_small[1];
  289. glvt.z = m_varray[vs].z + vspl.vad_small[2];
  290. glvs.x = m_varray[vs].x + vspl.vad_large[0];
  291. glvs.y = m_varray[vs].y + vspl.vad_large[1];
  292. glvs.z = m_varray[vs].z + vspl.vad_large[2];
  293. break;
  294. case 1:
  295. glvt.x = m_varray[vs].x + vspl.vad_small[0];
  296. glvt.y = m_varray[vs].y + vspl.vad_small[1];
  297. glvt.z = m_varray[vs].z + vspl.vad_small[2];
  298. glvs.x = glvt.x - vspl.vad_large[0];
  299. glvs.y = glvt.y - vspl.vad_large[1];
  300. glvs.z = glvt.z - vspl.vad_large[2];
  301. glvt.x = glvt.x + vspl.vad_large[0];
  302. glvt.y = glvt.y + vspl.vad_large[1];
  303. glvt.z = glvt.z + vspl.vad_large[2];
  304. break;
  305. default:
  306. throw CBadVsplitCode();
  307. }
  308. /*
  309. * 4) un-share wedges around vt (?) Add 2 wedges around Vs
  310. * -------------------------------------------------------
  311. * (may be gap on top). may modify wlclw and wrccw!
  312. */
  313. WORD wnl = UNDEF, wnr = UNDEF;
  314. int iil = 0, iir = ar_pwedges.num()-1;
  315. if (isl && (wlclw == wlccw))
  316. {
  317. /*
  318. * first go clw. Add new wedge.
  319. */
  320. wnl = m_numWedges++;
  321. /*
  322. * Add wnl to the list of wedges sharing Vs
  323. */
  324. m_wedgelist[wnl] = m_wedgelist[vs];
  325. m_wedgelist[vs] = wnl;
  326. /*
  327. * Copy wedge attributes
  328. */
  329. m_narray[wnl] = m_narray[wlccw];
  330. m_tarray[wnl] = m_tarray[wlccw];
  331. wlclw = wnl; // has been changed
  332. for (;;)
  333. {
  334. *ar_pwedges[iil] = wnl;
  335. iil++;
  336. if (iil > iir)
  337. {
  338. wrccw = wnl; // has been changed
  339. break;
  340. }
  341. if (*ar_pwedges[iil] != wlccw)
  342. break;
  343. }
  344. }
  345. if (isr && (wrccw == wrclw))
  346. {
  347. /*
  348. * now go ccw from other side.
  349. */
  350. if ((wrclw == wlccw) && (wnl != UNDEF))
  351. {
  352. wnr = wnl;
  353. }
  354. else
  355. {
  356. // Add new wedge
  357. wnr = m_numWedges++;
  358. // Add wnr to the list of wedges sharing vs
  359. m_wedgelist[wnr] = m_wedgelist[vs];
  360. m_wedgelist[vs] = wnr;
  361. // Copy wedge attributes
  362. m_narray[wnr] = m_narray[wrclw];
  363. m_tarray[wnr] = m_tarray[wrclw];
  364. }
  365. wrccw=wnr; // has been changed
  366. for (;;)
  367. {
  368. *ar_pwedges[iir] = wnr;
  369. iir--;
  370. if (iir < iil)
  371. {
  372. if (iir < 0) wlclw=wnr; // has been changed
  373. break;
  374. }
  375. if (*ar_pwedges[iir] != wrclw)
  376. break;
  377. }
  378. }
  379. /*
  380. * 5) Add other new wedges around Vt and record wedge ancestries
  381. * -------------------------------------------------------------
  382. */
  383. WORD wvtfl, wvtfr, vt = UNDEF;
  384. if (!isr)
  385. {
  386. wvtfr=UNDEF;
  387. switch (code&Vsplit::T_MASK)
  388. {
  389. case Vsplit::T_LSAME|Vsplit::T_RSAME:
  390. wvtfl=wlclw;
  391. break;
  392. case Vsplit::T_RSAME:
  393. // Add new wedge.
  394. wvtfl = m_numWedges++;
  395. m_wedgelist[wvtfl] = wvtfl;
  396. m_varray[wvtfl] = glvt;
  397. vt = wvtfl;
  398. break;
  399. default:
  400. throw CBadVsplitCode();
  401. }
  402. }
  403. else
  404. {
  405. switch (code&Vsplit::T_MASK)
  406. {
  407. case Vsplit::T_LSAME|Vsplit::T_RSAME|Vsplit::T_CSAME:
  408. case Vsplit::T_LSAME|Vsplit::T_RSAME:
  409. wvtfl=wlclw;
  410. wvtfr=wrccw;
  411. break;
  412. case Vsplit::T_LSAME|Vsplit::T_CSAME:
  413. wvtfl=wlclw;
  414. wvtfr=wvtfl;
  415. break;
  416. case Vsplit::T_RSAME|Vsplit::T_CSAME:
  417. wvtfl=wrccw;
  418. wvtfr=wvtfl;
  419. break;
  420. case Vsplit::T_LSAME:
  421. wvtfl=wlclw;
  422. // Add new wedge.
  423. wvtfr = m_numWedges++;
  424. m_wedgelist[wvtfr] = wvtfr;
  425. m_varray[wvtfr] = glvt;
  426. vt = wvtfr;
  427. break;
  428. case Vsplit::T_RSAME:
  429. // Add new wedge.
  430. wvtfl = m_numWedges++;
  431. m_wedgelist[wvtfl] = wvtfl;
  432. m_varray[wvtfl] = glvt;
  433. vt = wvtfl;
  434. wvtfr=wrccw;
  435. break;
  436. case Vsplit::T_CSAME:
  437. // Add new wedge.
  438. wvtfl = m_numWedges++;
  439. m_wedgelist[wvtfl] = wvtfl;
  440. m_varray[wvtfl] = glvt;
  441. vt = wvtfl;
  442. wvtfr=wvtfl;
  443. break;
  444. case 0:
  445. // Add new wedge.
  446. wvtfl = m_numWedges++;
  447. m_varray[wvtfl] = glvt;
  448. vt = wvtfl;
  449. // Add new wedge.
  450. wvtfr = m_numWedges++;
  451. m_varray[wvtfr] = glvt;
  452. // Add wvtfr and wvtfl to list of wedges sharing vt
  453. m_wedgelist[wvtfl] = wvtfr;
  454. m_wedgelist[wvtfr] = wvtfl;
  455. break;
  456. default:
  457. throw CBadVsplitCode();
  458. }
  459. }
  460. /*
  461. * 6) Add other new wedges around Vs.
  462. * ----------------------------------
  463. * Do we really need to find vertex index ? Optimize
  464. */
  465. WORD wvsfl, wvsfr;
  466. if (!isr)
  467. {
  468. wvsfr = UNDEF;
  469. switch (code&Vsplit::S_MASK)
  470. {
  471. case Vsplit::S_LSAME|Vsplit::S_RSAME:
  472. wvsfl=wlccw;
  473. break;
  474. case Vsplit::S_RSAME:
  475. // Add new wedge.
  476. wvsfl = m_numWedges++;
  477. m_varray[wvsfl] = glvs;
  478. // Add wvsfl to the list wedges sharing vs
  479. m_wedgelist[wvsfl] = m_wedgelist[vs];
  480. m_wedgelist[vs] = wvsfl;
  481. break;
  482. default:
  483. throw CBadVsplitCode();
  484. }
  485. }
  486. else
  487. {
  488. switch (code&Vsplit::S_MASK)
  489. {
  490. case Vsplit::S_LSAME|Vsplit::S_RSAME|Vsplit::S_CSAME:
  491. case Vsplit::S_LSAME|Vsplit::S_RSAME:
  492. wvsfl=wlccw;
  493. wvsfr=wrclw;
  494. break;
  495. case Vsplit::S_LSAME|Vsplit::S_CSAME:
  496. wvsfl=wlccw;
  497. wvsfr=wvsfl;
  498. break;
  499. case Vsplit::S_RSAME|Vsplit::S_CSAME:
  500. wvsfl=wrclw;
  501. wvsfr=wvsfl;
  502. break;
  503. case Vsplit::S_LSAME:
  504. wvsfl=wlccw;
  505. // Add new wedge.
  506. wvsfr = m_numWedges++;
  507. m_wedgelist[wvsfr] = m_wedgelist[vs];
  508. m_wedgelist[vs] = wvsfr;
  509. m_varray[wvsfr] = glvs;
  510. break;
  511. case Vsplit::S_RSAME:
  512. // Add new wedge.
  513. wvsfl = m_numWedges++;
  514. m_wedgelist[wvsfl] = m_wedgelist[vs];
  515. m_wedgelist[vs] = wvsfl;
  516. m_varray[wvsfl] = glvs;
  517. wvsfr=wrclw;
  518. break;
  519. case Vsplit::S_CSAME:
  520. // Add new wedge.
  521. wvsfl = m_numWedges++;
  522. m_wedgelist[wvsfl] = m_wedgelist[vs];
  523. m_wedgelist[vs] = wvsfl;
  524. m_varray[wvsfl] = glvs;
  525. wvsfr = wvsfl;
  526. break;
  527. case 0:
  528. // Add new wedge.
  529. wvsfl = m_numWedges++;
  530. m_varray[wvsfl] = glvs;
  531. // Add new wedge.
  532. wvsfr = m_numWedges++;
  533. m_varray[wvsfr] = glvs;
  534. // Add wvsfr and wvsfl to list of wedges sharing vt
  535. m_wedgelist[wvsfl] = m_wedgelist[vs];
  536. m_wedgelist[wvsfr] =wvsfl;
  537. m_wedgelist[vs] = wvsfr;
  538. break;
  539. default:
  540. throw CBadVsplitCode();
  541. }
  542. }
  543. /*
  544. * 7) Add outside wedges wvlfl and wvrfr
  545. * -------------------------------------
  546. */
  547. WORD wvlfl, wvrfr;
  548. if (isl)
  549. {
  550. switch (code&Vsplit::L_MASK)
  551. {
  552. case Vsplit::L_ABOVE:
  553. wvlfl = m_farray[flclw].w[jlclw2];
  554. break;
  555. case Vsplit::L_BELOW:
  556. wvlfl = m_farray[flccw].w[(jlccw+1)%3];
  557. break;
  558. case Vsplit::L_NEW:
  559. {
  560. wvlfl = m_numWedges++;
  561. WORD vl = (flclw != UNDEF) ? m_farray[flclw].w[jlclw2] :
  562. m_farray[flccw].w[(jlccw+1)%3];
  563. m_wedgelist[wvlfl] = m_wedgelist[vl];
  564. m_wedgelist[vl] = wvlfl;
  565. m_varray[wvlfl] = m_varray[vl];
  566. }
  567. break;
  568. default:
  569. throw CBadVsplitCode();
  570. }
  571. }
  572. if (!isr)
  573. {
  574. wvrfr = UNDEF;
  575. }
  576. else
  577. {
  578. switch (code&Vsplit::R_MASK)
  579. {
  580. case Vsplit::R_ABOVE:
  581. wvrfr = m_farray[frccw].w[(jrccw+1)%3];
  582. break;
  583. case Vsplit::R_BELOW:
  584. wvrfr = m_farray[frclw].w[(jrclw+2)%3];
  585. break;
  586. case Vsplit::R_NEW:
  587. {
  588. wvrfr = m_numWedges++;
  589. WORD vr = m_farray[frccw].w[(jrccw+1)%3];
  590. m_wedgelist[wvrfr] = m_wedgelist[vr];
  591. m_wedgelist[vr] = wvrfr;
  592. m_varray[wvrfr] = m_varray[vr];
  593. }
  594. break;
  595. default:
  596. throw CBadVsplitCode();
  597. }
  598. }
  599. /*
  600. * 8) Add 1 or 2 faces, and update adjacency information.
  601. * ------------------------------------------------------
  602. */
  603. WORD fl, fr;
  604. m_matcnt [flmatid]++;
  605. fl = m_matpos[flmatid] + m_matcnt[flmatid] - 1;
  606. m_facemap [m_numFaces] = fl;
  607. if (isr)
  608. {
  609. m_matcnt [frmatid]++;
  610. fr = m_matpos[frmatid] + m_matcnt[frmatid] - 1;
  611. m_facemap [m_numFaces+1] = fr;
  612. m_numFaces += 2;
  613. }
  614. else
  615. {
  616. fr = UNDEF;
  617. m_numFaces ++;
  618. }
  619. if (isl)
  620. {
  621. m_farray[fl].w[0] = wvsfl;
  622. m_farray[fl].w[1] = wvtfl;
  623. m_farray[fl].w[2] = wvlfl;
  624. if (flccw != UNDEF) m_fnei[flccw][(jlccw+2)%3] = fl;
  625. if (flclw != UNDEF) m_fnei[flclw][(jlclw+1)%3] = fl;
  626. m_fnei[fl][0] = flclw;
  627. m_fnei[fl][1] = flccw;
  628. m_fnei[fl][2] = fr;
  629. }
  630. if (isr)
  631. {
  632. m_farray[fr].w[0] = wvsfr;
  633. m_farray[fr].w[1] = wvrfr;
  634. m_farray[fr].w[2] = wvtfr;
  635. if (frccw != UNDEF) m_fnei[frccw][(jrccw+2)%3] = fr;
  636. if (frclw != UNDEF) m_fnei[frclw][(jrclw+1)%3] = fr;
  637. m_fnei[fr][0] = frccw;
  638. m_fnei[fr][1] = fl;
  639. m_fnei[fr][2] = frclw;
  640. }
  641. /*
  642. * 9) Update wedge vertices.
  643. * -------------------------
  644. */
  645. if (wnl != UNDEF)
  646. {
  647. WedgeListDelete(wnl);
  648. m_varray[wnl] = glvt;
  649. if (vt == UNDEF)
  650. {
  651. m_wedgelist[wnl] = wnl;
  652. vt = wnl;
  653. }
  654. else
  655. {
  656. m_wedgelist[wnl] = m_wedgelist[vt];
  657. m_wedgelist[vt] = wnl;
  658. }
  659. }
  660. if (wnr != UNDEF)
  661. {
  662. WedgeListDelete(wnr);
  663. m_varray[wnr] = glvt;
  664. if (vt==UNDEF)
  665. {
  666. m_wedgelist[wnr] = wnr;
  667. vt = wnr;
  668. }
  669. else
  670. {
  671. m_wedgelist[wnr] = m_wedgelist[vt];
  672. m_wedgelist[vt] = wnr;
  673. }
  674. }
  675. WORD prev = UNDEF;
  676. for (; iil <= iir; iil++)
  677. {
  678. WORD w = *ar_pwedges[iil];
  679. if (w != prev)
  680. {
  681. WedgeListDelete(w);
  682. m_varray[w] = glvt;
  683. if (vt==UNDEF)
  684. {
  685. m_wedgelist[w] = w;
  686. vt = w;
  687. }
  688. else
  689. {
  690. m_wedgelist[w] = m_wedgelist[vt];
  691. m_wedgelist[vt] = w;
  692. }
  693. }
  694. prev = w;
  695. }
  696. /*
  697. * 10) Update all wedges sharing Vs to it's new coordinates.
  698. * ---------------------------------------------------------
  699. * Note the prev loop in ar_pwedges could have modified wedge pointed by
  700. * vs to be part of vt now.
  701. * wvsfl is the only sure way of a wedge pointing to vs
  702. */
  703. WORD p = wvsfl;
  704. do
  705. {
  706. m_varray[p] = glvs;
  707. p = m_wedgelist[p];
  708. }
  709. while (p != wvsfl);
  710. /*
  711. * 11) Update wedge attributes.
  712. * ----------------------------
  713. */
  714. GLwedgeAttrib awvtfr, awvsfr;
  715. if (isr)
  716. {
  717. // backup for isr
  718. //awvtfrV = m_varray[wvtfr];
  719. awvtfr.n = m_narray[wvtfr];
  720. awvtfr.t = m_tarray[wvtfr];
  721. // backup for isr
  722. //awvsfrV = m_varray[wvsfr];
  723. awvsfr.n = m_narray[wvsfr];
  724. awvsfr.t = m_tarray[wvsfr];
  725. }
  726. int lnum = 0;
  727. if (isl)
  728. {
  729. int nt = !(code&Vsplit::T_LSAME);
  730. int ns = !(code&Vsplit::S_LSAME);
  731. if (nt && ns)
  732. {
  733. add_zero(wvtfl, vspl.ar_wad[lnum++]);
  734. add_zero(wvsfl, vspl.ar_wad[lnum++]);
  735. }
  736. else
  737. {
  738. switch (ii)
  739. {
  740. case 2:
  741. {
  742. GLwedgeAttrib wa;
  743. if (ns)
  744. {
  745. m_narray[wvsfl] = m_narray[wvtfl];
  746. m_tarray[wvsfl] = m_tarray[wvtfl];
  747. }
  748. if (!ns) {wa.n = m_narray[wvsfl]; wa.t = m_tarray[wvsfl];}
  749. else {wa.n = m_narray[wvtfl]; wa.t = m_tarray[wvtfl];}
  750. add(wvtfl, wa, vspl.ar_wad[lnum++]);
  751. break;
  752. }
  753. case 0:
  754. {
  755. GLwedgeAttrib wa;
  756. if (nt)
  757. {
  758. m_narray[wvtfl] = m_narray[wvsfl];
  759. m_tarray[wvtfl] = m_tarray[wvsfl];
  760. }
  761. if (!nt) {wa.n = m_narray[wvtfl]; wa.t = m_tarray[wvtfl];}
  762. else {wa.n = m_narray[wvsfl]; wa.t = m_tarray[wvsfl];}
  763. add(wvsfl, wa, vspl.ar_wad[lnum++]);
  764. break;
  765. }
  766. case 1:
  767. {
  768. const WEDGEATTRD& wad = vspl.ar_wad[lnum];
  769. if (!ns)
  770. {
  771. GLwedgeAttrib wabase;
  772. wabase.n = m_narray[wvsfl];
  773. wabase.t = m_tarray[wvsfl];
  774. add(wvtfl, wabase, wad);
  775. sub_reflect(wvsfl, wabase, wad);
  776. }
  777. else
  778. {
  779. GLwedgeAttrib wabase;
  780. wabase.n = m_narray[wvtfl];
  781. wabase.t = m_tarray[wvtfl];
  782. sub_reflect(wvsfl, wabase, wad);
  783. add(wvtfl, wabase, wad);
  784. }
  785. lnum++;
  786. }
  787. break;
  788. default:
  789. throw CBadVsplitCode();
  790. }
  791. }
  792. }
  793. if (isr)
  794. {
  795. int nt = !(code&Vsplit::T_RSAME);
  796. int ns = !(code&Vsplit::S_RSAME);
  797. int ut = !(code&Vsplit::T_CSAME);
  798. int us = !(code&Vsplit::S_CSAME);
  799. if (nt && ns)
  800. {
  801. if (ut)
  802. add_zero(wvtfr, vspl.ar_wad[lnum++]);
  803. if (us)
  804. add_zero(wvsfr, vspl.ar_wad[lnum++]);
  805. }
  806. else
  807. {
  808. switch (ii)
  809. {
  810. case 2:
  811. if (us && ns)
  812. {
  813. m_narray[wvsfr] = awvtfr.n;
  814. m_tarray[wvsfr] = awvtfr.t;
  815. }
  816. if (ut)
  817. add(wvtfr, (!ns?awvsfr:awvtfr), vspl.ar_wad[lnum++]);
  818. break;
  819. case 0:
  820. if (ut && nt)
  821. {
  822. m_narray[wvtfr] = awvsfr.n;
  823. m_tarray[wvtfr] = awvsfr.t;
  824. }
  825. if (us)
  826. add(wvsfr, (!nt?awvtfr:awvsfr), vspl.ar_wad[lnum++]);
  827. break;
  828. case 1:
  829. {
  830. const WEDGEATTRD& wad = vspl.ar_wad[lnum];
  831. if (!ns)
  832. {
  833. const GLwedgeAttrib& wabase = awvsfr;
  834. if (ut)
  835. add(wvtfr, wabase, wad);
  836. if (us)
  837. sub_reflect(wvsfr, wabase, wad);
  838. }
  839. else
  840. {
  841. const GLwedgeAttrib& wabase=awvtfr;
  842. if (us)
  843. sub_reflect(wvsfr, wabase, wad);
  844. if (ut)
  845. add(wvtfr, wabase, wad);
  846. }
  847. if (ut || us)
  848. lnum++;
  849. }
  850. break;
  851. default:
  852. throw CBadVsplitCode();
  853. }
  854. }
  855. }
  856. if (code&Vsplit::L_NEW)
  857. {
  858. add_zero(wvlfl, vspl.ar_wad[lnum++]);
  859. }
  860. if (code&Vsplit::R_NEW)
  861. {
  862. add_zero(wvrfr, vspl.ar_wad[lnum++]);
  863. }
  864. }
  865. void CAugGlMesh::undo_vsplit(const Vsplit& vspl)
  866. {
  867. unsigned int code=vspl.code;
  868. int ii=(code&Vsplit::II_MASK)>>Vsplit::II_SHIFT;
  869. const int isl=1; int isr;
  870. WORD fl, fr;
  871. GLvertex glvs, glvt;
  872. /*
  873. * 1) Remove the faces
  874. * -------------------
  875. */
  876. if (vspl.vlr_offset1 > 1)
  877. {
  878. WORD frmid = vspl.fr_matid, flmid = vspl.fl_matid;
  879. isr = 1;
  880. // remove fr
  881. m_matcnt[frmid]--;
  882. fr = m_matpos[frmid] + m_matcnt[frmid];
  883. // remove fl
  884. m_matcnt[flmid]--;
  885. fl = m_matpos[flmid] + m_matcnt[flmid];
  886. m_numFaces -= 2;
  887. }
  888. else
  889. {
  890. WORD frmid = vspl.fr_matid, flmid = vspl.fl_matid;
  891. isr = 0;
  892. // remove fl
  893. m_matcnt[flmid]--;
  894. fl = m_matpos[flmid] + m_matcnt[flmid];
  895. fr = UNDEF;
  896. --m_numFaces;
  897. }
  898. /*
  899. * 2) Get wedges in neighborhood.
  900. * ------------------------------
  901. */
  902. WORD wvsfl, wvtfl, wvlfl;
  903. WORD wvsfr, wvtfr, wvrfr;
  904. wvsfl = m_farray[fl].w[0];
  905. wvtfl = m_farray[fl].w[1];
  906. wvlfl = m_farray[fl].w[2];
  907. if (!isr)
  908. {
  909. wvsfr=UNDEF;
  910. wvtfr=UNDEF;
  911. wvrfr=UNDEF;
  912. }
  913. else
  914. {
  915. wvsfr = m_farray[fr].w[0];
  916. wvtfr = m_farray[fr].w[2];
  917. wvrfr = m_farray[fr].w[1];
  918. }
  919. /*
  920. * 3) Obtain the vertices Vs and Vt and save them.
  921. * -----------------------------------------------
  922. */
  923. WORD vs = FindVertexIndex (wvsfl);
  924. WORD vt = FindVertexIndex (wvtfl);
  925. glvt.x = m_varray[vt].x;
  926. glvt.y = m_varray[vt].y;
  927. glvt.z = m_varray[vt].z;
  928. /*
  929. * 4) Get adjacent faces and wedges on left and right.
  930. * ---------------------------------------------------
  931. * (really needed??)
  932. */
  933. WORD flccw, flclw; // either (not both) may be UNDEF
  934. WORD frccw, frclw; // either (or both) may be UNDEF
  935. /*
  936. * Also find index of vs within those adjacent faces
  937. */
  938. int jlccw2, jlclw0, jlclw2, jrccw, jrclw1; // only defined if faces exist
  939. WORD* pwlclw;
  940. WORD wlccw, wlclw, wrccw, wrclw; // UNDEF if faces does not exist
  941. /*
  942. * Left side
  943. */
  944. if (isl)
  945. {
  946. flccw = m_fnei[fl][1];
  947. flclw = m_fnei[fl][0];
  948. if (flccw == UNDEF)
  949. {
  950. wlccw=UNDEF;
  951. }
  952. else
  953. {
  954. gather_vf_j2w (vs, flccw, jlccw2, wlccw);
  955. }
  956. if (flclw==UNDEF)
  957. {
  958. wlclw = UNDEF;
  959. }
  960. else
  961. {
  962. gather_vf_j0j2pw (vt, flclw, jlclw0, jlclw2, pwlclw);
  963. wlclw = *pwlclw;
  964. }
  965. }
  966. /*
  967. * Right side
  968. */
  969. if (!isr)
  970. {
  971. frccw = frclw = wrccw = wrclw = UNDEF;
  972. }
  973. else
  974. {
  975. frccw = m_fnei[fr][0];
  976. frclw = m_fnei[fr][2];
  977. if (frccw == UNDEF)
  978. {
  979. wrccw = UNDEF;
  980. }
  981. else
  982. {
  983. gather_vf_jw(vt, frccw, jrccw, wrccw);
  984. }
  985. if (frclw == UNDEF)
  986. {
  987. wrclw = UNDEF;
  988. }
  989. else
  990. {
  991. gather_vf_j1w (vs, frclw, jrclw1, wrclw);
  992. }
  993. }
  994. int thru_l = ((wlccw == wvsfl) && (wlclw == wvtfl));
  995. int thru_r = ((wrclw == wvsfr) && (wrccw == wvtfr));
  996. /*
  997. * 5) Update adjacency information.
  998. * --------------------------------
  999. */
  1000. if (flccw != UNDEF) m_fnei[flccw][jlccw2] = flclw;
  1001. if (flclw != UNDEF) m_fnei[flclw][(jlclw0+1)%3] = flccw;
  1002. if (frccw != UNDEF) m_fnei[frccw][(jrccw+2)%3] = frclw;
  1003. if (frclw != UNDEF) m_fnei[frclw][jrclw1] = frccw;
  1004. /*
  1005. * 6) Propagate wedges id's across collapsed faces if can go thru.
  1006. * ---------------------------------------------------------------
  1007. */
  1008. WORD ffl = flclw, ffr = frccw;
  1009. int jjl0 = jlclw0, jjl2 = jlclw2, jjr = jrccw;
  1010. WORD* pwwl=pwlclw;
  1011. /*
  1012. * first go clw
  1013. */
  1014. if (thru_l)
  1015. {
  1016. for (;;)
  1017. {
  1018. *pwwl = wlccw;
  1019. if (ffl == ffr)
  1020. {
  1021. ffl = ffr = UNDEF; // all wedges seen
  1022. break;
  1023. }
  1024. ffl = m_fnei[ffl][jjl2];
  1025. if (ffl == UNDEF) break;
  1026. gather_vf_j0j2pw(vt, ffl, jjl0, jjl2, pwwl);
  1027. if (*pwwl != wlclw) break;
  1028. }
  1029. }
  1030. /*
  1031. * now go ccw from other side
  1032. */
  1033. if ((ffr != UNDEF) && thru_r)
  1034. {
  1035. WORD* pw = &(m_farray[ffr].w[jjr]);
  1036. for (;;)
  1037. {
  1038. *pw = wrclw;
  1039. if (ffr == ffl)
  1040. {
  1041. ffl = ffr = UNDEF; // all wedges seen
  1042. break;
  1043. }
  1044. ffr = m_fnei[ffr][(jjr+1)%3];
  1045. if (ffr == UNDEF) break;
  1046. gather_vf_jpw (vt, ffr, jjr, pw);
  1047. if (*pw != wrccw) break;
  1048. }
  1049. }
  1050. /*
  1051. * 7) Identify those wedges that will need to be updated to vs.
  1052. * ------------------------------------------------------------
  1053. * (wmodif may contain some duplicates)
  1054. */
  1055. PArray<WORD,10> ar_wmodif;
  1056. if (ffl!=UNDEF)
  1057. {
  1058. for (;;)
  1059. {
  1060. int w = *pwwl;
  1061. ar_wmodif += w;
  1062. if (ffl == ffr)
  1063. {
  1064. ffl = ffr = UNDEF;
  1065. break;
  1066. }
  1067. ffl = m_fnei[ffl][jjl2];
  1068. if (ffl == UNDEF) break;
  1069. gather_vf_j0j2pw (vt, ffl, jjl0, jjl2, pwwl);
  1070. }
  1071. }
  1072. /*
  1073. * 8) Update wedge vertices to vs.
  1074. * -------------------------------
  1075. */
  1076. for (int i=0; i<ar_wmodif.num(); ++i)
  1077. {
  1078. // _wedges[w].vertex=vs;
  1079. WORD w = ar_wmodif[i];
  1080. WedgeListDelete(w);
  1081. m_varray[w] = m_varray[vs];
  1082. m_wedgelist[w] = m_wedgelist[vs];
  1083. m_wedgelist[vs] = w;
  1084. }
  1085. /*
  1086. * 9) Update vertex attributes.
  1087. * ----------------------------
  1088. */
  1089. float vsx, vsy, vsz;
  1090. switch (ii)
  1091. {
  1092. case 2:
  1093. glvs.x = m_varray[vs].x - vspl.vad_small[0];
  1094. glvs.y = m_varray[vs].y - vspl.vad_small[1];
  1095. glvs.z = m_varray[vs].z - vspl.vad_small[2];
  1096. break;
  1097. case 0:
  1098. glvs.x = glvt.x - vspl.vad_small[0];
  1099. glvs.y = glvt.y - vspl.vad_small[1];
  1100. glvs.z = glvt.z - vspl.vad_small[2];
  1101. break;
  1102. case 1:
  1103. glvs.x = glvt.x - vspl.vad_large[0] - vspl.vad_small[0];
  1104. glvs.y = glvt.y - vspl.vad_large[1] - vspl.vad_small[1];
  1105. glvs.z = glvt.z - vspl.vad_large[2] - vspl.vad_small[2];
  1106. break;
  1107. default:
  1108. throw CBadVsplitCode();
  1109. }
  1110. /*
  1111. * 10) update all wedges sharing vs with it's coordinates
  1112. * ------------------------------------------------------
  1113. */
  1114. WORD p = vs;
  1115. do
  1116. {
  1117. m_varray[p] = glvs;
  1118. p = m_wedgelist[p];
  1119. }
  1120. while (p!=vs);
  1121. /*
  1122. * 11) Udpate wedge attributes. they are currently predicted exactly.
  1123. * ------------------------------------------------------------------
  1124. */
  1125. GLwedgeAttrib awvtfr, awvsfr;
  1126. //GLvertex awvtfrV, awvsfrV;
  1127. if (isr)
  1128. {
  1129. //awvtfrV = m_varray[wvtfr];
  1130. awvtfr.n = m_narray[wvtfr];
  1131. awvtfr.t = m_tarray[wvtfr];
  1132. //awvsfrV = m_varray[wvsfr];
  1133. awvsfr.n = m_narray[wvsfr];
  1134. awvsfr.t = m_tarray[wvsfr];
  1135. }
  1136. int problem = 0;
  1137. if (isl)
  1138. {
  1139. int nt = !(code&Vsplit::T_LSAME);
  1140. int ns = !(code&Vsplit::S_LSAME);
  1141. if (nt && ns)
  1142. {
  1143. problem = 1;
  1144. }
  1145. else
  1146. {
  1147. switch (ii)
  1148. {
  1149. case 2:
  1150. if (!thru_l)
  1151. {
  1152. m_narray[wvtfl] = m_narray[wvsfl];
  1153. m_tarray[wvtfl] = m_tarray[wvsfl];
  1154. }
  1155. break;
  1156. case 0:
  1157. m_narray[wvsfl] = m_narray[wvtfl];
  1158. m_tarray[wvsfl] = m_tarray[wvtfl];
  1159. break;
  1160. case 1:
  1161. sub_noreflect (wvsfl, wvtfl, vspl.ar_wad[0]);
  1162. if (!thru_l)
  1163. {
  1164. m_narray[wvtfl] = m_narray[wvsfl];
  1165. m_tarray[wvtfl] = m_tarray[wvsfl];
  1166. }
  1167. break;
  1168. default:
  1169. throw CBadVsplitCode();
  1170. }
  1171. }
  1172. }
  1173. if (isr)
  1174. {
  1175. int nt = !(code&Vsplit::T_RSAME);
  1176. int ns = !(code&Vsplit::S_RSAME);
  1177. int ut = !(code&Vsplit::T_CSAME);
  1178. int us = !(code&Vsplit::S_CSAME);
  1179. if (problem || us || ut)
  1180. {
  1181. switch (ii) {
  1182. case 2:
  1183. /*
  1184. * If thru_r, then wvtfr & wrccw no longer exist.
  1185. * This may be duplicating some work already done for isl.
  1186. */
  1187. if (!nt && !thru_r)
  1188. {
  1189. m_narray[wvtfr] = awvsfr.n;
  1190. m_tarray[wvtfr] = awvsfr.t;
  1191. }
  1192. break;
  1193. case 0:
  1194. // This may be duplicating some work already done for isl.
  1195. if (!ns)
  1196. {
  1197. m_narray[wvsfr] = awvtfr.n;
  1198. m_tarray[wvsfr] = awvtfr.t;
  1199. }
  1200. break;
  1201. case 1:
  1202. {
  1203. GLwedgeAttrib wa;
  1204. interp(wa, awvsfr, awvtfr, 0.5f, 0.5f);
  1205. if (!ns)
  1206. {
  1207. m_narray[wvsfr] = wa.n;
  1208. m_tarray[wvsfr] = wa.t;
  1209. }
  1210. if (!nt && !thru_r)
  1211. {
  1212. m_narray[wvtfr] = wa.n;
  1213. m_tarray[wvtfr] = wa.t;
  1214. }
  1215. }
  1216. break;
  1217. default:
  1218. throw CBadVsplitCode();
  1219. }
  1220. }
  1221. }
  1222. /*
  1223. * 12) Remove wedges.
  1224. * ------------------
  1225. */
  1226. if (isr && (code&Vsplit::R_NEW))
  1227. {
  1228. WORD w = --m_numWedges; // wvrfr
  1229. WedgeListDelete(w);
  1230. }
  1231. if (code&Vsplit::L_NEW)
  1232. {
  1233. WORD w = --m_numWedges; // wvlfl
  1234. WedgeListDelete(w);
  1235. }
  1236. if (isr && (!(code&Vsplit::S_CSAME) && !(code&Vsplit::S_RSAME)))
  1237. {
  1238. WORD w = --m_numWedges; // wvsfr
  1239. WedgeListDelete(w);
  1240. }
  1241. if ((!(code&Vsplit::S_LSAME) && (!(code&Vsplit::S_CSAME) ||
  1242. !(code&Vsplit::S_RSAME))))
  1243. {
  1244. WORD w = --m_numWedges; // wvsfl
  1245. WedgeListDelete(w);
  1246. }
  1247. if (isr && (!(code&Vsplit::T_CSAME) && !(code&Vsplit::T_RSAME)))
  1248. {
  1249. WORD w = --m_numWedges; // wvtfr
  1250. WedgeListDelete(w);
  1251. }
  1252. if ((!(code&Vsplit::T_LSAME) && (!(code&Vsplit::T_CSAME) ||
  1253. !(code&Vsplit::T_RSAME))))
  1254. {
  1255. WORD w = --m_numWedges; // wvtfl
  1256. WedgeListDelete(w);
  1257. }
  1258. int was_wnl = isl && (code&Vsplit::T_LSAME) && (code&Vsplit::S_LSAME);
  1259. if (isr && (code&Vsplit::T_RSAME) && (code&Vsplit::S_RSAME) &&
  1260. !(was_wnl && (code&Vsplit::T_CSAME)))
  1261. {
  1262. WORD w = --m_numWedges; // wrccw
  1263. WedgeListDelete(w);
  1264. }
  1265. if (was_wnl)
  1266. {
  1267. WORD w = --m_numWedges; // wlclw
  1268. WedgeListDelete(w);
  1269. }
  1270. }
  1271. void CAugGlMesh::sub_reflect(WORD a, const GLwedgeAttrib& abase,
  1272. const WEDGEATTRD& ad)
  1273. {
  1274. /*
  1275. * note: may have abase==a -> not really const
  1276. * dr == -d +2*(d.n)n
  1277. * an = n + dr
  1278. * optimized: a.normal=-d+((2.f)*dot(d,n)+1.f)*n;
  1279. */
  1280. register float vdot = ad[0]*abase.n.x + ad[1]*abase.n.y + ad[2]*abase.n.z;
  1281. register float vdot2p1 = vdot * 2.0f + 1.0f;
  1282. m_narray[a].x = -ad[0] + vdot2p1*abase.n.x;
  1283. m_narray[a].y = -ad[1] + vdot2p1*abase.n.y;
  1284. m_narray[a].z = -ad[2] + vdot2p1*abase.n.z;
  1285. m_tarray[a].s = abase.t.s - ad[3];
  1286. m_tarray[a].t = abase.t.t - ad[4];
  1287. }
  1288. void CAugGlMesh::sub_noreflect(WORD a, WORD abase, const WEDGEATTRD& ad)
  1289. {
  1290. m_narray[a].x = m_narray[abase].x - ad[0];
  1291. m_narray[a].y = m_narray[abase].y - ad[1];
  1292. m_narray[a].z = m_narray[abase].z - ad[2];
  1293. m_tarray[a].s = m_tarray[abase].s - ad[3];
  1294. m_tarray[a].t = m_tarray[abase].t - ad[4];
  1295. }
  1296. void interp(GLwedgeAttrib& a, const GLwedgeAttrib& a1,
  1297. const GLwedgeAttrib& a2, float f1, float f2)
  1298. {
  1299. if (a1.n.x==a2.n.x && a1.n.y==a2.n.y && a1.n.z==a2.n.z)
  1300. {
  1301. a.n = a1.n;
  1302. }
  1303. else
  1304. {
  1305. a.n.x = f1*a1.n.x + f2*a2.n.x;
  1306. a.n.y = f1*a1.n.y + f2*a2.n.y;
  1307. a.n.z = f1*a1.n.z + f2*a2.n.z;
  1308. float denom = (float) sqrt ((double)(a.n.x*a.n.x + a.n.y*a.n.y +
  1309. a.n.z*a.n.z));
  1310. if (denom!=0)
  1311. {
  1312. a.n.x/=denom;
  1313. a.n.y/=denom;
  1314. a.n.z/=denom;
  1315. }
  1316. }
  1317. a.t.s = f1*a1.t.s + f2*a2.t.s;
  1318. a.t.t = f1*a1.t.t + f2*a2.t.t;
  1319. }
  1320. void CAugGlMesh::gather_vf_jw (WORD v, WORD f, int& j, WORD& w) const
  1321. {
  1322. j = get_jvf (v,f);
  1323. w = (m_farray[f]).w[j];
  1324. }
  1325. void CAugGlMesh::gather_vf_j0j2pw(WORD v, WORD f, int& j0, int& j2, WORD*& pw)
  1326. {
  1327. j0 = get_jvf (v,f);
  1328. pw = &(m_farray[f]).w[j0];
  1329. j2 = (j0 + 2) % 3;
  1330. }
  1331. void CAugGlMesh::gather_vf_j2w(WORD v, WORD f, int& j2, WORD& w) const
  1332. {
  1333. WORD j = get_jvf (v,f);
  1334. w = (m_farray[f]).w[j];
  1335. j2 = (j + 2) % 3;
  1336. }
  1337. void CAugGlMesh::gather_vf_j1w (WORD v, WORD f, int& j1, WORD& w) const
  1338. {
  1339. WORD j = get_jvf(v,f);
  1340. w = (m_farray[f]).w[j];
  1341. j1 = (j + 1) % 3;
  1342. }
  1343. void CAugGlMesh::gather_vf_jpw(WORD v, WORD f, int& j, WORD*& pw)
  1344. {
  1345. j = get_jvf(v,f);
  1346. pw = &(m_farray[f]).w[j];
  1347. }
  1348. WORD CAugGlMesh::MatidOfFace(WORD f)
  1349. {
  1350. //Binary search helps if there are a lot of materials
  1351. for (WORD i=1; i<m_numMaterials; ++i)
  1352. if (f < m_matpos[i])
  1353. return i-1;
  1354. return m_numMaterials-1;
  1355. //throw CBadFace();
  1356. //return 0; // never
  1357. }