STRUCTURE-SYNTH(1)

๐Ÿ“ฆ
version 1.5.0 ยท 2 versions
, in debian trixie, ubuntu questing, ubuntu resolute, ubuntu stonking

๐Ÿ’– NAME ๐Ÿ’–

okay bestie, so this is structure-synth(1) โ€” like, the manual page for structure-synth, which is your girl for creating 3D structures. that's it, that's the whole vibe. ๐Ÿฆ‹


โœจ SYNOPSIS โœจ

structure-synth

literally just run it. no flags, no drama, no cap. ๐Ÿ’…


๐ŸŒธ DESCRIPTION ๐ŸŒธ

so <pink>Structure Synth</pink> is this app for making 3D structures out of a set of rules you specify. you feed it rules, it gives you art. iconic behavior. ๐ŸŽ€

once you've built your little structure, you can look at it in the integrated OpenGL viewer, or export it out to various formats if you wanna share the slay with the world. โœจ

and for the lore girlies: the program was inspired by the CFDG syntax by Chris Coyne, and the Context Free GUI by Mark Lentczner and John Horigan. give them their flowers fr fr. ๐Ÿ‘‘


๐Ÿงš STATES, TRANSFORMATIONS AND ACTIONS ๐Ÿงš

okay so the WHOLE thing here is about states. a state is just: where you are (the current coordinate system) + how you're coloring (the current coloring mode). and the coordinate system is what decides the position, orientation and size of every single object drawn while you're chillin' in that state. ๐Ÿ’ซ

now, states get modified by transformations. like, you can scoot the coordinate system one unit over in the x-direction with this transformation: { x 1 }. yes girl, that easy. and you can rotate the whole coordinate system 90 degrees about the x-axis with: { rx 90 }. iconic. ๐ŸŒ€

and here's the cute part โ€” states are automatically combined while parsing. so { x 1 x 1 } is literally the same thing as { x 2 }. math ate, honestly. ๐Ÿ“

states can get combined with rule calls to create actions. example: { x 2 } box is a transformation followed by a rule call. box is a built-in rule. and (not surprisingly bestie) this rule draws a box located at (0,0,0) -> (1,1,1) in the current coordinate system. one unit cube, no thoughts, just vibes. ๐Ÿ“ฆ

๐Ÿ” Iterated actions:

you can also do iterated actions โ€” you do it with the multiplication symbol. so for instance, 3 * { x 2 } box would be equal to creating three actions. watch this:

{ x 2 } box
{ x 4 } box
{ x 6 } box

three boxes, three positions, zero extra typing. we love efficiency. ๐Ÿ’…

๐ŸŽจ Color transformations:

same energy as the spatial transformations, except it's the current rendering color getting transformed instead. Structure Synth uses HSV โ€” that's Hue, Saturation and Value โ€” for representing colors.

