### 5 releases

0.1.4 | Dec 1, 2018 |
---|---|

0.1.3 | Nov 24, 2018 |

0.1.2 | Nov 20, 2018 |

0.1.1 | Nov 17, 2018 |

0.1.0 | Nov 17, 2018 |

**Apache-2.0**

46KB

804 lines

# immense

A library for describing 3D meshes with simple composable rules.

`rule!``[`
`tf!``[`
`Tf``::`saturation`(``0.``8``)``,`
`Tf``::`hue`(``160.``0``)``,`
`Replicate``::`n`(``36``,` `vec!``[``Tf``::`rz`(``10.``0``)``,` `Tf``::`ty`(``0.``1``)``]``)``,`
`Replicate``::`n`(``36``,` `vec!``[``Tf``::`ry`(``10.``0``)``,` `Tf``::`tz`(``1.``2``)``,` `Tf``::`hue`(``3.``4``)``]``)``,`
`]` `=>` `cube``(``)`
`]`

###
`lib.rs`

:

immense describes 3D structures with simple composable rules and outputs them as Wavefront object files you can plug into your renderer of choice.

# Demo

` ``#` `use` `immense``::``*``;`
`Rule``::`new`(``)``.``push``(``vec!``[`
`Replicate``::`n`(``1``,` `vec!``[``Tf``::`saturation`(``0.``8``)``,` `Tf``::`hue`(``160.``0``)``]``)``,`
`Replicate``::`n`(``36``,` `vec!``[``Tf``::`rz`(``10.``0``)``,` `Tf``::`ty`(``0.``1``)``]``)``,`
`Replicate``::`n`(``36``,` `vec!``[``Tf``::`ry`(``10.``0``)``,` `Tf``::`tz`(``1.``2``)``,` `Tf``::`hue`(``3.``4``)``]``)``,`
`]``,`
`cube``(``)``,`
`)`
`#` `;`

# Table of Contents

# Intro

In immense, you create a Rule that describes your structure, which is ultimately composed of meshes. immense provides some builtin meshes, such as cube, and you can create your own rules by using these builtins which you'll see in the next section.

After you've built your Rule, you can export the meshes it expands to as a Wavefront object file for the next part of your workflow, whether that is rendering it in Blender, printing it in your 3D printer, or importing it into your game!

# Composing Rules

Let's start with a cube. You probably want to write your meshes to a file and watch them in a viewer with autoreload. Meshlab is a great viewer (and much more) that can reload your meshes when changed. Check out ExportConfig to see what options you can set that will work best for your rendering or printing workflow.

`use` `immense``::``*``;`
`use` `std``::``fs``::`File`;`
`let` rule `=` `cube``(``)``;`
`let` meshes `=` rule`.``generate``(``)``;`
`let` `mut` output_file `=` `File``::`create`(``"`my_mesh.obj`"``)``?``;`
`write_meshes``(``ExportConfig``::`default`(``)``,` meshes`,` `&``mut` output_file`)``?``;`

We can translate the cube with the

family of functions which generate translate
transforms. We'll apply Tf::tx by creating our own rule and
invoking the cube rule with a transform.`Tf ::`t

`*`

`let` rule `=` `Rule``::`new`(``)``.``push``(``Tf``::`tx`(``3.``0``)``,` `cube``(``)``)``;`

We can replicate transforms with Replicate which generates multiple invocations of a subrule, each with more applications of the same transform applied to it.

`let` rule `=` `Rule``::`new`(``)``.``push``(``Replicate``::`n`(``3``,` `Tf``::`ty`(``1.``1``)``)``,` `cube``(``)``)``;`

Notice that our translation is 1.1 and that that is 0.1 more than the length of our cube. That's no coincidence! All the built in meshes are 1 in length so that you can use convenient measurements like this, even when deep in a transform stack.

## Recursion

You can generate rules recursively with the api we've covered so far, but doing so would put your entire rule tree in memory at one time, which can become a problem. immense provides a trait, ToRule, so you can give it types that can instantiate rules when needed.

