Creating a sandbox Lua script
With a basic sandbox application out of the way, we're going to create the basic Lua script that sets up the sandbox. First, create a new Sandbox.lua
script within the script folder:
Create the Lua file as follows:
src/my_sandbox/script/Sandbox.lua
A sandbox Lua script must implement four global functions that the C++ code will call, and they are Sandbox_Cleanup
, Sandbox_HandleEvent
, Sandbox_Initialize
, and Sandbox_Update
:
Sandbox.lua
:
function Sandbox_Cleanup(sandbox) end function Sandbox_HandleEvent(sandbox, event) end function Sandbox_Initialize(sandbox) end function Sandbox_Update(sandbox, deltaTimeInMillis) end
With the basic hooks in place, modify your SandboxApplication
class to create a sandbox based on your Lua script:
MySandbox.cpp
:
void MySandbox::Initialize() { SandboxApplication::Initialize(); ... CreateSandbox("Sandbox.lua"); }
Tip
Don't forget to recompile your sandbox application whenever a change is made to any of the C++ files.
Creating a floor
Now that your sandbox is initialized and hooked into Lua, we can start adding some basic geometry and lighting. The sandbox package exposed to Lua provides a CreatePlane
function that will create a plane mesh specified by a width and length. A corresponding physics half-space will also be created and added into the physics simulation.
Tip
A physics half-space is a plane that expands infinitely in both the x and z directions.
Once a plane object has been created, we'll assign an Ogre material through the Core.SetMaterial
function to give the plane a texture defined within media/materials/base.material
.
Tip
The sandbox is set up to handle standard diffuse, specular, and normal mapped material types. New materials can be added to the media/materials/base.material
file.
In this case we'll assign the Ground2
Ogre material to our newly created plane.
Sandbox.lua
:
function Sandbox_Initialize(sandbox) local plane = Sandbox.CreatePlane(sandbox, 200, 200); Core.SetMaterial(plane, "Ground2"); end
If you run the sandbox at this point, you might expect to see the plane you created, but you'll see a black screen instead. Without any lighting in our sandbox, even though our plane had been created, we won't be able to see it yet.
Adding a light
Our plane isn't very exciting, as the sandbox has no lighting. The core package provides additional functions that create a directional light and assign diffuse and specular colors. The Core.CreateDirectionalLight
function requires two parameters, the sandbox and a vector representing the direction of the light. Using a vector of (1, -1, 1)
will create a light source that points diagonally in a downward direction.
Sandbox.lua
:
function Sandbox_Initialize(sandbox) ... local directional = Core.CreateDirectionalLight( sandbox, Vector.new(1, -1, 1)); --- Color is represented by a red, green, and blue vector. Core.SetLightDiffuse( directional, Vector.new(1.8, 1.4, 0.9)); Core.SetLightSpecular( directional, Vector.new(1.8, 1.4, 0.9)); end
Tip
Note that the color of the diffuse and specular light values defined by Vector.new(red, green, blue)
are set to values above one. This allows you to change the amount of light emitted.
Now that we have a light source, you can run your sandbox and look at the beautiful plane you created. To orient the camera, simply hold the right mouse button and drag the mouse in the direction in which you would like to point the camera. To navigate through the sandbox, we can move the camera around the world using the w, a, s, and d keys. Holding the Shift key while pressing any of the w, a, s, and d keys will move the camera significantly faster.
Adding a skybox
Looking into infinite blackness isn't very exciting; Sandbox.CreateSkyBox
allows us to create a skybox defined by the six textures specified in the Ogre material (media/materials/skybox.material
). If you're unfamiliar with skyboxes, they are essentially six-sided boxes with a different texture on each face of the box. As the camera moves around the sandbox, the skybox moves accordingly in order to give the illusion of an actual sky.
Tip
The sandbox comes with multiple skybox materials. Take a peek at the skybox.material
file in any text editor to see other available skybox textures and how to create your own brand new skybox material.
Our Sandbox.CreateSkyBox
function takes in three parameters: the sandbox itself, the name of the Ogre material, as well as a rotation vector. The rotation vector is represented in degrees and allows us to add an initial offset to our skybox. In this case, we can rotate the initial skybox by 180 degrees to have the sky textures match the directional light we created previously:
Sandbox.lua
:
function Sandbox_Initialize(sandbox) ... Sandbox.CreateSkyBox( sandbox, "ThickCloudsWaterSkyBox", Vector.new(0, 180, 0)); end
Running the sandbox now will show a cloudy sky and a lit environment.
A new sandbox with a skybox and ground plane
Adding meshes to the sandbox
An Ogre mesh is simply a visual piece of geometry within the sandbox without any physics representation. To add an Ogre mesh to the sandbox, simply call Core.CreateMesh
and pass in the location and filename of an Ogre mesh file.
Setting the position and rotation of a mesh can be done through the Core.SetPosition
and Core.SetRotation
functions:
Sandbox.lua
:
function Sandbox_Initialize(sandbox) ... local mesh = Core.CreateMesh( sandbox, "models/nobiax_modular/modular_block.mesh"); Core.SetPosition(mesh, Vector.new(0, 1, 0)); Core.SetRotation(mesh, Vector.new(0, 45, 0)); end
The rotation function expects a vector of angles expressed in degrees. For example, Vector.new(0, 45, 0)
will rotate the mesh 45 degrees around the y axis.
Creating sandbox objects
If you want an Ogre mesh to be simulated with physics, you can create a sandbox object instead. Sandbox.CreateObject
will automatically generate a convex hull for any Ogre mesh and allow the object to be simulated with physics.
Note
As generating a physics representation for an arbitrary mesh happens at runtime, complex meshes might increase the load times of your sandbox. Internally, bullet physics creates a simplified convex hull that approximates the Ogre mesh instead of being an identical one-to-one mapping. Keep this in mind, as the physics representation of any Ogre mesh will always be an approximation and never an exact replica of the original mesh.
We can now convert the block mesh we created earlier to a full-fledged physically simulated object.
Sandbox.lua
:
function Sandbox_Initialize(sandbox) ... local object = Sandbox.CreateObject( sandbox, "models/nobiax_modular/modular_block.mesh"); -- Set the mass of the block in kilograms. Core.SetMass(object, 15); Core.SetPosition(object, Vector.new(0, 1, 0)); Core.SetRotation(object, Vector.new(0, 45, 0)); end