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.

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:
-
The ground (see
geometry/ground.obj
), which is assigned material label (ID) 105, and is instanced once with the instance label "ground". -
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.
-
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:
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 themaxdist
. -
An image DC of
255
is the highest area density and that corresponds to items being no closer than themindist
-
If the algorithm can no longer insert an instance without violating the
mindist
andmaxdist
, 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:
-
Run the DIRSIG
densitymap.sim
file -
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.
