Skip to content

mjurczyk/openvdb

Repository files navigation

OpenVDB

This project indirectly ports OpenVDB file format and tools to JavaScript, TypeScript, and Node. Specific 3D library implementations can be found in sub-directories.

What is OpenVDB

VDB is a volumetric data format originally implemented in C++ (AcademySoftwareFoundation/openvdb.) It allows to efficiently store voxel structures of this like smoke, fire, and fluid simulations - as well as normal 3D models converted to voxels.

Keep in mind that, due to memory-access and multithreading limitations of JS, this repo may be more similar to a read-only NanoVDB, instead of the original OpenVDB. Code is nevertheless based on original OpenVDB.

Usage

With three.js:

import * as Three from 'three';
import * as OpenVDB from 'openvdb/three';

const scene = new Three.Scene();

// NOTE To load an existing VDB model - use VDBLoader:
new OpenVDB.VDBLoader().load('./assets/bunny.vdb', function (vdb) {
  const fogVolume = new OpenVDB.FogVolume(vdb, {
    resolution: 100,
    progressive: true,
    steps: 20,
    absorbance: 1.0,
    baseColor: 0xff00ff,
  });

  scene.add(fogVolume);
});

// NOTE To create a primitive volumetric shape - use volume converters directly:
const primitiveVolume = new OpenVDB.SphereVolume();
const fogPrimitive = new OpenVDB.FogVolume(primitiveVolume, {
  resolution: 50,
  progressive: false,
  steps: 50,
  absorbance: 0.5,
  baseColor: 0xff00ff,
});

scene.add(fogPrimitive);

With react-three-fiber:

import * as Three from 'three';
import * as OpenVDB from 'openvdb/three';

export const VDBComponent = () => {
  const [model, setModel] = useState(new Three.Object3D());

  useEffect(() => {
    new OpenVDB.VDBLoader().load('./assets/bunny.vdb', function (vdb) {
      const fogVolume = new OpenVDB.FogVolume(vdb, {
        resolution: 100,
        progressive: true,
        steps: 20,
        absorbance: 1.0,
        baseColor: 0xff00ff,
      });

      setModel(fogVolume);
    });

    return () => {
      fogVolume.dispose();
    };
  }, []);

  return <primitive object={model} />;
};

Without library:

import * as OpenVDB from 'openvdb';

const vdbReader = await OpenVDB.loadVDB('./assets/bunny.vdb');

vdbReader.grids.forEach(function (grid) {
  const voxelValue = grid.getValue({ x: 0.0, y: 0.0, z: 1.0 });
});

Docs

loadVDB

  • loadVDB( url ): Promise<OpenVDB.OpenVDBReader>

Loads OpenVDB file and parses its grids. Grids can be accessed via .grids property of the value returned from the Promise.

Each grid has a .getValue( position: Three.Vector3 ): float method, which returns a voxel value for the given position. See src/openvdb/three/VolumeToFog.js for an example of VDB file parsing.


VDBLoader

  • VDBLoader( manager: Three.LoadingManager )

  • VDBLoader.load( url, onLoad, onProgress, onError ): void

Loads VDB model. onLoad is called when VDB is loaded and parsed. onError is called when error happens. onProgress is currently not used.


VolumeToBbox

  • VolumeToBbox( vdb: OpenVDB.OpenVDBReader | OpenVDB.GridDescriptor | Array<OpenVDB.GridDescriptor> ): Three.Object3D

Converts given OpenVDBReader to Three.Object3D. Resulting object consists of wireframe bounding boxes of all internal nodes within the given VDB. If multiple grids are given - each grid is drawn in a different wireframe color.


VolumeToFog

  • VolumeToFog( vdb: OpenVDB.OpenVDBReader | OpenVDB.GridDescriptor | Array<OpenVDB.GridDescriptor>, { resolution, steps, progressive, absorbance, opacity, radius, baseColor }, onConverted: () => void, onProgress: ({ convertedVoxels, totalVoxels, convertedGrids, totalGrids }) => void ): Three.Object3D

