Irrlicht - from Noob to Pro: Objektauswahl realisieren

Vorwort Bearbeiten

 
Beispielanwendung: Auswahl eines Objektes

In diesem Beispiel wollen wir

  • darstellen, wie wir eine Irrlicht-Anwendung ohne Konsole realisieren
  • die Mauskoordinaten sowie den Status der Maustasten mit einem Event-Receiver abfragen und speichern.
  • ein Licht im Zentrum der Szene sowie SceneNodes außen herum erstellen.
  • die 2 gängigen Methoden zur Abfrage der Objektselektion (getSceneNodeFromScreenCoordinatesBB und getRayFromScreenCoordinates) verwenden.
  • die Objektselektion kontrollieren, indem wir das selektierte Objekt ohne Lichtberechnung rendern (linke Maustaste) oder als Wireframe darstellen (rechte Maustaste).
  • den durch Irrlicht berechneten Strahl (Ray) der Funktion getRayFromScreenCoordinates mit der Funktion draw3DLine farblich darstellen.

Konsole abschalten Bearbeiten

Die Konsole kann wie folgt abgeschaltet werden:

//Einbinden der Header-Datei von Irrlicht
#include <irrlicht.h>
//Im Falle von Windows ...
#ifdef _IRR_WINDOWS_
#pragma comment(lib, "Irrlicht.lib") //Library-Datei definieren
#pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup") //Keine Konsole anzeigen
#endif

Hier ist die Zeile

#pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup")

interessant.

  • /subsystem:windows sagt dem Linker, dass diese Anwendung keine Konsole braucht und seine Fenster selbst erstellt.
  • /ENTRY:mainCRTStartup teilt dem Linker mit, dass der Einsprungpunkt des Programms die Funktion int main() ist. CRTStartup bedeutet, dass die C-RunTime Funktionen mit initalisiert werden.

Der Event-Receiver mit Mausabfrage Bearbeiten

Wir erstellen nun wie üblich die Klasse für unseren Event-Receiver:

class MyEventReceiver : public IEventReceiver
{
public:
        //Implementierung der Standard OnEvent - Funktion
        virtual bool OnEvent(const SEvent& event)
        {
          return false;
        }
        
        MyEventReceiver() //Konstruktur
        {
        }
};

So sind wir nun mal grundlegend in der Lage, einen Auslöser (Event) abzufangen. Nun begrenzen wir dies noch auf Mausereignisse:

        //Implementierung der Standard OnEvent - Funktion
        virtual bool OnEvent(const SEvent& event)
        {		//Handelt es sich um ein Maus-Event ?
                if (event.EventType == irr::EET_MOUSE_INPUT_EVENT)
                {
                }
          return false;
        }

Jetzt benötigen wir noch den Auslöser des Ereignisses, welches wir durch Irrlichts eingebaute Routinen abfragen:

//Implementierung der Standard OnEvent - Funktion
        virtual bool OnEvent(const SEvent& event)
        {		//Handelt es sich um ein Maus-Event ?
                if (event.EventType == irr::EET_MOUSE_INPUT_EVENT)
                {
                        switch(event.MouseInput.Event)
                        {
                        case EMIE_LMOUSE_PRESSED_DOWN: //Linke Maustaste gedrückt ?                                
                                break;
                        case EMIE_LMOUSE_LEFT_UP: //Linke Maustaste losgelassen ?
                                break;
			case EMIE_RMOUSE_PRESSED_DOWN: //Rechte Maustaste gedrückt ?
 			        break;
			case EMIE_RMOUSE_LEFT_UP: //Rechte Maustaste losgelassen ?
				break;
			case EMIE_MMOUSE_PRESSED_DOWN: //Mittlere Maustaste gedrückt ?
 			        break;
			case EMIE_MMOUSE_LEFT_UP: //Mittlere Maustaste losgelassen ?
				break;
                        case EMIE_MOUSE_MOVED: //Maustaste bewegt ?
                                break;
                        default:break;
                        }
                }
		  return false;
	}

Hierdurch ist es uns möglich, den Status der linken, rechten und mittleren Maustaste abzufragen. Wir definieren nun noch eine Struktur, um den Status der Maus zu speichern und verwenden diese dann im Code:

