Keywords: bundled, materials, local

Summary

This example shows how to create "bundled objects", which are folders that contain geometry and all the material and maps (material, texture, etc.). This approach allows collections of fully attributed objects to be created that can be injected into scenes without any need to manually merge material properties.

Important
This demo uses material and texture maps that are defined in the material database file, and the Material Database Editor does not understand how to handle these (yet). If you open and save the various material files used in this demo, these map configurations will be lost. These material configurations must be manually edited at this time.

The following demos, manuals and tutorials can provide additional information about the topics at the focus of this demo:

  • Related Demos

    • N/A

  • Related Manuals

    • The GLIST manual, specifically this section on bundled objects.

  • Related Tutorials

    • N/A

Details

The introduction of "bundled objects" in DIRSIG 4.7 was an effort to help users streamline the creation, use and reuse of attributed scene objects. The concept is to encapsulate a fully attributed object (the geometry, the materials, the material optical properties, attribution maps, etc.) in a carefully constructed folder. That folder is not dependent on anything outside of the folder and it can be inserted into a scene without needing to do anything other than instance the GLIST file contained in the folder.

This capability became possible because of the following changes made under the hood in DIRSIG 4.7:

  • The ability to use alphanumeric labels (formerly called "IDs" when they were limited to numeric values).

  • The ability to setup most maps in the material file rather than in the scene file.

  • The ability to specify "local materials" in the GLIST file, which takes precedence over the local materials defined in a parent GLIST file (if the GLIST file is instanced) and ultimately the scene level material file.

The following GLIST snippet shows where the ability to define "local materials" is configured:

  <object search_paths="local">
    <localmaterials>example.mat</localmaterials>
    <basegeometry>
      ...
    </basegeometry>
    ...
  </object>

The first piece of the puzzle is the new <localmaterials> element, which specifies the name of a material file to be used with this object. In this small example, we have specified the filename example.mat. By default, this filename will be looked for relative to the simulation run folder. In addition, the default location to look for all the map images and optical property files will default to the search paths defined in the top-level .scene file. However, the point of this demo is to encapsulate the geometry and the materials in a single folder. Hence, the new search_paths attribute in the <object> element in the GLIST file was added. It has two possible values:

scene

This is the default (used if the attribute is not present). It indicates relative filenames will be found using the geometry and material search paths defined in the parent .scene file.

local

This indicates that relative filenames are assumed to be relative to the folder containing the GLIST file.

In this demo, we are using the local option which allows all the material properties to be stored and located at run-time from a single folder.

Important Files

Top-Level GLIST File

This scene is composed of two objects: a car and a parking lot. These two objects are brought together into the scene in the main GLIST file (see geometry/demo.glist):

The top-level GLIST file.
<geometrylist>
  <object enabled="true">
    <basegeometry>
      <glist>
        <filename>bundles/parking_lot/parking_lot.glist</filename>
      </glist>
    </basegeometry>
    <staticinstance name="lot"/>
  </object>

  <object enabled="true">
    <basegeometry>
      <glist>
        <filename>bundles/infiniti_g35/infiniti_g35.glist</filename>
      </glist>
    </basegeometry>
    <staticinstance name="car">
      <translation>
        <point><x>-2.6</x><y>3.1</y><z>0.0</z></point>
      </translation>
      <rotation units="degrees" rotationorder="xyz">
        <cartesiantriple><x>0</x><y>0</y><z>-90</z></cartesiantriple>
      </rotation>
    </staticinstance>
  </object>
</geometrylist>

So far this looks an ordinary GLIST file that instances two other GLIST files (one for the parking lot and one for the car). The special stuff happens in those GLIST files we placed in the geometry/bundles folder.

Note
We have been using the subfolder bundles as a special place for keeping these bundled objects in our scenes. This alerts us to the fact that these object use their own materials. Using a separate subfolder is simply a recommendation and not a requirement.

Let’s look at what that geometry/bundles folder looks like:

geometry/bundles
geometry/bundles/infiniti_g35
geometry/bundles/infiniti_g35/infiniti_g35.glist
geometry/bundles/infiniti_g35/infiniti_g35.mat
geometry/bundles/infiniti_g35/infiniti_g35.obj
geometry/bundles/infiniti_g35/materials
geometry/bundles/infiniti_g35/materials/blue.ems
geometry/bundles/infiniti_g35/materials/glass.ext
geometry/bundles/infiniti_g35/materials/glass_brdf.ems
geometry/bundles/infiniti_g35/materials/glass_brdf.fit
geometry/bundles/infiniti_g35/materials/gloss.fit
geometry/bundles/infiniti_g35/materials/tire_black.ems
geometry/bundles/infiniti_g35/materials/vinyl_tan.ems
geometry/bundles/parking_lot
geometry/bundles/parking_lot/1x1.obj
geometry/bundles/parking_lot/maps
geometry/bundles/parking_lot/maps/lines_texture.jpg
geometry/bundles/parking_lot/maps/parking_material.jpg
geometry/bundles/parking_lot/maps/parking_texture.jpg
geometry/bundles/parking_lot/materials
geometry/bundles/parking_lot/materials/asphalt_mixed.ems
geometry/bundles/parking_lot/materials/white.ems
geometry/bundles/parking_lot/parking_lot.glist
geometry/bundles/parking_lot/parking_lot.mat

