Time for action — using static geometry

We are going to modify the code from the last example to make it render faster:

  1. Remove the print statement; we don't need it anymore.
  2. Now get back to the manual object and remove all position() function calls that would add a point we already have added. For each quad, this should be points 4 and 6. Here is the code after removing duplicate entries:
    manual->position(5.0, 0.0, 0.0);
    manual->textureCoord(1,1);
    manual->position(-5.0, 10.0, 0.0);
    manual->textureCoord(0,0);
    manual->position(-5.0, 0.0, 0.0);
    manual->textureCoord(0,1);
    manual->position(5.0, 10.0, 0.0);
    manual->textureCoord(1,0);
    manual->position(2.5, 0.0, 4.3);
    manual->textureCoord(1,1);
    manual->position(-2.5, 10.0, -4.3);
    manual->textureCoord(0,0);
    manual->position(-2.0, 0.0, -4.3);
    manual->textureCoord(0,1);
    manual->position(2.5, 10.0, 4.3);
    manual->textureCoord(1,0);
    manual->position(2.5, 0.0, -4.3);
    manual->textureCoord(1,1);
    manual->position(-2.5, 10.0, 4.3);
    manual->textureCoord(0,0);
    manual->position(-2.0, 0.0, 4.3);
    manual->textureCoord(0,1);
    manual->position(2.5, 10.0, -4.3);
    manual->textureCoord(1,0);
    
  3. Now we describe the triangles we want to create using so-called indices. The first quad consists of two triangles; the first triangle uses the first three points and the second triangle uses the first, second, and fourth points. Keep in mind that, like everything else with computers, the points are counted starting with zero:
    manual->index(0);
    manual->index(1);
    manual->index(2);
    manual->index(0);
    manual->index(3);
    manual->index(1);
    
  4. Add the other two quads the same way:
    manual->index(4);
    manual->index(5);
    manual->index(6);
    manual->index(4);
    manual->index(7);
    manual->index(5);
    manual->index(8);
    manual->index(9);
    manual->index(10);
    manual->index(8);
    manual->index(11);
    manual->index(9);
    
  5. Now let the SceneManager create a new StaticGeometry instance:
    Ogre::StaticGeometry* field = mSceneMgr->createStaticGeometry("FieldOfGrass");
    
  6. Now in the for loop, create the grass entity. However, this time add it to the static geometry instance instead of the scene node:
    for(int i=0;i<50;i++)
    {
    for(int j=0;j<50;j++)
    {
    Ogre::Entity * ent = mSceneMgr->createEntity("BladesOfGrass");
    field->addEntity(ent,Ogre::Vector3(i*3,-10,j*3));
    }
    }
    
  7. To finish the static geometry, call the build function:
    field->build();
    
  8. Compile and run the application, and you should see the same field of grass, but this time, the application should be a lot faster:
    Time for action — using static geometry

What just happened?

We created the same scene we had before, but this time it runs faster. Why? The sole reason why it runs faster is static geometry. So how does static geometry differ from the "normal" approach we used before?

Rendering pipeline

Each time we are rendering a scene, Ogre 3D and the graphic card has to perform some steps. We have already covered some of them, but not all. One step we covered is culling; now let's discuss some steps we haven't met until now.

We know that there are different spaces an object can be in, like local space or world space. We also know that to render an object, we need to transform them from local space into world space. The transformation from local space to world space is a combination of simple mathematical operations, but they take up some computational time. When rendering our 2,500 grass entities, Ogre 3D has to calculate the world position of every grass entity for each frame. That's a lot of operations per frame, but what's even worse is that each grass entity is sent separately to the GPU for rendering. This takes a lot of time and is the reason why the application is so slow.

We can solve this problem with static geometry; we created an instance of the static geometry class using the scene manager in step 5. However, inside the for loop, we added the created entities, not to a scene node like we are used to doing it. Here, we added it directly to the static geometry and gave as a second parameter the position we want the entity to be.

After we finished adding entities to the static geometry instance, we had to call the build() function. This function takes all entities we have added and calculates the world position. It does even more. We can only add models that used the indices list because static geometry tries to combine models using the same material or vertex list to optimize itself even more. The price we pay is that we can't move an entity that has been added to static geometry. In the case of our grass field, this isn't a huge trade-off; grass doesn't usually move. Normally, static geometry is used for everything that isn't moving in a scene because it gives a huge speedup with practically no disadvantages. One disadvantage is that when we have a large part of the scene in a static geometry instance, culling is less effective because when one part of the static geometry is inside the view frustum, all of it must be rendered.

Indices

We discovered that we can only add entities that use indices to our static geometry instance. But we haven't discussed what indices are in the first place. To understand this, let's get back to our quad.

Indices

This quad has four points, which define the two triangles the quad is made of. When we look at the code we used to create this quad, we notice that we added six points instead of four and two points are added twice.

//First triangle
manual->position(5.0, 0.0, 0.0);
manual->textureCoord(1,1);
manual->position(-5.0, 10.0, 0.0);
manual->textureCoord(0,0);
manual->position(-5.0, 0.0, 0.0);
manual->textureCoord(0,1);
//Second triangle
manual->position(5.0, 0.0, 0.0);
manual->textureCoord(1,1);
manual->position(5.0, 10.0, 0.0);
manual->textureCoord(1,0);
manual->position(-5.0, 10.0, 0.0);
manual->textureCoord(0,0);

Points 1 and 2 in the picture are added twice because they are used in both triangles. One way to prevent this information duplication is to use a two-step system for describing triangles. First, we create a list with the points we want to use, and second, we create a list that defines the triangles we want to build out of the points.

Indices

Here we defined four points and then said that triangle one uses points 1, 2 and 3 and triangle two uses points 1, 2, and 4. This saves us from adding some point twice or, even more often, from using them more than twice. Here it may seem like a small difference, but when we have models with several thousand triangles, this really can make a difference. Static geometry demands that we only use entities with indices because, in this way, static geometry can simply create one big list with all points (also known as vertices) and another list with all indices. If we add entities that use the same points, static geometry only needs to add some indices and not new points. For a big level, this can be a huge space saver.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.222.169.139