Get rid of c++ in blenkernel and modifiers
[blender.git] / source / gameengine / Converter / BL_MeshDeformer.cpp
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  * Simple deformation controller that restores a mesh to its rest position
29  */
30
31 /** \file gameengine/Converter/BL_MeshDeformer.cpp
32  *  \ingroup bgeconv
33  */
34
35
36 #if defined(WIN32) && !defined(FREE_WINDOWS)
37 // This warning tells us about truncation of __long__ stl-generated names.
38 // It can occasionally cause DevStudio to have internal compiler warnings.
39 #pragma warning( disable : 4786 )     
40 #endif
41
42 #include "RAS_IPolygonMaterial.h"
43 #include "BL_DeformableGameObject.h"
44 #include "BL_MeshDeformer.h"
45 #include "RAS_MeshObject.h"
46 #include "DNA_mesh_types.h"
47 #include "DNA_meshdata_types.h"
48
49 #include "CTR_Map.h"
50 #include "STR_HashedString.h"
51 #include "BLI_math.h"
52
53 bool BL_MeshDeformer::Apply(RAS_IPolyMaterial*)
54 {
55         size_t i;
56
57         // only apply once per frame if the mesh is actually modified
58         if(m_pMeshObject->MeshModified() &&
59            m_lastDeformUpdate != m_gameobj->GetLastFrame()) {
60                 // For each material
61                 for(list<RAS_MeshMaterial>::iterator mit= m_pMeshObject->GetFirstMaterial();
62                         mit != m_pMeshObject->GetLastMaterial(); ++ mit) {
63                         if(!mit->m_slots[(void*)m_gameobj])
64                                 continue;
65
66                         RAS_MeshSlot *slot = *mit->m_slots[(void*)m_gameobj];
67                         RAS_MeshSlot::iterator it;
68
69                         // for each array
70                         for(slot->begin(it); !slot->end(it); slot->next(it)) {
71                                 //      For each vertex
72                                 for(i=it.startvertex; i<it.endvertex; i++) {
73                                         RAS_TexVert& v = it.vertex[i];
74                                         v.SetXYZ(m_bmesh->mvert[v.getOrigIndex()].co);
75                                 }
76                         }
77                 }
78
79                 m_lastDeformUpdate = m_gameobj->GetLastFrame();
80
81                 return true;
82         }
83
84         return false;
85 }
86
87 BL_MeshDeformer::~BL_MeshDeformer()
88 {       
89         if (m_transverts)
90                 delete [] m_transverts;
91         if (m_transnors)
92                 delete [] m_transnors;
93 }
94  
95 void BL_MeshDeformer::ProcessReplica()
96 {
97         m_transverts = NULL;
98         m_transnors = NULL;
99         m_tvtot = 0;
100         m_bDynamic=false;
101         m_lastDeformUpdate = -1;
102 }
103
104 void BL_MeshDeformer::Relink(CTR_Map<class CTR_HashedPtr, void*>*map)
105 {
106         void **h_obj = (*map)[m_gameobj];
107
108         if (h_obj)
109                 m_gameobj = (BL_DeformableGameObject*)(*h_obj);
110         else
111                 m_gameobj = NULL;
112 }
113
114 /**
115  * @warning This function is expensive!
116  */
117 void BL_MeshDeformer::RecalcNormals()
118 {
119         /* We don't normalize for performance, not doing it for faces normals
120          * gives area-weight normals which often look better anyway, and use
121          * GL_NORMALIZE so we don't have to do per vertex normalization either
122          * since the GPU can do it faster */
123         list<RAS_MeshMaterial>::iterator mit;
124         RAS_MeshSlot::iterator it;
125         size_t i;
126
127         /* set vertex normals to zero */
128         memset(m_transnors, 0, sizeof(float)*3*m_bmesh->totvert);
129
130         /* add face normals to vertices. */
131         for(mit = m_pMeshObject->GetFirstMaterial();
132                 mit != m_pMeshObject->GetLastMaterial(); ++ mit) {
133                 if(!mit->m_slots[(void*)m_gameobj])
134                         continue;
135
136                 RAS_MeshSlot *slot = *mit->m_slots[(void*)m_gameobj];
137
138                 for(slot->begin(it); !slot->end(it); slot->next(it)) {
139                         int nvert = (int)it.array->m_type;
140
141                         for(i=0; i<it.totindex; i+=nvert) {
142                                 RAS_TexVert& v1 = it.vertex[it.index[i]];
143                                 RAS_TexVert& v2 = it.vertex[it.index[i+1]];
144                                 RAS_TexVert& v3 = it.vertex[it.index[i+2]];
145                                 RAS_TexVert *v4 = NULL;
146
147                                 const float *co1 = m_transverts[v1.getOrigIndex()];
148                                 const float *co2 = m_transverts[v2.getOrigIndex()];
149                                 const float *co3 = m_transverts[v3.getOrigIndex()];
150                                 const float *co4 = NULL;
151                                 
152                                 /* compute face normal */
153                                 float fnor[3], n1[3], n2[3];
154
155                                 if(nvert == 4) {
156                                         v4 = &it.vertex[it.index[i+3]];
157                                         co4 = m_transverts[v4->getOrigIndex()];
158
159                                         n1[0]= co1[0]-co3[0];
160                                         n1[1]= co1[1]-co3[1];
161                                         n1[2]= co1[2]-co3[2];
162
163                                         n2[0]= co2[0]-co4[0];
164                                         n2[1]= co2[1]-co4[1];
165                                         n2[2]= co2[2]-co4[2];
166                                 }
167                                 else {
168                                         n1[0]= co1[0]-co2[0];
169                                         n2[0]= co2[0]-co3[0];
170                                         n1[1]= co1[1]-co2[1];
171
172                                         n2[1]= co2[1]-co3[1];
173                                         n1[2]= co1[2]-co2[2];
174                                         n2[2]= co2[2]-co3[2];
175                                 }
176
177                                 fnor[0]= n1[1]*n2[2] - n1[2]*n2[1];
178                                 fnor[1]= n1[2]*n2[0] - n1[0]*n2[2];
179                                 fnor[2]= n1[0]*n2[1] - n1[1]*n2[0];
180                                 normalize_v3(fnor);
181
182                                 /* add to vertices for smooth normals */
183                                 float *vn1 = m_transnors[v1.getOrigIndex()];
184                                 float *vn2 = m_transnors[v2.getOrigIndex()];
185                                 float *vn3 = m_transnors[v3.getOrigIndex()];
186
187                                 vn1[0] += fnor[0]; vn1[1] += fnor[1]; vn1[2] += fnor[2];
188                                 vn2[0] += fnor[0]; vn2[1] += fnor[1]; vn2[2] += fnor[2];
189                                 vn3[0] += fnor[0]; vn3[1] += fnor[1]; vn3[2] += fnor[2];
190
191                                 if(v4) {
192                                         float *vn4 = m_transnors[v4->getOrigIndex()];
193                                         vn4[0] += fnor[0]; vn4[1] += fnor[1]; vn4[2] += fnor[2];
194                                 }
195
196                                 /* in case of flat - just assign, the vertices are split */
197                                 if(v1.getFlag() & RAS_TexVert::FLAT) {
198                                         v1.SetNormal(fnor);
199                                         v2.SetNormal(fnor);
200                                         v3.SetNormal(fnor);
201                                         if(v4)
202                                                 v4->SetNormal(fnor);
203                                 }
204                         }
205                 }
206         }
207
208         /* assign smooth vertex normals */
209         for(mit = m_pMeshObject->GetFirstMaterial();
210                 mit != m_pMeshObject->GetLastMaterial(); ++ mit) {
211                 if(!mit->m_slots[(void*)m_gameobj])
212                         continue;
213
214                 RAS_MeshSlot *slot = *mit->m_slots[(void*)m_gameobj];
215
216                 for(slot->begin(it); !slot->end(it); slot->next(it)) {
217                         for(i=it.startvertex; i<it.endvertex; i++) {
218                                 RAS_TexVert& v = it.vertex[i];
219
220                                 if(!(v.getFlag() & RAS_TexVert::FLAT))
221                                         v.SetNormal(m_transnors[v.getOrigIndex()]); //.safe_normalized()
222                         }
223                 }
224         }
225 }
226
227 void BL_MeshDeformer::VerifyStorage()
228 {
229         /* Ensure that we have the right number of verts assigned */
230         if (m_tvtot!=m_bmesh->totvert){
231                 if (m_transverts)
232                         delete [] m_transverts;
233                 if (m_transnors)
234                         delete [] m_transnors;
235                 
236                 m_transverts=new float[m_bmesh->totvert][3];
237                 m_transnors=new float[m_bmesh->totvert][3];
238                 m_tvtot = m_bmesh->totvert;
239         }
240 }
241