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