Page 1 of 1

When to use drop()

Posted: Thu Feb 07, 2008 1:54 am
by chaotischerapostel
I'm starting to get the hang of Irrlicht but I'm curious, when are you sopposed to use drop()? From what I'v learned you should use it as soon as you wont need something anymore, but I would just like to make shore I'm right.

Posted: Thu Feb 07, 2008 1:56 am
by zeno60
When you create an object in the Irrlicht engine, calling a method which starts with 'create', an object is created, and you get a pointer to the new object. If you no longer need the object, you have to call drop(). This will destroy the object, if grab() was not called in another part of you program, because this part still needs the object. Note, that you only need to call drop() to the object, if you created it, and the method had a 'create' in it.
A simple example:

If you want to create a texture, you may want to call an imaginable method IDriver::createTexture. You call ITexture* texture = driver->createTexture(dimension2d<s32>(128, 128)); If you no longer need the texture, call texture->drop(). If you want to load a texture, you may want to call imaginable method IDriver::loadTexture. You do this like ITexture* texture = driver->loadTexture("example.jpg"); You will not have to drop the pointer to the loaded texture, because the name of the method does not start with 'create'. The texture is stored somewhere by the driver.

Posted: Thu Feb 07, 2008 3:11 am
by chaotischerapostel
Well that sums it up, thanks for the quick and great response.

Posted: Thu Feb 07, 2008 10:34 am
by rogerborg
Also, you don't have to drop() it as soon as you're done with it, you just need to be sure to do it before your final device->drop() so that everything gets cleaned up neatly.

What's more important is that once you've called drop() on an object that you shouldn't assume that it is still valid, or that it will remain so, and so you shouldn't use it again.

Some of the examples unfortunately show objects being used after a drop() call; this works because other objects still have references to the dropped() object, but it is bad practice, particularly as the examples don't verify the refcount before the drop() to ensure that it's > 1.

Posted: Thu Feb 07, 2008 11:16 am
by chaotischerapostel
You guys are probably sick of looking at other peoples code but if you could take a look, did I use drop() correctly?

Code: Select all

#include <irrlicht.h>
#include <iostream>

using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;

#pragma comment(lib, "Irrlicht.lib")

