|
Tutorial 3. customscenenode |
This tutorial is more difficult, so if you do not have the relevant knowledge, please read the previous tutorial first. This tutorial demonstrates how to create a custom scenario node and how to use it in the engine. If you want to implement rendering technology that is not currently supported by the irrlicht engine, it is necessary to customize scene nodes. For example, you can write an indoor Renderer or an advanced Terrain Scene node by yourself. When creating a custom scenario node, you can easily expand the irrlicht engine and adapt it to your needs.
I will continue to make this tutorial easier to understand: the explanation should be as simple as possible, written in a CPP file as much as possible, and the engine will be used in all other tutorials as here. After this tutorial is complete, the results will be shown in the following figure. This does not look very beautiful, but it provides a complete custom scenario node and is a good start to create your own scenario node.
First, I include the header file, use the IRR namespace, and tell the linker to link the Lib file.
#include <irrlicht.h>using namespace irr;#pragma comment(lib, "Irrlicht.lib")
The most complex part of this tutorial is the custom scenario node class. To keep it simple,
Our scene node will not be an indoor Renderer or Terrain Scene node, but a simple still. It consists of three-dimensional objects consisting of 4 connected vertices. It is only responsible for drawing itself and not doing anything else.
class CSampleSceneNode : public scene::ISceneNode
{
First, we declare some member variables to save the data of the triangle: the surrounding box, four vertices, and the material of the triangle.
core::aabbox3d<f32> Box;video::S3DVertex Vertices[4];video::SMaterial Material;
Parameters of the constructor include the parent scenario node, the scenario management pointer, and the scenario node ID. In the constructor itself, we call the constructor of the parent class, set the material we use to draw the scene node, and create the four vertices to be drawn.
public:CSampleSceneNode(scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id) : scene::ISceneNode(parent, mgr, id){ Material.Wireframe = false; Material.Lighting = false; Vertices[0] = video::S3DVertex(0,0,10, 1,1,0,video::SColor(255,0,255,255),0,1); Vertices[1] = video::S3DVertex(10,0,-10, 1,0,0,video::SColor(255,255,0,255),1,1); Vertices[2] = video::S3DVertex(0,20,0, 0,1,1,video::SColor(255,255,255,0),1,0); Vertices[3] = video::S3DVertex(-10,0,-10, 0,0,1,video::SColor(255,0,255,0),0,0);
The irrlicht engine needs to know the perimeter box of your scenario node. It will use it for automatic cropping and other things. Therefore, we need to create an incircle with four vertices. If you do not want the engine to use auto crop, or you do not want to create a box, you can also write
Automaticcullingenabled = false ;.
Box.reset(Vertices[0].Pos); for (s32 i=1; i<4; ++i) Box.addInternalPoint(Vertices[i].Pos);}
Before rendering, the scenario manager calls the onprerender () method for each scenario node in the scenario (). If you want to draw a scene node, you should first register it in the scenario manager before the scenario manager calls: render method ,. Generally, scene nodes render their content one by one, and then render the template buffer shadow, and the camera or lighting scene node must be rendered before all. Here we just register it for general rendering. If we want it to be rendered like a camera or light, we can write scenemanager-> registernodeforrendering (this,
Snrt_light_and_camera );
After that, we call the onprerender method of the base class iscenenode, so that all the subscenario nodes can register.
virtual void OnPreRender(){ if (IsVisible) SceneManager->registerNodeForRendering(this); ISceneNode::OnPreRender();}
Some interesting things are executed in the render () method: Scene node rendering. We override this method and draw
virtual void render(){ u16 indices[] = { 0,2,3, 2,1,3, 1,0,3, 2,0,1 }; video::IVideoDriver* driver = SceneManager->getVideoDriver(); driver->setMaterial(Material); driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); driver->drawIndexedTriangleList(&Vertices[0], 4, &indices[0], 4);}
At least, we have created three small extra methods. Getboundingbox () returns the surrounding box of the node in this scenario. getmaterialcount () returns the number of materials on the node in this scenario (we only have one material for the triangle), and getmaterial () returns the material of the specified index. Because we only have one material, we can return only one material. If there are more than one material, we can use indexes to specify which one.
virtual const core::aabbox3d<f32>& getBoundingBox() const { return Box; } virtual u32 getMaterialCount() { return 1; } virtual video::SMaterial& getMaterial(u32 i) { return Material; } };
That's it. The scenario node is complete. Now, we only need to start the engine, create a scene node and a camera, and check the results.
int main(){ IrrlichtDevice *device = createDevice(video::EDT_OPENGL, core::dimension2d<s32>(640, 480), 16, false); device->setWindowCaption(L"Custom Scene Node - Irrlicht Engine Demo"); video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); smgr->addCameraSceneNode(0, core::vector3df(0,-40,0), core::vector3df(0,0,0));
Create a scenario node. Please note that do not call the drop () function immediately after creation. It is possible that the scenario manager is using it. We can delete the program after it is executed.
Csamplescenenode * mynode = new csamplescenenode (smgr-> getrootscenenode (), smgr, 666); // ** Program executed ** // mynode-> drop ();
Now, let's move the operator down and display it. Now you can use your custom scenario node like other scenario nodes using the engine, we add an animation scene node to rotate our triangle.
scene::ISceneNodeAnimator* anim = smgr->createRotationAnimator(core::vector3df(0.8f, 0, 0.8f));myNode->addAnimator(anim);anim->drop();
Now draw and complete everything.
while(device->run()) { driver->beginScene(true, true, video::SColor(0,100,100,100)); smgr->drawAll(); driver->endScene(); }device->drop();return 0;}
All right, compile and try this program.