#include "TxsMesh.h" #include "TxsQuadFace.h" using namespace TXS; void TxsMesh::detachVertex(TxsVertex *v) { if(v->getNumIncidentFaces() != 0) { __ERROR__("tried to detach a vertex that still had some faces attached!"); } else { this->verts.remove(v); delete v; } } /* * Disconnects the given triangle * from all its vertices in the connectivity * graph. It does NOT delete the TxsVertex objects, * of course, so isolated verts may exist * But it does delete the face objects from the list. */ void TxsMesh::detachFace(TxsFace *f) { // go thru each vert for(int iv = 0; iv < f->getNumVerts(); ++iv) { TxsVertex *v = f->getVertexMod(iv); // remove this face from v's inc faces list list &incFaces = v->getIncidentFacesRef(); incFaces.remove(f); } // lastly, kill the face and let it go this->faces.remove(f); delete f; } void TxsMesh::attachFace(TxsFace *f) { // go thru each of the face's verts for(int iv = 0; iv < f->getNumVerts(); ++iv) { TxsVertex *v = f->getVertexMod(iv); // add it list &incFaces = v->getIncidentFacesRef(); incFaces.push_back(f); } this->faces.push_back(f); } /* * This will make all necessary adjustments to * the mesh's connectivity graph to collapse into the quad. * This means: * removing collpased tris from the inc-face lists of their vertices * removing tris from this->faces * deleting the tri-objects * creating the new quad face, adding to this->face * adding quad face to the inc-faces lists of its verts * removing the val4 vert from this->verts, and deleting it */ void TxsMesh::collapse_valence4_vert_tris_into_quad(TxsVertex *vert) { // accumulate the 4 vertices of the new quad // by walking around the vertice's triangles vector quadVerts; for(int i = 0; i < 4; ++i) { quadVerts.push_back(NULL); } list::iterator f_iter; list &incFaces = vert->getIncidentFacesRef(); TxsFace *f = NULL; // start with VB of the first face f_iter = incFaces.begin(); f = *f_iter; quadVerts[0] = f->getVertexBefore(vert); // it's gone! this->detachFace(f); __LOG__("inc faces: " << incFaces.size()); // now find the rest for(int iQuadVert = 1; iQuadVert < 4; ++iQuadVert) { TxsVertex *prevVB = quadVerts[iQuadVert-1]; __STAT__("finding vert " << prevVB << " at " << prevVB->getPoint()); // find the face with VA == previous VB for(f_iter = incFaces.begin(); f_iter != incFaces.end(); ++f_iter) { f = *f_iter; TxsVertex *VA = f->getVertexAfter(vert); __STAT__("considering vert " << VA << " at " << VA->getPoint()); if(VA == prevVB) { // this is the next tri! // use its VA next quadVerts[iQuadVert] = f->getVertexBefore(vert); this->detachFace(f); __STAT__("found vert"); break; } } if(quadVerts[iQuadVert] == NULL) { __ERROR__("did not find a complete manifold disc!"); exit(1); } } // kill the vert this->detachVertex(vert); // lastly, create the quad face and add it // 2006-04-30 (19-14) - using TxsQuadFace! TxsFace *quad = new TxsQuadFace(&quadVerts, this->getUnitsPerPixel()); this->attachFace(quad); } void TxsMesh::collapse_tris_into_quads_around_valence_4_verts() { // collect all val 4 verts list val4Verts; list::iterator v_iter; for(v_iter = this->verts.begin(); v_iter != this->verts.end(); ++v_iter) { TxsVertex* v = *v_iter; if(v->getNumIncidentFaces() == 4) { val4Verts.push_back(v); } } __STAT__("got " << val4Verts.size() << " val4 verts"); // now collapse the tris around the val4 verts for(v_iter = val4Verts.begin(); v_iter != val4Verts.end(); ++v_iter) { TxsVertex* v = *v_iter; this->collapse_valence4_vert_tris_into_quad(v); } __STAT__("graph changes done"); // finally, do post-processing this->doneFeedingTris(); // TODO - do some checks // make sure all faces have 4 verts list::iterator f_iter; for(f_iter = this->faces.begin(); f_iter != this->faces.end(); ++f_iter) { TxsFace* f = *f_iter; if(f->getNumVerts() != 4) { __ERROR__("after val4 collapse, face @" << f << " still has " << f->getNumVerts() << " verts!"); } } } void TxsMesh::phongShadeAllFaces() { list::iterator f_iter; for(f_iter = this->faces.begin(); f_iter != this->faces.end(); ++f_iter) { TxsFace* f = *f_iter; f->fillTextureWithPhongShading(); } } void TxsMesh::addFace(list &faceVerts) { // The face object will adopt this list vector *vertObjs = new vector(); // accumulate vertex objects for this face: // for each vert of the face, either find it in // the existing list or create a new vert object list::iterator v_iter; for(v_iter = faceVerts.begin(); v_iter != faceVerts.end(); ++v_iter) { Point faceVert = *v_iter; // Is it in our graph already? Try to find it TxsVertex *vobj = findVertexAt(faceVert); if(vobj == NULL) { // create one and add it to the conn graph vobj = new TxsVertex(faceVert); this->verts.push_back(vobj); if(this->verts.size() == 1) { // this was the first vert // set it as mins/maxs this->mins = faceVert; this->maxs = faceVert; } else { this->stretchMinsMaxs(faceVert); } __DBd("Created vert " << vobj->getPoint()); } // Add the vobj to the face obj's list vertObjs->push_back(vobj); } // put the verts list into a new face object // choose the face object type depending on # of verts TxsFace *faceObj = NULL; if(vertObjs->size() == 3) { faceObj = new TxsFace(vertObjs, this->getUnitsPerPixel()); } else if(vertObjs->size() == 4) { faceObj = new TxsQuadFace(vertObjs, this->getUnitsPerPixel()); } else { __ERROR__("tried to add a face that wasn't a tri or a quad! num verts: " << vertObjs->size()); exit(1); } this->faces.push_back(faceObj); // now, make sure to update the incident faces for each vert used vector::iterator vit; for(vit = vertObjs->begin(); vit != vertObjs->end(); ++vit) { TxsVertex* vertObj = *vit; vertObj->addIncidentFace(faceObj); __DBd("added inc face to vert " << vertObj << " at pt " << vertObj->getPoint()); } // finally, we don't need the verts anymore. the TxsFace object keeps its own copy. delete vertObjs; }