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.

1422 lines
36 KiB

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