face_t new_tetrahedron() { edge_t edges[3]; vertex_t tv0, tv1, tv2, tv3; vertex_t verts[4]; face_t tf012, tf132, tf023, tf031; face_t tetrahedron; /* note tv0 = new_vert(0, 0, 0, "v0"); won't work -- ints! yikes */ /* The nice thing about string names is you can represent the topology (like name an e01 if it goes from v. 0 to v. 1 and e20 if it goes from 2 to 0.) hmmm */ tv0 = new_vert(0.0, 0.0, 0.0,0); verts[0] = tv0; tv1 = new_vert(2.0, 2.0, 0.0,1); verts[1] = tv1; tv2 = new_vert(2.0, 0.0, 2.0,2); verts[2] = tv2; tv3 = new_vert(0.0, 2.0, 2.0,3); verts[3] = tv3; edges[0] = new_edge(tv0, tv1,0); edges[1] = new_edge(tv1, tv2, 1); edges[2] = new_edge(tv2, tv0, 2); tf012 = new_face(edges, 3, 0); edges[0] = new_edge(tv1, tv3, 3); edges[1] = new_edge(tv3, tv2, 4); edges[2] = new_edge(tv2, tv1,5); tf132 = new_face(edges, 3, 1); edges[0] = new_edge(tv0, tv2,6); edges[1] = new_edge(tv2, tv3, 7); edges[2] = new_edge(tv3, tv0, 8); tf023 = new_face(edges, 3, 2); edges[0] = new_edge(tv0, tv3,9); edges[1] = new_edge(tv3, tv1, 10); edges[2] = new_edge(tv1, tv0, 11); tetrahedron = tf012; tf012->next_face = tf132; tf132->next_face = tf023; tf023->next_face = tf031; tf031->next_face = tf012; return(tetrahedron); }
void Surface_mesh:: split(Face f, Vertex v) { /* Split an arbitrary face into triangles by connecting each vertex of fh to vh. - fh will remain valid (it will become one of the triangles) - the halfedge handles of the new triangles will point to the old halfeges */ Halfedge hend = halfedge(f); Halfedge h = next_halfedge(hend); Halfedge hold = new_edge(to_vertex(hend), v); set_next_halfedge(hend, hold); set_face(hold, f); hold = opposite_halfedge(hold); while (h != hend) { Halfedge hnext = next_halfedge(h); Face fnew = new_face(); set_halfedge(fnew, h); Halfedge hnew = new_edge(to_vertex(h), v); set_next_halfedge(hnew, hold); set_next_halfedge(hold, h); set_next_halfedge(h, hnew); set_face(hnew, fnew); set_face(hold, fnew); set_face(h, fnew); hold = opposite_halfedge(hnew); h = hnext; } set_next_halfedge(hold, hend); set_next_halfedge(next_halfedge(hend), hold); set_face(hold, f); set_halfedge(v, hold); }
void quake3_bsp_map::add_mesh_surface(const quake3_face& f) { shared_ptr<map_face> new_face(new basic_face()); new_face->clear(); //Get the triangles that make up this face for (int i = 0; i < f.totalMeshVertices; i += 3) { int idx1 = f.startVertexIndex + m_raw_face_index_data[f.meshVertexIndex + i]; int idx2 = f.startVertexIndex + m_raw_face_index_data[f.meshVertexIndex + i + 2]; int idx3 = f.startVertexIndex + m_raw_face_index_data[f.meshVertexIndex + i + 1]; //Add the triangle to the new face new_face->add_triangle(m_vertices[idx1], m_vertices[idx2], m_vertices[idx3]); } new_face->set_texture_index(f.texID); //Set the index to the texture array m_faces.push_back(new_face); }
void Surface_mesh:: triangulate(Face f) { /* Split an arbitrary face into triangles by connecting each vertex of fh after its second to vh. - fh will remain valid (it will become one of the triangles) - the halfedge handles of the new triangles will point to the old halfedges */ Halfedge base_h = halfedge(f); Vertex start_v = from_vertex(base_h); Halfedge next_h = next_halfedge(base_h); while (to_vertex(next_halfedge(next_h)) != start_v) { Halfedge next_next_h(next_halfedge(next_h)); Face new_f = new_face(); set_halfedge(new_f, base_h); Halfedge new_h = new_edge(to_vertex(next_h), start_v); set_next_halfedge(base_h, next_h); set_next_halfedge(next_h, new_h); set_next_halfedge(new_h, base_h); set_face(base_h, new_f); set_face(next_h, new_f); set_face(new_h, new_f); base_h = opposite_halfedge(new_h); next_h = next_next_h; } set_halfedge(f, base_h); //the last face takes the handle _fh set_next_halfedge(base_h, next_h); set_next_halfedge(next_halfedge(next_h), base_h); set_face(base_h, f); }
void quake3_bsp_map::add_curved_surface(const quake3_face& f) { int width = f.size[0], height = f.size[1]; //FIXME: get width and height int num_patches_wide = (width - 1) >> 1; int num_patches_high = (height - 1) >> 1; int total_patches = num_patches_high * num_patches_wide; vector<quake3_subpatch> sub_patches(total_patches); for (int y = 0; y < num_patches_high; ++y) { for (int x = 0; x < num_patches_wide; ++x) { int current_patch = y * num_patches_wide + x; for (int row = 0; row < 3; ++row) { for (int point = 0; point < 3; ++point) { //Set the vertex for each point int control_point_index = row * 3 + point; int vertex_index = (y * 2 * width + x * 2) + row * width + point; map_vertex* control_points = sub_patches[current_patch].get_control_points(); control_points[control_point_index] = m_vertices[f.startVertexIndex + vertex_index]; //m_SubPatches[currentPatch].m_ControlPoints[row * 3 + point].m_Normal.Normalize(); } } //tesselate the subpatch sub_patches[current_patch].tesselate_vertices(); } } shared_ptr<map_face> new_face(new basic_face()); for (vector<quake3_subpatch>::iterator patch = sub_patches.begin(); patch != sub_patches.end(); ++patch) { (*patch).calculate_indices(); (*patch).append_triangles_to_array(new_face->get_vertices()); } new_face->set_texture_index(f.texID); //Set the index to the texture array m_faces.push_back(new_face); }
/* one new saddle face with 4 edges */ void newsad (struct surface *this_srf, struct arc *arc1, struct arc *arc2, struct circle *circle1, struct circle *circle2, struct torus *torus_ptr, double wrap_angle) { struct vertex *vertex1, *vertex2, *vertex3, *vertex4; struct arc *arc3, *arc4; struct face *saddle_fac; struct sphere *atom1, *atom2; atom1 = circle1 -> atm; atom2 = circle2 -> atm; /* gather vertices */ vertex1 = arc1 -> vtx[0]; vertex2 = arc1 -> vtx[1]; vertex3 = arc2 -> vtx[0]; vertex4 = arc2 -> vtx[1]; /* set up arcs */ arc3 = new_arc (circle2, vertex2, vertex3, CONVEX, 0, (double) 0.0, 0L, 0L, 0L); if (error()) return; this_srf -> n_arc++; arc4 = new_arc (circle1, vertex4, vertex1, CONVEX, 0, (double) 0.0, 0L, 0L, 0L); if (error()) return; this_srf -> n_arc++; arc3 -> phi = wrap_angle; arc4 -> phi = wrap_angle; /* add convex arcs to atom list */ arc3 -> next = atom2 -> first_arc; atom2 -> first_arc = arc3; arc4 -> next = atom1 -> first_arc; atom1 -> first_arc = arc4; /* set up saddle face */ saddle_fac = new_face (NULL, SADDLE); if (error()) return; saddle_fac -> ptr.tor = torus_ptr; link_face (this_srf, saddle_fac); if (error()) return; add2face (saddle_fac, arc1, arc3, arc2, arc4); if (error()) return; }
/* free (no collision) torus saddle surface */ void free_saddle (struct surface *this_srf, struct torus *torus_ptr) { struct face *saddle_fac; struct circle *circle1, *circle2; struct arc *arc1, *arc2; struct sphere *atom1, *atom2; atom1 = (torus_ptr -> atm[0]); atom2 = (torus_ptr -> atm[1]); /* set up circles */ circle1 = new_contact_circle (this_srf, torus_ptr, 0); if (error()) return; circle2 = new_contact_circle (this_srf, torus_ptr, 1); if (error()) return; /* set up arcs */ arc1 = new_arc (circle2, NULL, NULL, CONVEX, 0, (double) 0.0, 0L, 0L, 0L); if (error()) return; this_srf -> n_arc++; arc2 = new_arc (circle1, NULL, NULL, CONVEX, 0, (double) 0.0, 0L, 0L, 0L); if (error()) return; this_srf -> n_arc++; arc1 -> phi = 2 * PI; arc2 -> phi = 2 * PI; /* add convex arcs to atom list */ arc1 -> next = atom2 -> first_arc; atom2 -> first_arc = arc1; arc2 -> next = atom1 -> first_arc; atom1 -> first_arc = arc2; /* allocate saddle face */ saddle_fac = new_face (NULL, SADDLE); if (error()) return; saddle_fac -> ptr.tor = torus_ptr; link_face (this_srf, saddle_fac); if (error()) return; add2face (saddle_fac, arc1, arc2, NULL, NULL); if (error()) return; }
/* new concave face */ void new_concave_face (struct surface *this_srf, struct probe *prb) { int k; double probe_center[3]; double vertex1_coor[3], vertex2_coor[3], vertex3_coor[3], vertex4_coor[3]; double circle1_axis[3], circle2_axis[3], circle3_axis[3], circle4_axis[3]; struct circle *circle1, *circle2, *circle3, *circle4; struct vertex *vertex1, *vertex2, *vertex3, *vertex4; struct arc *arc1, *arc2, *arc3, *arc4; struct sphere *atom1, *atom2, *atom3, *atom4; struct face *concave_fac; struct pair *torus1, *torus2, *torus3, *torus4; double dot1, dot2, dot3, dot4; char message[MAX_STRING]; struct cept *ex; if (prb -> natom > 3) { sprintf (message, "%8ld probe square concave face", prb -> number); informd (message); } else { sprintf (message, "%8ld probe triangular concave face", prb -> number); informd2 (message); } atom1 = prb -> atm[0]; atom2 = prb -> atm[1]; atom3 = prb -> atm[2]; atom4 = prb -> atm[3]; torus1 = prb -> pairs[0]; torus2 = prb -> pairs[1]; torus3 = prb -> pairs[2]; torus4 = prb -> pairs[3]; for (k = 0; k < 3; k++) probe_center[k] = prb -> center[k]; /* compute vertex coordinates */ for (k = 0; k < 3; k++) { vertex1_coor[k] = (atom1 -> radius * probe_center[k] + this_srf -> probe_radius * atom1 -> center[k]) / (atom1 -> radius + this_srf -> probe_radius); vertex2_coor[k] = (atom2 -> radius * probe_center[k] + this_srf -> probe_radius * atom2 -> center[k]) / (atom2 -> radius + this_srf -> probe_radius); vertex3_coor[k] = (atom3 -> radius * probe_center[k] + this_srf -> probe_radius * atom3 -> center[k]) / (atom3 -> radius + this_srf -> probe_radius); if (atom4 != NULL) { vertex4_coor[k] = (atom4 -> radius * probe_center[k] + this_srf -> probe_radius * atom4 -> center[k]) / (atom4 -> radius + this_srf -> probe_radius); } } /* set up vertices */ vertex1 = new_vertex (vertex1_coor, (struct sphere *) atom1, prb, NULL, NULL); if (vertex1 == NULL) return; link_vertex (this_srf, vertex1); vertex2 = new_vertex (vertex2_coor, (struct sphere *) atom2, prb, NULL, NULL); if (vertex2 == NULL) return; link_vertex (this_srf, vertex2); vertex3 = new_vertex (vertex3_coor, (struct sphere *) atom3, prb, NULL, NULL); if (vertex3 == NULL) return; link_vertex (this_srf, vertex3); if (atom4 != NULL) { vertex4 = new_vertex (vertex4_coor, (struct sphere *) atom4, prb, NULL, NULL); if (vertex4 == NULL) return; link_vertex (this_srf, vertex4); } else vertex4 = NULL; /* calculate axes and set up circles */ setup_axis (probe_center, prb -> atm[0] -> center, prb -> atm[1] -> center, circle1_axis); setup_axis (probe_center, prb -> atm[1] -> center, prb -> atm[2] -> center, circle2_axis); if (atom4 == NULL) { setup_axis (probe_center, prb -> atm[2] -> center, prb -> atm[0] -> center, circle3_axis); } else if (atom4 != NULL) { setup_axis (probe_center, prb -> atm[2] -> center, prb -> atm[3] -> center, circle3_axis); setup_axis (probe_center, prb -> atm[3] -> center, prb -> atm[0] -> center, circle4_axis); } circle1 = new_circle (probe_center, this_srf -> probe_radius, circle1_axis); if (circle1 == NULL) return; link_circle (this_srf, circle1); circle1 -> theta = 0.0; circle1 -> subtype = GREAT_SUBTYPE; circle2 = new_circle (probe_center, this_srf -> probe_radius, circle2_axis); if (circle2 == NULL) return; link_circle (this_srf, circle2); circle2 -> theta = 0.0; circle2 -> subtype = GREAT_SUBTYPE; circle3 = new_circle (probe_center, this_srf -> probe_radius, circle3_axis); if (circle3 == NULL) return; link_circle (this_srf, circle3); circle3 -> theta = 0.0; circle3 -> subtype = GREAT_SUBTYPE; if (atom4 != NULL) { circle4 = new_circle (probe_center, this_srf -> probe_radius, circle4_axis); if (circle4 == NULL) return; link_circle (this_srf, circle4); circle4 -> theta = 0.0; circle4 -> subtype = GREAT_SUBTYPE; } else circle4 = NULL; /* set up arcs */ arc1 = new_arc (circle1, vertex1, vertex2, CONCAVE, 0, (double) 0.0, 0L, 0L, 0L); if (arc1 == NULL) return; this_srf -> n_arc++; arc2 = new_arc (circle2, vertex2, vertex3, CONCAVE, 0, (double) 0.0, 0L, 0L, 0L); if (arc2 == NULL) return; this_srf -> n_arc++; if (circle4 == NULL) { arc3 = new_arc (circle3, vertex3, vertex1, CONCAVE, 0, (double) 0.0, 0L, 0L, 0L); if (arc3 == NULL) return; this_srf -> n_arc++; arc4 = NULL; } else if (circle4 != NULL) { arc3 = new_arc (circle3, vertex3, vertex4, CONCAVE, 0, (double) 0.0, 0L, 0L, 0L); if (arc3 == NULL) return; this_srf -> n_arc++; arc4 = new_arc (circle4, vertex4, vertex1, CONCAVE, 0, (double) 0.0, 0L, 0L, 0L); if (arc4 == NULL) return; this_srf -> n_arc++; } /* add arcs to tori */ arc1 -> next = torus1 -> first_arc; torus1 -> first_arc = arc1; sprintf (message, "%8ld %8ld torus: add arc", torus1 -> sph[0] -> number, torus1 -> sph[1] -> number); informd2(message); arc2 -> next = torus2 -> first_arc; torus2 -> first_arc = arc2; sprintf (message, "%8ld %8ld torus: add arc", torus2 -> sph[0] -> number, torus2 -> sph[1] -> number); informd2(message); arc3 -> next = torus3 -> first_arc; torus3 -> first_arc = arc3; sprintf (message, "%8ld %8ld torus: add arc", torus3 -> sph[0] -> number, torus3 -> sph[1] -> number); informd2(message); if (torus4 != NULL) { arc4 -> next = torus4 -> first_arc; torus4 -> first_arc = arc4; sprintf (message, "%8ld %8ld torus: add arc", torus4 -> sph[0] -> number, torus4 -> sph[1] -> number); informd(message); } /* new concave face */ concave_fac = new_face (NULL, CONCAVE); if (concave_fac == NULL) return; concave_fac -> ptr.prb = prb; concave_fac -> chi = 1; link_face (this_srf, concave_fac); add2face (concave_fac, arc1, arc2, arc3, arc4); /* back pointer for cusp corrections */ prb -> fac = concave_fac; arc1 -> fac = concave_fac; arc2 -> fac = concave_fac; arc3 -> fac = concave_fac; if (arc4 != NULL) { arc4 -> fac = concave_fac; } }
void Surface_mesh:: split(Edge e, Vertex v) { Halfedge h0 = halfedge(e, 0); Halfedge o0 = halfedge(e, 1); Vertex v2 = to_vertex(o0); Halfedge e1 = new_edge(v, v2); Halfedge t1 = opposite_halfedge(e1); Face f0 = face(h0); Face f3 = face(o0); set_halfedge(v, h0); set_vertex(o0, v); if (!is_boundary(h0)) { Halfedge h1 = next_halfedge(h0); Halfedge h2 = next_halfedge(h1); Vertex v1 = to_vertex(h1); Halfedge e0 = new_edge(v, v1); Halfedge t0 = opposite_halfedge(e0); Face f1 = new_face(); set_halfedge(f0, h0); set_halfedge(f1, h2); set_face(h1, f0); set_face(t0, f0); set_face(h0, f0); set_face(h2, f1); set_face(t1, f1); set_face(e0, f1); set_next_halfedge(h0, h1); set_next_halfedge(h1, t0); set_next_halfedge(t0, h0); set_next_halfedge(e0, h2); set_next_halfedge(h2, t1); set_next_halfedge(t1, e0); } else { set_next_halfedge(prev_halfedge(h0), t1); set_next_halfedge(t1, h0); // halfedge handle of _vh already is h0 } if (!is_boundary(o0)) { Halfedge o1 = next_halfedge(o0); Halfedge o2 = next_halfedge(o1); Vertex v3 = to_vertex(o1); Halfedge e2 = new_edge(v, v3); Halfedge t2 = opposite_halfedge(e2); Face f2 = new_face(); set_halfedge(f2, o1); set_halfedge(f3, o0); set_face(o1, f2); set_face(t2, f2); set_face(e1, f2); set_face(o2, f3); set_face(o0, f3); set_face(e2, f3); set_next_halfedge(e1, o1); set_next_halfedge(o1, t2); set_next_halfedge(t2, e1); set_next_halfedge(o0, e2); set_next_halfedge(e2, o2); set_next_halfedge(o2, o0); } else { set_next_halfedge(e1, next_halfedge(o0)); set_next_halfedge(o0, e1); set_halfedge(v, e1); } if (halfedge(v2) == h0) set_halfedge(v2, t1); }
Surface_mesh::Face Surface_mesh:: add_face(const std::vector<Vertex>& vertices) { Vertex v; unsigned int i, ii, n((int)vertices.size()), id; std::vector<Halfedge> halfedges(n); std::vector<bool> is_new(n), needs_adjust(n, false); Halfedge inner_next, inner_prev, outer_next, outer_prev, boundary_next, boundary_prev, patch_start, patch_end; // cache for set_next_halfedge and vertex' set_halfedge typedef std::pair<Halfedge, Halfedge> NextCacheEntry; typedef std::vector<NextCacheEntry> NextCache; NextCache next_cache; next_cache.reserve(3*n); // don't allow degenerated faces assert (n > 2); // test for topological errors for (i=0, ii=1; i<n; ++i, ++ii, ii%=n) { if ( !is_boundary(vertices[i]) ) { std::cerr << "Surface_meshT::add_face: complex vertex\n"; return Face(); } halfedges[i] = find_halfedge(vertices[i], vertices[ii]); is_new[i] = !halfedges[i].is_valid(); if (!is_new[i] && !is_boundary(halfedges[i])) { std::cerr << "Surface_meshT::add_face: complex edge\n"; return Face(); } } // re-link patches if necessary for (i=0, ii=1; i<n; ++i, ++ii, ii%=n) { if (!is_new[i] && !is_new[ii]) { inner_prev = halfedges[i]; inner_next = halfedges[ii]; if (next_halfedge(inner_prev) != inner_next) { // here comes the ugly part... we have to relink a whole patch // search a free gap // free gap will be between boundary_prev and boundary_next outer_prev = opposite_halfedge(inner_next); outer_next = opposite_halfedge(inner_prev); boundary_prev = outer_prev; do boundary_prev = opposite_halfedge(next_halfedge(boundary_prev)); while (!is_boundary(boundary_prev) || boundary_prev==inner_prev); boundary_next = next_halfedge(boundary_prev); assert(is_boundary(boundary_prev)); assert(is_boundary(boundary_next)); // ok ? if (boundary_next == inner_next) { std::cerr << "Surface_meshT::add_face: patch re-linking failed\n"; return Face(); } // other halfedges' handles patch_start = next_halfedge(inner_prev); patch_end = prev_halfedge(inner_next); // relink next_cache.push_back(NextCacheEntry(boundary_prev, patch_start)); next_cache.push_back(NextCacheEntry(patch_end, boundary_next)); next_cache.push_back(NextCacheEntry(inner_prev, inner_next)); } } } // create missing edges for (i=0, ii=1; i<n; ++i, ++ii, ii%=n) if (is_new[i]) halfedges[i] = new_edge(vertices[i], vertices[ii]); // create the face Face f(new_face()); set_halfedge(f, halfedges[n-1]); // setup halfedges for (i=0, ii=1; i<n; ++i, ++ii, ii%=n) { v = vertices[ii]; inner_prev = halfedges[i]; inner_next = halfedges[ii]; id = 0; if (is_new[i]) id |= 1; if (is_new[ii]) id |= 2; if (id) { outer_prev = opposite_halfedge(inner_next); outer_next = opposite_halfedge(inner_prev); // set outer links switch (id) { case 1: // prev is new, next is old boundary_prev = prev_halfedge(inner_next); next_cache.push_back(NextCacheEntry(boundary_prev, outer_next)); set_halfedge(v, outer_next); break; case 2: // next is new, prev is old boundary_next = next_halfedge(inner_prev); next_cache.push_back(NextCacheEntry(outer_prev, boundary_next)); set_halfedge(v, boundary_next); break; case 3: // both are new if (!halfedge(v).is_valid()) { set_halfedge(v, outer_next); next_cache.push_back(NextCacheEntry(outer_prev, outer_next)); } else { boundary_next = halfedge(v); boundary_prev = prev_halfedge(boundary_next); next_cache.push_back(NextCacheEntry(boundary_prev, outer_next)); next_cache.push_back(NextCacheEntry(outer_prev, boundary_next)); } break; } // set inner link next_cache.push_back(NextCacheEntry(inner_prev, inner_next)); } else needs_adjust[ii] = (halfedge(v) == inner_next); // set face handle set_face(halfedges[i], f); } // process next halfedge cache NextCache::const_iterator ncIt(next_cache.begin()), ncEnd(next_cache.end()); for (; ncIt != ncEnd; ++ncIt) set_next_halfedge(ncIt->first, ncIt->second); // adjust vertices' halfedge handle for (i=0; i<n; ++i) if (needs_adjust[i]) adjust_outgoing_halfedge(vertices[i]); return f; }