int main()
{
	//Create Irrlicht, the driver, and the scene manager
	IrrlichtDevice *device = 
		createDevice(EDT_DIRECT3D9, dimension2d<s32>(512, 384), 32,
			false, false, false, 0);
	IVideoDriver* driver = device->getVideoDriver();
	ISceneManager* smgr = device->getSceneManager();

	//Hide the mouse
	device->getCursorControl()->setVisible(false);

	//The walls, ground
	//The ground
	ISceneNode* Floor = smgr->addCubeSceneNode();
	Floor->setScale(vector3df(300,1,300));
	Floor->setMaterialTexture(0, driver->getTexture("../Amphitheatrum Flavium/media/Sand.bmp"));
	Floor->setMaterialFlag(EMF_LIGHTING, false);
	//Floor Collision
	ITriangleSelector* FloorCollision = smgr->createTriangleSelectorFromBoundingBox(Floor); 
	Floor->setTriangleSelector(FloorCollision); 

	//The first wall
	ISceneNode* Wall1 = smgr->addCubeSceneNode();
	Wall1->setScale(vector3df(300,50,1));
	Wall1->setMaterialTexture(0, driver->getTexture("../Amphitheatrum Flavium/media/Walls.bmp"));
	Wall1->setMaterialFlag(EMF_LIGHTING, false);
	Wall1->setPosition(vector3df(0,0,1500));
	//Wall1 Collision
	ITriangleSelector* Wall1Collision = smgr->createTriangleSelectorFromBoundingBox(Wall1); 
	Wall1->setTriangleSelector(Wall1Collision); 
	
	//The second wall
	ISceneNode* Wall2 = smgr->addCubeSceneNode();
	Wall2->setScale(vector3df(300,50,1));
	Wall2->setMaterialTexture(0, driver->getTexture("../Amphitheatrum Flavium/media/Walls.bmp"));
	Wall2->setMaterialFlag(EMF_LIGHTING, false);
	Wall2->setPosition(vector3df(0,0,-1500));
	//Wall2 Collision
	ITriangleSelector* Wall2Collision = smgr->createTriangleSelectorFromBoundingBox(Wall2); 
	Wall2->setTriangleSelector(Wall2Collision); 

	//The third wall
	ISceneNode* Wall3 = smgr->addCubeSceneNode();
	Wall3->setScale(vector3df(1,50,300));
	Wall3->setMaterialTexture(0, driver->getTexture("../Amphitheatrum Flavium/media/Walls.bmp"));
	Wall3->setMaterialFlag(EMF_LIGHTING, false);
	Wall3->setPosition(vector3df(1500,0,0));
	//Wall3 Collision
	ITriangleSelector* Wall3Collision = smgr->createTriangleSelectorFromBoundingBox(Wall3); 
	Wall3->setTriangleSelector(Wall3Collision); 

	//The fourth wall
	ISceneNode* Wall4 = smgr->addCubeSceneNode();
	Wall4->setScale(vector3df(1,50,300));
	Wall4->setMaterialTexture(0, driver->getTexture("../Amphitheatrum Flavium/media/Walls.bmp"));
	Wall4->setMaterialFlag(EMF_LIGHTING, false);
	Wall4->setPosition(vector3df(-1500,0,0));
	//Wall4 Collision
	ITriangleSelector* Wall4Collision = smgr->createTriangleSelectorFromBoundingBox(Wall4); 
	Wall4->setTriangleSelector(Wall4Collision); 

	//Combine the triangle selectors into a meta selector
	IMetaTriangleSelector * CollisionMeta = smgr->createMetaTriangleSelector(); 
	CollisionMeta->addTriangleSelector(FloorCollision); 
	CollisionMeta->addTriangleSelector(Wall1Collision); 
	CollisionMeta->addTriangleSelector(Wall2Collision);
	CollisionMeta->addTriangleSelector(Wall3Collision);
	CollisionMeta->addTriangleSelector(Wall4Collision);
	
	//Skybox
	driver->setTextureCreationFlag(ETCF_CREATE_MIP_MAPS, false);
	smgr->addSkyBoxSceneNode(
		driver->getTexture("../Amphitheatrum Flavium/media/irrlicht2_up.jpg"),
		driver->getTexture("../Amphitheatrum Flavium/media/irrlicht2_dn.jpg"),
		driver->getTexture("../Amphitheatrum Flavium/media/irrlicht2_lf.jpg"),
		driver->getTexture("../Amphitheatrum Flavium/media/irrlicht2_rt.jpg"),
		driver->getTexture("../Amphitheatrum Flavium/media/irrlicht2_ft.jpg"),
		driver->getTexture("../Amphitheatrum Flavium/media/irrlicht2_bk.jpg"));

	//The camera
	ICameraSceneNode* camera =
		smgr->addCameraSceneNodeFPS();
	camera->setPosition(vector3df(0,50,0));
	camera->setTarget(vector3df(2397*2,343*2,2700*2));
	camera->setFarValue(20000.0f);
	//Create response animator for the camera
	ISceneNodeAnimatorCollisionResponse* CameraAnimator;
	CameraAnimator = smgr->createCollisionResponseAnimator( 
		CollisionMeta, camera, 
		vector3df(10,10,10), 
		vector3df(0,-2,0), 
		vector3df(0,25,0)); 
	camera->addAnimator(CameraAnimator); 

	while(device->run())
	{	
		driver->beginScene(true, true, SColor(0, 200, 200, 200));

		smgr->drawAll();

		driver->endScene();
	}
	
	//Drop everything that was created
	Floor->drop();
	FloorCollision->drop();
	Wall1->drop();
	Wall1Collision->drop();
	Wall2->drop();
	Wall2Collision->drop();
	Wall3->drop();
	Wall3Collision->drop();
	Wall4->drop();
	Wall4Collision->drop();
	CollisionMeta->drop();
	CameraAnimator->drop();
	device->drop();

	return 0;
}

