BGE: support modifiers without mapping to original mesh both graphically and physical...
authorBenoit Bolsee <benoit.bolsee@online.be>
Sun, 23 Jan 2011 17:17:21 +0000 (17:17 +0000)
committerBenoit Bolsee <benoit.bolsee@online.be>
Sun, 23 Jan 2011 17:17:21 +0000 (17:17 +0000)
Support for physics is done by skiping the modifiers that
don't support mapping to original mesh. This mapping is
required to report the hit polygon to the application
by the rayCast() function.

Support for graphics is done by using the same render
function that blender uses for the 3D view. This guantees
equal result.

Limitation: there is still a known bug if all these conditions are met:
- Display list enabled
- Old tex face with a several textures mapped to the same material
- no armature or shape keys
- active modifiers

In this case, only a part of the mesh will be rendered
with the wrong texture. To avoid this bug, use the GLSL
materials or make sure to have 1 material=1 texture in
your old tex face objects.

12 files changed:
source/blender/blenkernel/BKE_DerivedMesh.h
source/blender/blenkernel/intern/DerivedMesh.c
source/gameengine/Converter/BL_BlenderDataConversion.cpp
source/gameengine/Converter/BL_ModifierDeformer.cpp
source/gameengine/Converter/BL_ModifierDeformer.h
source/gameengine/Ketsji/KX_PolygonMaterial.cpp
source/gameengine/Ketsji/KX_PolygonMaterial.h
source/gameengine/Physics/Bullet/CcdPhysicsController.cpp
source/gameengine/Rasterizer/RAS_Deformer.h
source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp
source/gameengine/Rasterizer/RAS_IPolygonMaterial.h
source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp

