Deleting body woes

Kim2

27-09-2008 12:14:08

I can't work out why when I try to delete my enemy objects it crashes my program.

It seems like the program is still trying to call the transform callback even though I delete the body and the node it is attached to. Please somebody help me!

Here is how I make the object and then try to delete it immediately afterwards (as people on the ogre forums said to do) as a test:


enemy = new Enemy(mSceneMgr, m_World, Vector3((event[1] * 2-125),20.0,0.0),Quaternion::IDENTITY, counter, 100);
Enemies.push_back(enemy);

counter++;

for (int i; i < enemy->Enemynode->numAttachedObjects();++i){

mSceneMgr->destroyMovableObject( enemy->Enemynode->getAttachedObject(i) );
}

delete enemy->bod;
enemy->Enemynode->removeAndDestroyAllChildren(); //Remove All Child Nodes
mSceneMgr->destroySceneNode(enemy->Enemynode->getName()); //Remove This Node



Any attempt to delete the body crashes the program and similar for trying to delete the node (I guess because this automatically means the body is deleted?). As I mentioned, the last call looking at the debug info is to the transform callback.

This probably isn't necessary but just in case, the code for the Enemy:


#include "Enemy.h"
#include "include/MaterialsList.h"

void Enemy::ApplyForceAndTorqueEvent (OgreNewt::Body* body)
{

float mass;
float Ixx;
float Iyy;
float Izz;

Vector3 force;
Vector3 torque;

force[0] = 0.0;
force[1] = 0.0;
force[2] = 2000.0;

torque[0] = 0.0;
torque[1] = 0.0;
torque[2] = 0.0;

body->addForce(force);
}

// Default constructor
Enemy::Enemy(Ogre::SceneManager* mgr, OgreNewt::World* world, Ogre::Vector3 Position, Ogre::Quaternion Orientation, int counter, float scale)
{
//statePointer = &state;

mSceneManager = mgr;
MaterialsList* test = new MaterialsList(world);

pos = Position;
orient = Orientation;

Ogre::Real mass = 100;

// calculate the inertia based on box formula and mass
Ogre::Vector3 inertia = OgreNewt::MomentOfInertia::CalcBoxSolid( mass, Ogre::Vector3(3.5,2.5,1.2));

EnemyEnt = mgr->createEntity( "Enemy"+Ogre::StringConverter::toString(counter), "enemyS1.mesh" );
Enemynode = mgr->getRootSceneNode()->createChildSceneNode("Enemy"+Ogre::StringConverter::toString(counter));
Enemynode->attachObject( EnemyEnt );
Enemynode->setPosition(Vector3(Position.x, Position.y, Position.z));
Enemynode->setScale(scale/70, scale/70, scale/70);

OgreNewt::ConvexCollision* col = new OgreNewt::CollisionPrimitives::ConvexHull(world,Enemynode);
bod = new OgreNewt::Body( world, col );
delete col;

bod->attachToNode( Enemynode );
bod->setMassMatrix( mass, inertia );
bod->setCenterOfMass(Ogre::Vector3(0,0,0));
bod->setCustomForceAndTorqueCallback<Enemy>( &Enemy::ApplyForceAndTorqueEvent, this );
bod->setAutoFreeze(1);
bod->setPositionOrientation(Vector3(Position.x, Position.y, Position.z),Orientation);
}

Vector3 Enemy::GetPos()
{
return Vector3(pos.x, pos.y-3, pos.z);
}

Quaternion Enemy::GetOrient()
{
return orient;
}


Thanks a lot for any help or advice!

BardockSSJ

27-09-2008 22:45:26

Try

delete Objects[k]->Body;
Objects[k]->Body = NULL;


Also remember to remove callbacks and user data
//EDIT: Ahh and remove collision before body if you dont do it when after creating it!

Kim2

28-09-2008 13:02:35

Try

delete Objects[k]->Body;
Objects[k]->Body = NULL;


Also remember to remove callbacks and user data
//EDIT: Ahh and remove collision before body if you dont do it when after creating it!


I still get crashes just using that code but could you please explain how to remove the callbacks?

Kim2

28-09-2008 13:12:43

