Creating a Scene

Each time you want to invoke Beast to light and render a world or level in your game, you need to use the Beast API to create a scene: a representation of the geometry and light sources that should be taken into account during the rendering.

A scene is essentially a container for:

The scene acts as factory for all these object types; the memory used for these types of objects is managed by the scene they belong to. When you release a scene, all handles to the objects owned by that scene will be invalidated.

Scenes do not have a graph or a hierarchy. You are expected to flatten the transformations you provide for the objects in your scene so that they are all expressed in world space.

Scenes are not persisted in the cache by the Beast Manager. Therefore, they cannot be re-used by other Beast Managers, or re-used once they are destroyed.

Setting up a scene

You create and set up a scene as follows:

  1. Create meshes to represent the elements of the geometry in your world. You set up each mesh with its own array of vertices and normals, as well as other optional data such as materials, colors, tangents and bitangents, and UV sets.

    Meshes are not part of a scene themselves; they represent a definition of an object's geometry and properties. Meshes are created by the Beast Manager outside the scene, and are maintained in the cache on their own. Later, you will create instances of your mesh that place the geometry at a specific translation and rotation within your scene. This indirection allows each mesh to be re-used multiple times within each scene (and across multiple scenes at the same time) with a minimal additional memory cost.

    For details on meshes, and on how to create and set up mesh handles, see Creating Meshes.

  2. Create textures to represent the different input textures that should be applied to your meshes. Like meshes, textures are created and maintained outside the scene, so that each texture can be referenced by multiple mesh instances at the same time.

    For details on textures, and on how to create and set up texture handles, see Creating Textures.

  3. Create and initialize a scene handle, which will be a container that holds all of the other objects you add to the scene. You must create a new ILBSceneHandle object, and initialize it through a call to ILBBeginPhysicalScene().
  4. Create mesh instances that place your meshes at specific locations and orientations within your scene. You can also assign textures and materials to your instances.

    For details on mesh instances, and on how to create and set up instance handles, see Creating Mesh Instances.

  5. Create materials to represent the different kinds of surfaces on your meshes and mesh instances.

    When you create your meshes and instances, you assign materials to them by name. Then, within each scene, you create the actual referenced materials with those names. The properties of each material are set up within each scene. This indirection allows a single mesh to be used across multiple scenes with different material properties in each scene.

    For details on materials, and on how to create and set up material handles, see Creating Physical Materials.

  6. For each light in your scene, create and set up a light source through the API. You set up what type of light source it is (point light, spot light, sky light, etc.), its translation and rotation within the scene, and other optional properties that depend on this type.

    For details on light sources, and on how to create and set up light source handles, see Creating Light Sources.

  7. You can create cameras, if desired, to represent viewpoints in your scene. These viewpoints may be used during rendering, depending on the type of rendering you set up. For example, the camera may define the starting viewpoint for the eRnsT viewer, or the frame of view for rendering a still image of your scene.

    For details on cameras, and on how to create and set up camera handles, see Creating Cameras.

  8. If you want to dynamically affect the lighting applied to objects as they move around your scenes at runtime, you can create point clouds to bake the lighting at selected positions in the open spaces of your world.

    For details on point clouds, and on how to create and set up point cloud handles, see Creating Point Clouds.

  9. If desired, you can create light links between light sources and mesh instances in your scene. These links control whether or not the light from specific light sources apply to specific instances. For details, see Creating Light Links.
  10. When you have added all the objects outlined above to your scene, you must close the scene handle by calling ILBEndScene(). After you close the scene, you will be ready to set up and launch a rendering job as described under Rendering the Scene. Once the scene has been closed, you can only modify it during the course of a live eRnsT session.

The steps above do not have to be done in exactly the order specified. The only requirement is that you must set up all of your instances, materials, light sources, cameras and point clouds after you initialize your scene handle (step 3) and before you close your scene handle (step 10).

