"nature" demo

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
andyZER0
Posts: 5
Joined: Thu Jan 05, 2006 7:37 am
Location: Irvine, CA, USA
Contact:

"nature" demo

Post by andyZER0 »

What I'm trying to render is a grassy field (a terrain) populated with around 8,000-10,000 flowers.

First I...

Code: Select all

#define NUMBER_OF_DAFFODILS 8192
core::array<ISceneNode *> node; /* have nodes representing flower meshes */
core::array<ISceneNode *> particleNode; /* have nodes representing flower particles (this is for my "level of detail") */
core::array<vector3df> origNodeRotations; // original rotations for meshes
core::array<vector3df> origPartNodePositions; // original positions for particles/billboards.  cuz you can't rotate them :(
Basically, I have n amount of nodes and n amount of particle nodes for how many flowers I want to put in the scene.

I load the data in for every node. Each flower "mesh" node has a random position which is scattered all over the terrain. Each "particle" flower node shares that same position with the mesh node. Each mesh node also has its own rotation (which gets modified over time) so that it looks like its swaying in the wind. Then, depending on the distance, either the mesh will show, its billboarded/particle version will show, or nothing will show at all.

Code: Select all


if (countUp) // if swaying in one direction already
		{
			// sway some more
			rotAngle += angleInc * irrtime::timeFactor;
			if (rotAngle >= maxAngle) // if it gets to that maximum "sway" angle
			{ // sway other direction
				rotAngle = maxAngle;
				countUp = false;
			}
		}
		else
		{
			rotAngle -= angleInc * irrtime::timeFactor;
			if (rotAngle <= minAngle)
			{
				rotAngle = minAngle;
				countUp = true;
			}
		}

		vector3df pos1 = camera->getPosition();
		for (int i = 0; i < NUMBER_OF_DAFFODILS; ++i)
		{
#define MAX_DISTANCE 5000.0f
#define MAX_SPRITE_DISTANCE MAX_DISTANCE*0.1f
			vector3df pos2 = node[i]->getPosition();
			vector3df rotation = node[i]->getRotation();
			f32 distance = sqrtf((pos2.X - pos1.X)*(pos2.X - pos1.X) +
				  (pos2.Y - pos1.Y)*(pos2.Y - pos1.Y) +
				  (pos2.Z - pos1.Z)*(pos2.Z - pos1.Z));
			if (distance <= MAX_DISTANCE)
			{
				if (distance <= MAX_SPRITE_DISTANCE)
				{
					// show mesh
					node[i]->setVisible(true);
					particleNode[i]->setVisible(false);
				}
				else
				{
					// show particle
					node[i]->setVisible(false);
					particleNode[i]->setVisible(true);
				}
			}
			else 
			{
				// too far.  show nothing
				node[i]->setVisible(false);
				particleNode[i]->setVisible(false);
			}

			// rotate/translate entities if they can be seen
			if (node[i]->isVisible())
				node[i]->setRotation(origNodeRotations[i] + vector3df(0,0,rotAngle));
			if (particleNode[i]->isVisible())
				particleNode[i]->setPosition(origPartNodePositions[i] + vector3df(-rotAngle,0,0));
		}
So I get the results... (picture on the right shows "level of detail" in action ;)
ImageImage

Is there a better/more optimized way of doing this? Some way to possibly get more frames per second? Instancing or something or possibly shaders? Thanks in advance.
bitplane
Admin
Posts: 3204
Joined: Mon Mar 28, 2005 3:45 am
Location: England
Contact:

Post by bitplane »

I like your method, pretty cool LOD control going on there.
I made a flat grass node, which creates square grass patches as separate mesh buffers and only draws those closest to the camera
http://irrlicht.sourceforge.net/phpBB2/ ... hp?t=10762

heres some things i did to optimize it -
draw all the billboards into one mesh buffer, rather than as separate nodes (designed that way, i think this matters a lot)
drop blades depending on 'depth' in grass-box and distance: 145fps to 175fps
check each blade is inside the camera's frustrums bounding box before processing (150fps to 175fps)
in distant squares of grass, i don't loop so deep (175 to 255 fps)
only update the shared mesh buffer if a certain amount of time has passed (at 0 = 140fps, at 30 = 320fps, at 3000 = 370fps!!)
i've got to a point where drawing the buffers is the slow part, to take it any further would really need hardware mesh buffers and doing the wind and the fading out on a shader or something.

feel free to use any of my code, but you should probably start with CParticleSystemSceneNode.cpp/h instead, as the main optimization is getting all those billboards into one mesh buffer.
Submit bugs/patches to the tracker!
Need help right now? Visit the chat room
omaremad
Competition winner
Posts: 1027
Joined: Fri Jul 15, 2005 11:30 pm
Location: Cairo,Egypt

Post by omaremad »

maybe both of you might be intrested in the last demo of this page

i will also read it as it looks like the "proper" solution for this tough problem

http://download.developer.nvidia.com/de ... mples.html
bitplane
Admin
Posts: 3204
Joined: Mon Mar 28, 2005 3:45 am
Location: England
Contact:

Post by bitplane »

aww... as cool as it looks, my graphics card doesn't support it :(
Submit bugs/patches to the tracker!
Need help right now? Visit the chat room
Guest

Post by Guest »

if you are familar with shaders you might google for shader particle systems (since you use billboards you can say "particle system").. you can do millions of particles with shaders, but you have to know how to work with shaders and how to integrate them efficently in irrlicht. otherwise you should check the irrlicht source, focus on one render api and then try to put all objects which are the same (same vertices, textures, ... just like your flowers) and put all geometry data and stuff into a single buffer which only needs a single render-call (this will speed up everything A LOT)
Post Reply