#ifndef _TEXTURED_MESH_ #define _TEXTURED_MESH_ #include #include #include #include namespace CGAL { template class Textured_facet : public CGAL::HalfedgeDS_face_base { // normal Norm m_normal; public: // life cycle // no constructors to repeat, since only // default constructor mandatory Textured_facet() { } // normal typedef Norm Normal_3; Normal_3& normal() { return m_normal; } const Normal_3& normal() const { return m_normal; } }; template class Textured_halfedge : public CGAL::HalfedgeDS_halfedge_base { public: // life cycle Textured_halfedge() { } }; template class Textured_vertex : public CGAL::HalfedgeDS_vertex_base { // normal Norm m_normal; double m_u; double m_v; public: // life cycle Textured_vertex() {} // repeat mandatory constructors Textured_vertex(const P& pt) : CGAL::HalfedgeDS_vertex_base(pt) { } // normal typedef Norm Normal_3; Normal_3& normal() { return m_normal; } const Normal_3& normal() const { return m_normal; } // u,v coordinates double& u() { return m_u; } const double& u() const { return m_u; } double& v() { return m_v; } const double& v() const { return m_v; } }; struct Textured_items : public CGAL::Polyhedron_items_3 { // wrap vertex template struct Vertex_wrapper { typedef typename Traits::Point_3 Point; typedef typename Traits::Vector_3 Normal; typedef Textured_vertex Vertex; }; // wrap face template struct Face_wrapper { typedef typename Traits::Point_3 Point; typedef typename Traits::Vector_3 Normal; typedef Textured_facet Face; }; // wrap halfedge template struct Halfedge_wrapper { typedef typename Traits::Vector_3 Normal; typedef Textured_halfedge Halfedge; }; }; // compute facet normal struct Facet_normal // (functor) { template void operator()(Facet& f) { typename Facet::Normal_3 sum = CGAL::NULL_VECTOR; typename Facet::Halfedge_around_facet_circulator h = f.facet_begin(); do { typename Facet::Normal_3 normal = CGAL::cross_product(h->next()->vertex()->point() - h->vertex()->point(), h->next()->next()->vertex()->point() - h->next()->vertex()->point()); double sqnorm = normal * normal; if (sqnorm != 0) normal = normal / (float)std::sqrt(sqnorm); sum = sum + normal; } while (++h != f.facet_begin()); float sqnorm = sum * sum; if (sqnorm != 0.0) f.normal() = sum / std::sqrt(sqnorm); else f.normal() = CGAL::NULL_VECTOR; } }; // compute vertex normal struct Vertex_normal // (functor) { template void operator()(Vertex& v) { typename Vertex::Normal_3 normal = CGAL::NULL_VECTOR; typename Vertex::Halfedge_around_vertex_const_circulator pHalfedge = v.vertex_begin(); typename Vertex::Halfedge_around_vertex_const_circulator begin = pHalfedge; CGAL_For_all(pHalfedge,begin) if(!pHalfedge->is_border()) normal = normal + pHalfedge->facet()->normal(); float sqnorm = normal * normal; if (sqnorm != 0.0f) v.normal() = normal / (float)std::sqrt(sqnorm); else v.normal() = CGAL::NULL_VECTOR; } }; //********************************************************* template class Textured_polyhedron : public CGAL::Polyhedron_3 { public : typedef typename Kernel::FT FT; typedef typename Kernel::Point_3 Point; typedef typename Kernel::Vector_3 Vector; typedef typename CGAL::Polyhedron_3 Base; typedef typename CGAL::Polyhedron_3 Basic_polyhedron; typedef typename Base::Vertex_handle Vertex_handle; typedef typename Base::Vertex_iterator Vertex_iterator; typedef typename Base::Halfedge_handle Halfedge_handle; typedef typename Base::Halfedge_iterator Halfedge_iterator; typedef typename Base::Halfedge_around_facet_circulator Halfedge_around_facet_circulator; typedef typename Base::Halfedge_around_vertex_circulator Halfedge_around_vertex_circulator; typedef typename Base::Edge_iterator Edge_iterator; typedef typename Base::Facet Facet; typedef typename Base::Facet_iterator Facet_iterator; typedef typename Base::Facet_handle Facet_handle; public : // life cycle Textured_polyhedron() { } virtual ~Textured_polyhedron() { } // normals (per facet, then per vertex) void compute_normals_per_facet() { std::for_each(this->facets_begin(),this->facets_end(),Facet_normal()); } void compute_normals_per_vertex() { std::for_each(this->vertices_begin(),this->vertices_end(),Vertex_normal()); } void compute_normals() { compute_normals_per_facet(); compute_normals_per_vertex(); } void gl_draw_textured_triangles(bool smooth_shading, bool use_normals, const double scaling_tex_coordinates) { ::glBegin(GL_TRIANGLES); Facet_iterator f = this->facets_begin(); for(;f!= this->facets_end();f++) gl_draw_textured_facet(f,smooth_shading,use_normals,scaling_tex_coordinates); ::glEnd(); } void gl_draw_textured_facet(Facet_handle f, bool smooth_shading, bool use_normals, const double scaling_tex_coordinates) { // one normal per face if(use_normals && !smooth_shading) { const typename Facet::Normal_3& n = f->normal(); ::glNormal3f(n[0],n[1],n[2]); } // revolve around current face to get vertices Halfedge_around_facet_circulator he = f->facet_begin(); do { // one normal per vertex if(use_normals && smooth_shading) { const typename Facet::Normal_3& n = he->vertex()->normal(); ::glNormal3d(n[0],n[1],n[2]); } // polygon assembly is performed per vertex const Point& p = he->vertex()->point(); const double u = he->vertex()->u(); const double v = he->vertex()->v(); // std::cout << u << " " << v << std::endl; ::glTexCoord2d(u * scaling_tex_coordinates, v * scaling_tex_coordinates); ::glVertex3d(p[0],p[1],p[2]); } while(++he != f->facet_begin()); } }; // end class Textured_polyhedron }; // end namespace CGAL #endif // _TEXTURED_MESH_