Tutorial 1.HelloWorld | - -
- This Tutorial shows how to set up the IDE for using the
- Irrlicht Engine and how to write a simple HelloWorld program
- with it. The program will show how to use the basics of
- the VideoDriver, the GUIEnvironment and the SceneManager.
|
-
-
Lets start! | -|||||||||||||||
-
-
-
-
-
-
- After we have set up the IDE, the compiler will know - where to find the Irrlicht Engine header files so - we can include it now into our code. -
In the Irrlicht Engine, everything can be found in - the namespace 'irr'. So if you want to use a class - of the engine, you'll have to type an irr:: before - the name of the class. For example, to use the IrrlichtDevice, - write: irr::IrrlichtDevice. To avoid having to put - irr:: before of the name of every class, we tell the - compiler that we use that namespace. -
There are 5 sub-namespaces in the Irrlicht Engine. - Take a look at them: you can read a detailed description - of them in the documentation by clicking on the top - menu item 'Namespace - List'. To keep this example simple, we don't want - to have to specify the name spaces, Hence: -
To be able to use the Irrlicht.DLL file, we need - to link with the Irrlicht.lib. We could set this option - in the project settings, but to make it easy we use - a pragma comment: -
Now the main method: to keep this example simple - we use int main(), which can be used on any platform. - However, on Windows platforms, we could also use the - WinMain method if we would want to get rid of the - console window which pops up when starting a program - with main(). -
The most important function of the engine is the - 'createDevice' function. The Irrlicht Device, which - is the root object for doing everything with the engine, - can be created with it. createDevice() has 7 parameters: -
Now we set the caption of the window to some nice text. - Note that there is a 'L' in front of the string: the - Irrlicht Engine uses wide character strings when displaying - text. -
Now we store a pointer to the video driver, the SceneManager, - and the graphical user interface environment so that - we do not always have to write device->getVideoDriver(), - device->getSceneManager(), and device->getGUIEnvironment(). -
We add a hello world label to the window using the - GUI environment. The text is placed at the position - (10,10) as top left corner and (200,22) as lower right - corner. -
To display something interesting, we load a Quake 2
- model and display it. We only have to get the Mesh from
- the Scene Manager with getMesh() and add a SceneNode
- to display the mesh with addAnimatedMeshSceneNode().
- Instead of loading a Quake2 file (.md2), it is also
- possible to load a Maya object file (.obj), a complete
- Quake3 map (.bsp), or a Milshape file (.ms3d).
To make the mesh look a little bit nicer, we change - its material a little bit: we disable lighting because - we do not have a dynamic light in here and the mesh - would be totally black. Then we set the frame loop so - that the animation is looped between the frames 0 and - 310. Then, at last, we apply a texture to the mesh. - Without it the mesh would be drawn using only a solid - color. -
To look at the mesh, we place a camera into 3d space - at the position (0, 10, -40). The camera looks from - there to (0,5,0). -
Ok. Now that we have set up the scene, let's draw everything: - we run the device in a while() loop until the device - does not want to run any more. This would be when the - user closes the window or presses ALT+F4 in Windows. -
Everything must be drawn between a beginScene() and - an endScene() call. The beginScene clears the screen - with a color and also the depth buffer, if desired. - Then we let the Scene Manager and the GUI environment - draw their content. With the endScene() call, everything - is presented on the screen. -
After we are finished, we have to delete the Irrlicht - Device created earlier with createDevice(). With the - Irrlicht Engine, you should delete all objects you created - with a method or function that starts with 'create'. - The object is deleted simply by calling ->drop(). - See the documentation - for more information. -
That's it. Compile and run. -- |
-
Possible Errors - or Problems | -|||||
-
-
-
-
- Visual Studio
Solution: You may have set the include directory improperly - in the Visual Studio options. See above - for information on setting it. - -
Solution: You may have set the library directory improperly.
- See above for information on
- setting it. Compiler independent problems
Solution: You may have forgotten to copy the Irrlicht.dll - file from Irrlicht\bin\VisualStudio to the directory - the tutorial's project file is in. - If the tutorial compiles and runs successfully but produces - errors in the console like:- -
Or: -
Solution: The file listed in the error message cannot
- be found. Ensure that the directory specified in the
- main.cpp exists and is where the file is located. |
-
- - diff --git a/examples/01.HelloWorld_Android/AndroidManifest.xml b/examples/01.HelloWorld_Android/AndroidManifest.xml deleted file mode 100755 index b26b4d40..00000000 --- a/examples/01.HelloWorld_Android/AndroidManifest.xml +++ /dev/null @@ -1,21 +0,0 @@ - -
^l|qW9
z)HDrr{B~n81;QI{==$icUD>A>Ey_M!t-1wsKNbNU$mbJJkz^V*t @l8w_E~_E=cT0`JDhl)1?)Zj
z{rryan~E`}G*PL@r*`ZxpYS|aY`2}nv0{v2 _wA>q kZ2pZCj^)V_dRL@vhpw Lets start like the HelloWorld example: We include the irrlicht header
- files and an additional file to be able As already written in the HelloWorld example, in the Irrlicht Engine,
- everything can be found in the namespace 'irr'. To get rid of the irr::
- in front of the name of every class, we tell the compiler that we use
- that namespace from now on, and we will not have to write that 'irr::'. Again, to be able to use the Irrlicht.DLL file, we need to link with
- the Irrlicht.lib. We could set this option in the project settings,
- but to make it easy, we use a pragma comment lib: Ok, lets start. Again, we use the main() method as start, not the WinMain(),
- because its shorter to write. Like in the HelloWorld example, we create an IrrlichtDevice with createDevice().
- The difference now is that we ask the user to select which hardware accelerated
- driver to use. The Software device would be too slow to draw a huge Quake
- 3 map, but just for the fun of it, we make this decision possible too. Get a pointer to the video driver and the SceneManager so that we do
- not always have to write device->getVideoDriver() and device->getSceneManager(). To display the Quake 3 map, we first need to load it. Quake 3 maps are
- packed into .pk3 files wich are nothing other than .zip files. So we add
- the .pk3 file to our FileSystem. After it was added, we are able to read
- from the files in that archive as they would directly be stored on disk. Now we can load the mesh by calling getMesh(). We get a pointer returned
- to a IAnimatedMesh. As you know, Quake 3 maps are not really animated,
- they are only a huge chunk of static geometry with some materials attached.
- Hence the IAnimated mesh consists of only one frame, Because the level was modelled not around the origin (0,0,0), we translate
- the whole level a little bit. Now we only need a Camera to look at the Quake 3 map. And we want to
- create a user controlled camera. There are some different cameras available
- in the Irrlicht engine. For example the Maya Camera which can be controlled
- compareable to the camera in Maya: Rotate with left mouse button pressed,
- Zoom with both buttons pressed, The mouse cursor needs not to be visible, so we make it invisible. We have done everything, so lets draw it. We also write the current frames
- per second and the drawn primitives to the caption of the window. The
- 'if (device->isWindowActive())' line is optional, but prevents the
- engine render to set the position of the mouse cursor after task switching
- when other program are active. In the end, delete the Irrlicht device. That's it. Compile and play around with the program. To start, I include the header files, use the irr namespace, and tell
- the linker to link with the .lib file. Here comes the most sophisticated part of this tutorial: The class
- of our very own custom scene node. To keep it simple, To let our scene node be able to be inserted into the Irrlicht Engine
- scene, the class we create needs only be derived from the ISceneNode
- class and has to override some methods. First, we declare some member variables, to hold data for our tetraeder:
- The bounding box, 4 vertices, and The parameters of the constructor specify the parent of the scene node,
- a pointer to the scene manager, and an id of the scene node. In the
- constructor itself, we call the parent classes constructor, set some
- properties of the material we use to draw the scene node and create
- the 4 vertices of the tetraeder we will draw later. Before it is drawn, the OnPreRender() method of every scene node in
- the scene is called by the scene manager. If the scene node wishes to
- draw itself, it may register itself in the scene manager to be drawn.
- This is necessary to tell the scene manager when it should call the
- ::render method. For example normal scene nodes render their content
- one after another, while stencil buffer shadows would like to be drawn
- after all other scene nodes. And camera or light scene nodes need to
- be rendered before all other scene nodes (if at all). In the render() method most of the interresting stuff happenes: The Scene
- node renders itself. We override this method and draw the tetraeder. At least, we create three small additional methods. GetBoundingBox()
- returns the bounding box of this scene node, That's it. The Scene node is done. Now we simply have to start the engine,
- create the scene node and a camera, and look at the result. Create our scene node. Note that it is dropped (->drop()) instantly
- after we create it. This is possible because the scene manager now takes
- care of it. This is not nessecary, it would also be possible to drop it
- at the end of the program. To animate something in this boring scene consisting only of one tetraeder,
- and to show, that you now can use your scene node like any other scene
- node in the engine, we add an animator to the scene node, which rotates
- the node a little bit. Now draw everything and finish. That's it. Compile and play around with the program. )zp^mVbYWDBh^K{CJL
z7;;WZvo_v)Ghc=mDEAKHqE7@fl`_&Zrs0+E)tUpCe%841}>F
zN*lJ0VYvW1`X#DdRL~JoP#~wOYAOv#l&M^>Q}o@kc#{?B
-
-
-
-
-
-
- {{{ SCRIPT }}}
-
-
diff --git a/examples/01.HelloWorld_iOS/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/01.HelloWorld_iOS/Assets.xcassets/AppIcon.appiconset/Contents.json
deleted file mode 100644
index 36d2c80d..00000000
--- a/examples/01.HelloWorld_iOS/Assets.xcassets/AppIcon.appiconset/Contents.json
+++ /dev/null
@@ -1,68 +0,0 @@
-{
- "images" : [
- {
- "idiom" : "iphone",
- "size" : "29x29",
- "scale" : "2x"
- },
- {
- "idiom" : "iphone",
- "size" : "29x29",
- "scale" : "3x"
- },
- {
- "idiom" : "iphone",
- "size" : "40x40",
- "scale" : "2x"
- },
- {
- "idiom" : "iphone",
- "size" : "40x40",
- "scale" : "3x"
- },
- {
- "idiom" : "iphone",
- "size" : "60x60",
- "scale" : "2x"
- },
- {
- "idiom" : "iphone",
- "size" : "60x60",
- "scale" : "3x"
- },
- {
- "idiom" : "ipad",
- "size" : "29x29",
- "scale" : "1x"
- },
- {
- "idiom" : "ipad",
- "size" : "29x29",
- "scale" : "2x"
- },
- {
- "idiom" : "ipad",
- "size" : "40x40",
- "scale" : "1x"
- },
- {
- "idiom" : "ipad",
- "size" : "40x40",
- "scale" : "2x"
- },
- {
- "idiom" : "ipad",
- "size" : "76x76",
- "scale" : "1x"
- },
- {
- "idiom" : "ipad",
- "size" : "76x76",
- "scale" : "2x"
- }
- ],
- "info" : {
- "version" : 1,
- "author" : "xcode"
- }
-}
\ No newline at end of file
diff --git a/examples/01.HelloWorld_iOS/HelloWorld_iOS.xcodeproj/project.pbxproj b/examples/01.HelloWorld_iOS/HelloWorld_iOS.xcodeproj/project.pbxproj
deleted file mode 100644
index 18933c8d..00000000
--- a/examples/01.HelloWorld_iOS/HelloWorld_iOS.xcodeproj/project.pbxproj
+++ /dev/null
@@ -1,302 +0,0 @@
-// !$*UTF8*$!
-{
- archiveVersion = 1;
- classes = {
- };
- objectVersion = 46;
- objects = {
-
-/* Begin PBXBuildFile section */
- 5E172FF01C1DB99B0024464F /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E172FEF1C1DB99B0024464F /* UIKit.framework */; };
- 5E172FF21C1DB9C80024464F /* CoreMotion.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E172FF11C1DB9C80024464F /* CoreMotion.framework */; };
- 5E172FF41C1DBA610024464F /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E172FF31C1DBA610024464F /* OpenGLES.framework */; };
- 5E172FF81C1DBAC30024464F /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E172FF71C1DBAC30024464F /* Foundation.framework */; };
- 5E172FFC1C1DBB280024464F /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E172FFB1C1DBB280024464F /* QuartzCore.framework */; };
- 5E6AC1831C1DA8A100DADD92 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5E6AC1821C1DA8A100DADD92 /* main.cpp */; };
- 5E6AC1881C1DA9C000DADD92 /* media in Resources */ = {isa = PBXBuildFile; fileRef = 5E6AC1871C1DA9C000DADD92 /* media */; };
- 5E6AC18B1C1DAA3100DADD92 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 5E6AC18A1C1DAA3100DADD92 /* Assets.xcassets */; };
- 5E6AC18D1C1DAD9500DADD92 /* libIrrlicht.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E6AC18C1C1DAD9500DADD92 /* libIrrlicht.a */; };
-/* End PBXBuildFile section */
-
-/* Begin PBXFileReference section */
- 5E172FEF1C1DB99B0024464F /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
- 5E172FF11C1DB9C80024464F /* CoreMotion.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMotion.framework; path = System/Library/Frameworks/CoreMotion.framework; sourceTree = SDKROOT; };
- 5E172FF31C1DBA610024464F /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; };
- 5E172FF71C1DBAC30024464F /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
- 5E172FFB1C1DBB280024464F /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
- 5E6AC1821C1DA8A100DADD92 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = "
-
-
-
-
-
-
-
-
-
-
- to ask the user for a driver type using the console.
-
-
-
-
- #include <irrlicht.h>
#include <iostream>
- There are 5 other sub namespaces 'core', 'scene', 'video', 'io' and
- 'gui'. Unlike in the HelloWorld example, we do not a 'using namespace'
- for these 5 other namespaces because in this way you will see what can
- be found in which namespace. But if you like, you can also include the
- namespaces like in the previous example. Code just like you want to.
-
-
-
-
- using namespace irr;
-
-
-
-
-
- #pragma comment(lib, "Irrlicht.lib")
-
-
-
-
- int main()
{
-
-
-
-
- // ask user for driver
video::E_DRIVER_TYPE driverType = video::EDT_DIRECT3D9;
printf("Please select the driver you want for this example:\n"\
" (a) Direct3D 9.0c\n (b) Direct3D 8.1\n (c) OpenGL 1.5\n"\
" (d) Software Renderer\n (e) Apfelbaum Software Renderer\n"\
" (f) NullDevice\n (otherKey) exit\n\n");
-char i;
std::cin >> i;
switch(i)
{
case 'a': driverType = video::EDT_DIRECT3D9;break;
case 'b': driverType = video::EDT_DIRECT3D8;break;
case 'c': driverType = video::EDT_OPENGL; break;
case 'd': driverType = video::EDT_SOFTWARE; break;
case 'e': driverType = video::EDT_BURNINGSVIDEO;break;
case 'f': driverType = video::EDT_NULL; break;
default: return 1;
}
// create device and exit if creation failed
IrrlichtDevice *device =
createDevice(driverType, core::dimension2d<s32>(640, 480));
if (device == 0)
return 1;
-
-
-
-
- video::IVideoDriver* driver = device->getVideoDriver();
-scene::ISceneManager* smgr = device->getSceneManager();
-
-
-
-
- device->getFileSystem()->addZipFileArchive("../../media/map-20kdm2.pk3");
- so we get the "first frame" of the "animation", which
- is our quake level and create an OctTree scene node with it, using addOctTreeSceneNode().
- The OctTree optimizes the scene a little bit, trying to draw only geometry
- which is currently visible. An alternative to the OctTree would be a AnimatedMeshSceneNode,
- which would draw always the complete geometry of the mesh, without optimization.
- Try it out: Write addAnimatedMeshSceneNode instead of addOctTreeSceneNode
- and compare the primitives drawed by the video driver. (There is a getPrimitiveCountDrawed()
- method in the IVideoDriver class). Note that this optimization with the
- Octree is only useful when drawing huge meshes consiting of lots of geometry.
-
-
-
-
- scene::IAnimatedMesh* mesh = smgr->getMesh("20kdm2.bsp");
scene::ISceneNode* node = 0;
-
-if (mesh)
node = smgr->addOctTreeSceneNode(mesh->getMesh(0));
-
-
-
-
- if (node)
node->setPosition(core::vector3df(-1300,-144,-1249));
- translate with right mouse button pressed. This could be created with
- addCameraSceneNodeMaya(). But for this example, we want to create a camera
- which behaves like the ones in first person shooter games (FPS):
-
-
-
-
- smgr->addCameraSceneNodeFPS();
-
-
-
-
- device->getCursorControl()->setVisible(false);
-
-
-
-
- int lastFPS = -1;
- while(device->run())
-{
- driver->beginScene(true, true, video::SColor(0,200,200,200));
- smgr->drawAll();
- driver->endScene();
- int fps = driver->getFPS();
- if (lastFPS != fps)
- {
- core::stringw str = L"Irrlicht Engine - Quake 3 Map example [";
str += driver->getName();
str += "] FPS:";
str += fps;
device->setWindowCaption(str.c_str());
lastFPS = fps;
- }
-}
-
-
-
-
- device->drop();
return 0;
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- #include <irrlicht.h>
using namespace irr;
#pragma comment(lib, "Irrlicht.lib")
- our scene node will not be an indoor portal renderer nor a terrain scene
- node, but a simple tetraeder, a 3d object consiting of 4 connected vertices,
- which only draws itself and does nothing more.
-
-
-
-
- class CSampleSceneNode : public scene::ISceneNode
{
- the material of the tetraeder.
-
-
-
-
- core::aabbox3d<f32> Box;
video::S3DVertex Vertices[4];
video::SMaterial Material;
-
-
-
-
- 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 bounding box of your scene node.
- It will use it for doing automatic culling and other things. Hence we
- need to create a bounding box from the 4 vertices we use. If you do not
- want the engine to use the box for automatic culling, and/or don't want
- to create the box, you could also write
- AutomaticCullingEnabled = false;.
-
-
-
-
-
-
- Box.reset(Vertices[0].Pos);
for (s32 i=1; i<4; ++i)
Box.addInternalPoint(Vertices[i].Pos);
-}
-
- So here we simply register the scene node to get rendered normally.
- If we would like to let it be rendered like cameras or light, we would
- have to call SceneManager->registerNodeForRendering(this, SNRT_LIGHT_AND_CAMERA);
-
- After this, we call the OnPreRender-method of the base class ISceneNode,
- which simply lets also all the child scene nodes of this node register
- themselves.
-
-
-
-
- virtual void OnPreRender()
{
if (IsVisible)
SceneManager->registerNodeForRendering(this);
-
- ISceneNode::OnPreRender();
-}
-
-
-
-
- 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);
-}
- GetMaterialCount() returns the amount of materials in this scene node
- (our tetraeder only has one material), and getMaterial() returns the material
- at an index. Because we have only one material here, we can return the
- only one material, assuming that no one ever calls getMaterial() with
- an index greater than 0.
-
-
-
-
- virtual const core::aabbox3d<f32>& getBoundingBox() const
{
return Box;
} virtual u32 getMaterialCount()
- {
- return 1;
- }
virtual video::SMaterial& getMaterial(u32 i)
- {
- return Material;
- }
-};
-
-
-
-
- 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));
-
-
-
-
-
- CSampleSceneNode *myNode =
new CSampleSceneNode(smgr->getRootSceneNode(), smgr, 666);
-
-myNode->drop();
-
-
-
-
- scene::ISceneNodeAnimator* anim =
smgr->createRotationAnimator(core::vector3df(0.8f, 0, 0.8f));
-
-myNode->addAnimator(anim);
-anim->drop();
-
-
-
-
- while(device->run())
{
driver->beginScene(true, true, video::SColor(0,100,100,100));
-
- smgr->drawAll();
-
- driver->endScene();
- }
-
-device->drop();
-return 0;
-}