Upon examination, we can see that there are two subfolders (geometry/bundles/infiniti_g35 and geometry/bundles/parking_lot) and within each of those we see the following:

  • A .glist file bearing the same name as the bundle.

  • A .mat file bearing the same name as the bundle.

  • A materials folder containing optical properties defined in the material database file.

  • An (optional) maps folder to store images used to drive maps.

Note
The name of the .glist file, the name and relative location of the .mat file and the relative location of the optical property input files are not part of a formal organizational standard. As long as the filenames are correctly specified in their respective locations, the user can choose to organize the files within the bundle folder in whatever way the like.

The Parking Lot Bundle

The folder geometry/bundles/parking_lot contains our parking lot geometry, materials and maps. The key entry point for using this bundled object is the parking_lot.glist file shown below:

<geometrylist>
  <object search_paths="local">
    <localmaterials>parking_lot.mat</localmaterials>
    <basegeometry>
      <obj swapyz="false">
        <filename>1x1.obj</filename>
        <assign id="1">panel</assign>
      </obj>
    </basegeometry>
     <staticinstance>
      <scale>
        <cartesiantriple><x>44.65</x><y>30.14</y><z>1.0</z></cartesiantriple>
      </scale>
    </staticinstance>
  </object>
</geometrylist>

The 1x1.obj file describes a 4-sided polygon that is 1m x 1m and centered about the origin. The <assign> element says to attribute all the polygons (there is only 1 in this case) with material label (ID) 1. The instancing scale increases the size of the 1m x 1m polygon to 44.65m x 30.14m.

The <localmaterials> element says to use the file parking_lot.mat to find material descriptions for the labels attributed to the geometry (in this case we only have a single label, 1). The search_paths attribute in the <object> has been set to local, which means that it will look for parking_lot.mat relative to the location of parking_lot.glist, or in geometry/bundles/parking_lot.

Note
If the local material file was materials/parking_lot.mat it would look for it in geometry/bundles/parking_lot/materials.

If we look inside geometry/bundles/parking_lot/parking_lot.mat, we will find that the material we are looking for (label = 1) is defined. In this case, we have a material map that will remap hits on that geometry to either material 2 or 3 (see the LUT section below). The image used to drive this mapping is specified as maps/parking_material.jpg and since we are using local search paths, it is assumed this file will be geometry/bundles/parking_lot/maps/parking_material.jpg.

Parking lot base material with material map.
MATERIAL_ENTRY {
    ID           = 1
    NAME         = Parking lot, base (remapped)
    DOUBLE_SIDED = TRUE

    MATERIAL_MAP {
        NAME = Terrain Map
        ENABLED = TRUE
        IMAGE_FILENAME = maps/parking_material.jpg
        UV_PROJECTOR {
            ORIGIN = CARTESIAN
            FLIPX = FALSE
            FLIPY = FALSE
            EXTENDX = MIRROR
            EXTENDY = MIRROR
        }
        LUT {
            0:2
            255:3
        }
        OPTIONS {
            ENABLE_MIXING = FALSE
        }
    }
}
Note
Since this material is simply remapping to other materials, it doesn’t need temperature solver, radiometry solver or properties.

The two remapped materials are defined in the rest of the parking_lot.mat file. Each material employs a texture map with the Classic Emissivity optical property. The location of the input emissivity and texture map image files are also assumed to be relative to the GLIST file. In our usage, we have chosen to place all the emissivity, extinction, BRDF, etc files in a materials subfolder inside the bundle. The texture map image file is in the maps subfolder inside the bundle.

