Subversion Repositories gelsvn

Rev

Blame | Last modification | View Log | RSS feed

#ifndef __IMESH_TRIMESHBUILDER_H__
#define __IMESH_TRIMESHBUILDER_H__

#include "TriMesh.h"

namespace IMesh
{

        /** The TriMeshBuilder constructs a TriMesh. The reason to have this
                        class is that indexed face sets are very "undynamic" to begin with.
                        Typically, we store all data in vectors for efficiency, and it is
                        difficult to add and especially remove data from these vectors.
                        By having a builder class, we can separate concerns so that the 
                        content adding is taken care of before the mesh is used. */
        class TriMeshBuilder: public TriMeshData
        {
                // A TriMeshBuilder is only constructed using the default constructor.
                TriMeshBuilder(const TriMeshBuilder&);
                bool did_call_get_trimesh;
        public:
                

                /** The constructor begins by registering the basic data
                                types, i.e. the */
                TriMeshBuilder();

                ~TriMeshBuilder();

                void clear();
                
                //----------------------------------------------------------------------
                // Register face sets and attributes
                //----------------------------------------------------------------------

                /** Register a new face set. If this is not the first face set, the 
                                first face set is copied into the presently registered face set. */
                int register_face_set();

                /** Register a face attribute of type ATTR. If there is an existing 
                                attribute of the same name, then the handle passed as second
                                argument is made to point to this attribute and no new attribute
                                is created. */
                template<class ATTR>
                void register_face_attribute(const std::string& attr_name,
                                                                                                                                 AttrHandle<ATTR>& handle)
                {
                        assert(!did_call_get_trimesh);
                        if(!get_fattr_handle(attr_name, handle))
                                {
                                        handle.idx = face_attr.size();
                                        face_attr.push_back(new AttrVec<ATTR>(attr_name));
                                }
                }

                /// Utility function, register face colours.
                void register_face_colors();
        
                /// Utility function that registers the use of face normals.
                void register_face_normals();

                /** Register a vertex attribute of type ATTR, indexed via FACESET.
                If there is an existing attribute of the same name, then the
                handle passed as second argument is made to point to this
                attribute and no new attribute is created. */
                template<class ATTR>
                void register_vertex_attribute(const std::string& attr_name,
                                                                                                                                         AttrHandle<ATTR>& handle, int face_set=0)
                {
                        assert(!did_call_get_trimesh);
                        assert(face_set < face_sets.size());
                        if(!get_vattr_handle(attr_name, handle))
                                {
                                        handle.idx = vert_attr.size();
                                        vert_attr.push_back(new AttrVec<ATTR>(attr_name));
                                        face_set_mapping.push_back(face_set);
                                }
                }

                // ----------------------------------------------------------------------
                // utility functions. These are used to register standard resources.
                // ----------------------------------------------------------------------
                
                /// Register vertex normals (of type Vec3f)
                void register_vertex_normals(int face_set = 0);
        
                /// Register vertex normals (of type Vec4f)
                void register_vertex_colors(int face_set = 0);
                
                /// Register vertex texture coords (of type Vec4f)
                void register_vertex_texcoords(int face_set = 0);
        
                /** Functions to add a face. When a face is added, the same face
                                is added to all facesets. Afterwards, use set_face to alter a face
                                in a given face_set. */
                void add_face(const CGLA::Vec3i& face);

                /// Add a vertex attribute
                template<class ATTR>
                int add_vattr(AttrHandle<ATTR> handle, const ATTR& val)
                {
                        int n = vert_attr[handle.idx]->size();
                        push_back_attr(*vert_attr[handle.idx],val);
                        return n;
                }

                /// Add a face attribute
                template<class ATTR>
                int add_fattr(AttrHandle<ATTR> handle, const ATTR& val)
                {
                        int n = face_attr[handle.idx]->size();
                        push_back_attr(*face_attr[handle.idx],val);
                        return n;
                }

                /// Add a face normal
                int add_fnorm(const CGLA::Vec3f& norm)
                {
                        return add_fattr(FA_NORM, norm);
                }

                /// Add a face colour
                int add_fcol(const CGLA::Vec4f& col)
                {
                        return add_fattr(FA_COL, col);
                }

                /// Add a vertex position to the mesh.
                int add_vpos(const CGLA::Vec3f& pos)
                {
                        return add_vattr(VA_POS, pos);
                }

                /// Add a vertex normal to the mesh.
                int add_vnorm(const CGLA::Vec3f& norm)
                {
                        return add_vattr(VA_NORM, norm);
                }

                /// Add a vertex colour to the mesh.
                int add_vcol(const CGLA::Vec4f& col)
                {
                        return add_vattr(VA_COL, col);
                }

                /// Add a vertex texture coordinate to the mesh.
                int add_vtex(const CGLA::Vec4f& tex)
                {
                        return add_vattr(VA_TEX, tex);
                }

                /** Build and return a resource ptr to the trimesh. After this function
                                has been called, the destructor is the only function which it is
                                allowed to call - unless the clear function is called.  */
                TriMesh* get_trimesh();
        };

        /** Register and compute face normals. if do_flip is true, the normals 
                        point opposite the ccw direction. */
        void compute_face_normals(TriMeshBuilder& bldr, bool do_flip=false);


        /** This function computes vertex normals for a mesh. If no vertex normals
                        have been registered, compute_vertex_normals will first register and
                        add vertex normals. The normals are registered to the default face set
                        meaning that there is a one to one relationship between vertices and
                        vertex normals. If vertex_normals are already registered, it is assumed
                        that the correct number of vertex normals have also been added.
                        
                        Vertex normals are then computed by adding the face normal weighted by
                        angle to the normal corresponding to each vertex of the face. Finally,
                        all vertex normals are normalized. */
        void compute_vertex_normals(TriMeshBuilder& bldr);

        /** This function is passed a builder and the handle of the smoothing group
                        attribute. vertex_normals are registered to a new face set, and the 
                        normal faces are computed using the smoothing group information. 
                        Finally, compute_vertex_normals(bldr) is called to generated the actual
                        normals. */
        void compute_vertex_normals(TriMeshBuilder& bldr, 
                                                                                                                        AttrHandle<int> smooth_group_attr);

        /** This function is passed a builder and the cosine of a crease angle.
                        vertex_normals are registered to a new face set, and the 
                        normal faces are computed using the smoothing group information. 
                        Finally, compute_vertex_normals(bldr) is called to generated the actual
                        normals. */
        void compute_vertex_normals(TriMeshBuilder& bldr, float);
                
}

#endif