Tutorial¶
Revl is all about generating pseudo-random Maya scenes by evaluating a set of weighted commands.
The built-in commands are fairly basic and might not cover all your needs, in which case you are encouraged to provide your own.
Generating a Scene¶
A scene can be generated in two steps: creating a set of weighted commands, and evaluating it.
Each weighted command can be defined either by using the class Command
or by using a tuple that follows the same structure than the Command
class. Indeed, all the command definitions below are equal:
>>> import revl
>>> command1 = revl.Command(weight=1.0, function=revl.createTransform)
>>> command2 = revl.Command(1.0, revl.createTransform)
>>> command3 = (1.0, revl.createTransform)
The command functions being evaluated at a later stage, its arguments also need to be passed to the command definition:
>>> import revl
>>> command1 = revl.Command(weight=1.0, function=revl.createTransform,
... args=(), kwargs={'parent': True})
>>> command2 = revl.Command(1.0, revl.createTransform, (), {'parent': True})
>>> command3 = (1.0, revl.createTransform, (), {'parent': True})
From there, actually generating a scene is only a matter of adding the commands
in a list and calling the run()
function:
>>> import revl
>>> commands = [
... (1.0, revl.createTransform),
... ]
>>> revl.run(commands, 100)
This example creates a scene with 100 transform nodes parented to the world.
Setting the createTransform()
function’s parameter parent
to True
like before, already helps with adding a bit of randomness into the result:
>>> import revl
>>> commands = [
... (1.0, revl.createTransform, (), {'parent': True}),
... ]
>>> revl.run(commands, 100)
The 100 transform nodes are now randomly parented under other transforms. The
Command.weight
attribute has no effect here, so let’s see it in action:
>>> import revl
>>> Type = revl.PrimitiveType
>>> commands = [
... (1.0, revl.createPrimitive, (), {'type': Type.POLY_CONE}),
... (2.0, revl.createPrimitive, (), {'type': Type.POLY_CUBE}),
... (5.0, revl.createPrimitive, (), {'type': Type.POLY_SPHERE}),
... ]
>>> revl.run(commands, 100)
Revl is invoking here a total of 100 evaluations inequally shared between the three distinct commands provided, leading the resulting scene to contain approximatively 12.5% of cones, 25% of cubes, and 62.5% of spheres.
Writing a Custom Command¶
The built-in commands don’t offer much features. Instead they aim to be simple and fast, and as such are good contenders to be used as building blocks to compose more advanced commands.
For example, it is possible to extend the function createPrimitive()
to
set the resulting shapes as templates:
>>> import revl
>>> def createTemplatedPrimitive(context, type=None, name=None,
... parent=False):
... primitive = revl.createPrimitive(context, type=type, name=name,
... parent=parent)
... for oShape in primitive.shapes:
... shape = OpenMaya.MFnDependencyNode(oShape)
... context.dg.newPlugValueBool(shape.findPlug('template'), True)
... return primitive
>>> commands = [
... (1.0, revl.createPrimitive),
... (1.0, createTemplatedPrimitive),
... ]
>>> revl.run(commands, 100)
This example will generate a scene with as much normal primitives than templated ones.
Note
When creating a new transform node, append the resulting maya.MObject
object to the Context.transforms
list attribute. This will allow
the function pickTransform()
to have more transform nodes to pick
from.
Note
For performance reasons, you are encouraged to make use of the
Context.dg
and Context.dag
attributes. This buffers the DG
and DAG operations, and applies them at the end of the run()
function.
If a custom command needs to access certain features requiring the graphs
to be up-to-date, then feel free to call their doIt()
methods.