Subversion Repositories gelsvn

Rev

Rev 396 | Rev 441 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

#include <GL/glew.h>

#include "CGLA/Mat4x4f.h"
#include "CGLA/Vec3d.h"
#include "draw.h"
#include "HMesh/FaceCirculator.h"

#include "SinglePassWireframeRenderer.h"
#include "IDBufferWireFrameRenderer.h"

using namespace CGLA;
using namespace HMesh;
using namespace std;

namespace 
{
        void set_material(const Geometry::Material& material)
        {
                if(material.has_texture && material.tex_id >=0)
                {
                        glEnable(GL_TEXTURE_2D);
                        glBindTexture(GL_TEXTURE_2D, material.tex_id);
                        glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
                }
                else
                        glDisable(GL_TEXTURE_2D);
                
                glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, material.ambient);
                glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, material.diffuse);
                glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, material.specular);
                glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, material.shininess);
        }
        
}

namespace GLGraphics
{
        
        void draw(Manifold& m, bool per_vertex_norms)
        {
                for(FaceIter f=m.faces_begin(); f != m.faces_end(); ++f)
                {
                        FaceCirculator fc(f);
                        if(!per_vertex_norms) 
                                glNormal3fv(normal(f).get());
                        if(no_edges(f)== 3) 
                                glBegin(GL_TRIANGLES);
                        else 
                                glBegin(GL_POLYGON);
                        while(!fc.end())
                        {
                                Vec3f n = normal(fc.get_vertex());
                                if(per_vertex_norms) 
                                        glNormal3fv(n.get());
                                glVertex3fv(fc.get_vertex()->pos.get());
                                ++fc;
                        }
                        glEnd();
                }
        }

        void draw(const Geometry::IndexedFaceSet& geometry)
        {
                glBegin(GL_TRIANGLES);
                for(int i=0;i<geometry.no_faces();i++)
                {
                                Vec3i g_face = geometry.face(i);
                                Vec3f vert0 = geometry.vertex(g_face[0]);
                                Vec3f vert1 = geometry.vertex(g_face[1]);
                                Vec3f vert2 = geometry.vertex(g_face[2]);
                                Vec3f norm = normalize(cross(vert1-vert0, vert2-vert0));
                                glNormal3fv(norm.get());
                                glVertex3fv(vert0.get());
                                glVertex3fv(vert1.get());
                                glVertex3fv(vert2.get());
                }
                glEnd();
        }
        
        void draw(const Geometry::TriMesh& tm, bool per_vertex_norms)
        {
                int old_mat_idx = -1;
                glBegin(GL_TRIANGLES);
                for(int i=0;i<tm.geometry.no_faces();i++)
                {
                        int new_mat_idx = i<static_cast<int>(tm.mat_idx.size()) ? tm.mat_idx[i] : -1;
                        if(new_mat_idx != old_mat_idx)
                        {
                                glEnd();
                                set_material(tm.materials[tm.mat_idx[i]]);
                                glBegin(GL_TRIANGLES);
                                old_mat_idx = new_mat_idx;
                        }
                        Vec3i n_face = tm.normals.face(i);
                        Vec3i g_face = tm.geometry.face(i);
                        Vec3i t_face = tm.texcoords.face(i);
                        
                        if(!per_vertex_norms)
                        {
                                Vec3f vert0 = tm.geometry.vertex(g_face[0]);
                                Vec3f vert1 = tm.geometry.vertex(g_face[1]);
                                Vec3f vert2 = tm.geometry.vertex(g_face[2]);
                                Vec3f norm = normalize(cross(vert1-vert0, vert2-vert0));
                                glNormal3fv(norm.get());
                        }
                        for(int j=0;j<3;j++)
                        {
                                if(per_vertex_norms && n_face != Geometry::NULL_FACE)
                                {
                                        Vec3f norm = tm.normals.vertex(n_face[j]);
                                        glNormal3fv(norm.get());
                                }
                                if(t_face != Geometry::NULL_FACE)
                                {
                                        Vec3f texc = tm.texcoords.vertex(t_face[j]);
                                        glTexCoord2fv(texc.get());
                                }
                                Vec3f vert = tm.geometry.vertex(g_face[j]);
                                glVertex3fv(vert.get());
                        }
                }
                glEnd();
                glDisable(GL_TEXTURE_2D);
        }
        
        
         
