Subversion Repositories gelsvn

Rev

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

// bdl, jab, feb 2005
// Inspired by Nate Robins Obj loader

#include "TriMesh.h"
#ifdef WIN32
#include <windows.h>
#endif
#include <GL/gl.h>
#include <GL/glu.h>

#include <CGLA/Vec3f.h>
#include <stdio.h>
#include <iostream>

using namespace std;
using namespace CGLA;

namespace Geometry 
{
        int TriMesh::find_material(const string& name) const
        {
                for(int i=0;i<materials.size(); ++i)
                        {
                                if(materials[i].name == name)
                                        return i;
                        }
                return 0;
        }

        int TriMesh::find_texmap(const string& name) const
        {
                for(int i=0;i<texmaps.size(); ++i)
                        {
                                if(texmaps[i].get_name() == name)
                                        return i;
                        }
                return -1;
        }

        void TriMesh::compute_normals()
        {               
                // By default the normal faces are the same as the geometry faces
                // and there are just as many normals as vertices, so we simply
                // copy.
                normals = geometry;

                const int NV = normals.no_vertices();
                // The normals are initialized to zero.
                int i;
                for(i=0;i<NV; ++i)
                        normals.vertex_rw(i) = Vec3f(0);

                // For each face
                int NF = geometry.no_faces();
                for(i=0;i<NF; ++i)
      {
                                // Compute the normal
                                const Vec3i& f  = geometry.face(i);
                                const Vec3f p0 = geometry.vertex(f[0]);
                                const Vec3f a  = geometry.vertex(f[1]) - p0;
                                const Vec3f b  = geometry.vertex(f[2]) - p0;
                                Vec3f face_normal = cross(a,b);
                                float l = sqr_length(face_normal);
                                if(l > 0.0f)
                                        face_normal /= sqrt(l);
                                
                                // Add the angle weighted normal to each vertex
                                for(int j=0;j<3; ++j)
                                        {
                                                const Vec3f p0 = geometry.vertex(f[j]);
                                                const Vec3f a = normalize(geometry.vertex(f[(j+1)%3]) - p0);
                                                const Vec3f b = normalize(geometry.vertex(f[(j+2)%3]) - p0);
                                                float d = max(-1.0f, min(1.0f, dot(a,b)));
                                                normals.vertex_rw(f[j]) += face_normal * acos(d);
                                        }
      }

                // Normalize all normals
    for(i=0;i<NV; ++i)
                        {
                                normals.vertex_rw(i).normalize();
                        }
        }

        void TriMesh::gl_init_textures()
        {
                for(int i=0;i<texmaps.size();++i)
                        texmaps[i].gl_init();
        }


        void TriMesh::gl_set_material(int idx)
        {
                assert(idx<materials.size());
                Material& material = materials[idx];
                if(material.tex_id >=0)
                        {
                                glEnable(GL_TEXTURE_2D);
                                texmaps[material.tex_id].gl_bind();
                                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);
        }

        void TriMesh::gl_draw()
        {
                int old_mat_idx = -1;
                glBegin(GL_TRIANGLES);
                for(int i=0;i<geometry.no_faces();i++) 
                        {
                                if(mat_idx[i] != old_mat_idx)
                                        {
                                                glEnd();
                                                gl_set_material(mat_idx[i]);
                                                glBegin(GL_TRIANGLES);
                                                old_mat_idx = mat_idx[i];
                                        }
                                Vec3i n_face = normals.face(i);
                                Vec3i g_face = geometry.face(i);
                                Vec3i t_face = texcoords.face(i);
                                for(int j=0;j<3;j++) 
                                        {
                                                if(n_face != NULL_FACE)
                                                        {
                                                                Vec3f norm = normals.vertex(n_face[j]);
                                                                glNormal3fv(norm.get());
                                                        }
                                                if(t_face != NULL_FACE)
                                                        {
                                                                Vec3f texc = texcoords.vertex(t_face[j]);
                                                                glTexCoord2fv(texc.get());
                                                        }
                                                Vec3f vert = geometry.vertex(g_face[j]);
                                                glVertex3fv(vert.get());
                                        }
                }
                glEnd();
                glDisable(GL_TEXTURE_2D);
        }

  void TriMesh::get_bbox(CGLA::Vec3f& p0, CGLA::Vec3f& p7) const
  {
    int i;
    p0 = geometry.vertex(0);
    p7 = geometry.vertex(0);
    for(i=1;i<geometry.no_vertices();i++) 
      {
                                p0 = v_min(geometry.vertex(i), p0);
                                p7 = v_max(geometry.vertex(i), p7);
      }
  }

  void TriMesh::get_bsphere(CGLA::Vec3f& c, float& r) const
  {
    Vec3f p0,p7;
    get_bbox(p0, p7);
    Vec3f rad = (p7 - p0)/2.0;
    c = p0 + rad;
    r = rad.length();
  }


}