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.
|