`struct` `RecursiveTile` `{`
`depth_budget``:` `usize`,
`}`
`impl` `ToRule ``for`` ``RecursiveTile` `{`
`fn` `to_rule``(``&``self``)`` ``->` Rule `{`
`let` rule `=` `Rule``::`new`(``)`
`.``push``(``vec!``[``Tf``::`t`(``0.``25``,` `0.``25``,` `0.``0``)``,` `Tf``::`s`(``0.``4``)``]``,` `cube``(``)``)`
`.``push``(``vec!``[``Tf``::`t`(``-``0.``25``,` `-``0.``25``,` `0.``0``)``,` `Tf``::`s`(``0.``4``)``]``,` `cube``(``)``)`
`.``push``(``vec!``[``Tf``::`t`(``-``0.``25``,` `0.``25``,` `0.``0``)``,` `Tf``::`s`(``0.``4``)``]``,` `cube``(``)``)``;`
`if` `self``.`depth_budget `>` `0` `{`
rule`.``push``(`
`vec!``[``Tf``::`t`(``0.``25``,` `-``0.``25``,` `0.``0``)``,` `Tf``::`s`(``0.``4``)``]``,`
RecursiveTile `{`
depth_budget`:` `self``.`depth_budget `-` `1``,`
`}``,`
`)`
`}` `else` `{`
rule
`}`
`}`
`}`
`let` rule `=` RecursiveTile `{`
depth_budget`:` `3`
`}``.``to_rule``(``)``;`

## Randomness

Using ToRule to delay rule construction, we can sample some random values each time our type builds a rule.

`struct` `RandCube``;`
`impl` `ToRule ``for`` ``RandCube` `{`
`fn` `to_rule``(``&``self``)`` ``->` Rule `{`
`Rule``::`new`(``)``.``push``(`
`*``thread_rng``(``)`
`.``choose``(``&``[``Tf``::`tx`(``0.``1``)``,`
`Tf``::`tx`(``-``0.``1``)``,`
`Tf``::`tx`(``0.``2``)``,`
`Tf``::`tx`(``-``0.``2``)``]``)`
`.``unwrap``(``)``,`
`cube``(``)``,`
`)`
`}`
`}`
`let` rule `=` `Rule``::`new`(``)``.``push``(``Replicate``::`n`(``4``,` `Tf``::`ty`(``1.``0``)``)``,`
RandCube `{``}``)``;`

# Color

immense can export some colors alongside your mesh, by linking the object file output to an mtl file (material library). Set the output mtl file in export_colors and immense will write out colors.

You can specify colors overrides and transforms in HSV color space using Ogeon's [palette][palette]. See Tf::color, Tf::hue, Tf::saturation, Tf::value.

# Ergonomics Macros

immense provides two ergonomics macros that make defining rules and transform sequences a little
easier once you have an intuition for their semantics. They are

and [`rule!`

], which
help compose rules and transform sequences respectively.`tf!`

They transform the demo code above into:

`rule!``[`
`tf!``[`
`Tf``::`saturation`(``0.``8``)``,`
`Tf``::`hue`(``160.``0``)``,`
`Replicate``::`n`(``36``,` `vec!``[``Tf``::`rz`(``10.``0``)``,` `Tf``::`ty`(``0.``1``)``]``)``,`
`Replicate``::`n`(``36``,` `vec!``[``Tf``::`ry`(``10.``0``)``,` `Tf``::`tz`(``1.``2``)``,` `Tf``::`hue`(``3.``4``)``]``)``,`
`]` `=>` `cube``(``)``,`
`]`

# Custom Meshes

You can create meshes on your own and use them as rules by calling Mesh::from if you format your meshes according to object file format.

Meshes can be expensive to allocate. immense handles the primitives on your behalf, but if you introduce your own meshes you must be careful not to allocate them more than once. One million references to a sphere are fine, one million spheres will probably kill the process.

An example is the sphere builtin which allows you to create a potentially expensive sphere estimation:

`let` sphere`:` `Rc``<`Mesh`>` `=` `sphere``(``/*`resolution=`*/``4``)``;`
`let` rule `=` `Rule``::`new`(``)``.``push``(``Tf``::`s`(``2.``0``)``,` sphere`)``;`

#### Dependencies

~6.5MB

~134K SLoC