volume_vector_to_fog

Creates a vector volume from scratch. Converts this vector volume to a fog volume. Inserts this fog volume as a child of a volume mesher.

volume_vector_to_fog.py

"""Creates a vector volume from scratch. Converts this vector volume to a fog volume. Inserts this fog volume as a child of a volume mesher.

Topics:
    * maxon.VolumeToolsInterface.CreateNewVector32Volume()
    * maxon.GridAccessorInterface
    * GridAccessorRef.InitWithWriteAccess()
    * GridAccessorRef.SetValue()
    * maxon.VolumeToolsInterface.ConvertVectorToFog()
    * c4d.VolumeObject
    * VolumeObject.SetVolume()
"""
__author__ = "Maxime Adam"
__copyright__ = "Copyright (C) 2026 MAXON Computer GmbH"
__license__ = "Apache-2.0 License"
__version__ = "R21"

import c4d
import maxon


def CreateVectorVolume(vectorValue):
    """Creates a VolumeRef defined as a vector volume, with a cube of 20 cm filled with the vector value passed.

    Args:
        vectorValue (maxon.Vector32): The vector value to set.

    Returns:
        maxon.VolumeRef: The created Vector volume with the value defined inside.
    """
    # Creates volume
    volumeRef = maxon.VolumeToolsInterface.CreateNewVector32Volume(maxon.Vector32(0.0))
    if volumeRef is None:
        raise MemoryError("Failed to create a float32 volume.")

    # Creates accessor
    access = maxon.GridAccessorInterface.Create(maxon.Vector32)
    if access is None:
        raise RuntimeError("Failed to retrieve the grid accessor.")

    # Initializes the grid for write access
    access.InitWithWriteAccess(volumeRef)

    # Sets values
    size = 20
    for x in range(size):
        for y in range(size):
            for z in range(size):
                pos = maxon.IntVector32(x, y, z)
                access.SetValue(pos, vectorValue)

    return volumeRef


def CreateVectorObject(volumeRef, name):
    """Creates a c4d.VolumeObject with the VolumeRef passed.
    Names this VolumeObject with the passed argument.

    Args:
        volumeRef (maxon.VolumeRef): The VolumeRef to use within the VolumeObject.
        name (str): The name of the inserted object into the scene.

    Returns:
        c4d.VolumeObject: The created VolumeObject
    """
    # Creates VolumeObject
    volumeObj = c4d.BaseObject(c4d.Ovolume)
    if volumeObj is None:
        raise MemoryError("Failed to create a volume object.")

    # Names the VolumeObject
    volumeObj.SetName(name)

    # Inserts volume in the VolumeObject
    volumeObj.SetVolume(volumeRef)

    return volumeObj


def main():
    # Creates a VectorVolume
    vecVolumeRef = CreateVectorVolume(maxon.Vector32(100.0))

    # Inserts these vector volume into a VolumeObject
    vecVolumeObj = CreateVectorObject(vecVolumeRef, "Vector Volume")

    # Mixes both vector volume together using cross product
    fogVolumeRef = maxon.VolumeToolsInterface.ConvertVectorToFog(vecVolumeRef, maxon.ThreadRef())

    # Inserts the mixed volume into the scene
    fogVolumeObj = CreateVectorObject(fogVolumeRef, "Fog Volume")

    # Creates a VolumeMesher and adds the volumeObject
    volumeMesher = c4d.BaseObject(c4d.Ovolumemesher)
    if volumeMesher is None:
        raise MemoryError("Failed to create a volume mesher object.")

    # Inserts the fog volume object under the volume mesher
    fogVolumeObj.InsertUnder(volumeMesher)

    # Inserts the volume mesher within the scene
    doc.InsertObject(volumeMesher, None, None)

    # Pushes an update event to Cinema 4D
    c4d.EventAdd()


if __name__ == '__main__':
    main()