Keywords: random fills

Summary

This demo shows how to setup a random fill (semi-random instances) based on a density map.

Important
This demo utilizes several features that are not supported in the GUI editor at this time. Please note that some aspects of the configuration can be lost if relevant input files are loaded into the GUI editor and then saved.

Details

The density map based random fill lets you take advantage of the mapping mechanisms to define populated areas that vary in density of the surface of an obect. This can be useful in cases where you know roughly where objects should be, but don’t want to define specific locations and don’t want them to be uniformly placed either.

The demo takes a simple terrain object, applies a density map to it based on the embedded UV texture coordinates, and fills it with a population of pebbles of different sizes.

Important Files

The key files in this demo are the geometry list file with the density map random fill defined as well as the object population and the image file that defines the spatial density.

geometry/pebble_*.obj

3D geometry for the three different pebble sizes (small, medium and large) used in the scene.

geometry/pebbles.base

Base geometry entries (with population weights) to be included into the glist (kept in a separate file to facilitate easily editing the file or generating it externally without worrying about the rest of the GLIST).

geometry/pebbles.glist

Includes the pebble base geometry and places them in a density map based random fill.

geometry/scene.glist

Top-level geometry list which provides the terrain instances the GLIST with a slight z-translation so the pebbles are slightly embedded in the surface.

maps/denity.png

A simple grayscale image used to define the relative spatial density.

demo.scene

The scene file that contains the list with the density map entry.

Important
It is not possible to instance a density map fill based object multiple times so that there are copies of it in the scene (a single copy can be instanced at an arbitrary depth, however, to add affine transforms).

Scene File

The first component of the configuration is to add a map to the <maplist> in the scene file. The <densitymap> element contains the image file to drive the pebble density (<image>), the projection method used to map that image onto the geometry (<projector>), and an association tag (<matid>):

  <mapdirectory>$SCENE_DIR/maps</mapdirectory>
  <maplist>
    <densitymap name="Pebble Density Map" enabled="true">
      <matidlist>
        <matid>105</matid>
      </matidlist>
      <projector origin="cartesian">
        <uvprojector/>
      </projector>
      <image>
        <filename>density.png</filename>
      </image>
    </densitymap>
  </maplist>

For most map types, the <matid> is used to associate the map with a specific material label (ID). For example, a texture map manipulates the reflectance of a specific material. In the case of a density map, the <matid> is primarily used to associate the map image and projector with a <randomfill> in a GLIST file, but also as a condition of placing objects (i.e. they have to fall on that material). Note that the material ID can correspond to a material map.

density
Figure 1. The map image used to drive the density of the pebbles.

Geometry Files

The top level geometry file for this scene is the geometry/scene.glist file. This GLIST file incorporates two components into the scene:

  1. The ground (see geometry/ground.obj), which is assigned material label (ID) 105, and is instanced once with the instance label "ground".

  2. The pebbles that are placed onto the ground.

    • The pebble base geometries and all the pebble locations (driven by a density map) are defined in the geometry/pebbles.glist file.

    • The population of semi-randomly placed pebbles is inserted into the scene once, with a slight negative Z translation is added to bury the pebbles into the ground slightly.

Contents of the geometry/scene.glist file.
<geometrylist>

  <!-- ground -->
  <object enabled="true">
    <basegeometry>
      <obj>
        <filename>ground.obj</filename>
        <assign id="105">default</assign>
      </obj>
    </basegeometry>
    <staticinstance name="ground"/>
  </object>

  <!-- density map based population -->
  <object enabled="true">
    <basegeometry>
      <glist>
        <filename>pebbles.glist</filename>
      </glist>
    </basegeometry>
    <staticinstance>
      <translation>
        <point><x>0</x><y>0</y><z>-0.001</z></point>
      </translation>
    </staticinstance>
  </object>

</geometrylist>

The meat of this density map demo is found in the geometry/pebbles.glist file. This GLIST file defines a population of pebbles (4 different shapes) and then uses a random fill driven by a density map to semi-randomly placed instances of those pebbles onto the ground. The use of a weighted base geometry population is described in more detail in other demos (for example, see GlistPopulations1 and Parking1). The geometry and population weights that will be placed is defined in the geometry/pebbles.base file:

