This page covers some more advanced features of the Volume Component.

Getting the triangles of the chunks

When you want to integrate the volume triangles in a physics engine for example, you need to hand over the exact triangles. For this scenario, the ChunkParameters hold a pointer to a MeshBuilderCallback and a number lodCallbackLod. The first is an interface with a single function trianglesReady which is called, when the triangles of a chunk are ready. The chunks are chosen via the lodCallbackLod. If you build a volume with 3 LOD levels and you want the triangles of the highest detail level, you set this parameter to 3. Example:

class MyMeshBuilderCallback : public MeshBuilderCallback
    virtual  ready(const SimpleRenderable *simpleRenderable, const VecVertex &vertices, const VecIndices &indices, size_t level, int inProcess)
        size_t count = indices.size();
        for (size_t i = 0; i < count; i += 3)
            Vertex v1 = vertices[indices[i]];
            Vertex v2 = vertices[indices[i + 1]];
            Vertex v3 = vertices[indices[i + 2]];
            // Do something with the Triangle...

And using it like this:

ChunkParameters parameters;
MyMeshBuilderCallback callback;
parameters.lodCallback = &callback;
parameters.lodCallbackLod = 3;
rootChunk->load(parent, from, to, 3, &parameters);

Or in case of loading from a configuration file:

MyMeshBuilderCallback callback;
rootChunk->load(parent, sceneManager, "myVolume.cfg", 0, &callback, 3);

You might have seen, that a pointer to a SimpleRenderable is handed in, too. This is actually the Chunk whose triangles are loaded. It's parent class is used to not create a circular dependency. You might get the triangle data from it, too by getting the Renderoperation.

Intersecting a ray with a volume

When you want to do something exactly on the volume surface, you can cast rays and find their first intersection point. Behold that the triangle representation might be slightly different than the actual volume surface. And you have to scale the ray origin just like the volume. Here is an example which uses the negative z-axis of the camera as ray as it might be done like in an ego-shooter:

Ray ray(mCamera->getPosition() / rootChunk->getScale(), -mCamera->getOrientation().zAxis());
Vector3 intersection;
Real scale = mVolumeRoot->getChunkParameters()->scale;
bool intersects = mVolumeRoot->getChunkParameters()->src->getFirstRayIntersection(ray, intersection, scale);
if (intersects)
    intersection *= scale; // As it is in volume space.
    // Do something with intersection.

Editing a Volume made from a GridSource

A usecase is realtime editing of volume terrain as seen as in the sample. Let's union the terrain with a sphere of the radius 2.5 and the center 123/123/123. volumeRoot is the Chunk instance with which the terrain was initially loaded. The factor 1.5 is just to have a save border arround the sphere which also gets updated. The rest of the parameters are 5 LOD levels and a volume mesh covering an area of 384^3.

Vector3 center(123);
Real radius = (Real)2.5;
CSGSphereSource sphere(radius, center);
CSGUnionSource operation;
static_cast<GridSource*>(volumeRoot->getChunkParameters()->src)->combineWithSource(&operation, &sphere, center, radius * (Real)1.5);
volumeRoot->getChunkParameters()->updateFrom = center - radius * (Real)1.5;
volumeRoot->getChunkParameters()->updateTo = center + radius * (Real)1.5;
volumeRoot->load(volumeRootNode, Vector3::ZERO, Vector3(384), 5, volumeRoot->getChunkParameters());