Loading...
Searching...
No Matches
UsdVol : USD Volume Schema

Overview

UsdVol provides schemas for representing volumes (smoke, fire, etc). UsdVol can be used directly for representing OpenVDB and Field3d assets, or extended to support other volume formats.

Volume Schemas

Volume

UsdVolVolume schema describes a volume composed of multiple fields. A field is a "grid" in OpenVDB terminology. Volume is a UsdGeomGprim, so it is transformable, renderable, can have a material binding, etc.

A Volume has one or more named relationships to FieldBase prims.

FieldBase

UsdVolFieldBase is an abstract schema representing a single volume field. This schema should be inherited by any schema representing a volume field.

FieldAsset

UsdVolFieldAsset inherits from FieldBase and is an abstract schema representing a single volume field that is stored as an asset separately from the layer or stage. USD does not currently support data types required to represent volumetric data directly, so volumes are generally stored using purpose-built file formats such as OpenVDB. This schema should be inherited by any schema representing a volume field stored as an asset outside of USD.

As field asset formats may store multiple fields in a single asset, UsdVolFieldAsset contains properties fieldName and fieldIndex to aid in selecting the single desired field.

OpenVDBAsset

UsdVolOpenVDBAsset inherits from FieldAsset and is a concrete schema representing a single volume field stored as an OpenVDB asset.

Learn about OpenVDB at https://www.openvdb.org/.

Field3DAsset

UsdVolField3DAsset inherits from FieldAsset and is a concrete schema representing a single volume field stored as a Field3D asset.

Learn about Field3D at https://sites.google.com/site/field3d/

Example Usage

Here is a simple example of a Volume prim, representing a static wisp of smoke:

def Volume "wisp"
{
    float3[] extent = [(-57, -91, -44), (57, 31, -23)]

    rel field:density = </wisp/density>

    def OpenVDBAsset "density"
    {
        asset filePath = @./wisp_01.vdb@
        token fieldName = "density"
    }
}

Volumes are generally not static. For volumes with OpenVDBAsset fields, volume animation is represented by setting time samples on the filePath attribute:

def Volume "wisp"
{
    float3[] extent = [(-57, -91, -44), (57, 31, -23)]

    rel field:density = </wisp/density>

    def OpenVDBAsset "density"
    {
        asset filePath.timeSamples = {
            101: @./wisp_01.101.vdb@,
            102: @./wisp_01.102.vdb@,
            103: @./wisp_01.103.vdb@,
            104: @./wisp_01.104.vdb@,
        }
        token fieldName = "density"
    }
}

Usage Notes

Namespace Organization and Transformation

UsdVolFieldAsset describes a single field that can be loaded from an external asset. FieldAsset has a filePath attribute that specifies an asset path where a volume file can be found.

Field prims are not required to be children of the Volume prim. But in most cases the Volume and its Fields are conceptually inseparable, so Field prims are generally created as children of the Volume prim for organization purposes, ease of referencing, and overall ease of use.

Relatedy, the grid extracted from a Field prim is positioned in world space by the local-to-world transformation of the Field prim, plus any transformation contained in a FieldAsset's external asset encoding. This semantic makes clear why organizing Fields under a Volume is useful: re-positioning the Volume prim will automatically move all its child Field prims along with it.

Field Relationships Establish Consumer Field Names

The Volume prim must establish named relationships to its Fields using the UsdVolVolume::CreateFieldRelationship() method. This is how the "field:density" relationship is created on the Volume prim in the examples above.

The naming of the field relationship on the Volume prim and setting a fieldName on the OpenVDBAsset may seem redundant, but it is not. The intention is to allow a Volume to define fields by the names appropriate for the Volume and/or pipeline, without tying these to the VDB grid name. For example, a Volume might want a "velocity" field for the purposes of shader parameters, but you have a VDB with a grid named "vel". Defining field:velocity on the Volume prim would accomplish that. You can also re-use Fields for multiple volume fields in this way.

Why is OpenVDBAsset not a FileFormat plugin?

USD does not have a way to describe volumetric data structures. This is similar to how textures are not FileFormat plugins either - USD does not have data structures to represent image data. In both cases, It can be argued that USD should not do this. A VDB can be thought of as a 3D texture for this purpose, so the OpenVDBAsset schema describes an asset path where it can be discovered for someone else (Hydra, your renderer, etc) to interpret.