class MyEventReceiver : public IEventReceiver
{
public:
        //Diese Struktur dient der Speicherung der Mauszustände
        struct SMouseState
        {
                core::position2di Position; //Position auf dem Bildschirm
                bool LeftButtonDown;        //linke Maustaste gedrückt ?
		bool RightButtonDown;       //rechte Maustaste gedrückt ?
		bool MiddleButtonDown;      //Mittlere Maustaste gedrückt ?
        } MouseState;

	//Implementierung der Standard OnEvent - Funktion
        virtual bool OnEvent(const SEvent& event)
        {	//Handelt es sich um ein Maus-Event ?
                if (event.EventType == irr::EET_MOUSE_INPUT_EVENT)
                {
                        switch(event.MouseInput.Event)
                        {
                        case EMIE_LMOUSE_PRESSED_DOWN: //Linke Maustaste gedrückt ?
                                MouseState.LeftButtonDown = true;
                                break;
                        case EMIE_LMOUSE_LEFT_UP: //Linke Maustaste losgelassen ?
                                MouseState.LeftButtonDown = false;
                                break;
			case EMIE_RMOUSE_PRESSED_DOWN: //Rechte Maustaste gedrückt ?
			        MouseState.RightButtonDown = true;
				break;
			case EMIE_RMOUSE_LEFT_UP: //Rechte Maustaste losgelassen ?
				MouseState.RightButtonDown = false;
				break;
			case EMIE_MMOUSE_PRESSED_DOWN: //Mittlere Maustaste gedrückt ?
			        MouseState.MiddleButtonDown = true;
				break;
			case EMIE_MMOUSE_LEFT_UP: //Mittlere Maustaste losgelassen ?
				MouseState.MiddleButtonDown = false;
			        break;
                        case EMIE_MOUSE_MOVED: //Maustaste bewegt ?
				//... Koordinaten speichern
                                MouseState.Position.X = event.MouseInput.X;
                                MouseState.Position.Y = event.MouseInput.Y;
                                break;
                        default:break;
                        }
                }
		 return false;
		}
		const SMouseState & GetMouseState(void) const //Funktion zur Abfrage des Status
        {
                return MouseState;
        }

        MyEventReceiver() //Konstruktur
        {
        }
};

Nun haben wir noch das Problem, dass der Datentyp bool in einer Klasse standardmäßig auf true gesetzt ist. Daher initialisieren wir unsere Variablen im Konstruktor der Klasse mit dem Wert false:

        MyEventReceiver() //Konstruktur
        {
	  //Variable initialisieren
	  this->MouseState.LeftButtonDown = false;
	  this->MouseState.RightButtonDown = false;
	  this->MouseState.MiddleButtonDown = false;
        }

Die Hauptfunktion int main() Bearbeiten

Den EventReceiver erstellen Bearbeiten

Hier erstellen wir unseren Event-Receiver anhand seiner Klasse:

int main()
{
		//Den Event-Receiver erstellen
		MyEventReceiver receiver;
}

Irrlicht initialisieren Bearbeiten

Wir initialisieren Irrlicht in gewohnter Weise, indem wir das Device, den Videotreiber und den Szenemanager erstellen und initialisieren:

        //Unser Irrlicht-Device erstellen und initialisieren
        IrrlichtDevice *device =
                createDevice( video::EDT_OPENGL, dimension2d<u32>(800, 600), 32,
                        false, false, false, &receiver);
 
        //Konnte das Device erstellt werden ?
        if (!device)
                return 1; //Falls nicht, Fehlercode zurückgeben und Programm abbrechen
 
        //Den Text des Hauptfensters festlegen
        device->setWindowCaption(L"Objektselektion in Irrlicht !");
 
        //Den Videotreiber erstellen und Zeiger aus dem Device abholen
        IVideoDriver* driver = device->getVideoDriver();      
 
        //Einen Szene-Manager erstellen und Zeiger aus dem Device abholen
        scene::ISceneManager* smgr = device->getSceneManager();

Die SceneNodes erstellen Bearbeiten

Wir wollen hier vier mal eine scene::ISceneNode erstellen, wobei drei davon sichtbar sind:

  • ein grüner Würfel links unten,
  • eine rote Kugel rechts unten und
  • ein blauer Würfel oben mittig

in der sichtbaren Szene. Wir benötigen allerdings auch noch eine ISceneNode, in welcher das selektierte Objekt gespeichert wird.

        //Erstellen der SceneNodes
        scene::ISceneNode * Wuerfel = smgr->addCubeSceneNode(1.0f);
	scene::ISceneNode * Wuerfel2 = smgr->addCubeSceneNode(1.0f);
	scene::ISceneNode * Kugel = smgr->addSphereSceneNode(1.0f, 64);
	scene::ISceneNode * node = 0; //Zum Speichern der ausgewählten SceneNode

