/************************************************************************ Adjacency model representation. $Id: AdjModel.cxx,v 1.1 1997/06/25 15:24:52 garland Exp $ Adapted from: mlab: (Id: polymodel.cc,v 1.21 1997/02/06 16:34:14 garland Exp) via simplif: (Id: polymodel.cc,v 1.5 1997/02/25 20:36:36 garland Exp) ************************************************************************/ #include "AdjModel.h" using namespace simplif; int Model::in_Vertex(const Vec3& p) { Vertex *v = newVertex(p[X], p[Y], p[Z]); bounds.addPoint(p); return vertCount() - 1; } int Model::in_Normal(const Vec3& n) { normals.add(n); return normCount()-1; } int Model::in_TexCoord(const Vec2& t) { texcoords.add(t); return texcoordCount()-1; } int Model::in_Face(int a, int b, int c, int n1, int n2, int n3, int t1, int t2, int t3) { Vertex *v1 = vertices(a-1); Vertex *v2 = vertices(b-1); Vertex *v3 = vertices(c-1); Face *t = newFace(v1, v2, v3); t->normals[0] = n1; t->normals[1] = n2; t->normals[2] = n3; t->texcoords[0] = t1; t->texcoords[1] = t2; t->texcoords[2] = t3; return faceCount() - 1; } int Model::miin_Face(int a, int b, int c) { Vertex *v1 = vertices(a); Vertex *v2 = vertices(b); Vertex *v3 = vertices(c); Face *t = newFace(v1, v2, v3); t->normals[0] = a; t->normals[1] = b; t->normals[2] = c; t->texcoords[0] = a; t->texcoords[1] = b; t->texcoords[2] = c; return faceCount() - 1; } #ifdef SUPPORT_FCOLOR int Model::in_FColor(const Vec3& c) { Face *f = faces(faces.length()-1); if( !f->props ) { f->props = new FProp; } f->props->color = c; return 0; } #endif #ifdef SUPPORT_VCOLOR int Model::in_VColor(const Vec3& c) { Vertex *v = vertices(vertices.length()-1); if( !v->props ) { v->props = new VProp; } v->props->color = c; return 0; } #endif Vec3 Model::synthesizeNormal(Vertex *v) { Vec3 n(0,0,0); int n_count = 0; edge_buffer& edges = v->edgeUses(); for(int i=0; ifaceUses(); for(int j=0; jplane().normal(); n_count++; } } if( n_count ) { n /= (real)n_count; } else { std::cerr << "Vertex with no normals!!: " << v->uniqID; std::cerr << " / " << v->tempID << std::endl; } return n; } //////////////////////////////////////////////////////////////////////// // // Model Transmogrification: // // These routines are the basic model munging procedures. // All model simplification is implemented in terms of these // transmogrification primitives. //////////////////////////////////////////////////////////////////////// Vertex *Model::newVertex(real x, real y, real z) { Vertex *v = new Vertex(x, y, z); v->vID = v->uniqID = vertices.add(v); /* if( logfile && selected_output&OUTPUT_MODEL_DEFN ) *logfile << "v " << x << " " << y << " " << z << std::endl; */ validVertCount++; return v; } Edge *Model::newEdge(Vertex *a, Vertex *b) { Edge *e = new Edge(a, b); e->uniqID = edges.add(e); e->sym()->uniqID = e->uniqID; validEdgeCount++; return e; } static Edge *get_edge(Model *m, Vertex *org, Vertex *v) { edge_buffer& edge_uses = org->edgeUses(); for (int i=0; idest() == v ) { return edge_uses(i); } } Edge *e = m->newEdge(org, v); return e; } Face *Model::newFace(Vertex *v1, Vertex *v2, Vertex *v3) { Edge *e0 = get_edge(this, v1, v2); // v1->edgeTo(m, v2); Edge *e1 = get_edge(this, v2, v3); // v2->edgeTo(m, v3); Edge *e2 = get_edge(this, v3, v1); // v3->edgeTo(m, v1); Face *t = new Face(e0, e1, e2); t->uniqID = faces.add(t); /* if( logfile && selected_output&OUTPUT_MODEL_DEFN ) *logfile << "f " << v1->uniqID+1 << " " << v2->uniqID+1 << " " << v3->uniqID+1 << std::endl; */ validFaceCount++; return t; } void Model::killVertex(Vertex *v) { if( v->isValid() ) { /* if( logfile && selected_output&OUTPUT_CONTRACTIONS ) *logfile << "v- " << v->uniqID+1 << std::endl; */ v->kill(); validVertCount--; } } void Model::killEdge(Edge *e) { if( e->isValid() ) { e->kill(); validEdgeCount--; } } void Model::killFace(Face *f) { if( f->isValid() ) { /* if( logfile && selected_output&OUTPUT_CONTRACTIONS ) *logfile << "f- " << f->uniqID+1 << std::endl; */ f->kill(); validFaceCount--; } } void Model::reshapeVertex(Vertex *v, real x, real y, real z) { v->set(x, y, z); #ifdef LOG_LOWLEVEL_OPS if( logfile ) { *logfile << "v! " << v->uniqID+1 << " " << x << " " << y << " " << z << endl; } #endif } void Model::remapVertex(Vertex *from, Vertex *to) { from->remapTo(to); #ifdef LOG_LOWLEVEL_OPS if( logfile ) { *logfile << "v> " << from->uniqID+1 << " " << to->uniqID+1 << endl; } #endif } void Model::contract(Vertex *v1, const vert_buffer& rest, const Vec3& to, face_buffer& changed) { int i; /* if( logfile && selected_output&OUTPUT_CONTRACTIONS ) { *logfile << "v% (" << v1->uniqID+1; for(i=0; iuniqID+1; *logfile << ") " << to[X] << " " << to[Y] << " " << to[Z] << std::endl; } */ // // Collect all the faces that are going to be changed // contractionRegion(v1, rest, changed); reshapeVertex(v1, to[X], to[Y], to[Z]); for(i=0; iremapTo(v1); } removeDegeneracy(changed); } void Model::maybeFixFace(Face *F) { // // Invalid faces do not need to be fixed. #ifdef SAFETY assert( F->isValid() ); #endif Vertex *v0=F->vertex(0); Vertex *v1=F->vertex(1); Vertex *v2=F->vertex(2); Edge *e0 = F->edge(0); Edge *e1 = F->edge(1); Edge *e2 = F->edge(2); bool a=(v0 == v1), b=(v0 == v2), c=(v1 == v2); if( a && c ) { // This triangle has been reduced to a point killEdge(e0); killEdge(e1); killEdge(e2); killFace(F); } // // In the following 3 cases, the triangle has become an edge else if( a ) { killEdge(e0); e1->remapTo(e2->sym()); killFace(F); } else if( b ) { killEdge(e2); e0->remapTo(e1->sym()); killFace(F); } else if( c ) { killEdge(e1); e0->remapTo(e2->sym()); killFace(F); } else { // This triangle remains non-degenerate /* // SUS: recalcular la normal en los triangulos cambiados no degenerados simplif::Vertex * auxv0 = F->vertex(0); simplif::Vertex * auxv1 = F->vertex(1); simplif::Vertex * auxv2 = F->vertex(2); simplif::Vec3 vd1(auxv1->operator[](simplif::X) - auxv0->operator[](simplif::X), auxv1->operator[](simplif::Y) - auxv0->operator[](simplif::Y), auxv1->operator[](simplif::Z) - auxv0->operator[](simplif::Z)); simplif::Vec3 vd2(auxv2->operator[](simplif::X) - auxv0->operator[](simplif::X), auxv2->operator[](simplif::Y) - auxv0->operator[](simplif::Y), auxv2->operator[](simplif::Z) - auxv0->operator[](simplif::Z)); simplif::unitize(vd1); simplif::unitize(vd2); simplif::Vec3 vn = vd1 ^ vd2; simplif::unitize(vn); //auxf->vertex_normals[0] = vn; //auxf->vertex_normals[1] = vn; //auxf->vertex_normals[2] = vn; F->vertex_normals[0][simplif::X] = vn[simplif::X]; F->vertex_normals[0][simplif::Y] = vn[simplif::Y]; F->vertex_normals[0][simplif::Z] = vn[simplif::Z]; F->vertex_normals[1][simplif::X] = vn[simplif::X]; F->vertex_normals[1][simplif::Y] = vn[simplif::Y]; F->vertex_normals[1][simplif::Z] = vn[simplif::Z]; F->vertex_normals[2][simplif::X] = vn[simplif::X]; F->vertex_normals[2][simplif::Y] = vn[simplif::Y]; F->vertex_normals[2][simplif::Z] = vn[simplif::Z];*/ } } void Model::removeDegeneracy(face_buffer& changed) { for(int i=0; i v1. This accomplishes the topological change that we want. v2->remapTo(v1); // std::cout << "Contract(QslimInds): " << v2->validID() << " --> " << v1->validID() << std::endl; removeDegeneracy(changed); } /* ostream& operator<<(ostream& out, Model& M) { int i; int uniqVerts = 0; out << "#$SMF 1.0" << endl; out_annotate(out, M); for(i=0; iisValid() ) { M.vertex(i)->tempID = ++uniqVerts; out_annotate(out, M.vertex(i)); const Vertex& v = *M.vertex(i); out << "v " << v[X] << " " << v[Y] << " " << v[Z] << endl; #ifdef SUPPORT_VCOLOR if( v.props ) out << ":vc " << v.props->color[X] << " " << v.props->color[Y] << " " << v.props->color[Z] << endl; #endif } else M.vertex(i)->tempID = -1; } for(i=0; iisValid() ) { Face *f = M.face(i); out_annotate(out, f); out << "f "; Vertex *v0 = (Vertex *)f->vertex(0); Vertex *v1 = (Vertex *)f->vertex(1); Vertex *v2 = (Vertex *)f->vertex(2); #ifdef SAFETY assert( v0->tempID >= 0 ); assert( v1->tempID >= 0 ); assert( v2->tempID >= 0 ); #endif out<tempID << " " <tempID<< " " <tempID<< endl; #ifdef SUPPORT_FCOLOR if( f->props ) out << ":fc " << f->props->color[X] << " " << f->props->color[Y] << " " << f->props->color[Z] << endl; #endif } } return out; } */