svn merge -r 15392:15551 https://svn.blender.org/svnroot/bf-blender/trunk/blender
[blender.git] / source / gameengine / Converter / BL_SkinDeformer.cpp
index e9ec6f9116b302d66d6f7f9f7b08e2ee8d3eca92..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
@@ -60,82 +57,76 @@ extern "C"{
 #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)
 {
-       if(m_releaseobject && m_armobj)
-               m_armobj->Release();
+       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;
 }
 
@@ -154,13 +145,11 @@ void BL_SkinDeformer::ProcessReplica()
 
 //void where_is_pose (Object *ob);
 //void armature_deform_verts(Object *armOb, Object *target, float (*vertexCos)[3], int numVerts, int deformflag); 
-void BL_SkinDeformer::Update(void)
+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... */
@@ -175,12 +164,27 @@ void BL_SkinDeformer::Update(void)
                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 */