Nun wollen wir diese Objekte noch einfärben:

        //Festlegen der Farbwerte
	Wuerfel->getMaterial(0).AmbientColor.set(255,0,255,0); //grüner Würfel
	Wuerfel->getMaterial(0).DiffuseColor.set(255,0,255,0);
	Wuerfel->getMaterial(0).EmissiveColor.set(10,0,20,0);

	Wuerfel2->getMaterial(0).AmbientColor.set(255,0,0,255); //blauer Würfel
	Wuerfel2->getMaterial(0).DiffuseColor.set(255,0,0,255);
	Wuerfel2->getMaterial(0).EmissiveColor.set(10,0,0,20);

	Kugel->getMaterial(0).AmbientColor.set(255,255,0,0); //rote Kugel
	Kugel->getMaterial(0).DiffuseColor.set(255,255,0,0);
	Kugel->getMaterial(0).EmissiveColor.set(10,20,0,0);

Hier zur Erklärung der Farbwerte:

  • AmbientColor ist der Farbwert, den das Objekt abstrahlt, wenn es im Schatten ist. Es ist also der Farbwert, den das Objekt im Umgebungslicht (Ambient Light) abgibt.
  • DiffuseColor ist der essentielle Farbwert, den das Objekt unter direktem Licht abstrahlt.
  • EmissiveColor ist der Farbwert, den das Objekt selbst abstrahlt.
  • SpecularColor ist der Farbwert der Reflektion von einstrahlendem Licht.

Nun müssen die Objekte noch platziert werden:

        //Positionierung
	Wuerfel->setPosition(core::vector3df(-2, -1, 3));
	Wuerfel2->setPosition(core::vector3df(0, 1, 3));
	Kugel->setPosition(core::vector3df(2, -1, 3));

Es werde Licht Bearbeiten

Zuerst erstellen wir ein leicht scheinendes Umgebungslicht, um die unbeleuchteten Flächen der Objekte nicht zu dunkel erscheinen zu lassen:

//Das Umbegungslicht ("Ambient Light") einstellen
smgr->setAmbientLight(video::SColorf(0.2f,0.2f,0.2f));

Danach platzieren wir noch eine Lichtquelle mit weisser Farbe in der Mitte der Szene, welche einen Abstrahlradius von 3.0 Einheiten hat:

//Unsere Lichtquelle
scene::ILightSceneNode * Lightnode = smgr->addLightSceneNode(0, core::vector3df(0, 0, 0), video::SColorf(1.0f, 1.0f, 1.0f, 1.0f), 3.0f);

Abfrage mittels getSceneNodeFromScreenCoordinatesBB() Bearbeiten

Da uns nun bekannt ist, wie der Status der Maus ist, können wir die erste Abfragemethode in unserer Renderloop implementieren:

//Linke Maustaste gedrückt ?
	/////////////////////////////
	if (receiver.GetMouseState().LeftButtonDown)
	{
		//Node unter dem Mauszeiger auswählen
		node =	smgr->getSceneCollisionManager()->getSceneNodeFromScreenCoordinatesBB(
				core::vector2d<s32>(receiver.GetMouseState().Position.X,receiver.GetMouseState().Position.Y));
		//Die ausgewählte ISceneNode nicht beleuchten (färbt sich weiss)
		if (node) node->setMaterialFlag(video::EMF_LIGHTING, false);				
	}

Die Funktion getSceneNodeFromScreenCoordinatesBB() prüft, ob sich eine BoundingBox eines Objekts innerhalb der aktuellen Kamera im ausgewählten 2D-Punkt befindet. Dazu wird ein Strahl berechnet, welcher von der XY-Koordinate der Maus in der dreidimensionalen Ansicht entlang der Kameraachse projiziert wird. Als Rückgabewert kommt entweder die ausgewählte ISceneNode oder 0 (kein Treffer) zurück. Dadurch, dass hier die BoundingBoxen der Objekte abgefragt werden, ist diese Methode nicht so rechentintensiv wie andere.

Die ausgewähtle ISceneNode wird zur Kontrolle anschließend weiss dargestellt, da sie sich der Lichtberechnung entzieht.

