00001
00002 #include "imesh_mesh.h"
00003
00004
00005
00006 #include <vgl/vgl_polygon.h>
00007 #include <vgl/vgl_area.h>
00008
00009 #include <vcl_iostream.h>
00010
00011
00012 imesh_mesh::imesh_mesh(const imesh_mesh& other)
00013 : vbl_ref_count(),
00014 verts_((other.verts_.get()) ? other.verts_->clone() : 0),
00015 faces_((other.faces_.get()) ? other.faces_->clone() : 0),
00016 half_edges_(other.half_edges_),
00017 tex_coords_(other.tex_coords_),
00018 tex_source_(other.tex_source_),
00019 valid_tex_faces_(other.valid_tex_faces_),
00020 tex_coord_status_(other.tex_coord_status_)
00021 {
00022 }
00023
00024
00025
00026 imesh_mesh& imesh_mesh::operator=(imesh_mesh const& other)
00027 {
00028 if (this != &other) {
00029 verts_ = vcl_auto_ptr<imesh_vertex_array_base>((other.verts_.get()) ?
00030 other.verts_->clone() : 0);
00031 faces_ = vcl_auto_ptr<imesh_face_array_base>((other.faces_.get()) ?
00032 other.faces_->clone() : 0);
00033 half_edges_ = other.half_edges_;
00034 tex_coords_ = other.tex_coords_;
00035 valid_tex_faces_ = other.valid_tex_faces_;
00036 tex_coord_status_ = other.tex_coord_status_;
00037 }
00038 return *this;
00039 }
00040
00041
00042
00043
00044 void imesh_mesh::merge(const imesh_mesh& other)
00045 {
00046 const unsigned num_v = this->num_verts();
00047 const unsigned num_e = this->num_edges();
00048 faces_ = imesh_merge(*this->faces_,*other.faces_,verts_->size());
00049 verts_->append(*other.verts_);
00050
00051 if (this->has_tex_coords() == TEX_COORD_NONE)
00052 {
00053 vcl_vector<vgl_point_2d<double> > tex;
00054 if (other.has_tex_coords() == TEX_COORD_ON_VERT) {
00055 tex = vcl_vector<vgl_point_2d<double> >(num_v, vgl_point_2d<double>(0,0));
00056 }
00057 else if (other.has_tex_coords() == TEX_COORD_ON_CORNER) {
00058 tex = vcl_vector<vgl_point_2d<double> >(2*num_e, vgl_point_2d<double>(0,0));
00059 }
00060
00061 tex.insert(tex.end(), other.tex_coords().begin(), other.tex_coords().end());
00062 this->set_tex_coords(tex);
00063 }
00064 else if (this->has_tex_coords() == other.has_tex_coords())
00065 {
00066 this->tex_coords_.insert(this->tex_coords_.end(),
00067 other.tex_coords().begin(),
00068 other.tex_coords().end());
00069 }
00070
00071 if (this->has_half_edges() && other.has_half_edges())
00072 this->build_edge_graph();
00073 else
00074 this->half_edges_.clear();
00075 }
00076
00077
00078
00079 void imesh_mesh::set_tex_coords(const vcl_vector<vgl_point_2d<double> >& tc)
00080 {
00081 if (tc.size() == this->num_verts())
00082 tex_coord_status_ = TEX_COORD_ON_VERT;
00083 else if (tc.size() == 2*this->num_edges())
00084 tex_coord_status_ = TEX_COORD_ON_CORNER;
00085 else
00086 tex_coord_status_ = TEX_COORD_NONE;
00087
00088 tex_coords_ = tc;
00089 }
00090
00091
00092
00093 void imesh_mesh::build_edge_graph()
00094 {
00095 const imesh_face_array_base& faces = this->faces();
00096 vcl_vector<vcl_vector<unsigned int> > face_list(faces.size());
00097 for (unsigned int f=0; f<faces.size(); ++f) {
00098 face_list[f].resize(faces.num_verts(f));
00099 for (unsigned int v=0; v<faces.num_verts(f); ++v)
00100 face_list[f][v] = faces(f,v);
00101 }
00102
00103 half_edges_.build_from_ifs(face_list);
00104 }
00105
00106
00107
00108 void imesh_mesh::compute_vertex_normals()
00109 {
00110 if (!this->has_half_edges())
00111 this->build_edge_graph();
00112
00113 const imesh_half_edge_set& half_edges = this->half_edges();
00114 imesh_vertex_array<3>& verts = this->vertices<3>();
00115
00116 vcl_vector<vgl_vector_3d<double> > normals(this->num_verts(),
00117 vgl_vector_3d<double>(0,0,0));
00118 vcl_vector<unsigned int> f_count(this->num_verts(),0);
00119
00120 for (unsigned int he=0; he < half_edges.size(); ++he) {
00121 imesh_half_edge_set::f_const_iterator fi(he,half_edges);
00122 if (fi->is_boundary())
00123 continue;
00124 unsigned int vp = fi->vert_index();
00125 unsigned int v = (++fi)->vert_index();
00126 unsigned int vn = (++fi)->vert_index();
00127 normals[v] += normalized(imesh_tri_normal(verts[v],verts[vn],verts[vp]));
00128 ++f_count[v];
00129 }
00130
00131 for (unsigned v=0; v<verts.size(); ++v)
00132 {
00133 normals[v] /= f_count[v];
00134 normalize(normals[v]);
00135 if (normals[v].length() < 0.5)
00136 vcl_cout << "normal "<<v<<" is "<<normals[v] <<vcl_endl;
00137 }
00138
00139 verts.set_normals(normals);
00140 }
00141
00142
00143
00144 void imesh_mesh::compute_vertex_normals_from_faces()
00145 {
00146 if (!this->has_half_edges())
00147 this->build_edge_graph();
00148
00149 if (!this->faces_->has_normals())
00150 this->compute_face_normals();
00151
00152 const vcl_vector<vgl_vector_3d<double> >& fnormals = faces_->normals();
00153
00154 const imesh_half_edge_set& half_edges = this->half_edges();
00155 imesh_vertex_array<3>& verts = this->vertices<3>();
00156
00157 vcl_vector<vgl_vector_3d<double> > normals(this->num_verts(),
00158 vgl_vector_3d<double>(0,0,0));
00159 vcl_vector<unsigned int> f_count(this->num_verts(),0);
00160
00161 for (unsigned int he=0; he < half_edges.size(); ++he) {
00162 const imesh_half_edge& half_edge = half_edges[he];
00163 if (half_edge.is_boundary())
00164 continue;
00165 unsigned int v = half_edge.vert_index();
00166 normals[v] += normalized(fnormals[half_edge.face_index()]);
00167 ++f_count[v];
00168 }
00169
00170 for (unsigned v=0; v<verts.size(); ++v)
00171 {
00172 normals[v] /= f_count[v];
00173 normalize(normals[v]);
00174 if (normals[v].length() < 0.5)
00175 vcl_cout << "normal "<<v<<" is "<<normals[v] <<vcl_endl;
00176 }
00177
00178 verts.set_normals(normals);
00179 }
00180
00181
00182
00183 void imesh_mesh::compute_face_normals(bool norm)
00184 {
00185 imesh_face_array_base& faces = this->faces();
00186 const imesh_vertex_array<3>& verts = this->vertices<3>();
00187
00188 vcl_vector<vgl_vector_3d<double> > normals(this->num_faces(),
00189 vgl_vector_3d<double>(0,0,0));
00190
00191 for (unsigned int i=0; i<faces.size(); ++i) {
00192 const unsigned int num_v = faces.num_verts(i);
00193 vgl_vector_3d<double>& n = normals[i];
00194 for (unsigned int j=2; j<num_v; ++j) {
00195 n += imesh_tri_normal(verts[faces(i,0)],
00196 verts[faces(i,j-1)],
00197 verts[faces(i,j)]);
00198 }
00199 if (norm)
00200 normalize(n);
00201 }
00202
00203 faces.set_normals(normals);
00204 }
00205
00206
00207
00208 vgl_point_2d<double> imesh_mesh::texture_map(unsigned int tri,
00209 double u, double v) const
00210 {
00211 vgl_point_2d<double> tex(0,0);
00212 if (this->tex_coord_status_ == TEX_COORD_ON_VERT)
00213 {
00214 unsigned int v1 = (*faces_)(tri,0);
00215 unsigned int v2 = (*faces_)(tri,1);
00216 unsigned int v3 = (*faces_)(tri,2);
00217 tex += (1-u-v)*vgl_vector_2d<double>(tex_coords_[v1].x(),tex_coords_[v1].y());
00218 tex += u*vgl_vector_2d<double>(tex_coords_[v2].x(),tex_coords_[v2].y());
00219 tex += v*vgl_vector_2d<double>(tex_coords_[v3].x(),tex_coords_[v3].y());
00220 }
00221 return tex;
00222 }
00223
00224
00225
00226 void imesh_mesh::set_valid_tex_faces(const vcl_vector<bool>& valid)
00227 {
00228 if (valid.size() == this->num_faces() && has_tex_coords())
00229 valid_tex_faces_ = valid;
00230 }
00231
00232
00233
00234
00235 void imesh_mesh::label_ccw_tex_faces_valid()
00236 {
00237 switch (tex_coord_status_)
00238 {
00239 case TEX_COORD_ON_VERT:
00240 {
00241 valid_tex_faces_.resize(this->num_faces());
00242 vgl_polygon<double> face(1);
00243 imesh_face_array_base& faces = this->faces();
00244 for (unsigned int f=0; f<num_faces(); ++f)
00245 {
00246 const unsigned int num_v = faces.num_verts(f);
00247 for (unsigned int i=0; i<num_v; ++i) {
00248 face.push_back(tex_coords_[faces(f,i)]);
00249 }
00250 valid_tex_faces_[f] = vgl_area_signed(face) > 0;
00251 }
00252 break;
00253 }
00254 case TEX_COORD_ON_CORNER:
00255 vcl_cerr << "imesh_mesh::label_ccw_tex_faces_valid()"
00256 << " not implemented for TEX_COORD_ON_CORNER\n";
00257 break;
00258 default:
00259 break;
00260 }
00261 }
00262
00263
00264 void vsl_b_write(vsl_b_ostream& , imesh_mesh_sptr&) {}
00265 void vsl_b_write(vsl_b_ostream& , imesh_mesh_sptr const&) {}
00266
00267
00268 void vsl_b_read(vsl_b_istream& , imesh_mesh_sptr&) {}
00269 void vsl_b_read(vsl_b_istream& , imesh_mesh_sptr const&) {}