Creating Terrain and using the test features

In this example, we're going to create a terrain from a heightmap using Newton's collision tree system. Also, we're going to use the dropTestCube() and dropTestSphere() functions to quickly make sure it's working properly. These functions use Irrlicht's built-in primitives to create the scene nodes, and so simply need a pointer to the scene manager and the position to drop them from.

To make the test functions useful, we're going to set up an Irrlicht IEventReceiver implementation which drops a test cube when the left mouse button is pressed, a sphere when the right mouse button is pressed, and in both cases drop them from wherever the camera is.

Main code:

	// start Irrlicht
	IrrlichtDevice* device = createDevice(EDT_OPENGL);


	// pointers to driver, scenemanager
	IVideoDriver* driver = device->getVideoDriver();
	ISceneManager* smgr = device->getSceneManager();

	// create an FPS camera
	ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS();

	// move the camera up a bit so we can see the terrain
	camera->setPosition(vector3df(100.0f, 200.0f, 100.0f));

	// start iphysics
	CPhysics physics;
	physics.init();

	// create our custom event receiver, set it as the active one
	CEventReceiver receiver(smgr, &physics, camera);
	device->setEventReceiver(&receiver);

	// create terrain from heightmap
	ITerrainSceneNode* terrainNode = smgr->addTerrainSceneNode("media/heightmap.bmp");
	terrainNode->setMaterialTexture(0, driver->getTexture("media/terrain_texture.jpg"));
	terrainNode->setMaterialTexture(1, driver->getTexture("media/terrain_detail.jpg"));
	terrainNode->setMaterialType(EMT_DETAIL_MAP);
	terrainNode->scaleTexture(1.0f, 10.0f);
	terrainNode->setMaterialFlag(EMF_LIGHTING, false);

	// create scale vector, apply to scene node and also add it to SPhysicsTerrain
	vector3df terrainScale(10.0f, 1.0f, 10.0f);
	terrainNode->setScale(terrainScale);

	// create SPhysicsTerrain
	SPhysicsTerrain terrain;
	terrain.terrainNode = terrainNode;
	terrain.terrainScale = terrainScale;

	// create Terrain entity
	IPhysicsEntity* terrainEntity = physics.addEntity(&terrain);

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

		smgr->drawAll();
		driver->endScene();

		// worry about accurate timing later
		physics.update(100.0f);

	}

This time we create an FPS camera so we can move about. After starting IPhysics, we create a terrain heightmap and then an SPhysicsTerrain - note that we store the terrain scale in the SPhysicsTerrain but also manually apply it to the terrain scene node.

Event receiver class:

class CEventReceiver : public IEventReceiver
{
public:
	CEventReceiver(ISceneManager* sceneManager, CPhysics* physics, ICameraSceneNode* camera)
	{
		m_sceneManager = sceneManager;
		m_physics = physics;
		m_camera = camera;
	}
	~CEventReceiver()
	{
	}
	bool OnEvent(SEvent event)
	{
		if(event.EventType == EET_MOUSE_INPUT_EVENT)
		{
			if(event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN)
			{
				// drop test cube from camera's position
				m_physics->dropTestCube(m_sceneManager, m_camera->getPosition());
			}
			else if(event.MouseInput.Event == EMIE_RMOUSE_PRESSED_DOWN)
			{
				// drop test sphere from camera's position
				m_physics->dropTestSphere(m_sceneManager, m_camera->getPosition());
			}
		}
		return false;
	}
protected:
	ISceneManager* m_sceneManager;
	CPhysics* m_physics;
	ICameraSceneNode* m_camera;
};

Here we create an implementation of IEventReceiver which stores a pointer to the scene manager, to CPhysics and also to the camera. Then when the mouse buttons are pressed we can drop a cube or a sphere and make sure that our terrain is working properly.