Abfrage mittels getSceneNodeFromRayBB() Bearbeiten

Alternativ kann anhand eines Strahls (engl. ray) die Kollision mit einer BoundingBox eines Objekts festgestellt werden. Man lässt dazu Irrlicht anhand der XY-Koordinaten des Mauszeigers einen Strahl entlang des Kamera-Vektors berechnen. Die Länge des Strahls ist begrenzt auf die Eigenschaft farValue (wird festgelegt durch ICameraSceneNode::setFarValue(f32 zf)). Dies funktioniert mittels getSceneNodeFromRayBB():

//Strahl aus den 2D-Mauskoordinaten entlang des Kameravektors berechnen
core::line3d<f32> ray = smgr->getSceneCollisionManager()->getRayFromScreenCoordinates(
	core::vector2d<s32>(receiver.GetMouseState().Position.X,receiver.GetMouseState().Position.Y),camera);

Ist nun der Strahl bekannt, so kann abgefragt werden, ob eine Kollision des Strahls mit einer BoundingBox stattfindet:

//Trifft der Strahl eine Bounding-Box einer SceneNode ?
node = smgr->getSceneCollisionManager()->getSceneNodeFromRayBB(ray);

Falls ein Treffer vorliegt, dann wird das ausgewählte Objekt in node zurückgegeben. Um die Auswahl zu markieren, schalten wir das Objekt in den Wireframe-Modus:

if (node) node->setMaterialFlag(video::EMF_WIREFRAME, true);

Den Strahl von getRayFromScreenCoordinates() anzeigen Bearbeiten

Auch hier wird der Strahl mittels der Funktion getRayFromScreenCoordinates berechnet. Anschließend wird dieser durch eine Linie dargestellt. Um die Linie deutlich sehen zu können, benötigen wir ein unbeleuchtetes Material, welches wir mit

//Ein Material deklarieren
video::SMaterial material;					 
//Das Material nimmt kein Licht an
material.Lighting = false;

erstellen. Danach muss dem Treiber mitgeteilt werden, dass dieses Material verwendet werden soll. Danach kann man die Linie (den berechneten Strahl) zeichnen lassen:

//Mittlere Maustaste gedrückt ?
////////////////////////////////
if (receiver.GetMouseState().MiddleButtonDown)
{				
	//Strahl aus den 2D-Mauskoordinaten entlang des Kameravektors berechnen
	core::line3d<f32> ray = smgr->getSceneCollisionManager()->getRayFromScreenCoordinates(
		core::vector2d<s32>(receiver.GetMouseState().Position.X,receiver.GetMouseState().Position.Y),camera);				 
	
	//Das unbeleuchtete Material festlegen
	driver->setMaterial(material);

	//Den Strahl zeichnen/anzeigen					
	driver->draw3DLine(ray.start, ray.end, video::SColor(255,255,0,0));
}

Zurücksetzen des Materials Bearbeiten

Falls weder die linke noch die rechte Maustaste gedrückt ist, soll das Material

  • mit berechneter Beleuchtung und
  • mit vollen Flächen (kein Wireframe)

dargestellt werden:

//Weder linke noch rechte Maustaste gedrückt ?
if ((!receiver.GetMouseState().RightButtonDown) && (!receiver.GetMouseState().LeftButtonDown))
{					
	//Alles zurücksetzen
	Wuerfel->setMaterialFlag(video::EMF_LIGHTING, true);
	Wuerfel->setMaterialFlag(video::EMF_WIREFRAME, false);					
	Wuerfel2->setMaterialFlag(video::EMF_LIGHTING, true);
	Wuerfel2->setMaterialFlag(video::EMF_WIREFRAME, false);				
	Kugel->setMaterialFlag(video::EMF_LIGHTING, true);
	Kugel->setMaterialFlag(video::EMF_WIREFRAME, false);					
}

Quellcode zum Beispiel Bearbeiten

//Einbinden der Header-Datei von Irrlicht
#include <irrlicht.h>
//Im Falle von Windows ...
#ifdef _IRR_WINDOWS_
#pragma comment(lib, "Irrlicht.lib") //Library-Datei definieren
#pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup") //Keine Konsole anzeigen
#endif
 
//Einbinden der Namespaces
using namespace irr;
using namespace core;
using namespace video;

