Scene Setup

Actornodes are used whenever dynamic objects should be visible. We can use actornodes to manage the location and orientation of objects, cameras or lightsources.

Step 1:

Using the basic scene setup from the first tutorial, we can create a box which is located in front of the camera

view = UtilFunctions.simplerenderqueue()
view.rClear:colorvalue(0.0,0.0,0.0,0) 

actor = actornode.new("actor",0,10,0)
actor.l3d = l3dprimitive.newbox("box",1,1,1)
actor.l3d:linkinterface(actor)

The camera is always located in the orgin in first place and is looking towards (0,1,0).

We create here an actornode and save it in the global value named actor. The actor has a name (which is pretty much irrelevant for using it) and we can pass optionally three coordinates of its spawn.

Any object that is created by the luxinia core can be used just as a table. We use this in order to save a l3d node in the object.

Notice that when we "lose" the reference of the actor, the actor is deleted when the garbage collector is collecting it.

When we start Luxinia, we can view the box in the center of the screen, fully white.

Using the console, we can manipulate the actor. You can move the position by typing actor:pos(1,10,1) or rotate it by typing actor:rotdeg(30,20,10), which rotates the actor by the given angles in degrees (radians can be used by calling rotrad).

Step 2: A different camera perspective

We can use actors to move the camera, by obtaining the default camera and linking it to an actor that we create for that purpose:

cam = actornode.new("camera",0,5,5)
l3dcamera.default():linkinterface(cam)
cam:lookat(0,10,0, 0,0,1)

The (default) camera is now attached to the actor named cam and can be moved around. The lookat method helps us, to set the camera's orientation so that the created box is sitting in the center of the screen. The first three coordinates are setting the coordinate which we want to view in the center while the following three numbers define the upvector, so up is (0,0,1):

Again, we can easily manipulate the camera's position from the console, using the actor named cam.

We could also change the fov and various other camera properties ther, i.e. by typing l3dcamera.default():fov(60) (which sets the fov to 60 degrees).

Step 3: Animation

Our scene could be more lively, if the camera was animated, i.e. circling around the target. Currently, our script is only called once and never again. However, we need to change the camera properties each frame in order to display a movement. Luxinia is not multithreaded, but we can create timers and we can also pause the execution of the script and let it continue later. Luxinia has two concepts here: Timertasks and the Timers. A Timertask is a function that is called somewhere in the future. A timer function called periodical. Both functions are called as coroutines, which means that we can always yield the execution and let it continue later. Creating a timer is quite simple

function moveit ()
  local t = os.clock()
  local x,y = math.sin(t) * 10,math.cos(t)*10
  cam:pos(x,y,5)
  cam:lookat(0,10,0,0,0,1)
end

Timer.set("cameramovement",moveit,20)
 -- movit is now called every 20 milliseconds

The camera will now circle around the origin. Since we call the lookat function each time we change the position, we will always keep on looking at the point. The lookat function sets only the current rotation and does not affect the rotation if we move the actor around.

Step 3: Changing the appearance and switching on the lights

We could change the box into a sphere by calling l3dprimitive.newsphere instead of l3dprimitive.newbox. The graphical appearance is only dependent on the l3dnode which is linked to the actor. Any l3dnode can be attached at actors or scenenodes and we can use the functions that the l3dnodes provide to change the appearance. For example, calling actor.l3d:color(1,0,0,1) will change the color of the box to red.

Most often, we want our scene to be lit from a direction. I change now the visual box into a sphere, since it makes it easier to view the illumination effect:

actor = actornode.new("actor",0,10,0)
actor.l3d = l3dprimitive.newsphere("sphere",1,1,1)
actor.l3d:linkinterface(actor)
actor.l3d:rfLitSun(true)

Luxinia supports 4 light sources: The sun and 3 effect lights. The sun is located in the center and we can move it to a different location by attaching it to an actor and move the actor

mysun = actornode.new("sun",100,200,600)
mysun.light = l3dlight.new("light")
mysun.light:linkinterface(mysun)
mysun.light:makesun()

We can again change the effects by using the functions that are available for the l3dlights. I.e. we can change the ambient or diffusecolors:

mysun.light:diffuse(.8,.5,0,1)
mysun.light:ambient(.1,.2,.5,1)

Of course we could animate the lightsource, depending on a timer function.