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