class MyEventReceiver : public IEventReceiver
{
public:
        //Diese Struktur dient der Speicherung der Mauszustände
        struct SMouseState
        {
                core::position2di Position;  //Position auf dem Bildschirm
                bool LeftButtonDown;         //linke Maustaste gedrückt ?
		bool RightButtonDown;        //rechte Maustaste gedrückt ?
		bool MiddleButtonDown;       //Mittlere Maustaste gedrückt ?
        } MouseState;

		//Implementierung der Standard OnEvent - Funktion
        virtual bool OnEvent(const SEvent& event)
        { //Handelt es sich um ein Maus-Event ?
                if (event.EventType == irr::EET_MOUSE_INPUT_EVENT)
                {
                        switch(event.MouseInput.Event)
                        {
                        case EMIE_LMOUSE_PRESSED_DOWN: //Linke Maustaste gedrückt ?
                                MouseState.LeftButtonDown = true;
                                break;
                        case EMIE_LMOUSE_LEFT_UP: //Linke Maustaste losgelassen ?
                                MouseState.LeftButtonDown = false;
                                break;
			case EMIE_RMOUSE_PRESSED_DOWN: //Rechte Maustaste gedrückt ?
			        MouseState.RightButtonDown = true;
				break;
			case EMIE_RMOUSE_LEFT_UP: //Rechte Maustaste losgelassen ?
				MouseState.RightButtonDown = false;
				break;
			case EMIE_MMOUSE_PRESSED_DOWN: //Mittlere Maustaste gedrückt ?
			    MouseState.MiddleButtonDown = true;
			        break;
			case EMIE_MMOUSE_LEFT_UP: //Mittlere Maustaste losgelassen ?
				MouseState.MiddleButtonDown = false;
				break;
                        case EMIE_MOUSE_MOVED: //Maustaste bewegt ?
				//... Koordinaten speichern
                                MouseState.Position.X = event.MouseInput.X;
                                MouseState.Position.Y = event.MouseInput.Y;
                                break;
                        default:break;
                        }
                }
		return false;
	}
	const SMouseState & GetMouseState(void) const //Funktion zur Abfrage des Status
        {
                return MouseState;
        }

        MyEventReceiver() //Konstruktur
        {
		//Variable initialisieren
		this->MouseState.LeftButtonDown = false;
		this->MouseState.RightButtonDown = false;
		this->MouseState.MiddleButtonDown = false;
        }
};

