BGE: support modifiers without mapping to original mesh both graphically and physically, fixes bug #24942 and #25286.

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.
This commit is contained in:
2011-01-23 17:17:21 +00:00
parent fa38da021c
commit fc66b3f2ef
12 changed files with 104 additions and 7 deletions

View 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 *,

View 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)

View 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);
}
}

View 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();

View 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;

View 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;

View 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.

View 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;
}

View 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?? */

View 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;

View 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;

View 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;
}