The state machine is the key to understanding how fluxus works, all it really means is that you can call functions which change the current context which has an effect on subsequent functions. This is a very efficient way of describing things, and is built on top of the OpenGl api, which works in a similar way. For example, in a function called every frame:
(colour (vector 1 0 0)) (draw-cube) (colour (vector 0 1 0)) (draw-cube)
Will draw a red cube, then a green cube (in this case, you can think of the (colour)
call as changing a pen colour before drawing something). States can also be stacked, for example:
(colour (vector 1 0 0)) (push) (colour (vector 0 1 0)) (draw-cube) (pop) (draw-cube)
will draw a green, then a red cube. the (push)
command stores the current state, and adds a copy to the top of the stack. (pop)
retrieves the previous state and deletes the current one (so changes to the state between the push and the pop are lost)
Both examples so far have used what is known as immediate mode, you have one state stack, the top of which is the current context, and everything is drawn once per frame. fluxus contains a structure known as a scenegraph for storing objects and their render states.
Time for another example:
(colour (vector 1 0 0)) (build-cube) (colour (vector 0 1 0)) (build-cube)
The only difference between this and the first example is the use of (build-cube) instead of (draw-cube). the build functions create a primitive object, copy the current renderstate and add the information into the scenegraph in a container called a scenenode.
The (build-*) functions return object ID's (just numbers really) which enable you to do things to the scene node after it's been created. you can now specify objects like this:
(define myob (build-cube))
The cube will now be persistant in the scene until destroyed with
(destroy myob)
If you want to modify a objects renderstate after it's been loaded into the scenegraph, you can use the grab function to temporarially set the current context to that of the object. use ungrab to turn fluxus back into normal state stack mode. this allows you to animate objects stored in the scenegraph, for instance:
(colour (vector 1 1 1)) (define obj1 (build-cube)) (push) (translate (vector 2 0 0)) (define obj2 (build-cube)) (pop)
—>8—
; in a function called per frame
(grab obj1) (rotate (vector 0 1 0)) (ungrab) (grab obj2) (rotate (vector 0 0 1)) (ungrab)
Do not call push or pop while an object is grabbed, it will have no effect - fluxus will print out a warning in this case.
The scenegraph also enables you to parent objects to one another, using the renderstate's parent setting. this is only effective before an object is loaded into the scenegraph, setting it afterwards via a grabbed state will be ignored:
(colour (vector 1 1 1)) (define a (build-cube)) (push) (parent a) (translate (vector 0 2 0)) (define b (build-cube)) (pop) (push) (parent b) (translate (vector 0 2 0)) (define c (build-cube)) (pop)
Creates three cubes, all attached to each other in a chain. transforms for object a will be passed down to b and c, transforms on b will effect c blah.
Destroying a object in such a hierachy will in turn destroy all child objects parented to it.