Gras
Für die Darstellung von Gras gibt es kein Modul in Irrlicht, man muss also selbst
eine Lösung dafür finden. Oder einfach im Forum suchen...
Das verwendete Plugin (Grass Node v0.3.2, siehe Links) ist eine sehr prototypische Implementierung, die für eine sinnvolle Verwendung noch
stark angepasst werden muss. Beispielsweise ist die Fläche, die durch das Gras
bedeckt wird, in der Demo begrenzt auf eine festgelegte Größe, d.h. sie ist
unabhängig von der Größe des Terrains. Ausserdem ist die Grasgenerierung
extrem ineffizient und reduziert die FPS drastisch. Ein Gras tile-manager wäre
noch zu entwickeln.
Trotzdem hier erst einmal eine kleine Beschreibung zur Verwendung des Grass Nodes wie
er ist:
Die Grundidee ist, kleine billboard Grasbüschel (als Partikel) so auf dem Terrain zu verteilen,
wie es auf der "Grassmap" codiert ist. Eine Grassmap funktioniert dabei analog zu einer
Heightmap: durch die Helligkeit der Pixel wird die Höhe des Grases angegeben.
Die Dichte (d.h. der Abstand der Grasbüschel) wird separat im Quellcode angegeben.
(Allerdings sollte ohne vorherige Implementierung eines tile-managers keine zu Hohe Dichte eingestellt werden - die FPS-Dezimierung ist beachtlich...)
Aus Performanzgründen sind die Grasbüschel in Grasflicken organisiert. Es wird
also nicht ein einzelner Grasteppich auf den Terrain gelegt, sondern immer nur Ausschnitte
davon. Ist so ein Flicken in Reichweite, wird für die enthaltenen Büschel
ihr Abstand zur Kamera geprüft und sie werden ggf. gerendert. So muss nicht für
jedes Grasbüschel der Abstand zur Kamera berechnet werden. Das ist auch schon
der einzige Grund für die Existenz dieser "Flicken-Struktur", auch wenn sie für die Entwicklung eines tile-managers noch nützlich sein könnte.
Ein schönes Feature dieses Grasplugins ist die Simulation von Wind, der durch die
Gräser streift. Die ist zwar nicht besonders realistisch, sieht aber nett aus.
Folgende Optionen können angepasst werden:
- setDrawDistance:
der Abstand den ein Grasbüschel zur Kamera haben muss,
damit es gezeichnet wird
- setMaxDensity:
die Maximale Dichte ( = geringster Abstand zwischen Büscheln)
- setRefreshDelay:
bestimmt wie oft das Gras aktualisiert wird. (nimmt bisher
keine Rüchsicht auf die Entfernung des Grases zur Kamera)
- setWindRes:
bestimmt die Größe des Windrasters ( = wie viele Windbüschel gleichzeitig vom Wind erfasst werden und sich gleichzeitig in die selbe Richtung bewegen)
Zur Verwendung müssen folgende Dateien importiert werden:
#include "CGrassPatchSceneNode.h"
#include "CWindGenerator.h"
Die Größe des Grasteppichs ist aus der Demo entnommen = ein 10x10 Grasflickenraster. Eine sinnvolle Funktion zur
Generierung von Gras in Abhängigkeit vom Terrain wäre natürlich besser.
#define width 10
#define height 10
Als nächstes ein paar Deklarationen.
//grass and wind
ITexture *tex1;
ITexture *tex2;
IWindGenerator *wind;
CGrassPatchSceneNode *grass[width*height];
Der Rest spielt sich in der main-Funktion ab.
Der Windgenerator begnügt sich mit 2 Argumenten:
Zum einen wäre da strength, die Stärke des Windes,
zum anderen regularity, die Gleichmäßigkeit des Windes.
Das war's auch schon für den Wind.
//create wind
wind = createWindGenerator( 30.0f, 3.0f );
Als nächstes müssen die Bilder für Grassmap, Heightmap und Colormap geladen werden. Letztere bestimmt die Farbe der Grashalme, während erstere für
Höhe und Positionierung der Grasbüschel gebraucht werden.
//make maps for adding grass
IImage* heightMap = irrDriver->createImageFromFile(
- "textures/03heightmap3.bmp");
IImage* textureMap = irrDriver->createImageFromFile(
- "textures/terrain-grasscol.bmp");
IImage* grassMap = irrDriver->createImageFromFile(
- "textures/terrain-grassmap2.png");
Danach werden die Texturen für das Gras geladen. Die folgende Methode
fügt einen Alpha-Channel hinzu. Das zweite Argument
colorKeyPixelPos bezeichnet das Pixel, dessen Farbe als transparent
gelten soll.
tex1 = irrDriver->getTexture("textures/grass.png");
tex2 = irrDriver->getTexture("textures/grass2.bmp");
irrDriver->makeColorKeyTexture(tex2, position2d(0,0));
Alle Vorbereitungen sind getroffen - das Gras kann erzeugt werden.
Zuerst die Schleife, damit nicht jeder Flicken per Hand erstellt werden muss.
//add grass
for (int x=0; x<width; ++x)
- for (int z=0; z<height; ++z)
Nun zur Erzeugung der Grasknoten. Ihre Klasse heisst CGrassPatchSceneNode
und möchte stolze 9 Argumente:
- terrain: Der Terrain, auf den das Gras gepflanzt werden soll
- mgr: Der SceneManager
- id: Die Id für den Grasflicken
- gridpos: Die Position des Grasflickens
- filepath: Ein string, der eigentlich gar nicht gebraucht wird
- hightmap: Die Heightmap des Terrains
- colourMap: Die Colormap für das Gras
- grassMap: Die grassMap
- windgen: Der Windgenerator
- // add a grass node
- grass[x*width + z] = new CGrassPatchSceneNode(
- terrain, irrSceneMgr, -1, vector3d(x,0,z), "grass", heightMap, textureMap, grassMap, wind);
- grass[x*width + z]->setMaterialFlag(EMF_LIGHTING,true);
- grass[x*width + z]->setMaterialType(EMT_TRANSPARENT_ALPHA_CHANNEL);
- grass[x*width + z]->setMaterialTexture(0,tex1);
- grass[x*width + z]->drop();
- }
Schließlich müssen Height-, Grass- und Texturemap noch zerstört werden.
(am Ende des Programms)
heightMap->drop();
textureMap->drop();
grassMap->drop();
zurück
weiter