BGE patch: approve patch #17312: Multiple material IPOs per mesh in BGE.

This commit is contained in:
Benoit Bolsee 2008-07-25 13:45:57 +00:00
parent ab44742cf3
commit a7f951f25e
11 changed files with 96 additions and 29 deletions

@ -1989,10 +1989,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
gameobj->NodeUpdateGS(0,true);
BL_ConvertIpos(blenderobject,gameobj,converter);
// TODO: expand to multiple ipos per mesh
Material *mat = give_current_material(blenderobject, 1);
if(mat) BL_ConvertMaterialIpos(mat, gameobj, converter);
BL_ConvertMaterialIpos(blenderobject, gameobj, converter);
sumolist->Add(gameobj->AddRef());
BL_ConvertProperties(blenderobject,gameobj,timemgr,kxscene,isInActiveLayer);
@ -2171,9 +2169,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
gameobj->NodeUpdateGS(0,true);
BL_ConvertIpos(blenderobject,gameobj,converter);
// TODO: expand to multiple ipos per mesh
Material *mat = give_current_material(blenderobject, 1);
if(mat) BL_ConvertMaterialIpos(mat, gameobj, converter);
BL_ConvertMaterialIpos(blenderobject,gameobj, converter);
sumolist->Add(gameobj->AddRef());