For example, the following code fragment illustrates the overall process of setting up a very simple scene:

// 1. Create meshes
std::basic_string<TCHAR> sphereMatName(_T("SphereMaterial"));
std::basic_string<TCHAR> floorMatName(_T("FloorMaterial"));
ILBMeshHandle floorMesh;
ILBBeginMesh(bmh, _T("Floor"), &floorMesh);
... // add triangles
ILBEndMesh(floorMesh);
ILBMeshHandle sphereMesh;
ILBBeginMesh(bmh, _T("Sphere"), &sphereMesh);
... // add triangles
ILBEndMesh(sphereMesh);

// 2. Create a texture used by the floor
ILBTextureHandle floorTex;
ILBBeginTexture(bm, _T("FloorTexture"), 256, 256, ILB_PF_RGBA_BYTE, &floorTex);
... // add pixel data
ILBEndTexture(floorTex);

// 3. Create the scene handle
ILBSceneHandle scene;
ILBBeginPhysicalScene(bmh, _T("SimpleScene"), &scene);

// 4. Create instances of the meshes
ILBInstanceHandle floorInstance;
bex::Matrix4x4 floorTrans = bex::scaleTranslation(bex::Vec3(10.0f, 1.0f, 10.0f), bex::Vec3(0.0f, -5.0f, 0.0f));
ILBCreateInstance(scene, floorMesh, _T("FloorInstance"), &floorTrans, &floorInstance);
ILBInstanceHandle sphereInstance;
bex::Matrix4x4 sphereTrans = bex::scaleTranslation(bex::Vec3(10.0f, 1.0f, 10.0f), bex::Vec3(0.0f, -5.0f, 0.0f));
ILBCreateInstance(scene, floorMesh, _T("SphereInstance"), &sphereTrans, &sphereInstance);

// 5. Set up the materials
ILBMaterialHandle floorMat; 
ILBCreateMaterial(scene, floorMatName.c_str(), &floorMat); 
ILBShaderHandle diffuseShader;
ILBCreateShader(scene, _T("diffuse"), _T("diffuseTexture.osl"), &diffuseShader);
ILBSetShader(floorMat, diffuseShader);

// 6. Create light sources
ILBLightHandle light;
ILBCreateDirectionalLight(scene, _T("Sun"), 
       &bex::directionalLightOrientation(bex::Vec3(1.0, -1.0f, -1.0f)), 
       &bex::ColorRGB(1.0f, 1.0f, .8f), 
       &light);
ILBSetCastShadows(light, true);
ILBSetShadowSamples(light, 32);
ILBSetShadowAngle(light, .1f);
ILBLightHandle skyLight;
ILBCreateSkyLight(scene, 
    _T("SkyLight"),
    &bex::identity(),
    &bex::ColorRGB(0.21f, 0.21f, 0.3f),
    &skyLight);

// 7. Create a camera
ILBCameraHandle camera;
ILBCreatePerspectiveCamera(scene, 
    _T("Camera"), 
	   &bex::setCameraMatrix(bex::Vec3(.3f, 3.0f, 20.0f), 
    bex::Vec3(.1f, -0.3f, -1.0f), 
    bex::Vec3(0.0f, 1.0f, 0.0f)), 
    &camera);
ILBSetFov(camera, static_cast<float>(M_PI) / 4.0f, 1.0f);

// 8. Create a point cloud
ILBPointCloudHandle pch;
ILBCreatePointCloud(scene, _T("DynamicCloud"), &pch);
... // set up the grid of points in the cloud
ILBEndPointCloud(pch);

// 9. Create light links
ILBAddLightLightLinks(skyLight, ILB_LL_EXCLUDING, sphereInstance, 1);

// 10. Finalize the scene
ILBEndScene(scene);

Thread safety

You can add objects to a single scene from multiple threads simultaneously. However:

Related API functions

API functions related to the creation and setup of scenes are declared in the beastscene.h file.