Reverting change to decimation to fix compatibility with
[blender.git] / intern / decimation / intern / LOD_ExternNormalEditor.cpp
1 /**
2  * $Id$
3  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version. The Blender
9  * Foundation also sells licenses for use in proprietary software under
10  * the Blender License.  See http://www.blender.org/BL/ for information
11  * about this.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software Foundation,
20  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  *
22  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
23  * All rights reserved.
24  *
25  * The Original Code is: all of this file.
26  *
27  * Contributor(s): none yet.
28  *
29  * ***** END GPL/BL DUAL LICENSE BLOCK *****
30  */
31
32 #include "LOD_ExternNormalEditor.h"
33 #include <vector>
34
35 #ifdef HAVE_CONFIG_H
36 #include <config.h>
37 #endif
38
39 using namespace std;
40
41
42 LOD_ExternNormalEditor::
43 LOD_ExternNormalEditor(
44         LOD_Decimation_InfoPtr extern_info,
45         LOD_ManMesh2 &mesh
46 ) :
47         m_extern_info (extern_info),
48         m_mesh(mesh)
49 {
50 }
51
52         LOD_ExternNormalEditor *
53 LOD_ExternNormalEditor::
54 New(
55         LOD_Decimation_InfoPtr extern_info,
56         LOD_ManMesh2 &mesh
57 ){
58         if (extern_info == NULL) return NULL;
59         
60         MEM_SmartPtr<LOD_ExternNormalEditor> output(new LOD_ExternNormalEditor(extern_info,mesh));
61
62         int face_num = mesh.FaceSet().size();
63
64         MEM_SmartPtr<vector<MT_Vector3> > normals(new vector<MT_Vector3>);
65
66         if (output == NULL ||
67                 normals == NULL
68         ) {
69                 return NULL;
70         }       
71
72         normals->reserve(face_num);
73         output->m_normals = normals.Release();
74
75         return output.Release();
76 };
77         
78
79         void
80 LOD_ExternNormalEditor::
81 Remove(
82         std::vector<LOD_FaceInd> &sorted_faces
83 ){
84         // assumes a collection of faces sorted in descending order .
85         
86         vector<MT_Vector3> & normals = m_normals.Ref();
87
88         vector<LOD_FaceInd>::const_iterator it_start = sorted_faces.begin();
89         vector<LOD_FaceInd>::const_iterator it_end = sorted_faces.end();
90
91         for (; it_start != it_end; ++it_start) {
92
93                 if (normals.size() > 0) {
94                         MT_Vector3 temp = normals[*it_start];
95                 
96                         normals[*it_start] = normals.back();
97                         normals.back() = temp;
98
99                         normals.pop_back();
100                 }
101
102                 // FIXME - throw exception
103         }
104 }
105
106
107         void
108 LOD_ExternNormalEditor::
109 Add(
110 ){
111         MT_Vector3 zero(0.0f,0.0f,0.0f);
112         m_normals->push_back(zero);
113 };      
114
115         void
116 LOD_ExternNormalEditor::
117 Update(
118         std::vector<LOD_FaceInd> &sorted_faces
119 ){
120         vector<MT_Vector3> & normals = m_normals.Ref();
121
122         vector<LOD_FaceInd>::const_iterator it_start = sorted_faces.begin();
123         vector<LOD_FaceInd>::const_iterator it_end = sorted_faces.end();
124
125         const vector<LOD_TriFace> &faces = m_mesh.FaceSet();
126
127         for (; it_start != it_end; ++it_start) {                
128                 normals[*it_start] = ComputeNormal(faces[*it_start]);           
129         }       
130 };
131
132
133
134         
135 // vertex normals
136 /////////////////
137
138         void
139 LOD_ExternNormalEditor::
140 RemoveVertexNormals(
141         std::vector<LOD_VertexInd> &sorted_verts
142 ){
143
144         float * vertex_normals = m_extern_info->vertex_normal_buffer;
145
146         // assumption here that the vertexs normal number corresponds with 
147         // the number of vertices !
148
149         int vertex_normal_num = m_extern_info->vertex_num; 
150
151         vector<LOD_VertexInd>::const_iterator it_start = sorted_verts.begin();
152         vector<LOD_VertexInd>::const_iterator it_end = sorted_verts.end();
153
154         for (; it_start != it_end; ++it_start) {
155
156                 if (vertex_normal_num > 0) {
157                         float * vertex_normal = vertex_normals + int(*it_start)*3;
158                         float * last_vertex = vertex_normals + ((vertex_normal_num-1)*3);
159
160                         MT_Vector3 last_v(last_vertex);
161                         last_v.getValue(vertex_normal);
162                         vertex_normal_num--;
163                 }
164
165                 // FIXME - through exception
166         }
167 };
168
169
170
171         void
172 LOD_ExternNormalEditor::
173 UpdateVertexNormals(
174         std::vector<LOD_VertexInd> &sorted_verts
175 ){
176         float * vertex_normals = m_extern_info->vertex_normal_buffer;
177
178         vector<LOD_VertexInd>::const_iterator it_start = sorted_verts.begin();
179         vector<LOD_VertexInd>::const_iterator it_end = sorted_verts.end();
180
181         for (; it_start != it_end; ++it_start) {                
182                 MT_Vector3 temp = ComputeVertexNormal(*it_start);               
183                 float * vertex_normal = vertex_normals + int(*it_start)*3;
184                 temp.getValue(vertex_normal);
185         }
186 }
187
188 // Editor specific methods
189 //////////////////////////
190
191         void
192 LOD_ExternNormalEditor::
193 BuildNormals(
194 ) {
195         const vector<LOD_TriFace> &faces = m_mesh.FaceSet();
196         vector<MT_Vector3> & normals = m_normals.Ref();
197
198         int face_num = faces.size();
199         int cur_face = 0;
200
201         for (; cur_face < face_num; ++cur_face) {
202
203                 MT_Vector3 new_normal = ComputeNormal(faces[cur_face]); 
204                 normals.push_back(new_normal); 
205         }
206 }
207
208 const 
209         MT_Vector3 
210 LOD_ExternNormalEditor::
211 ComputeNormal(
212         const LOD_TriFace &face
213 ) const {
214
215         const vector<LOD_Vertex> &verts = m_mesh.VertexSet();
216
217         MT_Vector3 vec1 = 
218                 verts[face.m_verts[1]].pos - 
219                 verts[face.m_verts[0]].pos;
220
221         MT_Vector3 vec2 = 
222                 verts[face.m_verts[2]].pos - 
223                 verts[face.m_verts[1]].pos;
224
225         vec1 = vec1.cross(vec2);
226
227         if (!vec1.fuzzyZero()) {
228                 vec1.normalize();
229                 return (vec1);
230         } else {                
231                 return (MT_Vector3(1.0,0,0));
232         }               
233 }
234
235 const 
236         MT_Vector3 
237 LOD_ExternNormalEditor::
238 ComputeVertexNormal(
239         const LOD_VertexInd v
240 ) const {
241
242         // average the face normals surrounding this
243         // vertex and normalize
244         vector<LOD_Vertex> &verts = m_mesh.VertexSet();
245         const vector<MT_Vector3> & face_normals = m_normals.Ref();
246
247         vector<LOD_FaceInd> vertex_faces;
248         vertex_faces.reserve(32);
249         
250         m_mesh.VertexFaces(v,vertex_faces);
251         
252         MT_Vector3 normal(0,0,0);
253
254         vector<LOD_FaceInd>::const_iterator face_it = vertex_faces.begin();
255         vector<LOD_FaceInd>::const_iterator face_end = vertex_faces.end();
256
257         for (; face_it != face_end; ++face_it) {
258                 normal += face_normals[*face_it];
259         }
260         
261         if (!normal.fuzzyZero()) {
262                 normal.normalize();
263                 return (normal);
264         } else {                
265                 return (MT_Vector3(1.0,0,0));
266         }               
267 }