svn merge -r 15392:15551 https://svn.blender.org/svnroot/bf-blender/trunk/blender
[blender.git] / source / gameengine / Converter / BL_SkinDeformer.cpp
index ee298d70bafe4bc45fa171520d2f559278182357..d3442fe529811a2858333496e93afebf4520bc01 100644 (file)
@@ -1,15 +1,12 @@
 /**
  * $Id$
  *
- * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ * ***** BEGIN GPL LICENSE BLOCK *****
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version. The Blender
- * Foundation also sells licenses for use in proprietary software under
- * the Blender License.  See http://www.blender.org/BL/ for information
- * about this.
+ * of the License, or (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -27,7 +24,7 @@
  *
  * Contributor(s): none yet.
  *
- * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * ***** END GPL LICENSE BLOCK *****
  */
 
 #ifdef WIN32
 #include "BKE_action.h"
 #include "MT_Point3.h"
 
+extern "C"{
+       #include "BKE_lattice.h"
+}
+ #include "BKE_utildefines.h"
+
 #include "BLI_blenlib.h"
 #include "BLI_arithb.h"
 
 #define __NLA_DEFNORMALS
 //#undef __NLA_DEFNORMALS
 
-BL_SkinDeformer::~BL_SkinDeformer()
+BL_SkinDeformer::BL_SkinDeformer(BL_DeformableGameObject *gameobj,
+                                                               struct Object *bmeshobj, 
+                                                               class BL_SkinMeshObject *mesh,
+                                                               BL_ArmatureObject* arma)
+                                                       :       //
+                                                       BL_MeshDeformer(gameobj, bmeshobj, mesh),
+                                                       m_armobj(arma),
+                                                       m_lastArmaUpdate(-1),
+                                                       m_defbase(&bmeshobj->defbase),
+                                                       m_releaseobject(false)
 {
+       Mat4CpyMat4(m_obmat, bmeshobj->obmat);
 };
 
-/* XXX note, this __NLA_OLDDEFORM define seems to be obsolete */
+BL_SkinDeformer::BL_SkinDeformer(
+       BL_DeformableGameObject *gameobj,
+       struct Object *bmeshobj_old,    // Blender object that owns the new mesh
+       struct Object *bmeshobj_new,    // Blender object that owns the original mesh
+       class BL_SkinMeshObject *mesh,
+       bool release_object,
+       BL_ArmatureObject* arma)        :       
+               BL_MeshDeformer(gameobj, bmeshobj_old, mesh),
+               m_armobj(arma),
+               m_lastArmaUpdate(-1),
+               m_defbase(&bmeshobj_old->defbase),
+               m_releaseobject(release_object)
+       {
+               // this is needed to ensure correct deformation of mesh:
+               // the deformation is done with Blender's armature_deform_verts() function
+               // that takes an object as parameter and not a mesh. The object matrice is used
+               // in the calculation, so we must use the matrix of the original object to
+               // simulate a pure replacement of the mesh.
+               Mat4CpyMat4(m_obmat, bmeshobj_new->obmat);
+       }
 
-bool BL_SkinDeformer::Apply(RAS_IPolyMaterial *mat)
+BL_SkinDeformer::~BL_SkinDeformer()
 {
-       size_t                  i, j, index;
-       vecVertexArray  array;
-#ifdef __NLA_OLDDEFORM
-       vecMVertArray   mvarray;
-#else
-       vecIndexArrays  mvarray;
-#endif
-       vecMDVertArray  dvarray;
-       vecIndexArrays  diarray;
+       if(m_releaseobject && m_armobj)
+               m_armobj->Release();
+}
 