Parking lot asphalt material with texture map.
MATERIAL_ENTRY {
    ID           = 2
    NAME         = Roadway Surfaces, Asphalt, Old, Gray
    EDITOR_COLOR = 0.500008, 0.500008, 0.500008
    DOUBLE_SIDED = TRUE

    RAD_SOLVER_NAME = Simple
    RAD_SOLVER {
        QUALITY = LOW
    }

    TEMP_SOLVER_NAME = Therm
    TEMP_SOLVER {
        SPECIFIC_HEAT        = 0.16
        MASS_DENSITY         = 1.6
        THERMAL_CONDUCTIVITY = 8.17
        SOLAR_ABSORPTION     = -1
        THERMAL_EMISSIVITY   = 0.94
        EXPOSED_AREA         = 0.4
        THICKNESS            = 7
    }

    SURFACE_PROPERTIES {

        EMISSIVITY_PROP_NAME = ClassicEmissivity
        EMISSIVITY_PROP {
            FILENAME = materials/asphalt_mixed.ems
            SPECULAR_FRACTION = 0
            TEXTURE_MAP {
                IMAGE_LIST {
                    IMAGE {
                        FILENAME = maps/parking_texture.jpg
                        MIN_WAVELENGTH = 0.4
                        MAX_WAVELENGTH = 0.7
                    }
                }
                UV_PROJECTOR {
                    ORIGIN = IMAGE
                    FLIPX = FALSE
                    FLIPY = FALSE
                    EXTENDX = MIRROR
                    EXTENDY = MIRROR
                }
            }
        }
    }
}
Parking lot white lines material.
MATERIAL_ENTRY {
    ID           = 3
    NAME         = Roadway Surfaces, Asphalt, Old, Gray, lines
    EDITOR_COLOR = 1, 1, 1
    DOUBLE_SIDED = TRUE

    RAD_SOLVER_NAME = Simple
    RAD_SOLVER {
        QUALITY = LOW
    }

    TEMP_SOLVER_NAME = Therm
    TEMP_SOLVER {
        SPECIFIC_HEAT        = 0.465
        MASS_DENSITY         = 1
        THERMAL_CONDUCTIVITY = 20.93
        SOLAR_ABSORPTION     = -1
        THERMAL_EMISSIVITY   = 0.75
        EXPOSED_AREA         = -0.34
        THICKNESS            = 10
    }

    SURFACE_PROPERTIES {

        EMISSIVITY_PROP_NAME = ClassicEmissivity
        EMISSIVITY_PROP {
            FILENAME = materials/white.ems
            SPECULAR_FRACTION = 0
            TEXTURE_MAP {
                IMAGE_LIST {
                    IMAGE {
                        FILENAME = maps/lines_texture.jpg
                        MIN_WAVELENGTH = 0.4
                        MAX_WAVELENGTH = 0.7
                        STATS = 150,30
                    }
                }
                UV_PROJECTOR {
                    ORIGIN = IMAGE
                    FLIPX = FALSE
                    FLIPY = FALSE
                    EXTENDX = MIRROR
                    EXTENDY = MIRROR
                }
            }
        }
    }
}

The key takeaway of this example is that because we use local materials and local search paths, the parking_lot folder can be relocated anywhere. As soon as the parking_lot/parking_lot.glist file is instanced, it will find all the supporting material files by searching relative to the location of that file.

The Infinity G35 Bundle

The folder geometry/bundles/infiniti_g35 contains our Infinity G35 car geometry and materials. The key entry point for using this bundled object is the infiniti_g35.glist file shown below:

Infiniti G35 bundle GLIST file.
<geometrylist>
  <object search_paths="local">
    <localmaterials>infiniti_g35.mat</localmaterials>
    <basegeometry>
      <obj swapyz="false">
        <filename>infiniti_g35.obj</filename>
        <assign name="paint" id="1">default</assign>
        <assign id="2">windows</assign>
        <assign id="2">headlights</assign>
        <assign id="2">taillights</assign>
        <assign id="3">grill</assign>
        <assign id="3">rims</assign>
        <assign id="3">sideview</assign>
        <assign id="4">tires</assign>
        <assign id="4">wipers</assign>
        <assign id="5">interior</assign>
        <assign id="5">seats</assign>
      </obj>
    </basegeometry>
    <staticinstance/>
  </object>
</geometrylist>

Once again, we are using local materials and local search paths. The various <assign> elements allow us to map the usemtl assignments in the infiniti_g35.obj to DIRSIG material labels (IDs). Consider the following material assignments in the OBJ file:

...
g brakelight
usemtl 40100
f 7914/24181/7819 7915/24182/7820 7916/24183/7821
...

The OBJ file defines a group with the name "brakelight" which is assigned a material with the name "40100". The group name tells us that this geometry group is most likely the brakelight(s). Normally the name supplied to the usemtl will be used to find a material in the DIRSIG material file with the same label (ID). However, the <assign name="paint" id="1">default</assign> entry in the GLIST says we will default all usemtl mappings to material label (ID) 1. The remaining <assign> entries can change that default to a specific material. However, since we don’t see "40100" in those <assign> entries, we can assume that this geometry will get mapped to label (ID) 1, which is the body paint (we essentially change the brakelights to more body).

Now consider this group in the OBJ file:

...
g grill
usemtl grill
f 9692/29696/0 9693/29697/0 9694/29698/0
...

