Subversion Repositories gelsvn

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
688 khor 1
/* ----------------------------------------------------------------------- *
2
* This file is part of GEL, http://www.imm.dtu.dk/GEL
3
* Copyright (C) the authors and DTU Informatics
4
* For license and list of authors, see ../../doc/intro.pdf
5
* ----------------------------------------------------------------------- */
6
 
7
#include "../CGLA/Vec3f.h"
8
#include <stdio.h>
9
#include <iostream>
10
#include <set>
11
 
12
#include "TriMesh.h"
13
 
14
using namespace std;
15
using namespace CGLA;
16
 
17
namespace Geometry 
18
{
19
  int TriMesh::find_material(const string& name) const
20
  {
21
    for(size_t i = 0; i < materials.size(); ++i)
22
      if(materials[i].name == name)
23
        return i;
24
    return 0;
25
  }
26
 
27
  void TriMesh::compute_normals()
28
  {
29
    // By default the normal faces are the same as the geometry faces
30
    // and there are just as many normals as vertices, so we simply
31
    // copy.
32
    normals = geometry;
33
 
34
    const int NV = normals.no_vertices();
35
    // The normals are initialized to zero.
36
    int i;
37
    for(i=0;i<NV; ++i)
38
      normals.vertex_rw(i) = Vec3f(0);
39
 
40
    // For each face
41
    int NF = geometry.no_faces();
42
    for(i=0;i<NF; ++i)
43
    {
44
      // Compute the normal
45
      const Vec3i& f  = geometry.face(i);
46
      const Vec3f& p0 = geometry.vertex(f[0]);
47
      const Vec3f& a  = geometry.vertex(f[1]) - p0;
48
      const Vec3f& b  = geometry.vertex(f[2]) - p0;
49
      Vec3f face_normal = cross(a,b);
50
      float l = sqr_length(face_normal);
51
      if(l > 0.0f)
52
        face_normal /= sqrt(l);
53
 
54
      // Add the angle weighted normal to each vertex
55
      for(int j=0;j<3; ++j)
56
      {
57
        const Vec3f& p0 = geometry.vertex(f[j]);
58
        Vec3f a = geometry.vertex(f[(j+1)%3]) - p0;
59
        float l_a = sqr_length(a);
60
        if(l_a > 0.0f)
61
          a /= sqrt(l_a);
62
        Vec3f b = geometry.vertex(f[(j+2)%3]) - p0;
63
        float l_b = sqr_length(b);
64
        if(l_b > 0.0f)
65
          b /= sqrt(l_b);
66
        float d = max(-1.0f, min(1.0f, dot(a,b)));
67
        normals.vertex_rw(f[j]) += face_normal * acos(d);
68
      }
69
    }
70
 
71
    // Normalize all normals
72
    for(i=0;i<NV; ++i)
73
    {
74
      float l_vert_rw = sqr_length(normals.vertex_rw(i));
75
      if(l_vert_rw > 0.0f)
76
        normals.vertex_rw(i) /= sqrt(l_vert_rw);
77
    }
78
  }
79
 
80
  void TriMesh::compute_areas()
81
  {
82
    int no_of_faces = geometry.no_faces();
83
    surface_area = 0.0f;
84
    face_areas.resize(no_of_faces);
85
    face_area_cdf.resize(no_of_faces);
86
    for(int i = 0; i < no_of_faces; ++i)
87
    {
88
      const Vec3i& f  = geometry.face(i);
89
      const Vec3f& p0 = geometry.vertex(f[0]);
90
      const Vec3f& a  = geometry.vertex(f[1]) - p0;
91
      const Vec3f& b  = geometry.vertex(f[2]) - p0;
92
      face_areas[i] = 0.5f*cross(a, b).length();
93
      face_area_cdf[i] = surface_area + face_areas[i];
94
      surface_area += face_areas[i];
95
    }
96
    if(surface_area > 0.0f)
97
      for(int i = 0; i < no_of_faces; ++i)
98
        face_area_cdf[i] /= surface_area;
99
  }
100
 
101
  bool TriMesh::get_bbox(Vec3f& p0, Vec3f& p7) const
102
  {
103
    if(geometry.no_vertices() == 0)
104
      return false;
105
 
106
    int i;
107
    p0 = geometry.vertex(0);
108
    p7 = geometry.vertex(0);
109
    for(i = 1; i < geometry.no_vertices(); ++i) 
110
    {
111
      p0 = v_min(geometry.vertex(i), p0);
112
      p7 = v_max(geometry.vertex(i), p7);
113
    }
114
    return true;
115
  }
116
 
117
  bool TriMesh::get_bsphere(Vec3f& c, float& r) const
118
  {
119
    Vec3f p0,p7;
120
    if(!get_bbox(p0, p7))
121
      return false;
122
 
123
    Vec3f rad = (p7 - p0)/2.0;
124
    c = p0 + rad;
125
    r = rad.length();
126
    return true;
127
  }
128
 
129
  void TriMesh::transform(const Mat4x4f& m)
130
  {
131
    for(int i = 0; i < geometry.no_vertices(); ++i)
132
      geometry.vertex_rw(i) = m.mul_3D_point(geometry.vertex(i));
133
    for(int i = 0; i < normals.no_vertices(); ++i)
134
      normals.vertex_rw(i) = normalize(m.mul_3D_vector(normals.vertex(i)));
135
  }
136
 
137
  void TriMesh::tex_transform(const Mat4x4f& m)
138
  {
139
    for(int i = 0; i < texcoords.no_vertices(); ++i)
140
      texcoords.vertex_rw(i) = m.mul_3D_point(texcoords.vertex(i));
141
  }
142
 
143
  void TriMesh::tex_transform(const Mat4x4f& m, const string& material)
144
  {
145
    set<int> v_touched;
146
    int m_idx = find_material(material);
147
    for(int i = 0; i < texcoords.no_faces(); ++i)
148
      if(mat_idx[i] == m_idx)
149
      {
150
        Vec3i face = texcoords.face(i);
151
        for(int j = 0; j < 3; ++j)
152
        {
153
          int v_idx = face[j];
154
          if(v_touched.count(v_idx) == 0)
155
          {
156
            v_touched.insert(v_idx);
157
            texcoords.vertex_rw(v_idx) = m.mul_3D_point(texcoords.vertex(v_idx));
158
          }
159
        }
160
      }
161
  }
162
}