Ah never mind I got it now. I just had to remove the callbacks. Thanks a lot for your help.

So the complete process for deleting is:


enemy->bod->removeTransformCallback();
enemy->bod->removeForceAndTorqueCallback();
enemy->bod = NULL;
delete enemy->bod;
mSceneMgr->destroySceneNode(enemy->Enemynode->getName());
mSceneMgr->destroyEntity(enemy->EnemyEnt->getName());
delete enemy;

Kim2

28-09-2008 18:08:00

I mustn't be doing it completely right because despite the fact that the enemies are getting removed the game starts to chug after hundreds have been deleted.


enemy = new Enemy(mSceneMgr, m_World, Vector3((event[6][1] * 4-295),20.0,0.0),Quaternion::IDENTITY, counter, 100);
Enemies.push_back(enemy);



for(int i = 0; i < Enemies.size(); i++)
{
if(Enemies[i]->GetPos().z > 140)
{
Enemies[i]->Destroy();
Enemies.erase(Enemies.begin() + i);
}

}



void Enemy::Destroy()
{
bod->removeTransformCallback();
bod->removeForceAndTorqueCallback();
bod = NULL;
delete bod;
mSceneManager->destroySceneNode(Enemynode->getName());
mSceneManager->destroyEntity(EnemyEnt->getName());
}


I'm making an arcade style shooter which needs many hundreds of enemies to get destroyed or pass by off screen (where they are removed) so this needs to work. How can I make sure that absolutely all of the resources for each enemy object are freed up?

Thanks a lot.

BardockSSJ

28-09-2008 19:30:27

I must worry you - Ogre is slow in destroying Entity and Scene Node... if you do too much in time - it will slow down... sorry

Kim2

28-09-2008 19:35:53

I must worry you - Ogre is slow in destroying Entity and Scene Node... if you do too much in time - it will slow down... sorry

I don't think that's the problem because it's only slowing down gradually over time as more enemies are deleted. Could you explain what you mean by that though, please? How slow?

Kim2

28-09-2008 19:40:59

Also, if that is the case how would you handle say, a system for creating/destroying bullets?

Kim2

28-09-2008 22:56:58

I'm trying to delete some objects from inside a user callback now.


if(m_body1->getUserData()) {
void* getBullet = m_body1->getUserData();
RapidBullet* bullet = (RapidBullet*) getBullet;
bullet->Destroy();
}

// OR
m_body1->removeForceAndTorqueCallback();
m_body1->removeTransformCallback();
m_body1->removeAutoactiveCallback();
delete m_body1;


Neither work without crashing the program. Could someone please tell me how to correctly remove objects from inside a callback?

Thanks.

Kim2

28-09-2008 23:09:09

OK, I worked out that I should set a flag and then delete any objects in the next frame. But I'm still having big problems with the program eating up loads of memory and grinding to a halt.

BardockSSJ

29-09-2008 14:49:27

1. Dont try destroying body in its callback - crash - use instead std::vector of bodies and destroy them when end of frame

2.Bullet creating/recreating - simple. create vector of bullets and dont destroy any if it should, just set it state to unused, and if you want next bullet, use closest free in vector, or if no free create new. you can too create sensitive cleaning system (example: limit nodes deleted per frame t n and destroy n of them per frame) but i think no deleting is need for bullets. even for other things, you can use same method.

3. memory load- hard to tell but i think you using windows taks manager to get memory info - it will not show truth.

micken

08-10-2008 00:46:44

Ah never mind I got it now. I just had to remove the callbacks. Thanks a lot for your help.

So the complete process for deleting is:


enemy->bod->removeTransformCallback();
enemy->bod->removeForceAndTorqueCallback();
enemy->bod = NULL;
delete enemy->bod;
mSceneMgr->destroySceneNode(enemy->Enemynode->getName());
mSceneMgr->destroyEntity(enemy->EnemyEnt->getName());
delete enemy;


Pardon me if I'm wrong, but your memory leak could stem from your order of calls here. You are setting enemy->bod to NULL and then deleting it. You can't really delete NULL, and unless you have something ELSE pointing at where the body is stored in memory you've just created a memory leak.