/****************************************************************************** Write out a jot .sm file. ******************************************************************************/ void write_sm() { LMESHptr mesh = make_shared<LMESH>(); int i=0; //******** Build the mesh ******** err_adv(debug, "read ply file: %d vertices, %d faces\n", nverts, nfaces); err_adv(debug, "building mesh:"); // Add vertices to mesh err_adv(debug, " adding vertices..."); for (i = 0; i < nverts; i++) mesh->add_vertex(Wpt(vlist[i]->x, vlist[i]->y, vlist[i]->z)); err_adv(debug, " done\n"); // Add per-vertex colors if needed if (per_vertex_color) { err_adv(debug, " adding colors..."); for (i = 0; i < nverts; i++) mesh->bv(i)->set_color(COLOR(vlist[i]->r, vlist[i]->g, vlist[i]->b)); err_adv(debug, " done\n"); } // Add faces err_adv(debug, " adding faces..."); for (i = 0; i < nfaces; i++) add_face(mesh, flist[i]); err_adv(debug, " done\n"); //******** Filter the mesh ******** err_adv(debug, "filtering mesh..."); // Remove any isolated vertices for (i=mesh->nverts()-1; i>=0; i--) { if (mesh->bv(i)->degree() == 0) { mesh->remove_vertex(mesh->bv(i)); } } mesh->changed(); // Remove duplicate vertices while we're at it mesh->remove_duplicate_vertices(false); // don't keep the bastards // Check for consistent orientation of normals bool is_bad = false; for (i=0; i<mesh->nedges(); i++) if (!mesh->be(i)->consistent_orientation()) is_bad = true; if (is_bad) err_msg("Warning: inconsistently oriented triangles -- can't fix"); // Optional: recenter mesh if (Config::get_var_bool("JOT_RECENTER")) mesh->recenter(); // Optional: print stats if (Config::get_var_bool("JOT_PRINT_MESH")) mesh->print(); err_adv(debug, "done\n"); //******** Write mesh ******** err_adv(debug, "writing mesh..."); mesh->write_stream(cout); err_adv(debug, "done\n"); }
void fit(LMESHptr& mesh, bool do_gauss_seidel) { if (mesh->empty()) return; // time this stop_watch clock; double max_err = mesh->get_bb().dim().length() * 1e-5; int n = mesh->nverts(); // get original control point locations Wpt_list C(n); // original control points Wpt_list L(n); // current limit points for (int i=0; i<n; i++) { C += mesh->bv(i)->loc(); L += Wpt::Origin(); } // do 50 iterations... double prev_err = 0; for (int k=0; k<50; k++) { double err = 0; if (do_gauss_seidel) { // Gauss-Seidel iteration: use updated values from the // current iteration as they are computed... for (int j=0; j<n; j++) { // don't need that L[] array... Wpt limit; mesh->lv(j)->limit_loc(limit); Wvec delt = C[j] - limit; err += delt.length(); mesh->bv(j)->offset_loc(delt); } } else { // compute the new offsets from the offsets computed in the // previous iteration int j; for (j=0; j<n; j++) mesh->lv(j)->limit_loc(L[j]); for (j=0; j<n; j++) { Wvec delt = C[j] - L[j]; err += delt.length(); mesh->bv(j)->offset_loc(delt); } } // compute the average error: err /= n; if (prev_err != 0) { err_msg("Iter %d: avg error: %f, reduction: %f", k, err, err/prev_err); } else { err_msg("Iter %d: avg error: %f", k, err); } prev_err = err; if (err < max_err) break; } err_msg("fitting took %.2f seconds", clock.elapsed_time()); }