-       RAS_TexVert *tv;
-#ifdef __NLA_OLDDEFORM
-       MVert   *mvert;
-       MDeformVert     *dvert;
-#endif
-       MT_Point3 pt;
-//     float co[3];
+bool BL_SkinDeformer::Apply(RAS_IPolyMaterial *)
+{
+       size_t i, j;
 
-       if (!m_armobj)
+       if (!Update())
+               // no need to update the cache
                return false;
 
-       Update();
+       // Update all materials at once, so we can do the above update test
+       // without ending up with some materials not updated
+       for(RAS_MaterialBucket::Set::iterator mit = m_pMeshObject->GetFirstMaterial();
+               mit != m_pMeshObject->GetLastMaterial(); ++ mit) {
+               RAS_IPolyMaterial *mat = (*mit)->GetPolyMaterial();
 
-       array = m_pMeshObject->GetVertexCache(mat);
-#ifdef __NLA_OLDDEFORM
-       dvarray = m_pMeshObject->GetDVertCache(mat);
-#endif
-       mvarray = m_pMeshObject->GetMVertCache(mat);
-       diarray = m_pMeshObject->GetDIndexCache(mat);
-       
+               vecVertexArray& vertexarrays = m_pMeshObject->GetVertexCache(mat);
 
-       // For each array
-       for (i=0; i<array.size(); i++){
-               //      For each vertex
-               for (j=0; j<array[i]->size(); j++){
-
-                       tv = &((*array[i])[j]);
-                       
-                       index = ((*diarray[i])[j]);
-#ifdef __NLA_OLDDEFORM
-                       pt = tv->xyz();
-                       mvert = ((*mvarray[i])[index]);
-                       dvert = ((*dvarray[i])[index]);
-#endif
-                       
-                       //      Copy the untransformed data from the original mvert
-#ifdef __NLA_OLDDEFORM
-                       co[0]=mvert->co[0];
-                       co[1]=mvert->co[1];
-                       co[2]=mvert->co[2];
-
-                       //      Do the deformation
-/* XXX note, doesnt exist anymore */
-//                     GB_calc_armature_deform(co, dvert);
-                       tv->SetXYZ(co);
-#else
-                       //      Set the data
-                       tv->SetXYZ(m_transverts[((*mvarray[i])[index])]);
-#ifdef __NLA_DEFNORMALS
+               // For each array
+               for (i=0; i<vertexarrays.size(); i++) {
+                       KX_VertexArray& vertexarray = (*vertexarrays[i]);
 
-                       tv->SetNormal(m_transnors[((*mvarray[i])[index])]);
-#endif
-#endif
+                       // For each vertex
+                       // copy the untransformed data from the original mvert
+                       for (j=0; j<vertexarray.size(); j++) {
+                               RAS_TexVert& v = vertexarray[j];
+                               v.SetXYZ(m_transverts[v.getOrigIndex()]);
+                       }
                }
        }
-       
+
        return true;
 }
 
@@ -145,56 +143,53 @@ void BL_SkinDeformer::ProcessReplica()
 {
 }
 
-void BL_SkinDeformer::Update(void)
+//void where_is_pose (Object *ob);
+//void armature_deform_verts(Object *armOb, Object *target, float (*vertexCos)[3], int numVerts, int deformflag); 
+bool BL_SkinDeformer::Update(void)
 {
-
        /* See if the armature has been updated for this frame */
-       if (m_lastUpdate!=m_armobj->GetLastFrame()){    
-               
-               /* Do all of the posing necessary */
-               m_armobj->ApplyPose();
+       if (PoseUpdated()){     
+               float obmat[4][4];      // the original object matrice 
                
                /* XXX note: where_is_pose() (from BKE_armature.h) calculates all matrices needed to start deforming */
                /* but it requires the blender object pointer... */
-//             void where_is_pose (Object *ob);
-               
+
+               Object* par_arma = m_armobj->GetArmatureObject();
+               where_is_pose( par_arma ); 
+
                /* store verts locally */
-               for (int v =0; v<m_bmesh->totvert; v++){
-                       float co[3];
-                       /* XXX note, dunno about this line */
-                       m_transverts[v]=MT_Point3(m_bmesh->mvert[v].co);
-               }
-               
-               /* XXX note: now use this call instead */
-//             void armature_deform_verts(Object *armOb, Object *target, float (*vertexCos)[3], int numVerts, int deformflag) 
-               //              - armOb = armature object
-               //              - target = Mesh
-               //              - vertexCos[3] = array of numVerts float vectors (3 floats)
-               //              - set deformflag to ARM_DEF_VGROUP
-               //              example (after having filled the m_transverts array):
-               //              armature_deform_verts(m_armobj, m_meshobj, m_transverts, m_bmesh->totvert, ARM_DEF_VGROUP);
-               
                VerifyStorage();
-                       
-               RecalcNormals();
+       
+               /* duplicate */
+               for (int v =0; v<m_bmesh->totvert; v++)
+                       VECCOPY(m_transverts[v], m_bmesh->mvert[v].co);
+
+               // save matrix first
+               Mat4CpyMat4(obmat, m_objMesh->obmat);
+               // set reference matrix
+               Mat4CpyMat4(m_objMesh->obmat, m_obmat);
+
+               armature_deform_verts( par_arma, m_objMesh, NULL, m_transverts, NULL, m_bmesh->totvert, ARM_DEF_VGROUP, NULL, NULL );
                
+               // restore matrix 
+               Mat4CpyMat4(m_objMesh->obmat, obmat);
+
+#ifdef __NLA_DEFNORMALS
+               RecalcNormals();
+#endif
 
                /* Update the current frame */
-               m_lastUpdate=m_armobj->GetLastFrame();
+               m_lastArmaUpdate=m_armobj->GetLastFrame();
+               
+               /* indicate that the m_transverts and normals are up to date */
+               return true;
        }
+       return false;
 }
 
 /* XXX note: I propose to drop this function */
-
 void BL_SkinDeformer::SetArmature(BL_ArmatureObject *armobj)
 {
-//     m_armobj = armobj;
-
-//     for (bDeformGroup *dg=(bDeformGroup*)m_defbase->first; dg; dg=(bDeformGroup*)dg->next) {
-
-/*             dg->data no longer exists needs update
-                       dg->data = (void*)get_named_bone(m_armobj->GetArmature(), dg->name); */
-//     }
-               
-//             GB_validate_defgroups(m_bmesh, m_defbase);
+       // only used to set the object now
+       m_armobj = armobj;
 }