1527 lines
38 KiB
C++
1527 lines
38 KiB
C++
/**
|
|
** File : aglmesh.cxx
|
|
** Description: Implementations of CAugGlMesh class
|
|
**/
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
#include "array.h"
|
|
#include "aglmesh.h"
|
|
#include "pmerrors.h"
|
|
#include <math.h>
|
|
|
|
void interp(GLwedgeAttrib& a, const GLwedgeAttrib& a1,
|
|
const GLwedgeAttrib& a2, float f1, float f2);
|
|
|
|
|
|
/**************************************************************************/
|
|
|
|
/*
|
|
* CAugGlMesh: Constructor
|
|
*/
|
|
CAugGlMesh::CAugGlMesh() : CSimpGlMesh ()
|
|
{
|
|
//Dynamically allocated arrays
|
|
m_fnei = NULL;
|
|
m_facemap = NULL;
|
|
}
|
|
|
|
|
|
/*
|
|
* CAugGlMesh: Destructor
|
|
*/
|
|
CAugGlMesh::~CAugGlMesh()
|
|
{
|
|
delete [] m_fnei;
|
|
delete [] m_facemap;
|
|
}
|
|
|
|
|
|
PHASHENTRY* hashtable;
|
|
PHASHENTRY hashentries;
|
|
int freeptr, maxptr;
|
|
|
|
void CAugGlMesh::HashAdd(WORD va, WORD vb, WORD f)
|
|
{
|
|
#ifdef _DEBUG
|
|
if (va > m_numWedges || va < 0)
|
|
throw CHashOvrflw();
|
|
#endif
|
|
for (PHASHENTRY* t = &(hashtable[va]); *t; t = &((*t)->next));
|
|
PHASHENTRY p = &(hashentries[freeptr++]);
|
|
p->f = f;
|
|
p->v2 = vb;
|
|
p->next = NULL;
|
|
*t=p;
|
|
}
|
|
|
|
WORD CAugGlMesh::HashFind(WORD va, WORD vb)
|
|
{
|
|
#ifdef _DEBUG
|
|
if (va > m_baseWedges || va < 0)
|
|
throw CHashOvrflw();
|
|
#endif
|
|
for (PHASHENTRY* t = &(hashtable[va]); *t; t = &((*t)->next))
|
|
{
|
|
if ((*t)->v2 == vb)
|
|
{
|
|
return (*t)->f;
|
|
}
|
|
}
|
|
return USHRT_MAX;
|
|
}
|
|
|
|
|
|
void CAugGlMesh::ComputeAdjacency(void)
|
|
{
|
|
freeptr = 0;
|
|
maxptr = m_numFaces*3;
|
|
hashtable = new PHASHENTRY[m_numWedges];
|
|
|
|
// An entry for each 3 edges of each face in base mesh
|
|
hashentries = new hashentry[maxptr];
|
|
if (!hashtable)
|
|
throw CExNewFailed();
|
|
memset(hashtable, 0, sizeof(PHASHENTRY)*m_numWedges);
|
|
|
|
/*
|
|
* For each group of faces
|
|
*/
|
|
for(int i=0; i < (int)m_numMaterials; ++i)
|
|
{
|
|
/*
|
|
* For each face in the group
|
|
*/
|
|
for (int k=m_matpos[i]; k<(m_matpos[i]+m_matcnt[i]); ++k)
|
|
{
|
|
int v1 = FindVertexIndex((m_farray[k]).w[0]);
|
|
int v2 = FindVertexIndex((m_farray[k]).w[1]);
|
|
int v3 = FindVertexIndex((m_farray[k]).w[2]);
|
|
|
|
HashAdd(v1,v2,k);
|
|
HashAdd(v2,v3,k);
|
|
HashAdd(v3,v1,k);
|
|
}
|
|
}
|
|
|
|
#ifdef _DEBUG
|
|
if (freeptr > maxptr)
|
|
throw CHashOvrflw();
|
|
#endif
|
|
/*
|
|
* For each group of faces
|
|
*/
|
|
for(i=0; i < (int)m_numMaterials; ++i)
|
|
{
|
|
/*
|
|
* For each face in the group
|
|
*/
|
|
for (int k=m_matpos[i]; k<(m_matpos[i]+m_matcnt[i]); ++k)
|
|
{
|
|
int v1 = FindVertexIndex((m_farray[k]).w[0]);
|
|
int v2 = FindVertexIndex((m_farray[k]).w[1]);
|
|
int v3 = FindVertexIndex((m_farray[k]).w[2]);
|
|
|
|
m_fnei[k][0] = HashFind(v3,v2);
|
|
m_fnei[k][1] = HashFind(v1,v3);
|
|
m_fnei[k][2] = HashFind(v2,v1);
|
|
}
|
|
}
|
|
delete [] hashtable;
|
|
delete [] hashentries;
|
|
}
|
|
|
|
|
|
// note: vspl is modified!
|
|
void CAugGlMesh::apply_vsplit(Vsplit& vspl)
|
|
{
|
|
const BOOL isl = TRUE;
|
|
BOOL isr = vspl.vlr_offset1 > 1;
|
|
HRESULT hr;
|
|
|
|
/*
|
|
* Get vertices, faces, and wedges in the neigbhorhood of the split.
|
|
* Look at the diagram in mesh.vld for more information about the
|
|
* meanings of various variables.
|
|
*/
|
|
|
|
WORD vs;
|
|
WORD code=vspl.code;
|
|
int ii=(code&Vsplit::II_MASK)>>Vsplit::II_SHIFT;
|
|
WORD flccw, flclw; // either (not both) may be UNDEF
|
|
WORD frccw, frclw; // either (or both) may be UNDEF
|
|
WORD wlccw, wlclw, wrccw, wrclw; // ==UNDEF if faces do not exist
|
|
int jlccw, jlclw, jrccw, jrclw; // only defined if faces exist
|
|
int jlclw2;
|
|
WORD flmatid, frmatid;
|
|
GLvertex glvs, glvt; // vertices vs and vt
|
|
PArray<WORD*,10> ar_pwedges;
|
|
|
|
/*
|
|
* 1) Gather all the wedges surrounding Vs into ar_pwedges array
|
|
* -------------------------------------------------------------
|
|
*/
|
|
|
|
if (vspl.vlr_offset1 == 0)
|
|
{
|
|
/*
|
|
* Extremely rare case when flclw does not exist.
|
|
*/
|
|
flclw = UNDEF;
|
|
wlclw = UNDEF;
|
|
if (vspl.modified)
|
|
{
|
|
flccw = vspl.flclw;
|
|
}
|
|
else
|
|
{
|
|
flccw = WORD(m_facemap[WORD(vspl.flclw)]);
|
|
vspl.flclw = flccw;
|
|
vspl.modified = TRUE;
|
|
}
|
|
|
|
int vs_index = (code & Vsplit::VSINDEX_MASK)>>Vsplit::VSINDEX_SHIFT;
|
|
jlccw = vs_index;
|
|
wlccw = m_farray[flccw].w[jlccw];
|
|
vs = FindVertexIndex(wlccw);
|
|
frccw = frclw = wrccw = wrclw = UNDEF;
|
|
}
|
|
else
|
|
{
|
|
if (vspl.modified)
|
|
{
|
|
flclw = vspl.flclw;
|
|
}
|
|
else
|
|
{
|
|
flclw = WORD(m_facemap[WORD(vspl.flclw)]);
|
|
vspl.flclw = flclw;
|
|
vspl.modified = TRUE;
|
|
}
|
|
|
|
//flclw = WORD(m_facemap[WORD(vspl.flclw)]);
|
|
int vs_index = (code&Vsplit::VSINDEX_MASK)>>Vsplit::VSINDEX_SHIFT;
|
|
|
|
jlclw = vs_index; //The vs's index
|
|
jlclw2 = (jlclw + 2)%3; //The vl's index
|
|
|
|
WORD* pwlclw = &(m_farray[flclw].w[jlclw]);
|
|
wlclw = *pwlclw;
|
|
vs = FindVertexIndex (wlclw);
|
|
flccw = m_fnei[flclw][(jlclw+1)%3];
|
|
if (flccw == UNDEF)
|
|
{
|
|
wlccw = UNDEF;
|
|
}
|
|
else
|
|
{
|
|
gather_vf_jw(vs, flccw, jlccw, wlccw);
|
|
}
|
|
|
|
if (!isr)
|
|
{
|
|
frccw = frclw = wrccw = wrclw = UNDEF;
|
|
ar_pwedges += pwlclw;
|
|
|
|
/*
|
|
* Rotate around and record all wedges CLW from wlclw.
|
|
*/
|
|
int j0 = jlclw, j2 = jlclw2;
|
|
WORD f = flclw;
|
|
for (;;)
|
|
{
|
|
f = m_fnei[f][j2];
|
|
if (f == UNDEF) break;
|
|
WORD* pw;
|
|
gather_vf_j0j2pw (vs, f, j0, j2, pw);
|
|
ar_pwedges += pw;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ar_pwedges.init (vspl.vlr_offset1 - 1);
|
|
ar_pwedges[0] = pwlclw;
|
|
|
|
/*
|
|
* Rotate around the first vlr_offset-1 faces.
|
|
*/
|
|
int j0 = jlclw, j2 = jlclw2;
|
|
WORD f = flclw;
|
|
for(int count=0; count < vspl.vlr_offset1-2; ++count)
|
|
{
|
|
f = m_fnei[f][j2];
|
|
WORD* pw;
|
|
gather_vf_j0j2pw (vs, f, j0, j2, pw);
|
|
ar_pwedges[count+1] = pw;
|
|
}
|
|
frccw=f;
|
|
|
|
/*
|
|
* On the last face, find adjacent faces.
|
|
*/
|
|
jrccw = j0;
|
|
wrccw = m_farray[frccw].w[jrccw];
|
|
frclw = m_fnei[frccw][j2];
|
|
if (frclw==UNDEF)
|
|
{
|
|
wrclw=UNDEF;
|
|
}
|
|
else
|
|
{
|
|
gather_vf_jw(vs,frclw,jrclw,wrclw);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* 2) Obtain the matIDs of the two new faces generated by applying vsplit.
|
|
* -----------------------------------------------------------------------
|
|
* ?? could use L_MASK instead of ii for prediction instead.
|
|
* face_prediction() is the shady part.
|
|
*/
|
|
|
|
if (code & Vsplit::FLN_MASK)
|
|
{
|
|
flmatid = vspl.fl_matid;
|
|
}
|
|
else
|
|
{
|
|
flmatid = MatidOfFace(face_prediction(flclw,flccw,ii));
|
|
// save computed value for undo_vsplit and future vsplits
|
|
vspl.fl_matid = flmatid;
|
|
vspl.code |= Vsplit::FLN_MASK;
|
|
}
|
|
|
|
if (isr)
|
|
{
|
|
if (code&Vsplit::FRN_MASK)
|
|
frmatid = vspl.fr_matid;
|
|
else
|
|
{
|
|
frmatid = MatidOfFace(face_prediction(frccw,frclw,ii));
|
|
// save computed value for undo_vsplit and future vsplits
|
|
vspl.fr_matid = frmatid;
|
|
vspl.code|=Vsplit::FRN_MASK;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* 3) Compute new coordinates of vt and vs (calc coordinates).
|
|
* -----------------------------------------------------------
|
|
*/
|
|
|
|
switch (ii)
|
|
{
|
|
case 2:
|
|
glvt.x = m_varray[vs].x + vspl.vad_large[0];
|
|
glvt.y = m_varray[vs].y + vspl.vad_large[1];
|
|
glvt.z = m_varray[vs].z + vspl.vad_large[2];
|
|
|
|
glvs.x = m_varray[vs].x + vspl.vad_small[0];
|
|
glvs.y = m_varray[vs].y + vspl.vad_small[1];
|
|
glvs.z = m_varray[vs].z + vspl.vad_small[2];
|
|
break;
|
|
case 0:
|
|
glvt.x = m_varray[vs].x + vspl.vad_small[0];
|
|
glvt.y = m_varray[vs].y + vspl.vad_small[1];
|
|
glvt.z = m_varray[vs].z + vspl.vad_small[2];
|
|
|
|
glvs.x = m_varray[vs].x + vspl.vad_large[0];
|
|
glvs.y = m_varray[vs].y + vspl.vad_large[1];
|
|
glvs.z = m_varray[vs].z + vspl.vad_large[2];
|
|
break;
|
|
case 1:
|
|
glvt.x = m_varray[vs].x + vspl.vad_small[0];
|
|
glvt.y = m_varray[vs].y + vspl.vad_small[1];
|
|
glvt.z = m_varray[vs].z + vspl.vad_small[2];
|
|
|
|
glvs.x = glvt.x - vspl.vad_large[0];
|
|
glvs.y = glvt.y - vspl.vad_large[1];
|
|
glvs.z = glvt.z - vspl.vad_large[2];
|
|
|
|
glvt.x = glvt.x + vspl.vad_large[0];
|
|
glvt.y = glvt.y + vspl.vad_large[1];
|
|
glvt.z = glvt.z + vspl.vad_large[2];
|
|
break;
|
|
default:
|
|
throw CBadVsplitCode();
|
|
}
|
|
|
|
/*
|
|
* 4) un-share wedges around vt (?) Add 2 wedges around Vs
|
|
* -------------------------------------------------------
|
|
* (may be gap on top). may modify wlclw and wrccw!
|
|
*/
|
|
|
|
WORD wnl = UNDEF, wnr = UNDEF;
|
|
int iil = 0, iir = ar_pwedges.num()-1;
|
|
if (isl && (wlclw == wlccw))
|
|
{
|
|
/*
|
|
* first go clw. Add new wedge.
|
|
*/
|
|
|
|
wnl = m_numWedges++;
|
|
|
|
/*
|
|
* Add wnl to the list of wedges sharing Vs
|
|
*/
|
|
m_wedgelist[wnl] = m_wedgelist[vs];
|
|
m_wedgelist[vs] = wnl;
|
|
|
|
/*
|
|
* Copy wedge attributes
|
|
*/
|
|
m_narray[wnl] = m_narray[wlccw];
|
|
m_tarray[wnl] = m_tarray[wlccw];
|
|
wlclw = wnl; // has been changed
|
|
|
|
for (;;)
|
|
{
|
|
*ar_pwedges[iil] = wnl;
|
|
iil++;
|
|
if (iil > iir)
|
|
{
|
|
wrccw = wnl; // has been changed
|
|
break;
|
|
}
|
|
if (*ar_pwedges[iil] != wlccw)
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (isr && (wrccw == wrclw))
|
|
{
|
|
/*
|
|
* now go ccw from other side.
|
|
*/
|
|
|
|
if ((wrclw == wlccw) && (wnl != UNDEF))
|
|
{
|
|
wnr = wnl;
|
|
}
|
|
else
|
|
{
|
|
// Add new wedge
|
|
wnr = m_numWedges++;
|
|
|
|
// Add wnr to the list of wedges sharing vs
|
|
m_wedgelist[wnr] = m_wedgelist[vs];
|
|
m_wedgelist[vs] = wnr;
|
|
|
|
// Copy wedge attributes
|
|
m_narray[wnr] = m_narray[wrclw];
|
|
m_tarray[wnr] = m_tarray[wrclw];
|
|
}
|
|
wrccw=wnr; // has been changed
|
|
|
|
for (;;)
|
|
{
|
|
*ar_pwedges[iir] = wnr;
|
|
iir--;
|
|
if (iir < iil)
|
|
{
|
|
if (iir < 0) wlclw=wnr; // has been changed
|
|
break;
|
|
}
|
|
if (*ar_pwedges[iir] != wrclw)
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* 5) Add other new wedges around Vt and record wedge ancestries
|
|
* -------------------------------------------------------------
|
|
*/
|
|
|
|
WORD wvtfl, wvtfr, vt = UNDEF;
|
|
if (!isr)
|
|
{
|
|
wvtfr=UNDEF;
|
|
switch (code&Vsplit::T_MASK)
|
|
{
|
|
case Vsplit::T_LSAME|Vsplit::T_RSAME:
|
|
wvtfl=wlclw;
|
|
break;
|
|
case Vsplit::T_RSAME:
|
|
// Add new wedge.
|
|
wvtfl = m_numWedges++;
|
|
m_wedgelist[wvtfl] = wvtfl;
|
|
m_varray[wvtfl] = glvt;
|
|
vt = wvtfl;
|
|
break;
|
|
default:
|
|
throw CBadVsplitCode();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (code&Vsplit::T_MASK)
|
|
{
|
|
case Vsplit::T_LSAME|Vsplit::T_RSAME|Vsplit::T_CSAME:
|
|
case Vsplit::T_LSAME|Vsplit::T_RSAME:
|
|
wvtfl=wlclw;
|
|
wvtfr=wrccw;
|
|
break;
|
|
case Vsplit::T_LSAME|Vsplit::T_CSAME:
|
|
wvtfl=wlclw;
|
|
wvtfr=wvtfl;
|
|
break;
|
|
case Vsplit::T_RSAME|Vsplit::T_CSAME:
|
|
wvtfl=wrccw;
|
|
wvtfr=wvtfl;
|
|
break;
|
|
case Vsplit::T_LSAME:
|
|
wvtfl=wlclw;
|
|
// Add new wedge.
|
|
wvtfr = m_numWedges++;
|
|
m_wedgelist[wvtfr] = wvtfr;
|
|
m_varray[wvtfr] = glvt;
|
|
vt = wvtfr;
|
|
break;
|
|
case Vsplit::T_RSAME:
|
|
// Add new wedge.
|
|
wvtfl = m_numWedges++;
|
|
m_wedgelist[wvtfl] = wvtfl;
|
|
m_varray[wvtfl] = glvt;
|
|
vt = wvtfl;
|
|
wvtfr=wrccw;
|
|
break;
|
|
case Vsplit::T_CSAME:
|
|
// Add new wedge.
|
|
wvtfl = m_numWedges++;
|
|
m_wedgelist[wvtfl] = wvtfl;
|
|
m_varray[wvtfl] = glvt;
|
|
vt = wvtfl;
|
|
wvtfr=wvtfl;
|
|
break;
|
|
case 0:
|
|
// Add new wedge.
|
|
wvtfl = m_numWedges++;
|
|
m_varray[wvtfl] = glvt;
|
|
vt = wvtfl;
|
|
|
|
// Add new wedge.
|
|
wvtfr = m_numWedges++;
|
|
m_varray[wvtfr] = glvt;
|
|
|
|
// Add wvtfr and wvtfl to list of wedges sharing vt
|
|
m_wedgelist[wvtfl] = wvtfr;
|
|
m_wedgelist[wvtfr] = wvtfl;
|
|
break;
|
|
default:
|
|
throw CBadVsplitCode();
|
|
}
|
|
}
|
|
|
|
/*
|
|
* 6) Add other new wedges around Vs.
|
|
* ----------------------------------
|
|
* Do we really need to find vertex index ? Optimize
|
|
*/
|
|
|
|
WORD wvsfl, wvsfr;
|
|
if (!isr)
|
|
{
|
|
wvsfr = UNDEF;
|
|
switch (code&Vsplit::S_MASK)
|
|
{
|
|
case Vsplit::S_LSAME|Vsplit::S_RSAME:
|
|
wvsfl=wlccw;
|
|
break;
|
|
case Vsplit::S_RSAME:
|
|
// Add new wedge.
|
|
wvsfl = m_numWedges++;
|
|
m_varray[wvsfl] = glvs;
|
|
|
|
// Add wvsfl to the list wedges sharing vs
|
|
m_wedgelist[wvsfl] = m_wedgelist[vs];
|
|
m_wedgelist[vs] = wvsfl;
|
|
break;
|
|
default:
|
|
throw CBadVsplitCode();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (code&Vsplit::S_MASK)
|
|
{
|
|
case Vsplit::S_LSAME|Vsplit::S_RSAME|Vsplit::S_CSAME:
|
|
case Vsplit::S_LSAME|Vsplit::S_RSAME:
|
|
wvsfl=wlccw;
|
|
wvsfr=wrclw;
|
|
break;
|
|
case Vsplit::S_LSAME|Vsplit::S_CSAME:
|
|
wvsfl=wlccw;
|
|
wvsfr=wvsfl;
|
|
break;
|
|
case Vsplit::S_RSAME|Vsplit::S_CSAME:
|
|
wvsfl=wrclw;
|
|
wvsfr=wvsfl;
|
|
break;
|
|
case Vsplit::S_LSAME:
|
|
wvsfl=wlccw;
|
|
// Add new wedge.
|
|
wvsfr = m_numWedges++;
|
|
m_wedgelist[wvsfr] = m_wedgelist[vs];
|
|
m_wedgelist[vs] = wvsfr;
|
|
m_varray[wvsfr] = glvs;
|
|
break;
|
|
case Vsplit::S_RSAME:
|
|
// Add new wedge.
|
|
wvsfl = m_numWedges++;
|
|
m_wedgelist[wvsfl] = m_wedgelist[vs];
|
|
m_wedgelist[vs] = wvsfl;
|
|
m_varray[wvsfl] = glvs;
|
|
wvsfr=wrclw;
|
|
break;
|
|
case Vsplit::S_CSAME:
|
|
// Add new wedge.
|
|
wvsfl = m_numWedges++;
|
|
m_wedgelist[wvsfl] = m_wedgelist[vs];
|
|
m_wedgelist[vs] = wvsfl;
|
|
m_varray[wvsfl] = glvs;
|
|
wvsfr = wvsfl;
|
|
break;
|
|
case 0:
|
|
// Add new wedge.
|
|
wvsfl = m_numWedges++;
|
|
m_varray[wvsfl] = glvs;
|
|
|
|
// Add new wedge.
|
|
wvsfr = m_numWedges++;
|
|
m_varray[wvsfr] = glvs;
|
|
|
|
// Add wvsfr and wvsfl to list of wedges sharing vt
|
|
m_wedgelist[wvsfl] = m_wedgelist[vs];
|
|
m_wedgelist[wvsfr] =wvsfl;
|
|
m_wedgelist[vs] = wvsfr;
|
|
break;
|
|
default:
|
|
throw CBadVsplitCode();
|
|
}
|
|
}
|
|
|
|
/*
|
|
* 7) Add outside wedges wvlfl and wvrfr
|
|
* -------------------------------------
|
|
*/
|
|
|
|
WORD wvlfl, wvrfr;
|
|
if (isl)
|
|
{
|
|
switch (code&Vsplit::L_MASK)
|
|
{
|
|
case Vsplit::L_ABOVE:
|
|
wvlfl = m_farray[flclw].w[jlclw2];
|
|
break;
|
|
case Vsplit::L_BELOW:
|
|
wvlfl = m_farray[flccw].w[(jlccw+1)%3];
|
|
break;
|
|
case Vsplit::L_NEW:
|
|
{
|
|
wvlfl = m_numWedges++;
|
|
|
|
WORD vl = (flclw != UNDEF) ? m_farray[flclw].w[jlclw2] :
|
|
m_farray[flccw].w[(jlccw+1)%3];
|
|
m_wedgelist[wvlfl] = m_wedgelist[vl];
|
|
m_wedgelist[vl] = wvlfl;
|
|
|
|
m_varray[wvlfl] = m_varray[vl];
|
|
}
|
|
break;
|
|
default:
|
|
throw CBadVsplitCode();
|
|
}
|
|
}
|
|
|
|
if (!isr)
|
|
{
|
|
wvrfr = UNDEF;
|
|
}
|
|
else
|
|
{
|
|
switch (code&Vsplit::R_MASK)
|
|
{
|
|
case Vsplit::R_ABOVE:
|
|
wvrfr = m_farray[frccw].w[(jrccw+1)%3];
|
|
break;
|
|
case Vsplit::R_BELOW:
|
|
wvrfr = m_farray[frclw].w[(jrclw+2)%3];
|
|
break;
|
|
case Vsplit::R_NEW:
|
|
{
|
|
wvrfr = m_numWedges++;
|
|
WORD vr = m_farray[frccw].w[(jrccw+1)%3];
|
|
|
|
m_wedgelist[wvrfr] = m_wedgelist[vr];
|
|
m_wedgelist[vr] = wvrfr;
|
|
|
|
m_varray[wvrfr] = m_varray[vr];
|
|
}
|
|
break;
|
|
default:
|
|
throw CBadVsplitCode();
|
|
}
|
|
}
|
|
|
|
/*
|
|
* 8) Add 1 or 2 faces, and update adjacency information.
|
|
* ------------------------------------------------------
|
|
*/
|
|
|
|
WORD fl, fr;
|
|
m_matcnt [flmatid]++;
|
|
fl = m_matpos[flmatid] + m_matcnt[flmatid] - 1;
|
|
m_facemap [m_numFaces] = fl;
|
|
|
|
if (isr)
|
|
{
|
|
m_matcnt [frmatid]++;
|
|
fr = m_matpos[frmatid] + m_matcnt[frmatid] - 1;
|
|
m_facemap [m_numFaces+1] = fr;
|
|
m_numFaces += 2;
|
|
}
|
|
else
|
|
{
|
|
fr = UNDEF;
|
|
m_numFaces ++;
|
|
}
|
|
|
|
if (isl)
|
|
{
|
|
m_farray[fl].w[0] = wvsfl;
|
|
m_farray[fl].w[1] = wvtfl;
|
|
m_farray[fl].w[2] = wvlfl;
|
|
|
|
if (flccw != UNDEF) m_fnei[flccw][(jlccw+2)%3] = fl;
|
|
if (flclw != UNDEF) m_fnei[flclw][(jlclw+1)%3] = fl;
|
|
|
|
m_fnei[fl][0] = flclw;
|
|
m_fnei[fl][1] = flccw;
|
|
m_fnei[fl][2] = fr;
|
|
}
|
|
|
|
if (isr)
|
|
{
|
|
m_farray[fr].w[0] = wvsfr;
|
|
m_farray[fr].w[1] = wvrfr;
|
|
m_farray[fr].w[2] = wvtfr;
|
|
|
|
if (frccw != UNDEF) m_fnei[frccw][(jrccw+2)%3] = fr;
|
|
if (frclw != UNDEF) m_fnei[frclw][(jrclw+1)%3] = fr;
|
|
|
|
m_fnei[fr][0] = frccw;
|
|
m_fnei[fr][1] = fl;
|
|
m_fnei[fr][2] = frclw;
|
|
}
|
|
|
|
/*
|
|
* 9) Update wedge vertices.
|
|
* -------------------------
|
|
*/
|
|
|
|
if (wnl != UNDEF)
|
|
{
|
|
WedgeListDelete(wnl);
|
|
m_varray[wnl] = glvt;
|
|
|
|
if (vt == UNDEF)
|
|
{
|
|
m_wedgelist[wnl] = wnl;
|
|
vt = wnl;
|
|
}
|
|
else
|
|
{
|
|
m_wedgelist[wnl] = m_wedgelist[vt];
|
|
m_wedgelist[vt] = wnl;
|
|
}
|
|
}
|
|
|
|
if (wnr != UNDEF)
|
|
{
|
|
WedgeListDelete(wnr);
|
|
m_varray[wnr] = glvt;
|
|
|
|
if (vt==UNDEF)
|
|
{
|
|
m_wedgelist[wnr] = wnr;
|
|
vt = wnr;
|
|
}
|
|
else
|
|
{
|
|
m_wedgelist[wnr] = m_wedgelist[vt];
|
|
m_wedgelist[vt] = wnr;
|
|
}
|
|
}
|
|
|
|
WORD prev = UNDEF;
|
|
for (; iil <= iir; iil++)
|
|
{
|
|
WORD w = *ar_pwedges[iil];
|
|
if (w != prev)
|
|
{
|
|
WedgeListDelete(w);
|
|
m_varray[w] = glvt;
|
|
if (vt==UNDEF)
|
|
{
|
|
m_wedgelist[w] = w;
|
|
vt = w;
|
|
}
|
|
else
|
|
{
|
|
m_wedgelist[w] = m_wedgelist[vt];
|
|
m_wedgelist[vt] = w;
|
|
}
|
|
}
|
|
prev = w;
|
|
}
|
|
|
|
/*
|
|
* 10) Update all wedges sharing Vs to it's new coordinates.
|
|
* ---------------------------------------------------------
|
|
* Note the prev loop in ar_pwedges could have modified wedge pointed by
|
|
* vs to be part of vt now.
|
|
* wvsfl is the only sure way of a wedge pointing to vs
|
|
*/
|
|
|
|
WORD p = wvsfl;
|
|
do
|
|
{
|
|
m_varray[p] = glvs;
|
|
p = m_wedgelist[p];
|
|
}
|
|
while (p != wvsfl);
|
|
|
|
/*
|
|
* 11) Update wedge attributes.
|
|
* ----------------------------
|
|
*/
|
|
|
|
GLwedgeAttrib awvtfr, awvsfr;
|
|
if (isr)
|
|
{
|
|
// backup for isr
|
|
//awvtfrV = m_varray[wvtfr];
|
|
awvtfr.n = m_narray[wvtfr];
|
|
awvtfr.t = m_tarray[wvtfr];
|
|
|
|
// backup for isr
|
|
//awvsfrV = m_varray[wvsfr];
|
|
awvsfr.n = m_narray[wvsfr];
|
|
awvsfr.t = m_tarray[wvsfr];
|
|
}
|
|
|
|
int lnum = 0;
|
|
if (isl)
|
|
{
|
|
int nt = !(code&Vsplit::T_LSAME);
|
|
int ns = !(code&Vsplit::S_LSAME);
|
|
if (nt && ns)
|
|
{
|
|
add_zero(wvtfl, vspl.ar_wad[lnum++]);
|
|
add_zero(wvsfl, vspl.ar_wad[lnum++]);
|
|
}
|
|
else
|
|
{
|
|
switch (ii)
|
|
{
|
|
case 2:
|
|
{
|
|
GLwedgeAttrib wa;
|
|
if (ns)
|
|
{
|
|
m_narray[wvsfl] = m_narray[wvtfl];
|
|
m_tarray[wvsfl] = m_tarray[wvtfl];
|
|
}
|
|
if (!ns) {wa.n = m_narray[wvsfl]; wa.t = m_tarray[wvsfl];}
|
|
else {wa.n = m_narray[wvtfl]; wa.t = m_tarray[wvtfl];}
|
|
add(wvtfl, wa, vspl.ar_wad[lnum++]);
|
|
break;
|
|
}
|
|
case 0:
|
|
{
|
|
GLwedgeAttrib wa;
|
|
if (nt)
|
|
{
|
|
m_narray[wvtfl] = m_narray[wvsfl];
|
|
m_tarray[wvtfl] = m_tarray[wvsfl];
|
|
}
|
|
if (!nt) {wa.n = m_narray[wvtfl]; wa.t = m_tarray[wvtfl];}
|
|
else {wa.n = m_narray[wvsfl]; wa.t = m_tarray[wvsfl];}
|
|
add(wvsfl, wa, vspl.ar_wad[lnum++]);
|
|
break;
|
|
}
|
|
case 1:
|
|
{
|
|
const WEDGEATTRD& wad = vspl.ar_wad[lnum];
|
|
if (!ns)
|
|
{
|
|
GLwedgeAttrib wabase;
|
|
wabase.n = m_narray[wvsfl];
|
|
wabase.t = m_tarray[wvsfl];
|
|
add(wvtfl, wabase, wad);
|
|
sub_reflect(wvsfl, wabase, wad);
|
|
}
|
|
else
|
|
{
|
|
GLwedgeAttrib wabase;
|
|
wabase.n = m_narray[wvtfl];
|
|
wabase.t = m_tarray[wvtfl];
|
|
sub_reflect(wvsfl, wabase, wad);
|
|
add(wvtfl, wabase, wad);
|
|
}
|
|
lnum++;
|
|
}
|
|
break;
|
|
default:
|
|
throw CBadVsplitCode();
|
|
}
|
|
}
|
|
}
|
|
|
|
if (isr)
|
|
{
|
|
int nt = !(code&Vsplit::T_RSAME);
|
|
int ns = !(code&Vsplit::S_RSAME);
|
|
int ut = !(code&Vsplit::T_CSAME);
|
|
int us = !(code&Vsplit::S_CSAME);
|
|
if (nt && ns)
|
|
{
|
|
if (ut)
|
|
add_zero(wvtfr, vspl.ar_wad[lnum++]);
|
|
if (us)
|
|
add_zero(wvsfr, vspl.ar_wad[lnum++]);
|
|
}
|
|
else
|
|
{
|
|
switch (ii)
|
|
{
|
|
case 2:
|
|
if (us && ns)
|
|
{
|
|
m_narray[wvsfr] = awvtfr.n;
|
|
m_tarray[wvsfr] = awvtfr.t;
|
|
}
|
|
if (ut)
|
|
add(wvtfr, (!ns?awvsfr:awvtfr), vspl.ar_wad[lnum++]);
|
|
break;
|
|
case 0:
|
|
if (ut && nt)
|
|
{
|
|
m_narray[wvtfr] = awvsfr.n;
|
|
m_tarray[wvtfr] = awvsfr.t;
|
|
}
|
|
if (us)
|
|
add(wvsfr, (!nt?awvtfr:awvsfr), vspl.ar_wad[lnum++]);
|
|
break;
|
|
case 1:
|
|
{
|
|
const WEDGEATTRD& wad = vspl.ar_wad[lnum];
|
|
if (!ns)
|
|
{
|
|
const GLwedgeAttrib& wabase = awvsfr;
|
|
if (ut)
|
|
add(wvtfr, wabase, wad);
|
|
if (us)
|
|
sub_reflect(wvsfr, wabase, wad);
|
|
}
|
|
else
|
|
{
|
|
const GLwedgeAttrib& wabase=awvtfr;
|
|
if (us)
|
|
sub_reflect(wvsfr, wabase, wad);
|
|
if (ut)
|
|
add(wvtfr, wabase, wad);
|
|
}
|
|
if (ut || us)
|
|
lnum++;
|
|
}
|
|
break;
|
|
default:
|
|
throw CBadVsplitCode();
|
|
}
|
|
}
|
|
}
|
|
if (code&Vsplit::L_NEW)
|
|
{
|
|
add_zero(wvlfl, vspl.ar_wad[lnum++]);
|
|
}
|
|
if (code&Vsplit::R_NEW)
|
|
{
|
|
add_zero(wvrfr, vspl.ar_wad[lnum++]);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void CAugGlMesh::undo_vsplit(const Vsplit& vspl)
|
|
{
|
|
unsigned int code=vspl.code;
|
|
int ii=(code&Vsplit::II_MASK)>>Vsplit::II_SHIFT;
|
|
const int isl=1; int isr;
|
|
WORD fl, fr;
|
|
GLvertex glvs, glvt;
|
|
|
|
/*
|
|
* 1) Remove the faces
|
|
* -------------------
|
|
*/
|
|
|
|
if (vspl.vlr_offset1 > 1)
|
|
{
|
|
WORD frmid = vspl.fr_matid, flmid = vspl.fl_matid;
|
|
|
|
isr = 1;
|
|
|
|
// remove fr
|
|
m_matcnt[frmid]--;
|
|
fr = m_matpos[frmid] + m_matcnt[frmid];
|
|
|
|
// remove fl
|
|
m_matcnt[flmid]--;
|
|
fl = m_matpos[flmid] + m_matcnt[flmid];
|
|
|
|
m_numFaces -= 2;
|
|
}
|
|
else
|
|
{
|
|
WORD frmid = vspl.fr_matid, flmid = vspl.fl_matid;
|
|
|
|
isr = 0;
|
|
|
|
// remove fl
|
|
m_matcnt[flmid]--;
|
|
fl = m_matpos[flmid] + m_matcnt[flmid];
|
|
fr = UNDEF;
|
|
--m_numFaces;
|
|
}
|
|
|
|
/*
|
|
* 2) Get wedges in neighborhood.
|
|
* ------------------------------
|
|
*/
|
|
|
|
WORD wvsfl, wvtfl, wvlfl;
|
|
WORD wvsfr, wvtfr, wvrfr;
|
|
|
|
wvsfl = m_farray[fl].w[0];
|
|
wvtfl = m_farray[fl].w[1];
|
|
wvlfl = m_farray[fl].w[2];
|
|
|
|
if (!isr)
|
|
{
|
|
wvsfr=UNDEF;
|
|
wvtfr=UNDEF;
|
|
wvrfr=UNDEF;
|
|
}
|
|
else
|
|
{
|
|
wvsfr = m_farray[fr].w[0];
|
|
wvtfr = m_farray[fr].w[2];
|
|
wvrfr = m_farray[fr].w[1];
|
|
}
|
|
|
|
/*
|
|
* 3) Obtain the vertices Vs and Vt and save them.
|
|
* -----------------------------------------------
|
|
*/
|
|
|
|
WORD vs = FindVertexIndex (wvsfl);
|
|
WORD vt = FindVertexIndex (wvtfl);
|
|
|
|
glvt.x = m_varray[vt].x;
|
|
glvt.y = m_varray[vt].y;
|
|
glvt.z = m_varray[vt].z;
|
|
|
|
/*
|
|
* 4) Get adjacent faces and wedges on left and right.
|
|
* ---------------------------------------------------
|
|
* (really needed??)
|
|
*/
|
|
|
|
WORD flccw, flclw; // either (not both) may be UNDEF
|
|
WORD frccw, frclw; // either (or both) may be UNDEF
|
|
|
|
/*
|
|
* Also find index of vs within those adjacent faces
|
|
*/
|
|
int jlccw2, jlclw0, jlclw2, jrccw, jrclw1; // only defined if faces exist
|
|
WORD* pwlclw;
|
|
WORD wlccw, wlclw, wrccw, wrclw; // UNDEF if faces does not exist
|
|
|
|
/*
|
|
* Left side
|
|
*/
|
|
|
|
if (isl)
|
|
{
|
|
flccw = m_fnei[fl][1];
|
|
flclw = m_fnei[fl][0];
|
|
|
|
if (flccw == UNDEF)
|
|
{
|
|
wlccw=UNDEF;
|
|
}
|
|
else
|
|
{
|
|
gather_vf_j2w (vs, flccw, jlccw2, wlccw);
|
|
}
|
|
|
|
if (flclw==UNDEF)
|
|
{
|
|
wlclw = UNDEF;
|
|
}
|
|
else
|
|
{
|
|
gather_vf_j0j2pw (vt, flclw, jlclw0, jlclw2, pwlclw);
|
|
wlclw = *pwlclw;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Right side
|
|
*/
|
|
|
|
if (!isr)
|
|
{
|
|
frccw = frclw = wrccw = wrclw = UNDEF;
|
|
}
|
|
else
|
|
{
|
|
frccw = m_fnei[fr][0];
|
|
frclw = m_fnei[fr][2];
|
|
|
|
if (frccw == UNDEF)
|
|
{
|
|
wrccw = UNDEF;
|
|
}
|
|
else
|
|
{
|
|
gather_vf_jw(vt, frccw, jrccw, wrccw);
|
|
}
|
|
|
|
if (frclw == UNDEF)
|
|
{
|
|
wrclw = UNDEF;
|
|
}
|
|
else
|
|
{
|
|
gather_vf_j1w (vs, frclw, jrclw1, wrclw);
|
|
}
|
|
}
|
|
|
|
int thru_l = ((wlccw == wvsfl) && (wlclw == wvtfl));
|
|
int thru_r = ((wrclw == wvsfr) && (wrccw == wvtfr));
|
|
|
|
/*
|
|
* 5) Update adjacency information.
|
|
* --------------------------------
|
|
*/
|
|
|
|
if (flccw != UNDEF) m_fnei[flccw][jlccw2] = flclw;
|
|
if (flclw != UNDEF) m_fnei[flclw][(jlclw0+1)%3] = flccw;
|
|
if (frccw != UNDEF) m_fnei[frccw][(jrccw+2)%3] = frclw;
|
|
if (frclw != UNDEF) m_fnei[frclw][jrclw1] = frccw;
|
|
|
|
/*
|
|
* 6) Propagate wedges id's across collapsed faces if can go thru.
|
|
* ---------------------------------------------------------------
|
|
*/
|
|
|
|
WORD ffl = flclw, ffr = frccw;
|
|
int jjl0 = jlclw0, jjl2 = jlclw2, jjr = jrccw;
|
|
WORD* pwwl=pwlclw;
|
|
|
|
/*
|
|
* first go clw
|
|
*/
|
|
if (thru_l)
|
|
{
|
|
for (;;)
|
|
{
|
|
*pwwl = wlccw;
|
|
if (ffl == ffr)
|
|
{
|
|
ffl = ffr = UNDEF; // all wedges seen
|
|
break;
|
|
}
|
|
ffl = m_fnei[ffl][jjl2];
|
|
if (ffl == UNDEF) break;
|
|
gather_vf_j0j2pw(vt, ffl, jjl0, jjl2, pwwl);
|
|
if (*pwwl != wlclw) break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* now go ccw from other side
|
|
*/
|
|
if ((ffr != UNDEF) && thru_r)
|
|
{
|
|
WORD* pw = &(m_farray[ffr].w[jjr]);
|
|
for (;;)
|
|
{
|
|
*pw = wrclw;
|
|
if (ffr == ffl)
|
|
{
|
|
ffl = ffr = UNDEF; // all wedges seen
|
|
break;
|
|
}
|
|
ffr = m_fnei[ffr][(jjr+1)%3];
|
|
if (ffr == UNDEF) break;
|
|
gather_vf_jpw (vt, ffr, jjr, pw);
|
|
if (*pw != wrccw) break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* 7) Identify those wedges that will need to be updated to vs.
|
|
* ------------------------------------------------------------
|
|
* (wmodif may contain some duplicates)
|
|
*/
|
|
|
|
PArray<WORD,10> ar_wmodif;
|
|
if (ffl!=UNDEF)
|
|
{
|
|
for (;;)
|
|
{
|
|
int w = *pwwl;
|
|
ar_wmodif += w;
|
|
if (ffl == ffr)
|
|
{
|
|
ffl = ffr = UNDEF;
|
|
break;
|
|
}
|
|
|
|
ffl = m_fnei[ffl][jjl2];
|
|
if (ffl == UNDEF) break;
|
|
gather_vf_j0j2pw (vt, ffl, jjl0, jjl2, pwwl);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* 8) Update wedge vertices to vs.
|
|
* -------------------------------
|
|
*/
|
|
|
|
for (int i=0; i<ar_wmodif.num(); ++i)
|
|
{
|
|
// _wedges[w].vertex=vs;
|
|
WORD w = ar_wmodif[i];
|
|
WedgeListDelete(w);
|
|
m_varray[w] = m_varray[vs];
|
|
m_wedgelist[w] = m_wedgelist[vs];
|
|
m_wedgelist[vs] = w;
|
|
}
|
|
|
|
/*
|
|
* 9) Update vertex attributes.
|
|
* ----------------------------
|
|
*/
|
|
|
|
float vsx, vsy, vsz;
|
|
switch (ii)
|
|
{
|
|
case 2:
|
|
glvs.x = m_varray[vs].x - vspl.vad_small[0];
|
|
glvs.y = m_varray[vs].y - vspl.vad_small[1];
|
|
glvs.z = m_varray[vs].z - vspl.vad_small[2];
|
|
break;
|
|
case 0:
|
|
glvs.x = glvt.x - vspl.vad_small[0];
|
|
glvs.y = glvt.y - vspl.vad_small[1];
|
|
glvs.z = glvt.z - vspl.vad_small[2];
|
|
break;
|
|
case 1:
|
|
glvs.x = glvt.x - vspl.vad_large[0] - vspl.vad_small[0];
|
|
glvs.y = glvt.y - vspl.vad_large[1] - vspl.vad_small[1];
|
|
glvs.z = glvt.z - vspl.vad_large[2] - vspl.vad_small[2];
|
|
break;
|
|
default:
|
|
throw CBadVsplitCode();
|
|
}
|
|
|
|
/*
|
|
* 10) update all wedges sharing vs with it's coordinates
|
|
* ------------------------------------------------------
|
|
*/
|
|
|
|
WORD p = vs;
|
|
do
|
|
{
|
|
m_varray[p] = glvs;
|
|
p = m_wedgelist[p];
|
|
}
|
|
while (p!=vs);
|
|
|
|
/*
|
|
* 11) Udpate wedge attributes. they are currently predicted exactly.
|
|
* ------------------------------------------------------------------
|
|
*/
|
|
|
|
GLwedgeAttrib awvtfr, awvsfr;
|
|
//GLvertex awvtfrV, awvsfrV;
|
|
|
|
if (isr)
|
|
{
|
|
//awvtfrV = m_varray[wvtfr];
|
|
awvtfr.n = m_narray[wvtfr];
|
|
awvtfr.t = m_tarray[wvtfr];
|
|
|
|
//awvsfrV = m_varray[wvsfr];
|
|
awvsfr.n = m_narray[wvsfr];
|
|
awvsfr.t = m_tarray[wvsfr];
|
|
}
|
|
|
|
int problem = 0;
|
|
if (isl)
|
|
{
|
|
int nt = !(code&Vsplit::T_LSAME);
|
|
int ns = !(code&Vsplit::S_LSAME);
|
|
if (nt && ns)
|
|
{
|
|
problem = 1;
|
|
}
|
|
else
|
|
{
|
|
switch (ii)
|
|
{
|
|
case 2:
|
|
if (!thru_l)
|
|
{
|
|
m_narray[wvtfl] = m_narray[wvsfl];
|
|
m_tarray[wvtfl] = m_tarray[wvsfl];
|
|
}
|
|
break;
|
|
case 0:
|
|
m_narray[wvsfl] = m_narray[wvtfl];
|
|
m_tarray[wvsfl] = m_tarray[wvtfl];
|
|
break;
|
|
case 1:
|
|
sub_noreflect (wvsfl, wvtfl, vspl.ar_wad[0]);
|
|
if (!thru_l)
|
|
{
|
|
m_narray[wvtfl] = m_narray[wvsfl];
|
|
m_tarray[wvtfl] = m_tarray[wvsfl];
|
|
}
|
|
break;
|
|
default:
|
|
throw CBadVsplitCode();
|
|
}
|
|
}
|
|
}
|
|
|
|
if (isr)
|
|
{
|
|
int nt = !(code&Vsplit::T_RSAME);
|
|
int ns = !(code&Vsplit::S_RSAME);
|
|
int ut = !(code&Vsplit::T_CSAME);
|
|
int us = !(code&Vsplit::S_CSAME);
|
|
|
|
if (problem || us || ut)
|
|
{
|
|
switch (ii) {
|
|
case 2:
|
|
/*
|
|
* If thru_r, then wvtfr & wrccw no longer exist.
|
|
* This may be duplicating some work already done for isl.
|
|
*/
|
|
if (!nt && !thru_r)
|
|
{
|
|
m_narray[wvtfr] = awvsfr.n;
|
|
m_tarray[wvtfr] = awvsfr.t;
|
|
}
|
|
break;
|
|
case 0:
|
|
// This may be duplicating some work already done for isl.
|
|
if (!ns)
|
|
{
|
|
m_narray[wvsfr] = awvtfr.n;
|
|
m_tarray[wvsfr] = awvtfr.t;
|
|
}
|
|
break;
|
|
case 1:
|
|
{
|
|
GLwedgeAttrib wa;
|
|
interp(wa, awvsfr, awvtfr, 0.5f, 0.5f);
|
|
if (!ns)
|
|
{
|
|
m_narray[wvsfr] = wa.n;
|
|
m_tarray[wvsfr] = wa.t;
|
|
}
|
|
if (!nt && !thru_r)
|
|
{
|
|
m_narray[wvtfr] = wa.n;
|
|
m_tarray[wvtfr] = wa.t;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
throw CBadVsplitCode();
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* 12) Remove wedges.
|
|
* ------------------
|
|
*/
|
|
|
|
if (isr && (code&Vsplit::R_NEW))
|
|
{
|
|
WORD w = --m_numWedges; // wvrfr
|
|
WedgeListDelete(w);
|
|
}
|
|
|
|
if (code&Vsplit::L_NEW)
|
|
{
|
|
WORD w = --m_numWedges; // wvlfl
|
|
WedgeListDelete(w);
|
|
}
|
|
|
|
if (isr && (!(code&Vsplit::S_CSAME) && !(code&Vsplit::S_RSAME)))
|
|
{
|
|
WORD w = --m_numWedges; // wvsfr
|
|
WedgeListDelete(w);
|
|
}
|
|
|
|
if ((!(code&Vsplit::S_LSAME) && (!(code&Vsplit::S_CSAME) ||
|
|
!(code&Vsplit::S_RSAME))))
|
|
{
|
|
WORD w = --m_numWedges; // wvsfl
|
|
WedgeListDelete(w);
|
|
}
|
|
|
|
if (isr && (!(code&Vsplit::T_CSAME) && !(code&Vsplit::T_RSAME)))
|
|
{
|
|
WORD w = --m_numWedges; // wvtfr
|
|
WedgeListDelete(w);
|
|
}
|
|
|
|
if ((!(code&Vsplit::T_LSAME) && (!(code&Vsplit::T_CSAME) ||
|
|
!(code&Vsplit::T_RSAME))))
|
|
{
|
|
WORD w = --m_numWedges; // wvtfl
|
|
WedgeListDelete(w);
|
|
}
|
|
|
|
int was_wnl = isl && (code&Vsplit::T_LSAME) && (code&Vsplit::S_LSAME);
|
|
if (isr && (code&Vsplit::T_RSAME) && (code&Vsplit::S_RSAME) &&
|
|
!(was_wnl && (code&Vsplit::T_CSAME)))
|
|
{
|
|
WORD w = --m_numWedges; // wrccw
|
|
WedgeListDelete(w);
|
|
}
|
|
|
|
if (was_wnl)
|
|
{
|
|
WORD w = --m_numWedges; // wlclw
|
|
WedgeListDelete(w);
|
|
}
|
|
}
|
|
|
|
void CAugGlMesh::sub_reflect(WORD a, const GLwedgeAttrib& abase,
|
|
const WEDGEATTRD& ad)
|
|
{
|
|
/*
|
|
* note: may have abase==a -> not really const
|
|
* dr == -d +2*(d.n)n
|
|
* an = n + dr
|
|
* optimized: a.normal=-d+((2.f)*dot(d,n)+1.f)*n;
|
|
*/
|
|
|
|
register float vdot = ad[0]*abase.n.x + ad[1]*abase.n.y + ad[2]*abase.n.z;
|
|
register float vdot2p1 = vdot * 2.0f + 1.0f;
|
|
|
|
m_narray[a].x = -ad[0] + vdot2p1*abase.n.x;
|
|
m_narray[a].y = -ad[1] + vdot2p1*abase.n.y;
|
|
m_narray[a].z = -ad[2] + vdot2p1*abase.n.z;
|
|
|
|
m_tarray[a].s = abase.t.s - ad[3];
|
|
m_tarray[a].t = abase.t.t - ad[4];
|
|
}
|
|
|
|
|
|
void CAugGlMesh::sub_noreflect(WORD a, WORD abase, const WEDGEATTRD& ad)
|
|
{
|
|
m_narray[a].x = m_narray[abase].x - ad[0];
|
|
m_narray[a].y = m_narray[abase].y - ad[1];
|
|
m_narray[a].z = m_narray[abase].z - ad[2];
|
|
|
|
m_tarray[a].s = m_tarray[abase].s - ad[3];
|
|
m_tarray[a].t = m_tarray[abase].t - ad[4];
|
|
}
|
|
|
|
|
|
void interp(GLwedgeAttrib& a, const GLwedgeAttrib& a1,
|
|
const GLwedgeAttrib& a2, float f1, float f2)
|
|
{
|
|
if (a1.n.x==a2.n.x && a1.n.y==a2.n.y && a1.n.z==a2.n.z)
|
|
{
|
|
a.n = a1.n;
|
|
}
|
|
else
|
|
{
|
|
a.n.x = f1*a1.n.x + f2*a2.n.x;
|
|
a.n.y = f1*a1.n.y + f2*a2.n.y;
|
|
a.n.z = f1*a1.n.z + f2*a2.n.z;
|
|
float denom = (float) sqrt ((double)(a.n.x*a.n.x + a.n.y*a.n.y +
|
|
a.n.z*a.n.z));
|
|
if (denom!=0)
|
|
{
|
|
a.n.x/=denom;
|
|
a.n.y/=denom;
|
|
a.n.z/=denom;
|
|
}
|
|
}
|
|
a.t.s = f1*a1.t.s + f2*a2.t.s;
|
|
a.t.t = f1*a1.t.t + f2*a2.t.t;
|
|
}
|
|
|
|
void CAugGlMesh::gather_vf_jw (WORD v, WORD f, int& j, WORD& w) const
|
|
{
|
|
j = get_jvf (v,f);
|
|
w = (m_farray[f]).w[j];
|
|
}
|
|
|
|
void CAugGlMesh::gather_vf_j0j2pw(WORD v, WORD f, int& j0, int& j2, WORD*& pw)
|
|
{
|
|
j0 = get_jvf (v,f);
|
|
pw = &(m_farray[f]).w[j0];
|
|
j2 = (j0 + 2) % 3;
|
|
}
|
|
|
|
void CAugGlMesh::gather_vf_j2w(WORD v, WORD f, int& j2, WORD& w) const
|
|
{
|
|
WORD j = get_jvf (v,f);
|
|
w = (m_farray[f]).w[j];
|
|
j2 = (j + 2) % 3;
|
|
}
|
|
|
|
void CAugGlMesh::gather_vf_j1w (WORD v, WORD f, int& j1, WORD& w) const
|
|
{
|
|
WORD j = get_jvf(v,f);
|
|
w = (m_farray[f]).w[j];
|
|
j1 = (j + 1) % 3;
|
|
}
|
|
|
|
void CAugGlMesh::gather_vf_jpw(WORD v, WORD f, int& j, WORD*& pw)
|
|
{
|
|
j = get_jvf(v,f);
|
|
pw = &(m_farray[f]).w[j];
|
|
}
|
|
|
|
WORD CAugGlMesh::MatidOfFace(WORD f)
|
|
{
|
|
//Binary search helps if there are a lot of materials
|
|
for (WORD i=1; i<m_numMaterials; ++i)
|
|
if (f < m_matpos[i])
|
|
return i-1;
|
|
return m_numMaterials-1;
|
|
|
|
//throw CBadFace();
|
|
//return 0; // never
|
|
}
|
|
|