        template<class T>
        void draw_wireframe_oldfashioned(T& m, bool per_vertex_norms, const Vec3f& line_color)
        {
                // Store state that we change
                glPushAttrib(GL_POLYGON_BIT);
                GLboolean lights_on;
                glGetBooleanv(GL_LIGHTING, &lights_on);
                Vec4f current_color;
                glGetFloatv(GL_CURRENT_COLOR, &current_color[0]);
                
                // Draw filled
                glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
                draw(m, per_vertex_norms);
                
                // Draw lines
                glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
                glDisable(GL_LIGHTING);
                glEnable(GL_POLYGON_OFFSET_LINE);
                glPolygonOffset(0,-5);
                glColor3fv(line_color.get());
                draw(m, per_vertex_norms);
                
                // Put back old state
                glColor3fv(current_color.get());
                if(lights_on) glEnable(GL_LIGHTING);
                glPopAttrib();
        }
        
        template
        void draw_wireframe_oldfashioned<HMesh::Manifold>(HMesh::Manifold& m, bool per_vertex_norms, const Vec3f& line_color);

        template
        void draw_wireframe_oldfashioned(Geometry::TriMesh& m, bool per_vertex_norms, const Vec3f& line_color);

        
        void draw(const Geometry::AABox& box)
        {
                glBegin(GL_QUADS);
                Vec3f norm_neg[] = {Vec3f(0,0,-1), Vec3f(-1,0,0), Vec3f(0,-1,0)};
                Vec3f norm_pos[] = {Vec3f(0,0, 1), Vec3f( 1,0,0), Vec3f(0, 1,0)};
                for(int j=0;j<3;++j)
                {
                        glNormal3fv(norm_neg[j].get());
                        Vec3f p = box.get_pmin();
                        glVertex3f(p[0], p[1], p[2]);
                        p[(j+1)%3] = box.get_pmax()[(j+1)%3];
                        glVertex3f(p[0], p[1], p[2]);
                        p[j] = box.get_pmax()[j];
                        glVertex3f(p[0], p[1], p[2]);
                        p[(j+1)%3] = box.get_pmin()[(j+1)%3];
                        glVertex3f(p[0], p[1], p[2]);
                }
                glEnd();
                glBegin(GL_QUADS);
                for(int j=0;j<3;++j)
                {
                        glNormal3fv(norm_pos[j].get());
                        Vec3f p = box.get_pmax();
                        glVertex3f(p[0], p[1], p[2]);
                        p[j] = box.get_pmin()[j];
                        glVertex3f(p[0], p[1], p[2]);
                        p[(j+1)%3] = box.get_pmin()[(j+1)%3];
                        glVertex3f(p[0], p[1], p[2]);
                        p[j] = box.get_pmax()[j];
                        glVertex3f(p[0], p[1], p[2]);
                }
                glEnd();
        }
        
        void draw(const Geometry::OBox& box)
        {
                Mat4x4f m = identity_Mat4x4f();
                copy_matrix(box.get_rotation(), m);
                glPushMatrix();
                glMultMatrixf(m.get());
                draw(box.get_aabox());
                glPopMatrix();
        }
        
        /** Draw the tree. The first argument is the level counter, the second
         argument is the level at which to stop drawing. */
        template <class BoxType>
        void draw(const Geometry::BoundingINode<BoxType>& node, int level, int max_level)
        {
                if(level == max_level)
                {
                        draw(node); 
                        return;
                }
                node->left->draw(level + 1, max_level);
                node->right->draw(level + 1, max_level);  
        }
        
        template <class BoxType>
        void draw(const Geometry::BoundingLNode<BoxType>& node, int level, int max_level)
        {
#if USE_LEAF_BOXES
                draw(node); 
#endif
        }
        
        template <class BoxType>
        void draw(const Geometry::BoundingTree<BoxType>& tree, int max_level)
        {
                draw(*tree.root, 0, max_level);
        }
}