@ -36,6 +36,7 @@
#pragma warning (disable:4786)
#endif
#include "BKE_material.h" /* give_current_material */
#include "KX_GameObject.h"
#include "KX_IpoConvert.h"
@ -68,6 +69,8 @@
#include "SG_Node.h"
#include "STR_HashedString.h"
static BL_InterpolatorList *GetIpoList(struct Ipo *for_ipo, KX_BlenderSceneConverter *converter) {
BL_InterpolatorList *ipoList= converter->FindInterpolatorList(for_ipo);
@ -560,16 +563,15 @@ void BL_ConvertWorldIpos(struct World* blenderworld,KX_BlenderSceneConverter *co
}
}
void BL_ConvertMaterialIpos(
Material* blendermaterial,
static void ConvertMaterialIpos(
Material* blendermaterial,
dword matname_hash,
KX_GameObject* gameobj,
KX_BlenderSceneConverter *converter
)
{
if (blendermaterial->ipo) {
KX_MaterialIpoController* ipocontr = new KX_MaterialIpoController();
KX_MaterialIpoController* ipocontr = new KX_MaterialIpoController(matname_hash);
gameobj->GetSGNode()->AddSGController(ipocontr);
ipocontr->SetObject(gameobj->GetSGNode());
@ -596,7 +598,7 @@ void BL_ConvertMaterialIpos(
ipo = ipoList->GetScalarInterpolator(MA_COL_R);
if (ipo) {
if (!ipocontr) {
ipocontr = new KX_MaterialIpoController();
ipocontr = new KX_MaterialIpoController(matname_hash);
gameobj->GetSGNode()->AddSGController(ipocontr);
ipocontr->SetObject(gameobj->GetSGNode());
}
@ -610,7 +612,7 @@ void BL_ConvertMaterialIpos(
ipo = ipoList->GetScalarInterpolator(MA_COL_G);
if (ipo) {
if (!ipocontr) {
ipocontr = new KX_MaterialIpoController();
ipocontr = new KX_MaterialIpoController(matname_hash);
gameobj->GetSGNode()->AddSGController(ipocontr);
ipocontr->SetObject(gameobj->GetSGNode());
}
@ -624,7 +626,7 @@ void BL_ConvertMaterialIpos(
ipo = ipoList->GetScalarInterpolator(MA_COL_B);
if (ipo) {
if (!ipocontr) {
ipocontr = new KX_MaterialIpoController();
ipocontr = new KX_MaterialIpoController(matname_hash);
gameobj->GetSGNode()->AddSGController(ipocontr);
ipocontr->SetObject(gameobj->GetSGNode());
}
@ -638,7 +640,7 @@ void BL_ConvertMaterialIpos(
ipo = ipoList->GetScalarInterpolator(MA_ALPHA);
if (ipo) {
if (!ipocontr) {
ipocontr = new KX_MaterialIpoController();
ipocontr = new KX_MaterialIpoController(matname_hash);
gameobj->GetSGNode()->AddSGController(ipocontr);
ipocontr->SetObject(gameobj->GetSGNode());
}
@ -653,7 +655,7 @@ void BL_ConvertMaterialIpos(
ipo = ipoList->GetScalarInterpolator(MA_SPEC_R );
if (ipo) {
if (!ipocontr) {
ipocontr = new KX_MaterialIpoController();
ipocontr = new KX_MaterialIpoController(matname_hash);
gameobj->GetSGNode()->AddSGController(ipocontr);
ipocontr->SetObject(gameobj->GetSGNode());
}
@ -667,7 +669,7 @@ void BL_ConvertMaterialIpos(
ipo = ipoList->GetScalarInterpolator(MA_SPEC_G);
if (ipo) {
if (!ipocontr) {
ipocontr = new KX_MaterialIpoController();
ipocontr = new KX_MaterialIpoController(matname_hash);
gameobj->GetSGNode()->AddSGController(ipocontr);
ipocontr->SetObject(gameobj->GetSGNode());
}
@ -681,7 +683,7 @@ void BL_ConvertMaterialIpos(
ipo = ipoList->GetScalarInterpolator(MA_SPEC_B);
if (ipo) {
if (!ipocontr) {
ipocontr = new KX_MaterialIpoController();
ipocontr = new KX_MaterialIpoController(matname_hash);
gameobj->GetSGNode()->AddSGController(ipocontr);
ipocontr->SetObject(gameobj->GetSGNode());
}
@ -696,7 +698,7 @@ void BL_ConvertMaterialIpos(
ipo = ipoList->GetScalarInterpolator(MA_HARD);
if (ipo) {
if (!ipocontr) {
ipocontr = new KX_MaterialIpoController();
ipocontr = new KX_MaterialIpoController(matname_hash);
gameobj->GetSGNode()->AddSGController(ipocontr);
ipocontr->SetObject(gameobj->GetSGNode());
}
@ -710,7 +712,7 @@ void BL_ConvertMaterialIpos(
ipo = ipoList->GetScalarInterpolator(MA_SPEC);
if (ipo) {
if (!ipocontr) {
ipocontr = new KX_MaterialIpoController();
ipocontr = new KX_MaterialIpoController(matname_hash);
gameobj->GetSGNode()->AddSGController(ipocontr);
ipocontr->SetObject(gameobj->GetSGNode());
}
@ -725,7 +727,7 @@ void BL_ConvertMaterialIpos(
ipo = ipoList->GetScalarInterpolator(MA_REF);
if (ipo) {
if (!ipocontr) {
ipocontr = new KX_MaterialIpoController();
ipocontr = new KX_MaterialIpoController(matname_hash);
gameobj->GetSGNode()->AddSGController(ipocontr);
ipocontr->SetObject(gameobj->GetSGNode());
}
@ -739,7 +741,7 @@ void BL_ConvertMaterialIpos(
ipo = ipoList->GetScalarInterpolator(MA_EMIT);
if (ipo) {
if (!ipocontr) {
ipocontr = new KX_MaterialIpoController();
ipocontr = new KX_MaterialIpoController(matname_hash);
gameobj->GetSGNode()->AddSGController(ipocontr);
ipocontr->SetObject(gameobj->GetSGNode());
}
@ -752,3 +754,28 @@ void BL_ConvertMaterialIpos(
}
}
void BL_ConvertMaterialIpos(
struct Object* blenderobject,
KX_GameObject* gameobj,
KX_BlenderSceneConverter *converter
)
{
if (blenderobject->totcol==1)
{
Material *mat = give_current_material(blenderobject, 1);
// if there is only one material attached to the mesh then set material_index in BL_ConvertMaterialIpos to NULL
// --> this makes the UpdateMaterialData function in KX_GameObject.cpp use the old hack of using SetObjectColor
// because this yields a better performance as not all the vertex colors need to be edited
if(mat) ConvertMaterialIpos(mat, NULL, gameobj, converter);
}
else
{
for (int material_index=1; material_index <= blenderobject->totcol; material_index++)
{
Material *mat = give_current_material(blenderobject, material_index);
STR_HashedString matname = mat->id.name;
if(mat) ConvertMaterialIpos(mat, matname.hash(), gameobj, converter);
}
}
}

@ -46,7 +46,7 @@ void BL_ConvertCameraIpos(struct Camera* blendercamera,
class KX_GameObject* cameraobj,
class KX_BlenderSceneConverter *converter);
void BL_ConvertMaterialIpos(struct Material* blendermaterial,
void BL_ConvertMaterialIpos(struct Object* blenderobject,
class KX_GameObject* materialobj,
class KX_BlenderSceneConverter *converter);

@ -442,6 +442,7 @@ void KX_GameObject::UpdateIPO(float curframetime,
// IPO update
void
KX_GameObject::UpdateMaterialData(
dword matname_hash,
MT_Vector4 rgba,
MT_Vector3 specrgb,
MT_Scalar hard,
@ -460,9 +461,26 @@ KX_GameObject::UpdateMaterialData(
RAS_IPolyMaterial* poly = (*mit)->GetPolyMaterial();
if(poly->GetFlag() & RAS_BLENDERMAT )
{
SetObjectColor(rgba);
KX_BlenderMaterial *m = static_cast<KX_BlenderMaterial*>(poly);
m->UpdateIPO(rgba, specrgb,hard,spec,ref,emit, alpha);
if (matname_hash == NULL)
{
m->UpdateIPO(rgba, specrgb,hard,spec,ref,emit, alpha);
// if mesh has only one material attached to it then use original hack with no need to edit vertices (better performance)
SetObjectColor(rgba);
}
else
{
if (matname_hash == poly->GetMaterialNameHash())
{
m->UpdateIPO(rgba, specrgb,hard,spec,ref,emit, alpha);
m_meshes[mesh]->SetVertexColor(poly,rgba);
// no break here, because one blender material can be split into several game engine materials
// (e.g. one uvsphere material is split into one material at poles with ras_mode TRIANGLE and one material for the body
// if here was a break then would miss some vertices if material was split
}
}
}
}
}

@ -521,6 +521,7 @@ public:
*/
void
UpdateMaterialData(
dword matname_hash,
MT_Vector4 rgba,
MT_Vector3 specrgb,
MT_Scalar hard,

@ -37,6 +37,7 @@ bool KX_MaterialIpoController::Update(double currentTime)
//kxgameobj->SetObjectColor(m_rgba);
kxgameobj->UpdateMaterialData(
m_matname_hash,
m_rgba,
m_specrgb,
m_hard,

@ -7,6 +7,8 @@
#include "SG_Spatial.h"
#include "KX_IInterpolator.h"
#include "STR_String.h" //typedef dword
class KX_MaterialIpoController : public SG_Controller
{
public:
@ -23,10 +25,12 @@ private:
bool m_modified;
double m_ipotime;
dword m_matname_hash;
public:
KX_MaterialIpoController() :
KX_MaterialIpoController(dword matname_hash) :
m_modified(true),
m_ipotime(0.0)
m_ipotime(0.0),
m_matname_hash(matname_hash)
{}
virtual ~KX_MaterialIpoController();
virtual SG_Controller* GetReplica(class SG_Node* destnode);

@ -139,6 +139,11 @@ const STR_String& RAS_IPolyMaterial::GetMaterialName() const
return m_materialname;
}
dword RAS_IPolyMaterial::GetMaterialNameHash() const
{
return m_materialname.hash();
}
const STR_String& RAS_IPolyMaterial::GetTextureName() const
{
return m_texturename;

@ -138,6 +138,7 @@ public:
unsigned int hash() const;
int GetDrawingMode() const;
const STR_String& GetMaterialName() const;
dword GetMaterialNameHash() const;
const STR_String& GetTextureName() const;
const unsigned int GetFlag() const;

@ -201,7 +201,20 @@ void RAS_MeshObject::DebugColor(unsigned int abgr)
m_debugcolor = abgr;
}
void RAS_MeshObject::SetVertexColor(RAS_IPolyMaterial* mat,MT_Vector4 rgba)
{
RAS_TexVert* vertex = NULL;
const vecVertexArray & vertexvec = GetVertexCache(mat);
for (vector<KX_VertexArray*>::const_iterator it = vertexvec.begin(); it != vertexvec.end(); ++it)
{
KX_VertexArray::iterator vit;
for (vit=(*it)->begin(); vit != (*it)->end(); vit++)
{
vit->SetRGBA(rgba);
}
}
}
void RAS_MeshObject::SchedulePoly(const KX_VertexIndex& idx,
int numverts,

@ -189,6 +189,7 @@ public:
);
void DebugColor(unsigned int abgr);
void SetVertexColor(RAS_IPolyMaterial* mat,MT_Vector4 rgba);
/**
* Sorts the polygons by their transformed z values.