Contents of the geometry/pebbles.base file.
    <basegeometry weight="20">
      <obj swapyz="false">
        <filename>pebble_sml.obj</filename>
        <assign id="106">default</assign>
      </obj>
    </basegeometry>
    <basegeometry weight="10">
      <obj swapyz="false">
        <filename>pebble_med.obj</filename>
        <assign id="106">default</assign>
      </obj>
    </basegeometry>
    <basegeometry weight="1">
      <obj swapyz="false">
        <filename>pebble.obj</filename>
        <assign id="106">default</assign>
      </obj>
    </basegeometry>
    <basegeometry weight="1">
      <obj swapyz="false">
        <filename>pebble_lrg.obj</filename>
        <assign id="106">default</assign>
      </obj>
    </basegeometry>

This file is included (inserted or copied) in the geometry/pebbles.glist file using the XML <xi::include> feature. Note that the use of this include mechanism isn’t a requirement of the setup, but a good example of how even more modularity can be incorporated into the scene. For example, the geometry/pebbles.base file can be quickly updated to add a fifth pebble geometry. The various weight attributes on each <basegeometry> define the relative weights of each base geometry in the final population of semi-randomly placed pebbles. In this case, the small pebble has a weight of 20, the medium has a weight of 10 and the remaining two sizes have weights of 1. That means the small pebble should appear 20/32 = 62.50% of the time, the medium pebble 31.25% of the time, etc. in the final population.

The second key component of this configuration is the random fill using the density map. The user must provide the name of the geometry instance to "anchor" the randomly placed pebbles onto. In this case, the <anchor> element is set to "ground" which refers back to the single, named static instance for the ground OBJ geometry in the geometry/scene.glist file. The <matid> is only used here to find the image and projection defined in the scene file <densitymap>. This label does not need to have any connection to the geometry onto which the pebbles will be placed, it just needs to match the label used in the scene file.

<geometrylist>
  <!-- density map based population -->
  <object enabled="true">
    <xi:include href="pebbles.base"/>
    <randomfill savefile="pebbles.instances" loadinstances="false">
      <densitymap>
        <anchor>ground</anchor>
        <matid>105</matid>
        <count>20000</count>
        <mindist>0.001</mindist>
        <maxdist>0.030</maxdist>
        <seed>123454</seed>
        <randomorientation>true</randomorientation>
      </densitymap>
    </randomfill>
  </object>
</geometrylist>

The user must also provide the number of instances to be inserted onto this geometry (via the <count> element, which is 20000 in this case). The mindist and maxdist parameters are used to map the density image pixel brightnesses into spatial distances. The following algorithm is used while using the density map image to insert instances:

  • An image digital count (DC) of 0 always results in a density of 0 (nothing will land in these regions).

  • An image DC of 1 is the lowest (but non-zero) area density and that corresponds to items being no closer than the maxdist.

  • An image DC of 255 is the highest area density and that corresponds to items being no closer than the mindist

  • If the algorithm can no longer insert an instance without violating the mindist and maxdist, it will terminate the inserting of instances.

Important
The mindist and maxdist correspond to the distance between the bounding boxes of the objects. Hence, a distance of 0 means objects will just touch. If you want objects to overlap, you need to use negative values.

In this demo, we set the maximum number of instances to fill with to 20,000 but only about 1,500 are placed before the density is satisfied across the map. This number can be discovered by looking at how many lines are in the pebbles.instances file (created as a result of the savefile option to the <randomfill>). This file contains all the instances computed using the map. The loadinstances option to the <randomfill> tells DIRSIG to use the instances from the pebbles.instances file if it exisits. So the first simulation will figure out the positions for each pebble and subsequent runs will reuse those positions. If you want to reset the positions, then delete the pebbles.instances file.

Setup

To run the simulation, perform the following steps:

  1. Run the DIRSIG densitymap.sim file

  2. Load the resulting result.img file in the image viewer.

Results

The generated image should show a slightly undulating terrain with pebbles scattered over it. There two swathes of higher density and both are partially visible in the image. The areas without any pebbles correspond to the areas in the density image with a value of zero.

demo
Figure 2. Output radiance image.