use const for readonly strings and set some functions to static
[blender.git] / source / gameengine / Converter / BL_SkinDeformer.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  */
27
28 /** \file gameengine/Converter/BL_SkinDeformer.cpp
29  *  \ingroup bgeconv
30  */
31
32
33 #if defined(WIN32) && !defined(FREE_WINDOWS)
34 #pragma warning (disable : 4786)
35 #endif //WIN32
36
37 // Eigen3 stuff used for BGEDeformVerts
38 #include <Eigen/Core>
39 #include <Eigen/LU>
40
41 #include "BL_SkinDeformer.h"
42 #include "CTR_Map.h"
43 #include "STR_HashedString.h"
44 #include "RAS_IPolygonMaterial.h"
45 #include "RAS_MeshObject.h"
46
47 //#include "BL_ArmatureController.h"
48 #include "DNA_armature_types.h"
49 #include "DNA_action_types.h"
50 #include "DNA_mesh_types.h"
51 #include "DNA_meshdata_types.h"
52 #include "BLI_utildefines.h"
53 #include "BKE_armature.h"
54 #include "BKE_action.h"
55 #include "MT_Point3.h"
56
57 extern "C"{
58         #include "BKE_lattice.h"
59         #include "BKE_deform.h"
60 }
61  
62
63 #include "BLI_blenlib.h"
64 #include "BLI_math.h"
65
66 #define __NLA_DEFNORMALS
67 //#undef __NLA_DEFNORMALS
68
69 BL_SkinDeformer::BL_SkinDeformer(BL_DeformableGameObject *gameobj,
70                                                                 struct Object *bmeshobj, 
71                                                                 class RAS_MeshObject *mesh,
72                                                                 BL_ArmatureObject* arma)
73                                                         :       //
74                                                         BL_MeshDeformer(gameobj, bmeshobj, mesh),
75                                                         m_armobj(arma),
76                                                         m_lastArmaUpdate(-1),
77                                                         //m_defbase(&bmeshobj->defbase),
78                                                         m_releaseobject(false),
79                                                         m_poseApplied(false),
80                                                         m_recalcNormal(true),
81                                                         m_copyNormals(false),
82                                                         m_dfnrToPC(NULL)
83 {
84         copy_m4_m4(m_obmat, bmeshobj->obmat);
85 };
86
87 BL_SkinDeformer::BL_SkinDeformer(
88         BL_DeformableGameObject *gameobj,
89         struct Object *bmeshobj_old,    // Blender object that owns the new mesh
90         struct Object *bmeshobj_new,    // Blender object that owns the original mesh
91         class RAS_MeshObject *mesh,
92         bool release_object,
93         bool recalc_normal,
94         BL_ArmatureObject* arma)        :       
95                 BL_MeshDeformer(gameobj, bmeshobj_old, mesh),
96                 m_armobj(arma),
97                 m_lastArmaUpdate(-1),
98                 //m_defbase(&bmeshobj_old->defbase),
99                 m_releaseobject(release_object),
100                 m_recalcNormal(recalc_normal),
101                 m_copyNormals(false),
102                 m_dfnrToPC(NULL)
103         {
104                 // this is needed to ensure correct deformation of mesh:
105                 // the deformation is done with Blender's armature_deform_verts() function
106                 // that takes an object as parameter and not a mesh. The object matrice is used
107                 // in the calculation, so we must use the matrix of the original object to
108                 // simulate a pure replacement of the mesh.
109                 copy_m4_m4(m_obmat, bmeshobj_new->obmat);
110         }
111
112 BL_SkinDeformer::~BL_SkinDeformer()
113 {
114         if(m_releaseobject && m_armobj)
115                 m_armobj->Release();
116         if(m_dfnrToPC)
117                 delete [] m_dfnrToPC;
118 }
119
120 void BL_SkinDeformer::Relink(CTR_Map<class CTR_HashedPtr, void*>*map)
121 {
122         if (m_armobj) {
123                 void **h_obj = (*map)[m_armobj];
124
125                 if (h_obj)
126                         m_armobj = (BL_ArmatureObject*)(*h_obj);
127                 else
128                         m_armobj=NULL;
129         }
130
131         BL_MeshDeformer::Relink(map);
132 }
133
134 bool BL_SkinDeformer::Apply(RAS_IPolyMaterial *mat)
135 {
136         RAS_MeshSlot::iterator it;
137         RAS_MeshMaterial *mmat;
138         RAS_MeshSlot *slot;
139         size_t i, nmat, imat;
140
141         // update the vertex in m_transverts
142         if (!Update())
143                 return false;
144
145         if (m_transverts) {
146                 // the vertex cache is unique to this deformer, no need to update it
147                 // if it wasn't updated! We must update all the materials at once
148                 // because we will not get here again for the other material
149                 nmat = m_pMeshObject->NumMaterials();
150                 for (imat=0; imat<nmat; imat++) {
151                         mmat = m_pMeshObject->GetMeshMaterial(imat);
152                         if(!mmat->m_slots[(void*)m_gameobj])
153                                 continue;
154
155                         slot = *mmat->m_slots[(void*)m_gameobj];
156
157                         // for each array
158                         for(slot->begin(it); !slot->end(it); slot->next(it)) {
159                                 // for each vertex
160                                 // copy the untransformed data from the original mvert
161                                 for(i=it.startvertex; i<it.endvertex; i++) {
162                                         RAS_TexVert& v = it.vertex[i];
163                                         v.SetXYZ(m_transverts[v.getOrigIndex()]);
164                                         if (m_copyNormals)
165                                                 v.SetNormal(m_transnors[v.getOrigIndex()]);
166                                 }
167                         }
168                 }
169
170                 if (m_copyNormals)
171                         m_copyNormals = false;
172         }
173         return true;
174 }
175
176 RAS_Deformer *BL_SkinDeformer::GetReplica()
177 {
178         BL_SkinDeformer *result;
179
180         result = new BL_SkinDeformer(*this);
181         /* there is m_armobj that must be fixed but we cannot do it now, it will be done in Relink */
182         result->ProcessReplica();
183         return result;
184 }
185
186 void BL_SkinDeformer::ProcessReplica()
187 {
188         BL_MeshDeformer::ProcessReplica();
189         m_lastArmaUpdate = -1;
190         m_releaseobject = false;
191         m_dfnrToPC = NULL;
192 }
193
194 void BL_SkinDeformer::BlenderDeformVerts()
195 {
196         float obmat[4][4];      // the original object matrix
197         Object* par_arma = m_armobj->GetArmatureObject();
198
199         // save matrix first
200         copy_m4_m4(obmat, m_objMesh->obmat);
201         // set reference matrix
202         copy_m4_m4(m_objMesh->obmat, m_obmat);
203
204         armature_deform_verts( par_arma, m_objMesh, NULL, m_transverts, NULL, m_bmesh->totvert, ARM_DEF_VGROUP, NULL, NULL );
205                 
206         // restore matrix 
207         copy_m4_m4(m_objMesh->obmat, obmat);
208
209 #ifdef __NLA_DEFNORMALS
210                 if (m_recalcNormal)
211                         RecalcNormals();
212 #endif
213 }
214
215 void BL_SkinDeformer::BGEDeformVerts()
216 {
217         Object *par_arma = m_armobj->GetArmatureObject();
218         MDeformVert *dverts = m_bmesh->dvert;
219         bDeformGroup *dg;
220         int numGroups = BLI_countlist(&m_objMesh->defbase);
221
222         if (!dverts)
223                 return;
224
225         if (m_dfnrToPC == NULL)
226         {
227                 m_dfnrToPC = new bPoseChannel*[numGroups];
228                 int i;
229                 for (i=0, dg=(bDeformGroup*)m_objMesh->defbase.first;
230                         dg;
231                         ++i, dg=(bDeformGroup*)dg->next)
232                 {
233                         m_dfnrToPC[i] = get_pose_channel(par_arma->pose, dg->name);
234
235                         if (m_dfnrToPC[i] && m_dfnrToPC[i]->bone->flag & BONE_NO_DEFORM)
236                                 m_dfnrToPC[i] = NULL;
237                 }
238         }
239
240
241         for (int i=0; i<m_bmesh->totvert; ++i)
242         {
243                 float contrib = 0.f, weight, max_weight=0.f;
244                 bPoseChannel *pchan=NULL;
245                 MDeformVert *dvert;
246                 Eigen::Map<Eigen::Vector3f> norm(m_transnors[i]);
247                 Eigen::Vector4f vec(0, 0, 0, 1);
248                 Eigen::Matrix4f norm_chan_mat;
249                 Eigen::Vector4f co(m_transverts[i][0],
250                                                         m_transverts[i][1],
251                                                         m_transverts[i][2],
252                                                         1.f);
253
254                 dvert = dverts+i;
255
256                 if (!dvert->totweight)
257                         continue;
258
259                 for (int j=0; j<dvert->totweight; ++j)
260                 {
261                         int index = dvert->dw[j].def_nr;
262
263                         if (index < numGroups && (pchan=m_dfnrToPC[index]))
264                         {
265                                 weight = dvert->dw[j].weight;
266
267                                 if (weight)
268                                 {
269                                         Eigen::Vector4f cop(co);
270                                         Eigen::Matrix4f chan_mat = Eigen::Matrix4f::Map((float*)pchan->chan_mat);
271
272                                         // Update Vertex Position
273                                         cop = chan_mat*cop;
274                                         vec += (cop - co)*weight;
275
276                                         // Save the most influential channel so we can use it to update the vertex normal
277                                         if (weight > max_weight)
278                                         {
279                                                 max_weight = weight;
280                                                 norm_chan_mat = chan_mat;
281                                         }
282
283                                         contrib += weight;
284                                 }
285                         }
286                 }
287
288                 
289                 // Update Vertex Normal
290                 norm = norm_chan_mat.topLeftCorner<3, 3>()*norm;
291                                 
292                 if (contrib > 0.0001f)
293                 {
294                         vec *= 1.f/contrib;
295                         co += vec;
296                 }
297
298                 m_transverts[i][0] = co[0];
299                 m_transverts[i][1] = co[1];
300                 m_transverts[i][2] = co[2];
301         }
302         m_copyNormals = true;
303 }
304
305 bool BL_SkinDeformer::UpdateInternal(bool shape_applied)
306 {
307         /* See if the armature has been updated for this frame */
308         if (PoseUpdated()){     
309
310                 if(!shape_applied) {
311                         /* store verts locally */
312                         VerifyStorage();
313                 
314                         /* duplicate */
315                         for (int v =0; v<m_bmesh->totvert; v++)
316                         {
317                                 copy_v3_v3(m_transverts[v], m_bmesh->mvert[v].co);
318                                 normal_short_to_float_v3(m_transnors[v], m_bmesh->mvert[v].no);
319                         }
320                 }
321
322                 m_armobj->ApplyPose();
323
324                 switch (m_armobj->GetVertDeformType())
325                 {
326                         case ARM_VDEF_BGE_CPU:
327                                 BGEDeformVerts();
328                                 break;
329                         case ARM_VDEF_BLENDER:
330                         default:
331                                 BlenderDeformVerts();
332                 }
333
334                 /* Update the current frame */
335                 m_lastArmaUpdate=m_armobj->GetLastFrame();
336
337                 m_armobj->RestorePose();
338                 /* dynamic vertex, cannot use display list */
339                 m_bDynamic = true;
340                 /* indicate that the m_transverts and normals are up to date */
341                 return true;
342         }
343
344         return false;
345 }
346
347 bool BL_SkinDeformer::Update(void)
348 {
349         return UpdateInternal(false);
350 }
351
352 /* XXX note: I propose to drop this function */
353 void BL_SkinDeformer::SetArmature(BL_ArmatureObject *armobj)
354 {
355         // only used to set the object now
356         m_armobj = armobj;
357 }