ngl this is maybe not as familiar as the RGB color model, but it offers a slightly more intuitive representation once you get used to it. (at least that's what some people claim โ€” personally the original author still finds it easier to think in terms of red, green and blue components, and honestly? relatable.) ๐Ÿ™ˆ

the color transformations get applied using the hue, saturation and value operators. ๐Ÿ’–

ok so this next example is serving โ€” it demonstrates iterated actions AND color transformations to draw a cute little color cube:

10 * { x 1 hue 36 } 10 * { y 1 sat 0.9 } 10 * { z 1 b 0.9 } box

and here's another one showing off the different kinds of transformations:

10 * { x 2 } box
1 * { y 2 } 10 * { x 2 rx 6 } box
1 * { y 4 } 10 * { x 2 hue 9 } box
1 * { y 6 } 10 * { x 2 s 0.9 } box

like, look at her go. ๐ŸŒˆ

๐ŸงŠ Built-in rules:

the Box is an example of one of the primitives โ€” the built-in rules โ€” in Structure Synth. the other built-in rules are: Sphere, Dot, Grid, Line, Cylinder, Mesh, CylinderMesh. that's the whole squad, memorize them iykyk. โœจ


๐Ÿ‘‘ MAKING RULES ๐Ÿ‘‘

custom rules? that's the key to creating complex and sophisticated structures. this is where you become the main character. you make rules using the rule keyword, and a rule can be used the same way as any built-in primitive. ๐Ÿ’œ

but the most important aspect of rules is that they are able to call themselves. recursion baby!! take a look at this:

R1

rule R1 {
  { x 0.9 rz 6 ry 6 s 0.99  sat 0.99  } R1
  { s 2 } sphere
}

notice that this rule recursively calls itself. now, it would never terminate on its own โ€” but Structure Synth has a default maximum recursion depth of 1000 recursions, so she'll cut you off before things get truly unhinged. ๐Ÿ˜ญ

you can change that value with the set maxdepth xxx command. OR, another way to force termination would be using the set maxobjects xxx keyword, which makes Structure Synth keep track of the number of objects drawn. two ways to say "bestie, please stop." ๐Ÿซถ

๐ŸŽฒ Adding some randomness:

okay, in order to keep things interesting, we're probably gonna wanna create something less static โ€” by adding some randomness. and in Structure Synth you do that by creating multiple definitions for the same rule. like so:

R1

rule R1 {
  { x 0.9 rz 6 ry 6 s 0.99  sat 0.99  } R1
  { s 2 } sphere
}

rule R1  {
  { x 0.9 rz -6 ry 6 s 0.99  sat 0.99  } R1
  { s 2 } sphere
}

so you see the R1 rule has two definitions now. and from then on, whenever the Structure Synth builder needs to call the R1 rule, it will choose one of the definitions at random. chaos! art! slay! ๐Ÿ”ฅ

๐Ÿ“š REFERENCE ๐Ÿ“š

Actions ๐Ÿ’ซ

Termination criteria ๐Ÿ›‘

  • set maxdepth [integer] โ€” this is the "okay stop" button bestie. It breaks the whole thing after [integer] iterations (aka generations). Bonus: it also doubles as an upper recursion limit for all the rules. Every single one. ๐Ÿ’…
  • set maxobjects [integer] โ€” once [integer] objects have been created, the construction justโ€ฆ ends. Done. Terminated. No more objects for you. ๐Ÿšซ

Other ๐ŸŽฒ

  • set seed [integer] โ€” lets you set the random seed, which means you can literally reproduce creations. Same seed, same art, every time. No cap. ๐ŸŒฑ
  • set background [color] โ€” sets the background color. Colors are text-strings parsed using Qt's color parsing, so you get standard HTML RGB specs (like #F00 or #FF0000) and SVG keyword names (like red, or even lightgoldenrodyellow). Serve it. ๐ŸŽจ

Rule modifiers ๐ŸŽ€

  • md / maxdepth [integer] โ€” Rule Retirement. Sets the maximum recursive for the rule. Once that limit is hit, the rule would not execute any actions. Like, it's retired, it's living its best life elsewhere. ๐Ÿ–๏ธ
  • md / maxdepth [integer] > [rulename] โ€” Rule Retirement with substitution. Same max recursive deal, but once the limit has been reached, [rulename] will be executed instead of this rule. The understudy goes on stage, and honestly? Slay. ๐ŸŒŸ
  • w / weight [float] โ€” Ambiguous rules. If several rules are defined with the same name, a random definition is chosen according to the weight specified here. If no weight is specified, the default weight of 1 is used. It's giving weighted dice. ๐ŸŽฒ

Transformations ๐Ÿฆ‹

Geometrical transformations ๐Ÿ“

  • x [float] โ€” X axis translation. The float argument is the offset, measured in units of the local coordinate system. ๐Ÿซถ
  • y [float] โ€” Y axis translation. As above. โœจ
  • z [float] โ€” Z axis translation. As above. โœจ
  • rx [float] โ€” Rotation about the x axis. The float argument is the angle specified in degrees. The rotation axis is centered at the unit cube in the local coordinate system โ€” that is, the rotation axis contains the line segment from (0, 0.5, 0.5) -> (1, 0.5, 0.5). ๐Ÿ”„
  • ry [float] โ€” Rotation about the y axis. As above. ๐Ÿ”„
  • rz [float] โ€” Rotation about the z axis. As above. ๐Ÿ”„
  • s [float] โ€” Resizes the local coordinate system. Notice that the center for the resize is located at the center of the unit cube in the local system (at (0.5,0.5,0.5)). ๐ŸŽˆ
  • s [f1] [f2] [f3] โ€” Resizes the local coordinate system, as above, but with a separate scale for each dimension. Custom fit, iykyk. ๐Ÿ“
  • m [f1] ... [f9] โ€” Applies the specified 3x3 rotation matrix to the transformation matrix for the current state. About the argument order: [f1],[f2],[f3] defines the first row of the matrix. Math girlies rise up. ๐Ÿงฎ
  • fx: โ€” Mirrors the local coordinate system about the x-axis. As above, the mirroring plane is centered at the cube. ๐Ÿชž
  • fy: โ€” Mirrors the local coordinate system about the y-axis. ๐Ÿชž
  • fz: โ€” Mirrors the local coordinate system about the z-axis. ๐Ÿชž

Color space transformations ๐ŸŒˆ

  • h / hue [float] โ€” Adds the float value to the hue color parameter for the current state. Hues are measured from 0 to 360 and wrap cyclicly โ€” i.e. a hue of 400 is equal to a hue of 40. It's giving rotation, but for vibes. ๐Ÿ’œ
  • sat [float] โ€” Multiplies the float value with the saturation color parameter for the current state. Saturation is measured from 0 to 1 and is clamped to this interval (i.e. values larger then 1 are set to 1). ๐ŸŒธ
  • b / brightness [float] โ€” Multiples the float value with the brightness color parameter for the current state. Brightness is measured from 0 to 1 and is clamped to this interval. Notice that this parameter is sometimes called V or Value (and the color space is often referred to as HSV). โญ
  • a / alpha [float] โ€” Multiplies the float value with the alpha color parameter for the current state. Alpha is measured from 0 to 1 and is clamped to this interval. An alpha value of zero is completely transparent, and an alpha value of one is completely opaque. Ghost mode vs. main character mode. ๐Ÿ‘ป
  • color [color] โ€” This command sets the color to an absolute color (most other transformations are relative modifications on the current state). Colors are specified as text-strings parsed using Qt's color parsing, which allows for standard HTML RGB specifications (e.g. #F00 or #FF0000), but also SVG keyword names (e.g. red or even lightgoldenrodyellow). ๐ŸŽจ

Drawing primitives ๐Ÿ“

  • box: โ€” solid box. ๐Ÿ“ฆ
  • grid: โ€” wireframe box. ๐Ÿ•ธ๏ธ
  • sphere: โ€” the round thingy (as of now this primitive has some issues โ€” e.g. ellipsoids are not working.) โš ๏ธ
  • line: โ€” along x axis, centered in y,z plane. ๐Ÿ“
  • point: โ€” centered in coordinate system. โšซ
  • triangle: โ€” creates a custom polygon. Specify the coordinates as follows: Triangle[0,0,0;1,0,0;0.5,0.5,0.5] ๐Ÿ”บ
  • mesh: โ€” prototype mesh. ๐Ÿงš
  • cylinder: โ€” the symmetry axis will be the current x axis. [Not implemented] ๐Ÿšง
  • tube: โ€” polygonal cylinder (will be drawn smoothly as the coordinate system transforms). [Not implemented] ๐Ÿšง

Preprocessor commands ๐Ÿ’…

  • #define varname value โ€” substitutes every occurrence of varname with value. Value may contain spaces. It's a find-and-replace but make it fashion. โœจ

For Context Free / CFDG users ๐Ÿ‘‘

The EisenScript syntax in Structure Synth has a lot in common with CFDG. But bestie, there are a few important differences:

Context sensitivity ๐Ÿ”

A CFDG script can be viewed as a grammar, where the production rules are independent of their context โ€” or, put differently, when choosing between rules, CFDG does not have any knowledge of the history of the system. This "Context Free" property of CFDG was deliberately omitted in EisenScript, simply for pragmatic reasons: some structures would be difficult to create without having some way to change the rules after a certain number of recursions.

The startrule statement ๐Ÿš€

In CFDG, startrules are explicitly specified. In EisenScript, a more generic approach is used: statements which can be used in a rule definition can also be used at the top-level scope, so in order to specify a start-rule, just write the name of the rule. That's it, that's the whole trick. ๐ŸŽ€

Termination criteria ๐Ÿ›‘

In CFDG, recursion automatically terminates when the objects produced are too small to be visible. This is a very elegant solution, but it is not easy to do in a dynamic 3D world, where the user can move and zoom with the camera. Several options exist in Structure Synth for terminating the rendering.

Transformation order ๐Ÿ”„

In CFDG, transformations (which CFDG refers to as adjustments) in curly brackets are not applied in the order of appearance, and if multiple transformations of the same type are applied, only the last one is actually carried out. For transformations in square brackets in CFDG, the order on the other hand is significant. In Structure Synth, the transformation order is always significant: transformations are applied starting from the right-most one.


๐ŸŽฌ EXAMPLE ๐ŸŽฌ

Below is an EisenScript sample:

/*
  Sample Torus.
*/

set maxdepth 100
r1
36  * { x -2 ry 10   } r1

rule r1 maxdepth 10 {
   2 * { y -1 } 3 * { rz 15 x 1 b 0.9 h -20  } r2
   { y 1 h 12 a 0.9  rx 36 }  r1
}

rule r2 {
   { s 0.9 0.1 1.1 hue 10 } box // a comment
}

rule r2 w 2 {
   { hue 113 sat 19 a 23 s 0.1 0.9 1.1 } box
}

๐Ÿ‘€ SEE ALSO ๐Ÿ‘€


And that's a wrap on the whole page, bestie! ๐Ÿ’– This version is April 2009 energy, from the Structure Synth(1) manual โ€” go make something gorgeous with it. ๐Ÿฆ‹โœจ๐Ÿ‘‘

๐Ÿ“ฆ where this page comes from