Fluxus

Somebody Should Set The Title For This Chapter!

Primitives are the most interesting things in fluxus, as they are the things which actually get rendered and make up the scene.

Polygon Primitive

A poly cube, textured with test.pngPolygon primitives are the most versatile primitives, as fluxus is really designed around them. The other primitives are added in order to achieve special effects and have specific roles. The other primitive types often have commands to convert them into polygon primitives, for further processing.

There are many commands which create polygon primitives:

(build-cube)
(build-sphere 10 10)
(build-torus 1 2 10 10)
(build-plane)
(build-seg-plane 10 10)
(build-cylinder 10 10)
(build-polygons 100 'triangles)

The last one is useful if you are building your own shapes from scratch, the others are useful for giving you some preset shapes. All build-* functions return an id number which you can store and use to modify the primitive later on.

Pdata Types

The pdata arrays available for polygons are as follows:

Vertex normal n 3 vector Vertex texture coords t 3 vector for u and v, the 3rd number is ignored Vertex colours c 4 vector rgba

Use Name Data Type
Vertex position p 3 vector
Vertex normal n 3 vector
Vertex texture coords t 3 vector for u and v, the 3rd number is ignored
Vertex colours c 4 vector rgba

Polygon topology and pdata

With polygonal objects, we need to connect the vertices defined by the pdata into faces that describe a surface. The topology of the polygon primitive sets how this happens:

Quad-list topology

Triangle-list topology

Triangle-strip topology

Triangle-fan topology

Polygon topology

This lookup is the same for all the pdata on a particular polygon primitive - vertex positions, normals, colours and texture coordinates.

Although using these topologies means the primitive is optimised to be very quick to render, it costs some memory as points are duplicated - this can also cause a big speed impact if you are doing lots of per-vertex calculation. The most optimal poly topology are triangle strips as they maximise the sharing of vertices, but also see indexed polygons for a potentially even faster method.

You can find out the topology of a polygon primitive like this:

(define p (build-cube))

(with-primitive p
    (display (poly-type))(newline)) ; prints out quad-list

Indexed polygons

The other way of improving efficiency is converting polygons to indexed mode. Indexing means that vertices in different faces can share the same vertex data. You can set the index of a polygon manually with:

(with-primitive myobj
        (poly-set-index list-of-indices))

Or automatically – (which is recommended) with:

(with-primitive myobj
        (poly-convert-to-indexed))

This procedure compresses the polygonal object by finding duplicated or very close vertices and “gluing” them together to form one vertex and multiple index references. Indexing has a number of advantages, one that large models will take less memory - but the big deal is that deformation or other per-vertex calculations will be much quicker.

Problems with automatic indexing

As all vertex information becomes shared for coincident vertices, automatically indexed polygons can’t have different normals, colours or texture coordinates for vertices at the same position. This means that they will have to be smooth and continuous with respect to lighting and texturing. This should be fixed in time, with a more complicated conversion algorithm.

NURBS Primitives 10000000000000A800000096CEE9A83F.jpg

NURBS are parametric curved patch surfaces. They are handled in a similar way to polygon primitives, except that instead of vertices, pdata elements represent control vertices of the patch. Changing a control vertex causes the mesh to smoothly blend the change across it’s surface.

(build-nurbs-sphere 10 10)
(build-nurbs-plane 10 10)

Pdata Types

Use Name Data Type
Control vertex position p 3 vector
Control vertex texture coords t 3 vector for u and v, the 3rd number is ignored
Control vertex colours c 4 vector rgba

Particle primitive 10000000000000F7000000D92015ED97.jpg

Particle primitives use the pdata elements to represent a point, or a camera facing sprite which can be textured – depending on the render hints. This primitive is useful for lots of different effects including, water, smoke, clouds and explosions.

 

(build-particles num-particles)
Use Name Data Type
Particle position p 3 vector
Particle colour c
3 vector
Particle size s
3 vector for width and height, the 3rd number is ignored

Geometry hints

Particle primitives default to camera facing sprites, but can be made to render as points in screen space, which look quite different. To switch to points:
(with-primitive myparticles
    (hint-none)    ; turns off solid, which is default sprite mode
    (hint-points)) ; turn on points rendering

If you also enable (hint-anti-alias) you may get circular points, depending on your GPU – these can be scaled in pixel space using (point-width).

Ribbon primitives

1000000000000400000003003CC7B6FA.png

Ribbon primitives are similar to particles in that they are either hardware rendered lines or camera facing textured quads. This primitive draws a single line connecting each pdata vertex element together. The texture is stretched along the ribbon from the start to the end, and width wise across the line. The width can be set per vertex to change the shape of the line.

(build-ribbon num-points)

Pdata Types

Use
Name
Data Type
Ribbon vertex position
p
3 vector
Ribbon vertex colour
c
3 vector
Ribbon vertex width
w
number

Geometry hints

Ribbon primitives default to render camera facing quads. You can also switch them to draw wire frame lines in screen space:

(with-primitive myline
    (hint-none) ; turns off solid, which is default mode
    (hint-wire)) ; turn on lines rendering

Text primitive10000201000002A0000000F694751A11.png

Text primitives allow you to create text based on texture fonts. The font assumed to be non proportional – there is an example font shipped with fluxus.

(texture (load-texture “font.png”))
(build-text text-string)

The primitive makes a set of quads, one for each character, with texture coordinates set to show the correct character from the texture. This provides a fast and cheap way of displaying text, and is useful for debugging, or if the text is quite small. You can probably also find quite creative ways of using this just as a way of chopping up a texture into little squares.

Type Primitive10000201000002BB00000142210F9ECC.png

The type primitive provides a much higher quality typeface rendering than the text primitive. It creates polygonal geometry from a ttf font and some text. Optionally you can also extrude the text which results in 3D shapes.

(build-type ttf-font-filename text)
(build-extruded-type ttf-font-filename text
extrude depth)

You can also convert the type primitive into a polygon primitive for further deformation or applying textures, with:

(type->poly type-prim-id)

Locator primitive

The locator is a null primitive, as it doesn’t render anything. Locators are useful for various tasks, you can use them as a invisible scene node to group primitive under. They are also used to build skeletons for skinning. To view them, you can turn on hint-origin, which draws an axis representing their transform.

(hint-origin)
(build-locator)

Pixel primitive1000020100000279000001BFE6C91BB7.png

A pixel primitive is used for making procedural textures, which can then be applied to other primitives. For this reason, pixel primitives probably wont be rendered much directly, but you can render them to preview the texture on a flat plane.

(pixel-primitive width height)
  
Use Name Data Type
Pixel colour
c
3 vector
Pixel alpha
a
number

Extra pixel primitive commands

A pixel primitive’s pdata corresponds to pixel values in a texture, you write to them to make procedural texture data. The pixel primitive comes with some extra commands:

(pixels-upload pixelprimitiveid-number)

Uploads the texture data, you need to call this when you’ve finished writing to the pixelprim, and while it’s grabbed.

(pixels->texture pixelprimitiveid-number)

Returns a texture you can use exactly like a normal loaded one.
See the examples for some procedural texturing. It’s important to note that creating textures involves a large amount of processing time, so you don’t want to plan on doing something per-pixel/per-frame for large textures. The pdata-func extensions could be used to help here in the future.
This is a simple example of creating a noise texture on a pixel primitive:

(with-primitive (build-pixels 100 100)
    (pdata-map!
        (lambda (colour)
            (rndvec))
        "c")
    (pixels-upload))

Blobby Primitives10000201000001CB0000019F8ACA5A17.png

Blobby primitives are a higher level implicit surface representation in fluxus which is defined using influences in space. These influences are summed together, and a particular value is “meshed” (using the marching cubes algorithm) to form a smooth surface. The influences can be animated, and the smooth surface moves and deforms to adapt, giving the primitive it’s blobby name. (build-blobby) returns a new blobby primitive id. Numinfluences is the number of “blobs”. Subdivisions allows you to control the resolution of the surface in each dimension, while boundingvec sets the bounding area of the primitive in local object space. The mesh will not be calculated outside of this area. Influence positions and colours need to be set using pdata-set.

(build-blobby numinfluences subdivisionsvec boundingvec)

Pdata Types

 Use  Name  Data Type
Position p 3 vecor
Strengh s number
Colour c 3 vector

Converting to polygons

Blobbies can be slow to calculate, if you only need static meshes without animation, you can convert them into polygon primitives with:

(blobby->poly blobby-id-num)