Posted: Thu Feb 07, 2008 1:03 pm
by hybrid
No, you didn't. Because you also drop'ed objects which come from add...() methods. Don't drop those.

Posted: Thu Feb 07, 2008 6:27 pm
by MasterGod
Basically objects that you get from add..() methods are dropped automatically hence you don't have to take care of'em. Objects that are created with methods that starts with create..() returns you an object with reference counter of 1 (right?) and are not automatically dropped.
A simple rule: (I think rogerborg already mentioned something like this)
Drop every object that you've created with a create...() method when you don't need it any more. Know that some parts might have grabbed that object (which raises its ref counter by one, one for each grab() call) but they will also drop it automatically.

Two advices:
1. Check this.
2. Write simple programs that grab & drop objects and debug it (or with simple printf of the ref counter) to see how its effect.
Something like that:

Code: Select all

#include "irrlicht.h"
#include "iostream"
#include "process.h" // for system("Pause");

using namespace irr;
using namespace std;

#ifdef _IRR_WINDOWS_
#pragma comment(lib, "Irrlicht.lib")
#endif

class Human : public virtual IReferenceCounted
{
public:
	Human(const char* Name) : name(Name)
	{
		cout << "In Human constructor" << endl;
	}
	~Human()
	{
		cout << "In Human destructor" << endl;
	}

	virtual void PrintName() = 0;

protected:
	const char* name;
};

class Male : public Human
{
public:
	Male(const char* Name) : Human(Name) 
	{
		cout << "In Male constructor" << endl;
	}

	~Male()
	{
		cout << "In Male destructor" << endl;
	}

	void PrintName()
	{
		cout << name << endl;
	}
};

class Female : public Human
{
public:
	Female(const char* Name) : Human(Name) 
	{
		cout << "In Female constructor" << endl;
	}

	~Female()
	{
		cout << "In Female destructor" << endl;
	}

	void PrintName()
	{
		cout << name << endl;
	}
};


int main()
{
	Human* PersonA = new Male("Mr.MasterGod");
	Human* PersonB = new Female("Mrs.MasterGod");

	PersonA->PrintName();
	cout << PersonA->getReferenceCount() << endl;

	PersonB->PrintName();
	cout << PersonB->getReferenceCount() << endl;

	PersonB->grab(); // needs a matching drop()
	cout << "After Grabbing Mrs.MasterGod.." << endl;
	
	PersonA->PrintName();
	cout << PersonA->getReferenceCount() << endl;

	PersonB->PrintName();
	cout << PersonB->getReferenceCount() << endl;

	PersonA->grab(); // needs a matching drop()
	cout << "After Grabbing Mr.MasterGod.." << endl;
	
	PersonA->PrintName();
	cout << PersonA->getReferenceCount() << endl;

	PersonB->PrintName();
	cout << PersonB->getReferenceCount() << endl;

	PersonA->drop(); // matching drop()
	cout << "After Dropping Mr.MasterGod.." << endl;

	PersonA->PrintName();
	cout << PersonA->getReferenceCount() << endl;

	PersonB->PrintName();
	cout << PersonB->getReferenceCount() << endl;

	PersonB->drop(); // matching drop()
	cout << "After Dropping Mrs.MasterGod.." << endl;

	PersonA->PrintName();
	cout << PersonA->getReferenceCount() << endl;

	PersonB->PrintName();
	cout << PersonB->getReferenceCount() << endl;

	// match for the new op
	cout << "Dropping Mr.MasterGod, because reference couter is 1 it will be deleted" << endl;
	PersonA->drop();

        // match for the new op
	cout << "Dropping Mrs.MasterGod, because reference couter is 1 it will be deleted" << endl;
	PersonB->drop();

	system("Pause");

	return 0;
}
And ignore that unnecessary pure virtual method PrintName(), it doesn't matter for this exercise because it does the same things in both derived classes.. I should have made it just virtual..
Now run this code and write another one yourself to check this grab()/drop() concept.

Posted: Thu Feb 07, 2008 7:27 pm
by chaotischerapostel
Ohh wow thats easy to get, thanks for all the help :)

@MasterGod- your example relly tied it all together, thanks