So far we have mostly looked at describing objects and deformations to fluxus so it can build scenes for you. Another powerful technique is to get fluxus to inspect your scene and give you information on what is there.
Scene graph inspection
The simplest, and perhaps most powerful commands for inspection are these commands:
(get-children) returns a list of the children of the current primitive, it can also give you the list of children of the scene root node if you call it outside of
(get-parent) returns the parent of the current primitive. These commands can be used to navigate the scenegraph and find primitives without you needing to record their Ids manually. For instance, a primitive can change the colour of it's parent like this:
(with-primitive myprim (with-primitive (get-parent) (colour (vector 1 0 0))))
You can also visit every primitive in the scene with the following script:
; navigate the scene graph and print it out (define (print-heir children) (for-each (lambda (child) (with-primitive child (printf "id: ~a parent: ~a children: ~a~n" child (get-parent) (get-children)) (print-heir (get-children)))) children))
A very common thing you want to do is find out if two objects collide with each other (particularly when writing games). You can find out if the current primitive roughly intersects another one with this command:
(bb/bb-intersect? other-primitive box-expand)
This uses the automatically generated bounding box for the primitives, and so is quite fast and good enough for most collision detection. The box expand value is a number with which to add to the bounding box to expand or shrink the volume it uses for collision detection.
Note: The bounding box used is not the same one as you see with (hint-box), which is affected by the primitive's transform. bb-intersect generates new bounding boxes which are all axis aligned for speed of comparison.
Another extremely useful technique is to create rays, or lines in the scene and get information about where on primitives they intersect with. This can be used for detailed collision detection or in more complex techniques like raytracing.
(geo/line-intersect line-start-position line-end-position)
This command returns a list of pdata values at the points where the line intersects with the current primitive. The clever thing is that it values for the precise intersection point – not just the closest vertex.
The list it returns is designed to be accessed using Scheme (assoc) command. An intersection list looks like this:
(collision-point-list collision-point-list ...)
Where a collision point list looks like:
(("p" . position-vector) ("t" . texture-vector) ("n" . normal-vector) ("c" . colour-vector))
The green sphere in the illustration are positioned on the "p" pdata positions returned by the following snippet of code:
(clear) (define s (build-torus 1 2 10 10)) ; line endpoint positions (define a (vector 3 2.5 1)) (define b (vector -2 -3 -.1)) ; draw the line (with-primitive (build-ribbon 2) (hint-wire) (hint-unlit) (pdata-set! "p" 0 a) (pdata-set! "p" 1 b)) ; process intersection point list (with-primitive s (for-each (lambda (intersection) (with-state ; draw a sphere at the intersection point (translate (cdr (assoc "p" intersection))) (colour (vector 0 1 0)) (scale (vector 0.3 0.3 0.3)) (build-sphere 5 5))) (geo/line-intersect a b)))
poly-for-each-face poly-for-each-triangle poly-for-each-tri-sample