//Die Hauptprozedur main()
int main()
{
	//Den Event-Receiver erstellen
	MyEventReceiver receiver;

	//Unser Irrlicht-Device erstellen und initialisieren
        IrrlichtDevice *device =
                createDevice( video::EDT_OPENGL, dimension2d<u32>(800, 600), 32,
                        false, false, false, &receiver);
 
        //Konnte das Device erstellt werden ?
        if (!device)
                return 1; //Falls nicht, Fehlercode zurückgeben und Programm abbrechen
 
        //Den Text des Hauptfensters festlegen
        device->setWindowCaption(L"Objektselektion in Irrlicht !");
 
        //Den Videotreiber erstellen und Zeiger aus dem Device abholen
        IVideoDriver* driver = device->getVideoDriver();      
 
        //Einen Szene-Manager erstellen und Zeiger aus dem Device abholen
        scene::ISceneManager* smgr = device->getSceneManager();	
		
        //Erstellen der SceneNodes
        scene::ISceneNode * Wuerfel = smgr->addCubeSceneNode(1.0f);
	scene::ISceneNode * Wuerfel2 = smgr->addCubeSceneNode(1.0f);
	scene::ISceneNode * Kugel = smgr->addSphereSceneNode(1.0f, 64);
	scene::ISceneNode * node = 0; //Zum Speichern der ausgewählten SceneNode
	
	//Festlegen der Farbwerte
	Wuerfel->getMaterial(0).AmbientColor.set(255,0,255,0);
	Wuerfel->getMaterial(0).DiffuseColor.set(255,0,255,0);
	Wuerfel->getMaterial(0).EmissiveColor.set(10,0,20,0);

	Wuerfel2->getMaterial(0).AmbientColor.set(255,0,0,255);
	Wuerfel2->getMaterial(0).DiffuseColor.set(255,0,0,255);
	Wuerfel2->getMaterial(0).EmissiveColor.set(10,0,0,20);

	Kugel->getMaterial(0).AmbientColor.set(255,255,0,0);
	Kugel->getMaterial(0).DiffuseColor.set(255,255,0,0);
	Kugel->getMaterial(0).EmissiveColor.set(10,20,0,0);
		
	//Das Umbegungslicht ("Ambient Light") einstellen
        smgr->setAmbientLight(video::SColorf(0.2f,0.2f,0.2f));

	//Unsere Lichtquelle
	scene::ILightSceneNode * Lightnode = smgr->addLightSceneNode(0, core::vector3df(0, 0, 0), video::SColorf(1.0f, 1.0f, 1.0f, 1.0f), 3.0f);

	//Positionierung
	Wuerfel->setPosition(core::vector3df(-2, -1, 3));
	Wuerfel2->setPosition(core::vector3df(0, 1, 3));
	Kugel->setPosition(core::vector3df(2, -1, 3));

	//Eine Kamera erstellen
	scene::ICameraSceneNode * camera = smgr->addCameraSceneNode(0, core::vector3df(0,0,-2), core::vector3df(0,0,0)); 
	//Die Kamera als aktiv setzen
	smgr->setActiveCamera(camera);

	//Ein Material deklarieren
	video::SMaterial material;					 
	//Das Material nimmt kein Licht an
	material.Lighting = false;

	//Während das Device aktiv ist ...
        while(device->run())
        {         
                //Szene beginnen
                driver->beginScene(true, true, SColor(0,0,0,0));
				
		//Linke Maustaste gedrückt ?
		if (receiver.GetMouseState().LeftButtonDown)
		{
			//Node unter dem Mauszeiger auswählen
			node =	smgr->getSceneCollisionManager()->getSceneNodeFromScreenCoordinatesBB(
				core::vector2d<s32>(receiver.GetMouseState().Position.X,receiver.GetMouseState().Position.Y));
			//Die ausgewählte ISceneNode nicht beleuchten (färbt sich weiss)
			if (node) node->setMaterialFlag(video::EMF_LIGHTING, false);				
		}
				
		//Rechte Maustaste gedrückt ?
		if (receiver.GetMouseState().RightButtonDown)
		{				
			//Strahl aus den 2D-Mauskoordinaten entlang des Kameravektors berechnen
			core::line3d<f32> ray = smgr->getSceneCollisionManager()->getRayFromScreenCoordinates(
				core::vector2d<s32>(receiver.GetMouseState().Position.X,receiver.GetMouseState().Position.Y),camera);
				
			//Trifft der Strahl eine Bounding-Box einer SceneNode ?
			node = smgr->getSceneCollisionManager()->getSceneNodeFromRayBB(ray);
					
			//Falls ja, dann auf Wireframe umschalten
			if (node) node->setMaterialFlag(video::EMF_WIREFRAME, true);						
		}

		//Mittlere Maustaste gedrückt ?
		if (receiver.GetMouseState().MiddleButtonDown)
		{				
			//Strahl aus den 2D-Mauskoordinaten entlang des Kameravektors berechnen
			core::line3d<f32> ray = smgr->getSceneCollisionManager()->getRayFromScreenCoordinates(
				core::vector2d<s32>(receiver.GetMouseState().Position.X,receiver.GetMouseState().Position.Y),camera);				 
				
			//Das unbeleuchtete Material festlegen
			driver->setMaterial(material);

			//Den Strahl zeichnen/anzeigen					
			driver->draw3DLine(ray.start, ray.end, video::SColor(255,255,0,0));
		}

		//Weder linke noch rechte Maustaste gedrückt ?
		if ((!receiver.GetMouseState().RightButtonDown) && (!receiver.GetMouseState().LeftButtonDown))
		{					
			//Alles zurücksetzen
			Wuerfel->setMaterialFlag(video::EMF_LIGHTING, true);
			Wuerfel->setMaterialFlag(video::EMF_WIREFRAME, false);					
			Wuerfel2->setMaterialFlag(video::EMF_LIGHTING, true);
			Wuerfel2->setMaterialFlag(video::EMF_WIREFRAME, false);				
			Kugel->setMaterialFlag(video::EMF_LIGHTING, true);
			Kugel->setMaterialFlag(video::EMF_WIREFRAME, false);					
		}

	        //Dem Szenemanager sagen, dass er alle Nodes zeichnen soll
                smgr->drawAll();

		//Szene beenden
                driver->endScene();
	}

	//Das Device freigeben
        device->drop();

	//Keinen Fehler beim Beenden zurückgeben
	return 0;
}