index 5b33d9e1c536372b49f1584b2e51e1a10e432756..5ce6c522e9011c2cdfd858275c6739ce815e7aa0 100644 (file)
@@ -492,6 +492,8 @@ DerivedMesh *mesh_create_derived_no_deform_render(struct Scene *scene, struct Ob
 /* for gameengine */
 DerivedMesh *mesh_create_derived_no_virtual(struct Scene *scene, struct Object *ob, float (*vertCos)[3],
                                                                                        CustomDataMask dataMask);
+DerivedMesh *mesh_create_derived_physics(struct Scene *scene, struct Object *ob, float (*vertCos)[3],
+                                                                                       CustomDataMask dataMask);
 
 DerivedMesh *editmesh_get_derived_base(struct Object *, struct EditMesh *em);
 DerivedMesh *editmesh_get_derived_cage(struct Scene *scene, struct Object *, 
index c733a560620fafbfda8b063a946a733b1cb63866..a2ef625c6e6de6122bfac9d6dbee8ddcd63101eb 100644 (file)
@@ -2358,6 +2358,16 @@ DerivedMesh *mesh_create_derived_no_virtual(Scene *scene, Object *ob, float (*ve
        return final;
 }
 
+DerivedMesh *mesh_create_derived_physics(Scene *scene, Object *ob, float (*vertCos)[3],
+                                                                                       CustomDataMask dataMask)
+{
+       DerivedMesh *final;
+       
+       mesh_calc_modifiers(scene, ob, vertCos, NULL, &final, 0, -1, 1, dataMask, -1, 0);
+
+       return final;
+}
+
 DerivedMesh *mesh_create_derived_no_deform_render(Scene *scene, Object *ob,
                                                                                                  float (*vertCos)[3],
                                                                                                  CustomDataMask dataMask)
index 3cdc688f55d4239fbe5df518dee8c9928819c7ff..ab9882cab874d75585d4584d8d0adf574e13e5aa 100644 (file)
@@ -1525,7 +1525,7 @@ void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj,
        KX_BoxBounds bb;
        DerivedMesh* dm = NULL;
        if (gameobj->GetDeformer())
-               dm = gameobj->GetDeformer()->GetFinalMesh();
+               dm = gameobj->GetDeformer()->GetPhysicsMesh();
        my_get_local_bounds(blenderobject,dm,objprop.m_boundobject.box.m_center,bb.m_extends);
        if (blenderobject->gameflag & OB_BOUNDS)
        {
@@ -1618,6 +1618,10 @@ void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj,
        }
        delete shapeprops;
        delete smmaterial;
+       if (dm) {
+               dm->needsFree = 1;
+               dm->release(dm);
+       }
 }
 
 
index 5eb25b05567aae48e7dad66a18a86d747352e9e7..205892f5c774f66632498faea5b0fd413eff90b2 100644 (file)
@@ -135,6 +135,30 @@ bool BL_ModifierDeformer::HasArmatureDeformer(Object *ob)
        return false;
 }
 
+// return a deformed mesh that supports mapping (with a valid CD_ORIGINDEX layer)
+struct DerivedMesh* BL_ModifierDeformer::GetPhysicsMesh()
+{
+       // we need to compute the deformed mesh taking into account the current
+       // shape and skin deformers, we cannot just call mesh_create_derived_physics()
+       // because that would use the m_transvers already deformed previously by BL_ModifierDeformer::Update(),
+       // so restart from scratch by forcing a full update the shape/skin deformers 
+       // (will do nothing if there is no such deformer)
+       BL_ShapeDeformer::ForceUpdate();
+       BL_ShapeDeformer::Update();
+       // now apply the modifiers but without those that don't support mapping
+       Object* blendobj = m_gameobj->GetBlendObject();
+       /* hack: the modifiers require that the mesh is attached to the object
+          It may not be the case here because of replace mesh actuator */
+       Mesh *oldmesh = (Mesh*)blendobj->data;
+       blendobj->data = m_bmesh;
+       DerivedMesh *dm = mesh_create_derived_physics(m_scene, blendobj, m_transverts, CD_MASK_MESH);
+       /* restore object data */
+       blendobj->data = oldmesh;
+       /* m_transverts is correct here (takes into account deform only modifiers) */
+       /* the derived mesh returned by this function must be released by the caller !!! */
+       return dm;
+}
+
 bool BL_ModifierDeformer::Update(void)
 {
        bool bShapeUpdate = BL_ShapeDeformer::Update();
index 49998f36ccb15f84231b0b463b905cbbc8670710..caf1741ecaf330c6498e2d0ce6fb60ee806880bc 100644 (file)
@@ -95,7 +95,8 @@ public:
        {
                return m_dm;
        }
-
+       // The derived mesh returned by this function must be released!
+       virtual struct DerivedMesh* GetPhysicsMesh();
 
 protected:
        double                                   m_lastModifierUpdate;
index 57e11e02d5a5fe500a5494cbc01aba8c9c051a0d..1f4a34916954651fd942f8f743b7549ecc9f74b2 100644 (file)
@@ -108,6 +108,11 @@ KX_PolygonMaterial::~KX_PolygonMaterial()
 #endif // WITH_PYTHON
 }
 
+Image *KX_PolygonMaterial::GetBlenderImage() const
+{
+       return (m_tface) ? m_tface->tpage : NULL;
+}
+
 bool KX_PolygonMaterial::Activate(RAS_IRasterizer* rasty, TCachingInfo& cachingInfo) const 
 {
        bool dopass = false;
index 17adbac79c023335650a5d677b8e2cc32095f538..d71a34989a0506aee02259772750cfab81810426 100644 (file)
@@ -42,6 +42,7 @@
 struct MTFace;
 struct Material;
 struct MTex;
+struct Image;
 
 /**
  *  Material class.
@@ -107,6 +108,8 @@ public:
                return m_material;
        }
 
+       Image *GetBlenderImage() const;
+
        /**
         * Returns the Blender texture face structure that is used for this material.
         * @return The material's texture face.
index 54f98d16cf6555513ab30acc5a4c837271f199bc..8d3c1565d3adbaa6bac4e210f3b2e28422ab1154 100644 (file)
@@ -1694,12 +1694,16 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA
                return false;
 
        RAS_Deformer *deformer= gameobj ? gameobj->GetDeformer():NULL;
+       DerivedMesh* dm = NULL;
+
+       if (deformer)
+               dm = deformer->GetPhysicsMesh();
        
        /* get the mesh from the object if not defined */
        if(meshobj==NULL) {
                
                /* modifier mesh */
-               if(deformer && deformer->GetFinalMesh())
+               if(dm)
                        meshobj= deformer->GetRasMesh();
                
                /* game object first mesh */
@@ -1710,14 +1714,12 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA
                }
        }
        
-       if(deformer && deformer->GetFinalMesh() && deformer->GetRasMesh() == meshobj)
+       if(dm && deformer->GetRasMesh() == meshobj)
        {       /*
                 * Derived Mesh Update
                 *
                 * */
 
-               DerivedMesh* dm= gameobj->GetDeformer()->GetFinalMesh();
-
                MVert *mvert = dm->getVertArray(dm);
                MFace *mface = dm->getFaceArray(dm);
                numpolys = dm->getNumFaces(dm);
@@ -1977,6 +1979,10 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA
 
        m_meshObject= meshobj;
        
+       if (dm) {
+               dm->needsFree = 1;
+               dm->release(dm);
+       }
        return true;
 }
 
index f61ac7ea18ab5e44537ac7c6f209c4b93f7a6499..37543092e6858586e400eaed785fef2bcb2ab87d 100644 (file)
@@ -76,6 +76,10 @@ public:
        {
                return NULL;
        }
+       virtual struct DerivedMesh* GetPhysicsMesh()
+       {
+               return NULL;
+       }
        virtual class RAS_MeshObject* GetRasMesh()
        {
                /* m_pMesh does not seem to be being used?? */
index 0c81d7d82744a874f1da042cb2007e9e83e7b931..00f1f5f2848c7d5e2c98b88cba7d1af2c781696c 100644 (file)
@@ -208,6 +208,11 @@ Material *RAS_IPolyMaterial::GetBlenderMaterial() const
        return NULL;
 }
 
+Image *RAS_IPolyMaterial::GetBlenderImage() const
+{
+       return NULL;
+}
+
 Scene* RAS_IPolyMaterial::GetBlenderScene() const
 {
        return NULL;
index e7bd78c23094a0cccca842fa99a5f36109de6c87..59554e31c367b083dbea5c2166ddd5dd97707a28 100644 (file)
@@ -45,6 +45,7 @@
 class RAS_IRasterizer;
 struct MTFace;
 struct Material;
+struct Image;
 struct Scene;
 class SCA_IScene;
 
@@ -160,6 +161,7 @@ public:
        int                                     GetMaterialIndex() const;
 
        virtual Material*   GetBlenderMaterial() const;
+       virtual Image*      GetBlenderImage() const;
        virtual Scene*          GetBlenderScene() const;
        virtual void            ReleaseMaterial();
        virtual void            GetMaterialRGBAColor(unsigned char *rgba) const;
index e8c2db5526a8786f2a0aad6b16242f877b16f652..c2859394176d9d5e68487ee9e529b43309452b20 100644 (file)
@@ -731,6 +731,7 @@ static RAS_MeshSlot *current_ms;
 static RAS_MeshObject *current_mesh;
 static int current_blmat_nr;
 static GPUVertexAttribs current_gpu_attribs;
+static Image *current_image;
 static int CheckMaterialDM(int matnr, void *attribs)
 {
        // only draw the current material
@@ -769,6 +770,33 @@ static int CheckTexfaceDM(void *mcol, int index)
        return 0;
 }
 
+static int CheckTexDM(MTFace *tface, MCol *mcol, int matnr)
+{
+
+       // index is the original face index, retrieve the polygon
+       if (matnr == current_blmat_nr &&
+               (tface == NULL || tface->tpage == current_image)) {
+               // must handle color.
+               if (current_wireframe)
+                       return 2;
+               if (current_ms->m_bObjectColor) {
+                       MT_Vector4& rgba = current_ms->m_RGBAcolor;
+                       glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]);
+                       // don't use mcol
+                       return 2;
+               }
+               if (!mcol) {
+                       // we have to set the color from the material
+                       unsigned char rgba[4];
+                       current_polymat->GetMaterialRGBAColor(rgba);
+                       glColor4ubv((const GLubyte *)rgba);
+                       return 2;
+               }
+               return 1;
+       }
+       return 0;
+}
+
 void RAS_OpenGLRasterizer::IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi)
 { 
        bool obcolor = ms.m_bObjectColor;
@@ -807,7 +835,10 @@ void RAS_OpenGLRasterizer::IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi)
                        ms.m_pDerivedMesh->drawFacesGLSL(ms.m_pDerivedMesh, CheckMaterialDM);
                        GPU_set_material_blend_mode(current_blend_mode);
                } else {
-                       ms.m_pDerivedMesh->drawMappedFacesTex(ms.m_pDerivedMesh, CheckTexfaceDM, mcol);
+                       //ms.m_pDerivedMesh->drawMappedFacesTex(ms.m_pDerivedMesh, CheckTexfaceDM, mcol);
+                       current_blmat_nr = current_polymat->GetMaterialIndex();
+                       current_image = current_polymat->GetBlenderImage();
+                       ms.m_pDerivedMesh->drawFacesTex(ms.m_pDerivedMesh, CheckTexDM);
                }
                return;
        }