The GLIST includes <assign id="3">grill</assign>, which says that the "grill" material will get mapped to label (ID) 3 in the material file, which is "chrome like" material. Had this <assign> not been present, the grill would have defaulted to the body pint (material 1). Note that in this case the group name in the geometry is the same as the material name, but as we saw before that is not always the case. The <assign> entries define how usemtl entries will be mapped to DIRSIG materials and not how to assign materials to a group (part).

Note
This <assign> mechanism was original introduced in DIRSIG 4.6 as a way to map alphanumeric (and potentially terse) material names provided to usemtl entries to the numeric-only material IDs used in DIRSIG at the time. For example, usemtl PART000_MATERIAL4325 in the OBJ could get mapped to ID = 11 in the DIRSIG material file. As of DIRSIG 4.7, these labels can be alphanumeric (but cannot contain whitespace), which means this mapping in the GLIST is optional. For example, just make your material file have ID = PART000_MATERIAL4325. However, this "default plus specific remapping" mechanism can still be very useful.

The material file for this object is not as interesting as the parking lot because there are not any material or texture maps.

Note
The material labels (IDs) being used in the infiniti_g35 bundle (1-5) include some of the same used in the parking_lot bundle (which used 1-3). Since the material labels are local to the bundles, there is no need to plan, define and manage a global material index.

Scene Level Materials

The scene level (top-level) demo.mat materials file referenced in the demo.scene file is located in the top-level materials file. However, since all the materials are defined in the various bundles, there is no need to define any materials at the scene level. However, DIRSIG currently still requires a scene level materials file and the material file reader will throw an error if the file is empty. Hence, the file defines a simple, dummy material to satisfy these requirements:

MATERIAL_ENTRY {
    ID           = 99999
    NAME         = Dummy
    EDITOR_COLOR = 0, 0, 0
}

Setup

To run the simulation, perform the following steps:

  1. Run the DIRSIG demo.sim file

  2. Load the resulting demo.img radiance file in the image viewer.

Results

In order to help the user understand and resolve materials that are defined in multiple locations within a scene, a pair of tools are provided to the user. The first is a table included in the start-up output when the simulation runs. The table shows the mapping of the material indexes (used in the material truth) to the labels and names of materials. The text below shows the output for this simulation:

Material Index Table:
1 ->	Parking lot, base (remapped) (ID/Label = 1)
2 ->	Roadway Surfaces, Asphalt, Old, Gray (ID/Label = 2)
3 ->	Roadway Surfaces, Asphalt, Old, Gray, lines (ID/Label = 3)
4 ->	Gloss paint, blue (ID/Label = 1)
5 ->	Glass (ID/Label = 2)
6 ->	Chrome (ID/Label = 3)
7 ->	Tire, Rubber, Black, Fair (ID/Label = 4)
8 ->	Vinyl, tan (ID/Label = 5)

The second is a new material summary report (see the file material_report.json), which includes the same mapping info as the start-up output but also includes the path to the material that material was defined in. The file produced for this simulation shows the labels and names for the materials used in the respective parking lot and car bundles:

JSON Material Report.
{
  "info": {
    "created": "2023-12-18 08:18:31",
    "file_type": "Material Report",
    "generator": "scene2hdf",
    "version": "2023.50 (7a89f9a)"
  },
  "materials": {
    "bundles": [
      {
        "filename": "/Users/demos/BundledObject1/geometry/bundles/infiniti_g35/infiniti_g35.glist",
        "materials": {
          "1": {
            "materialIndex": 4,
            "name": "Gloss paint, blue (id = 1)"
          },
          "2": {
            "materialIndex": 5,
            "name": "Glass (id = 2)"
          },
          "3": {
            "materialIndex": 6,
            "name": "Chrome (id = 3)"
          },
          "4": {
            "materialIndex": 7,
            "name": "Tire, Rubber, Black, Fair (id = 4)"
          },
          "5": {
            "materialIndex": 8,
            "name": "Vinyl, tan (id = 5)"
          }
        },
        "objectIndex": 0
      },
      {
        "filename": "/Users/demos/BundledObject1/geometry/bundles/parking_lot/parking_lot.glist",
        "materials": {
          "1": {
            "materialIndex": 3,
            "name": "Parking lot, base (remapped) (id = 1)"
          },
          "2": {
            "materialIndex": 1,
            "name": "Roadway Surfaces, Asphalt, Old, Gray (id = 2)"
          },
          "3": {
            "materialIndex": 2,
            "name": "Roadway Surfaces, Asphalt, Old, Gray, lines (id = 3)"
          }
        },
        "objectIndex": 0
      }
    ],
    "scene": {}
  }
}
Note
Again, notice that the material labels (IDs) being used in the infiniti_g35 bundle (1-5) include some of the same used in the parking_lot bundle (which used 1-3). This table helps the user map the global material indexes reported in the material truth back to the local material labels (IDs) and which material file those materials are defined in.

The image below shows the output of the simulation:

Output of the simulation (default gamma scaling).

demo