forked from bartvdbraak/blender
BGE: fix memleaks.
SCA_RandomActuator: The random generator was shared between replicas and not deleted. Added ref counting between replicas to allow deletion at the end. KX_Camera: The scenegraph node was not deleted for temporary cameras (ImageMirror and shadow), causing 500 bytes leak per frame and per shadow light. KX_GameActuator: Global dictionary buffer was not deleted after saving. KX_MotionState: The motion state for compound child was not deleted KX_ReplaceMeshActuator: The mesh was unnecessarily converted for each actuator and not deleted, causing large memleak. After these fix, YoFrankie runs without memleak.
This commit is contained in:
parent
6d8d7cd768
commit
5441323dca
@ -729,6 +729,8 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools*
|
||||
bool skinMesh = false;
|
||||
int lightlayer = blenderobj->lay;
|
||||
|
||||
if ((meshobj = converter->FindGameMesh(mesh/*, ob->lay*/)) != NULL)
|
||||
return meshobj;
|
||||
// Get DerivedMesh data
|
||||
DerivedMesh *dm = CDDM_from_mesh(mesh, blenderobj);
|
||||
|
||||
@ -1043,7 +1045,7 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools*
|
||||
// pre calculate texture generation
|
||||
for(list<RAS_MeshMaterial>::iterator mit = meshobj->GetFirstMaterial();
|
||||
mit != meshobj->GetLastMaterial(); ++ mit) {
|
||||
mit->m_bucket->GetPolyMaterial()->OnConstruction();
|
||||
mit->m_bucket->GetPolyMaterial()->OnConstruction(lightlayer);
|
||||
}
|
||||
|
||||
if (layers)
|
||||
@ -1057,6 +1059,7 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools*
|
||||
delete kx_blmat;
|
||||
if (kx_polymat)
|
||||
delete kx_polymat;
|
||||
converter->RegisterGameMesh(meshobj, mesh);
|
||||
return meshobj;
|
||||
}
|
||||
|
||||
@ -1712,14 +1715,9 @@ static KX_GameObject *gameobject_from_blenderobject(
|
||||
case OB_MESH:
|
||||
{
|
||||
Mesh* mesh = static_cast<Mesh*>(ob->data);
|
||||
RAS_MeshObject* meshobj = converter->FindGameMesh(mesh, ob->lay);
|
||||
float center[3], extents[3];
|
||||
float radius = my_boundbox_mesh((Mesh*) ob->data, center, extents);
|
||||
|
||||
if (!meshobj) {
|
||||
meshobj = BL_ConvertMesh(mesh,ob,rendertools,kxscene,converter);
|
||||
converter->RegisterGameMesh(meshobj, mesh);
|
||||
}
|
||||
RAS_MeshObject* meshobj = BL_ConvertMesh(mesh,ob,rendertools,kxscene,converter);
|
||||
|
||||
// needed for python scripting
|
||||
kxscene->GetLogicManager()->RegisterMeshName(meshobj->GetName(),meshobj);
|
||||
|
@ -550,12 +550,12 @@ void KX_BlenderSceneConverter::RegisterGameMesh(
|
||||
|
||||
|
||||
RAS_MeshObject *KX_BlenderSceneConverter::FindGameMesh(
|
||||
struct Mesh *for_blendermesh,
|
||||
unsigned int onlayer)
|
||||
struct Mesh *for_blendermesh/*,
|
||||
unsigned int onlayer*/)
|
||||
{
|
||||
RAS_MeshObject** meshp = m_map_mesh_to_gamemesh[CHashedPtr(for_blendermesh)];
|
||||
|
||||
if (meshp && onlayer==(*meshp)->GetLightLayer()) {
|
||||
if (meshp/* && onlayer==(*meshp)->GetLightLayer()*/) {
|
||||
return *meshp;
|
||||
} else {
|
||||
return NULL;
|
||||
|
@ -115,7 +115,7 @@ public:
|
||||
struct Object *FindBlenderObject(KX_GameObject *for_gameobject);
|
||||
|
||||
void RegisterGameMesh(RAS_MeshObject *gamemesh, struct Mesh *for_blendermesh);
|
||||
RAS_MeshObject *FindGameMesh(struct Mesh *for_blendermesh, unsigned int onlayer);
|
||||
RAS_MeshObject *FindGameMesh(struct Mesh *for_blendermesh/*, unsigned int onlayer*/);
|
||||
|
||||
// void RegisterSumoShape(DT_ShapeHandle shape, RAS_MeshObject *for_gamemesh);
|
||||
// DT_ShapeHandle FindSumoShape(RAS_MeshObject *for_gamemesh);
|
||||
|
@ -59,6 +59,7 @@
|
||||
SCA_RandomNumberGenerator::SCA_RandomNumberGenerator(long seed) {
|
||||
// int mti = N + 1; /*unused*/
|
||||
m_seed = seed;
|
||||
m_refcount = 1;
|
||||
SetStartVector();
|
||||
}
|
||||
|
||||
|
@ -36,6 +36,9 @@
|
||||
|
||||
class SCA_RandomNumberGenerator {
|
||||
|
||||
/* reference counted for memleak */
|
||||
int m_refcount;
|
||||
|
||||
/** base seed */
|
||||
long m_seed;
|
||||
|
||||
@ -56,6 +59,16 @@ class SCA_RandomNumberGenerator {
|
||||
float DrawFloat();
|
||||
long GetSeed();
|
||||
void SetSeed(long newseed);
|
||||
SCA_RandomNumberGenerator* AddRef()
|
||||
{
|
||||
++m_refcount;
|
||||
return this;
|
||||
}
|
||||
void Release()
|
||||
{
|
||||
if (--m_refcount == 0)
|
||||
delete this;
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* __KX_RANDOMNUMBERGENERATOR */
|
||||
|
@ -50,7 +50,6 @@ SCA_RandomSensor::SCA_RandomSensor(SCA_EventManager* eventmgr,
|
||||
PyTypeObject* T)
|
||||
: SCA_ISensor(gameobj,eventmgr, T)
|
||||
{
|
||||
// m_basegenerator is never deleted => memory leak
|
||||
m_basegenerator = new SCA_RandomNumberGenerator(startseed);
|
||||
Init();
|
||||
}
|
||||
@ -59,7 +58,7 @@ SCA_RandomSensor::SCA_RandomSensor(SCA_EventManager* eventmgr,
|
||||
|
||||
SCA_RandomSensor::~SCA_RandomSensor()
|
||||
{
|
||||
/* Nothing to be done here. */
|
||||
m_basegenerator->Release();
|
||||
}
|
||||
|
||||
void SCA_RandomSensor::Init()
|
||||
@ -74,13 +73,18 @@ void SCA_RandomSensor::Init()
|
||||
CValue* SCA_RandomSensor::GetReplica()
|
||||
{
|
||||
CValue* replica = new SCA_RandomSensor(*this);
|
||||
// replication copies m_basegenerator pointer => share same generator
|
||||
// this will copy properties and so on...
|
||||
replica->ProcessReplica();
|
||||
|
||||
return replica;
|
||||
}
|
||||
|
||||
void SCA_RandomSensor::ProcessReplica()
|
||||
{
|
||||
SCA_ISensor::ProcessReplica();
|
||||
// increment reference count so that we can release the generator at this end
|
||||
m_basegenerator->AddRef();
|
||||
}
|
||||
|
||||
|
||||
bool SCA_RandomSensor::IsPositiveTrigger()
|
||||
|
@ -52,6 +52,7 @@ public:
|
||||
PyTypeObject* T=&Type);
|
||||
virtual ~SCA_RandomSensor();
|
||||
virtual CValue* GetReplica();
|
||||
virtual void ProcessReplica();
|
||||
virtual bool Evaluate();
|
||||
virtual bool IsPositiveTrigger();
|
||||
virtual void Init();
|
||||
|
@ -158,14 +158,14 @@ void KX_BlenderMaterial::ReleaseMaterial()
|
||||
mBlenderShader->ReloadMaterial();
|
||||
}
|
||||
|
||||
void KX_BlenderMaterial::OnConstruction()
|
||||
void KX_BlenderMaterial::OnConstruction(int layer)
|
||||
{
|
||||
if (mConstructed)
|
||||
// when material are reused between objects
|
||||
return;
|
||||
|
||||
if(mMaterial->glslmat)
|
||||
SetBlenderGLSLShader();
|
||||
SetBlenderGLSLShader(layer);
|
||||
|
||||
// for each unique material...
|
||||
int i;
|
||||
@ -902,10 +902,10 @@ KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getShader , "getShader()")
|
||||
}
|
||||
|
||||
|
||||
void KX_BlenderMaterial::SetBlenderGLSLShader(void)
|
||||
void KX_BlenderMaterial::SetBlenderGLSLShader(int layer)
|
||||
{
|
||||
if(!mBlenderShader)
|
||||
mBlenderShader = new BL_BlenderShader(mScene, mMaterial->material, m_lightlayer);
|
||||
mBlenderShader = new BL_BlenderShader(mScene, mMaterial->material, layer);
|
||||
|
||||
if(!mBlenderShader->Ok()) {
|
||||
delete mBlenderShader;
|
||||
|
@ -97,7 +97,7 @@ public:
|
||||
|
||||
// --------------------------------
|
||||
// pre calculate to avoid pops/lag at startup
|
||||
virtual void OnConstruction( );
|
||||
virtual void OnConstruction(int layer);
|
||||
|
||||
static void EndFrame();
|
||||
|
||||
@ -112,7 +112,7 @@ private:
|
||||
bool mModified;
|
||||
bool mConstructed; // if false, don't clean on exit
|
||||
|
||||
void SetBlenderGLSLShader();
|
||||
void SetBlenderGLSLShader(int layer);
|
||||
|
||||
void ActivatGLMaterials( RAS_IRasterizer* rasty )const;
|
||||
void ActivateTexGen( RAS_IRasterizer *ras ) const;
|
||||
|
@ -42,6 +42,7 @@ KX_Camera::KX_Camera(void* sgReplicationInfo,
|
||||
SG_Callbacks callbacks,
|
||||
const RAS_CameraData& camdata,
|
||||
bool frustum_culling,
|
||||
bool delete_node,
|
||||
PyTypeObject *T)
|
||||
:
|
||||
KX_GameObject(sgReplicationInfo,callbacks,T),
|
||||
@ -50,7 +51,8 @@ KX_Camera::KX_Camera(void* sgReplicationInfo,
|
||||
m_normalized(false),
|
||||
m_frustum_culling(frustum_culling),
|
||||
m_set_projection_matrix(false),
|
||||
m_set_frustum_center(false)
|
||||
m_set_frustum_center(false),
|
||||
m_delete_node(delete_node)
|
||||
{
|
||||
// setting a name would be nice...
|
||||
m_name = "cam";
|
||||
@ -64,6 +66,12 @@ KX_Camera::KX_Camera(void* sgReplicationInfo,
|
||||
|
||||
KX_Camera::~KX_Camera()
|
||||
{
|
||||
if (m_delete_node && m_pSGNode)
|
||||
{
|
||||
// for shadow camera, avoids memleak
|
||||
delete m_pSGNode;
|
||||
m_pSGNode = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -77,6 +85,13 @@ CValue* KX_Camera::GetReplica()
|
||||
return replica;
|
||||
}
|
||||
|
||||
void KX_Camera::ProcessReplica()
|
||||
{
|
||||
KX_GameObject::ProcessReplica();
|
||||
// replicated camera are always registered in the scene
|
||||
m_delete_node = false;
|
||||
}
|
||||
|
||||
MT_Transform KX_Camera::GetWorldToCamera() const
|
||||
{
|
||||
MT_Transform camtrans;
|
||||
|
@ -112,6 +112,11 @@ protected:
|
||||
MT_Scalar m_frustum_radius;
|
||||
bool m_set_frustum_center;
|
||||
|
||||
/**
|
||||
* whether the camera should delete the node itself (only for shadow camera)
|
||||
*/
|
||||
bool m_delete_node;
|
||||
|
||||
/**
|
||||
* Extracts the camera clip frames from the projection and world-to-camera matrices.
|
||||
*/
|
||||
@ -138,7 +143,7 @@ public:
|
||||
|
||||
enum { INSIDE, INTERSECT, OUTSIDE } ;
|
||||
|
||||
KX_Camera(void* sgReplicationInfo,SG_Callbacks callbacks,const RAS_CameraData& camdata, bool frustum_culling = true, PyTypeObject *T = &Type);
|
||||
KX_Camera(void* sgReplicationInfo,SG_Callbacks callbacks,const RAS_CameraData& camdata, bool frustum_culling = true, bool delete_node = false, PyTypeObject *T = &Type);
|
||||
virtual ~KX_Camera();
|
||||
|
||||
/**
|
||||
@ -149,6 +154,7 @@ public:
|
||||
virtual CValue*
|
||||
GetReplica(
|
||||
);
|
||||
virtual void ProcessReplica();
|
||||
|
||||
MT_Transform GetWorldToCamera() const;
|
||||
MT_Transform GetCameraToWorld() const;
|
||||
|
@ -980,6 +980,8 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj,
|
||||
compoundShape->calculateLocalInertia(mass,localInertia);
|
||||
rigidbody->setMassProps(mass,localInertia);
|
||||
}
|
||||
// delete motionstate as it's not used
|
||||
delete motionstate;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -149,6 +149,8 @@ bool KX_GameActuator::Update()
|
||||
} else {
|
||||
printf("Warning: could not create marshal buffer\n");
|
||||
}
|
||||
if (marshal_buffer)
|
||||
delete [] marshal_buffer;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1142,7 +1142,7 @@ void KX_KetsjiEngine::RenderShadowBuffers(KX_Scene *scene)
|
||||
if(m_drawingmode == RAS_IRasterizer::KX_TEXTURED && light->HasShadowBuffer()) {
|
||||
/* make temporary camera */
|
||||
RAS_CameraData camdata = RAS_CameraData();
|
||||
KX_Camera *cam = new KX_Camera(scene, scene->m_callbacks, camdata, false);
|
||||
KX_Camera *cam = new KX_Camera(scene, scene->m_callbacks, camdata, true, true);
|
||||
cam->SetName("__shadow__cam__");
|
||||
|
||||
MT_Transform camtrans;
|
||||
|
@ -220,7 +220,7 @@ PyAttributeDef KX_PolygonMaterial::Attributes[] = {
|
||||
KX_PYATTRIBUTE_INT_RW("tilexrep", INT_MIN, INT_MAX, true, KX_PolygonMaterial, m_tilexrep),
|
||||
KX_PYATTRIBUTE_INT_RW("tileyrep", INT_MIN, INT_MAX, true, KX_PolygonMaterial, m_tileyrep),
|
||||
KX_PYATTRIBUTE_INT_RW("drawingmode", INT_MIN, INT_MAX, true, KX_PolygonMaterial, m_drawingmode),
|
||||
KX_PYATTRIBUTE_INT_RW("lightlayer", INT_MIN, INT_MAX, true, KX_PolygonMaterial, m_lightlayer),
|
||||
//KX_PYATTRIBUTE_INT_RW("lightlayer", INT_MIN, INT_MAX, true, KX_PolygonMaterial, m_lightlayer),
|
||||
|
||||
KX_PYATTRIBUTE_BOOL_RW("transparent", KX_PolygonMaterial, m_alpha),
|
||||
KX_PYATTRIBUTE_BOOL_RW("zsort", KX_PolygonMaterial, m_zsort),
|
||||
|
@ -59,7 +59,7 @@ void RAS_IPolyMaterial::Initialize(
|
||||
m_transp = transp;
|
||||
m_alpha = alpha;
|
||||
m_zsort = zsort;
|
||||
m_lightlayer = lightlayer;
|
||||
//m_lightlayer = lightlayer;
|
||||
m_polymatid = m_newpolymatid++;
|
||||
m_flag = 0;
|
||||
m_multimode = 0;
|
||||
@ -80,7 +80,7 @@ RAS_IPolyMaterial::RAS_IPolyMaterial()
|
||||
m_transp(0),
|
||||
m_alpha(false),
|
||||
m_zsort(false),
|
||||
m_lightlayer(0),
|
||||
//m_lightlayer(0),
|
||||
m_polymatid(0),
|
||||
m_flag(0),
|
||||
m_multimode(0)
|
||||
@ -112,7 +112,7 @@ RAS_IPolyMaterial::RAS_IPolyMaterial(const STR_String& texname,
|
||||
m_transp(transp),
|
||||
m_alpha(alpha),
|
||||
m_zsort(zsort),
|
||||
m_lightlayer(lightlayer),
|
||||
//m_lightlayer(lightlayer),
|
||||
m_polymatid(m_newpolymatid++),
|
||||
m_flag(0),
|
||||
m_multimode(0)
|
||||
@ -172,10 +172,10 @@ bool RAS_IPolyMaterial::Less(const RAS_IPolyMaterial& rhs) const
|
||||
return m_polymatid < rhs.m_polymatid;
|
||||
}
|
||||
|
||||
int RAS_IPolyMaterial::GetLightLayer() const
|
||||
{
|
||||
return m_lightlayer;
|
||||
}
|
||||
//int RAS_IPolyMaterial::GetLightLayer() const
|
||||
//{
|
||||
// return m_lightlayer;
|
||||
//}
|
||||
|
||||
bool RAS_IPolyMaterial::IsAlpha() const
|
||||
{
|
||||
|
@ -73,7 +73,7 @@ protected:
|
||||
int m_transp;
|
||||
bool m_alpha;
|
||||
bool m_zsort;
|
||||
int m_lightlayer;
|
||||
//int m_lightlayer;
|
||||
int m_materialindex;
|
||||
|
||||
unsigned int m_polymatid;
|
||||
@ -147,7 +147,7 @@ public:
|
||||
|
||||
virtual bool Equals(const RAS_IPolyMaterial& lhs) const;
|
||||
bool Less(const RAS_IPolyMaterial& rhs) const;
|
||||
int GetLightLayer() const;
|
||||
//int GetLightLayer() const;
|
||||
bool IsAlpha() const;
|
||||
bool IsZSort() const;
|
||||
unsigned int hash() const;
|
||||
@ -167,7 +167,7 @@ public:
|
||||
/*
|
||||
* PreCalculate texture gen
|
||||
*/
|
||||
virtual void OnConstruction(){}
|
||||
virtual void OnConstruction(int layer){}
|
||||
};
|
||||
|
||||
inline bool operator ==( const RAS_IPolyMaterial & rhs,const RAS_IPolyMaterial & lhs)
|
||||
|
@ -91,7 +91,7 @@ struct RAS_MeshObject::fronttoback
|
||||
STR_String RAS_MeshObject::s_emptyname = "";
|
||||
|
||||
RAS_MeshObject::RAS_MeshObject(Mesh* mesh, int lightlayer)
|
||||
: m_lightlayer(lightlayer),
|
||||
: //m_lightlayer(lightlayer),
|
||||
m_bModified(true),
|
||||
m_bMeshModified(true),
|
||||
m_mesh(mesh),
|
||||
@ -112,10 +112,10 @@ bool RAS_MeshObject::MeshModified()
|
||||
return m_bMeshModified;
|
||||
}
|
||||
|
||||
unsigned int RAS_MeshObject::GetLightLayer()
|
||||
{
|
||||
return m_lightlayer;
|
||||
}
|
||||
//unsigned int RAS_MeshObject::GetLightLayer()
|
||||
//{
|
||||
// return m_lightlayer;
|
||||
//}
|
||||
|
||||
|
||||
|
||||
|
@ -54,7 +54,7 @@ class RAS_MeshObject
|
||||
{
|
||||
private:
|
||||
unsigned int m_debugcolor;
|
||||
int m_lightlayer;
|
||||
//int m_lightlayer;
|
||||
|
||||
bool m_bModified;
|
||||
bool m_bMeshModified;
|
||||
@ -94,7 +94,7 @@ public:
|
||||
list<RAS_MeshMaterial>::iterator GetFirstMaterial();
|
||||
list<RAS_MeshMaterial>::iterator GetLastMaterial();
|
||||
|
||||
unsigned int GetLightLayer();
|
||||
//unsigned int GetLightLayer();
|
||||
|
||||
/* name */
|
||||
void SetName(const char *name);
|
||||
|
@ -561,8 +561,8 @@ ImageRender::ImageRender (KX_Scene * scene, KX_GameObject * observer, KX_GameObj
|
||||
float yaxis[3] = {0.f, 1.f, 0.f};
|
||||
float mirrorMat[3][3];
|
||||
float left, right, top, bottom, back;
|
||||
|
||||
m_camera= new KX_Camera(scene, KX_Scene::m_callbacks, camdata);
|
||||
// make sure this camera will delete its node
|
||||
m_camera= new KX_Camera(scene, KX_Scene::m_callbacks, camdata, true, true);
|
||||
m_camera->SetName("__mirror__cam__");
|
||||
// don't add the camera to the scene object list, it doesn't need to be accessible
|
||||
m_owncamera = true;
|
||||
|
Loading…
Reference in New Issue
Block a user