Converts given OpenVDBReader to a volumetric Three.Object3D. onConverted and onProgress are called as the VDB is converted to a fog. Most importantly:

  • resolution: number - (required) resolution of the resulting 3D texture. Keep in mind this will be risen to the power of 3 - so resolution 200 results in 8 million voxels.
  • steps: number - (default: 100) detail of the resulting fog volume. High amount of steps combined with large amount of lights in the scene may decrease performance significantly.
  • progressive: boolean - set to true to render the fog on-the-go as it is being parsed, while preserving 60fps.
  • absorbance: number - (default: 1.0) 1.0 means fog absorbs all the light going through it, lower values all light to partially traverse through the fog.
  • densityScale: number - scales density of the entire grid.
  • densityCutoff: number - defines sharpness of the shape.
  • opacity: number - alpha opacity of the fog (doesn't affect light calculations.)
  • baseColor: Three.Color | string | number - (default: 0x000000) albedo color of the fog volume.
  • emissiveGrid - VDB emission grid.
  • baseColorGrid - VDB grid equivalent of baseColor.
  • maskGrid - static VDB grid mask applied to each voxel. Not affected by UV offset.
  • lights - bitmask of light types affecting the volume (lights.useDirectionalLights | lights.usePointLights | lights.useSpotLights | lights.useHemisphereLights | lights.useEnvironment)

VolumeToLevelSet

  • VolumeToLevelSet( vdb: OpenVDB.OpenVDBReader | OpenVDB.GridDescriptor | Array<OpenVDB.GridDescriptor>, onConverted: () => void, onProgress: () => void ): Three.Object3D

Not yet finished. Converts the given OpenVDBReader to a 3D mesh using marching cubes.


CubeVolume

  • CubeVolume(): OpenVDB.GridDescriptor

Generates a 1x1x1 volumetric cube.


SphereVolume

  • SphereVolume(): OpenVDB.GridDescriptor

Generates a 1x1x1 volumetric sphere.


CloudVolume

  • CloudVolume( { height: number, density: number } ): OpenVDB.GridDescriptor

Generates a 1x1x1 volumetric clouds based on noise inputs.


ParametricVolume

  • ParametricVolume( valueFunction(position: Three.Vector3) => number ): OpenVDB.GridDescriptor

Generates a 1x1x1 volume with values defined using a valueFunction. valueFunction is called with position of each voxel within the volumetric bounding cube - and expects a value between 0.0 and 1.0 to be returned (0.0 meaning given voxel is fully transparent, 1.0 meaning given voxel is fully opaque.)


Current Feature Support

Based on files hosted on https://www.openvdb.org/download/.

Model Support Notes
armadillo.vdb ✅ Yes
buddha.vdb ✅ Yes
bunny.vdb ✅ Yes
bunny_cloud.vdb ✅ Yes
crawler.vdb ❓ Partial Exceeds memory limits
cube.vdb ✅ Yes
dragon.vdb ✅ Yes
emu.vdb ✅ Yes
explosion.vdb ✅ Yes
fire.vdb ✅ Yes
icosahedron.vdb ✅ Yes
iss.vdb ✅ Yes
smoke1.vdb ✅ Yes
smoke2.vdb ✅ Yes
space.vdb ❓ Partial Exceeds memory limits
sphere.vdb ✅ Yes
torus.vdb ✅ Yes
torus_knot.vdb ✅ Yes
utahteapot.vdb ✅ Yes
venusstatue.vdb ✅ Yes
boat_points.vdb ❓ Partial Loads ok, points rendering not fully implemented
bunny_points.vdb ❓ Partial Loads ok, points rendering not fully implemented
sphere_points.vdb ❓ Partial Loads ok, points rendering not fully implemented
waterfall_points.vdb ❓ Partial Loads ok, points rendering not fully implemented

Development

git clone https://github.com/mjurczyk/openvdb
cd ./openvdb
npm run i
npm run dev

Credits

To avoid re-coding same things over again, parts of the library may be based / taken directly from the following:

Be sure to ⭐️ those!