Open Search
    OpenColorIO Manual

    Convert colors with the color profiles provided by the OpenColorIO (OCIO) configuration of a scene.

    Overview

    Cinema 4D implements color management primarily with International Color Consortium (ICC) color profiles and the OpenColorIO (OCIO) standard. OCIO implements a color management pipeline for digital content creation applications to decouple the color representation requirements of color computations from the requirements of displaying colors on hardware-devices. This allows for a lossless transfer of color data between different applications while giving artists always the ability to view their artwork with the colors the final consumer will see. OCIO achieves this by defining color spaces by purpose so that they can be applied selectively to color data. The two abstract color spaces and one transform defined by the OCIO standard are:

    • The Render Space is the color space the application does operate in. All color data is converted to this space before processing and the application does carry out all computations in this space. This is usually a linear color space. For Cinema 4D documents in OCIO mode this is by default the ACEScg space.
    • The Display Space is a space to convert colors from the Render Space to a color representation which is suited for displaying these colors on a screen. This is usually a non-linear color space. For Cinema 4D documents in OCIO mode this is by default the sRGB space.
    • The View Transform is a transform which is applied before the display space and is meant to emulate the final look of color data on a consumer device. This could for example emulate the look of a movie-screen on the display of an artist. For Cinema 4D documents in OCIO mode this is by default the ACES 1.0 SDR-video space.
    • Cinema 4D adds to this a special transform which is only applied to thumbnails, the Thumbnail View Transform.

    Each application in a color management pipeline assigns a color profile to each of these abstract color spaces to suite its specific needs. Applications communicate the possible choices for each space with the help of OCIO configuration files, allowing for a persistent color previewing experience along the pipeline without having to bake hardware dependent information into outputs (Fig. I).

    Fig. I: An example for an OCIO pipeline, the raw color data is passed in a linear format through the pipeline. For the Texturing stage this is a linear sRGB profile, for the Rendering and Editing stage, it is the ACEScg profile. Within each stage, the data from the Render Space is transformed with the view transform, to emulate the look of the final product on a consumer device, in the example an SDR video device is being emulated in all three stages. Finally, the colors are brought into a form which can be displayed on the display device of an artist, a non-linear sRGB profile for SDR displays in the Texturing and Rendering stage, and a DCI-P3 profile for HDR displays in the Editing stage. This forms a horizontal data transfer axis and a per stage individually configurable vertical view axis.

    Technical Overview

    Cinema 4D currently does provide only shallow public access to its OCIO API, with the consequence that high level OCIO concepts such as an OCIO configuration or an OCIO processor are not represented by dedicated types in the public API. There are however multiple entry points which provide access to the most important functionalities of OCIO.

    OCIO is bound intrinsically to a scene in form of cinema::BaseDocument, a scene can either have OCIO enabled or not, and also stores the currently active color profiles for the principal OCIO spaces. These settings are expressed as the parameters:

    Note
    There are two exception to the rule of OCIO color spaces being intrinsically bound to a document: The type cinema::BaseBitmap and cinema::VideoPostData. With the methods cinema::BaseBitmap::GetColorProfile and SetColorProfile, the three OCIO transforms render, display, and view can be overwritten on a per bitmap basis. This can be useful when a bitmap should ignore the OCIO display and view transforms in the Picture Viewer of Cinema 4D. Similarly, cinema::VideoPostData::GetColorProfileInfo allows for overriding color profile information in an upcoming rendering.

    These parameters can be read and written with cinema::BaseDocument::GetParameter and SetParameter. Due to the fact that the values of OCIO color spaces and transforms depend on the loaded OCIO configuration, the values written to the parameters must be retrieved with the following functions:

    Additionally, the following methods exist:

    • CopyLinearWorkflow: Copies the color management settings from one document to another.
    • GetOcioConfigPath: Returns the OCIO configuration path used by Cinema 4D.
    • UpdateOcioColorSpaces: Propagates changes made to the OCIO settings of a document to the bound OCIO color spaces.
    • GetOcioProfiles: Returns the color profiles for the currently active OCIO settings.

    To convert colors between OCIO color space representations, the type cinema::OcioConverter must be used, providing the methods:

    The transform paths are defined by the enumeration COLORSPACETRANSFORMATION. Note that a path can contain multiple transforms, as the path is always carried out in a sensible manner, e.g., OCIO_RENDERING_TO_VIEW will contain the display transform, as the OCIO transform chain is render->display->view. The available paths are:

    Related Topics

    Articles Color Management Manual Convert color data between color spaces and color formats provided by the Maxon API or loaded from disk.
    BaseDocument Manual

    Access the data structures of a Cinema 4D scene file.

    Important API Entities cinema::BaseDocument Represents a scene file and provides access to its OCIO settings and color spaces.
    cinema::OcioConverter Converts colors along OCIO conversion paths associated with a scene.
    cinema::SceneColorConverter Converts colors contained in scenes or elements of scenes to a new OCIO Render space.
    cinema::BaseBitmap

    Represents a bitmap which can be modified, read and written from disk, and displayed in GUIs.

    SDK Plugins OCIO Plugin

    Contains the examples shown in this manual.

    Examples Color Convert Scenes Convert all colors contained in a document or contained in a set of elements in a document to a new OCIO Render space.
    Copy Color Management Settings Copy all color management settings from one document to another.
    Read and Write OCIO Settings Read and write the OCIO color management settings stored in a document.
    Convert Colors Convert colors along OCIO conversion paths defined by the OCIO color spaces associated with a document.
    Convert Colors Arbitrarily Convert colors from and to OCIO color spaces using arbitrary in- and output spaces.
    Get and Set Color Parameters Read and write color parameters in an OCIO document either in the native Render space of the document or other spaces.
    Manage Bitmap OCIO Color Profiles Read and write the OCIO color spaces associated with cinema::BaseBitmap instances to change or nullify parts of an OCIO conversion path for them.
    OCIO Aware Render Realizes a renderer which manipulates the OCIO profiles of an upcoming rendering.
    Initialize Colors of Scene Elements in 2025 [New in 2025.0.0] Demonstrates the changes made to color initiations for scene elements in 2025.0.0.
    Drawing with OCIO Colors in a Viewport [New in 2025.0.0] Demonstrates how to draw into a viewport when OCIO color management is enabled in a document.

    Examples

    The examples shown here are all part of the OCIO Plugin in the SDK. Once the SDK has been compiled and installed, the plugin can be found under the menu entry Extensions\Example.image\C++ SDK: OCIO Examples.

    Color Convert Scenes

    Convert all colors contained in a document or contained in a set of elements in a document to a new OCIO Render space.

    maxon::Result<void> ConvertSceneOrElements(BaseDocument* doc)
    {
    // Using SceneColorConverter is only necessary when the operation must be carried out silently
    // with no GUI. If showing a popup dialog is acceptable or even desired, one can simply call
    // the command plugin for it.
    // Int32 idConvertSceneCommand = 1059360;
    // CallCommand(idConvertSceneCommand);
    // Ensure that the document is in OCIO color management mode.
    BaseContainer* bc = doc->GetDataInstance();
    {
    doc->UpdateOcioColorSpaces();
    }
    // Get then OCIO render space name to convert to, we could also define it manually here.
    maxon::CString renderSpaceName, _dummy;
    doc->GetActiveOcioColorSpacesNames(renderSpaceName, _dummy, _dummy, _dummy);
    // Allocate and initialize the converter, currently it is not possible to retrieve the linear
    // and non-linear input color space names "input-low" and "input-high" that are associated
    // with an OCIO config file. Instead they must be hardcoded. Except for the the target render
    // space, the Init call uses here the default values of the native dialog.
    AutoAlloc<SceneColorConverter> converter;
    if (!converter)
    return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION, "Could not allocate converter interface."_s);
    converter->Init(doc, "sRGB"_cs, "scene-linear Rec.709-sRGB"_cs, renderSpaceName) iferr_return;
    // Carry out the conversion for the whole document, the second argument is the conversion target,
    // here the whole document. But it could for example also be a singular BaseMaterial. Multiple
    // objects in a single document can be converted at once with ::ConvertObjects().
    converter->ConvertObject(doc, doc, result) iferr_return;
    // When converting a whole document, one should mark it as already converted when the conversion
    // did succeed.
    ApplicationOutput("\tConverted @ elements in '@' to OCIO Render space named '@'.",
    result.GetCount(), doc, renderSpaceName);
    return maxon::OK;
    }
    NONE
    Definition: asset_browser.h:1
    Definition: string.h:1542
    Definition: hashmap.h:3031
    PyObject PyObject * result
    Definition: abstract.h:43
    @ DOCUMENT_COLOR_MANAGEMENT
    Definition: ddoc.h:153
    @ DOCUMENT_COLOR_MANAGEMENT_OCIO_CONVERTED
    Definition: ddoc.h:157
    @ DOCUMENT_COLOR_MANAGEMENT_OCIO
    Definition: ddoc.h:155
    return OK
    Definition: apibase.h:2740
    #define MAXON_FUNCTIONNAME
    This macro returns the function name of the current member or global function.
    Definition: objectbase.h:2902
    #define MAXON_SOURCE_LOCATION
    Definition: memoryallocationbase.h:69
    #define ApplicationOutput(formatString,...)
    Definition: debugdiagnostics.h:204
    #define ConstDescID(...)
    Definition: lib_description.h:592
    void EventAdd(EVENT eventflag=EVENT::NONE)
    const char * doc
    Definition: pyerrors.h:226
    #define iferr_scope
    Definition: resultbase.h:1396
    #define iferr_return
    Definition: resultbase.h:1531

    Copy Color Management Settings

    Copy all color management settings from one document to another.

    This does not entail any scene element color space conversions, one must instead use SceneColorConverter as demonstrated in the example Color Convert Scenes .

    maxon::Result<void> CopyColorManagementSettings(BaseDocument* doc)
    {
    // Allocate a new document and copy over the settings from #doc to #newDoc. This is just a
    // convenient manner to copy all color management settings from one document to another. This
    // does NOT entail a conversion of the colors of scene elements to OCIO, see
    // ConvertSceneOrElements() for that.
    AutoAlloc<BaseDocument> newDoc;
    BaseDocument::CopyLinearWorkflow(doc, newDoc, false);
    newDoc->SetName(doc->GetName() + "(Copy)");
    ApplicationOutput("\tCopied color management settings from '@' to '@'.",
    doc->GetName(), newDoc->GetName());
    newDoc.Free();
    return maxon::OK;
    }

    Read and Write OCIO Settings

    Read and write the OCIO color management settings stored in a document.

    maxon::Result<void> GetSetColorManagementSettings(BaseDocument* doc)
    {
    return maxon::NullptrError(MAXON_SOURCE_LOCATION, "Invalid document pointer"_s);
    // Ensure that the document is in OCIO color management mode.
    BaseContainer* bc = doc->GetDataInstance();
    {
    doc->UpdateOcioColorSpaces();
    }
    // Print the names for all OCIO color spaces and transforms that are available in the OCIO
    // configuration file loaded by the document.
    ApplicationOutput("\tAll OCIO transform names: @", doc->GetOcioColorSpaceNames());
    ApplicationOutput("\tOCIO render transform names: @", doc->GetOcioRenderingColorSpaceNames());
    ApplicationOutput("\tOCIO view transform names: @", doc->GetOcioViewTransformNames());
    ApplicationOutput("\tOCIO display transform names: @", doc->GetOcioDisplayColorSpaceNames());
    // Since an OCIO configuration file can contain any combination of color spaces and transforms,
    // the description IDs for the render space, display space, view transform, and view thumbnail
    // transform parameters must be dynamic IDs.
    for (maxon::CString s : doc->GetOcioRenderingColorSpaceNames())
    {
    ApplicationOutput("\t\tThe render transform label '@' corresponds to the ID '@'.",
    s, doc->GetColorSpaceIdFromName(DOCUMENT_OCIO_RENDER_COLORSPACE, s));
    }
    // So, this would be the pattern to set for example the render space to a specific space name,
    // here the 'ACES2065 - 1' render space contained in the default OCIO 2.0 config file.
    // The method GetColorSpaceIdFromName() will return #NOTOK to indicate unknown space labels.
    maxon::Int32 id = doc->GetColorSpaceIdFromName(DOCUMENT_OCIO_RENDER_COLORSPACE, "ACES2065-1"_cs);
    if (id == NOTOK)
    return maxon::IllegalArgumentError(MAXON_SOURCE_LOCATION,
    "OCIO configuration does not contain a 'ACES2065 - 1' render space."_s);
    doc->SetParameter(ConstDescID(DescLevel(DOCUMENT_OCIO_RENDER_COLORSPACE)), GeData(id), DESCFLAGS_SET::NONE);
    doc->UpdateOcioColorSpaces();
    return maxon::OK;
    }
    PyObject PyObject const char const char char ** s
    Definition: bytesobject.h:60
    @ DOCUMENT_OCIO_RENDER_COLORSPACE
    Definition: ddoc.h:144
    #define NOTOK
    Definition: ge_sys_math.h:258
    int32_t Int32
    32 bit signed integer datatype.
    Definition: apibase.h:175
    #define MAXON_UNLIKELY(...)
    Definition: compilerdetection.h:427

    Convert Colors

    Convert colors along OCIO conversion paths defined by the OCIO color spaces associated with a document.

    maxon::Result<void> ConvertOcioColors(BaseDocument* doc)
    {
    return maxon::NullptrError(MAXON_SOURCE_LOCATION, "Invalid document pointer"_s);
    // OcioConverter can only initialized with a document which is in OCIO color management mode.
    BaseContainer* bc = doc->GetDataInstance();
    {
    doc->UpdateOcioColorSpaces();
    }
    // Get the default OcioConverter from #doc. OcioConverter is a helper interface to convert colors
    // between the color spaces associated with the OCIO configuration of a document, for its
    // initialization to succeed, the document must be in OCIO color management mode.
    OcioConverterRef converter = doc->GetColorConverter();
    if (!converter)
    {
    // Attempt to manually initialize the converter if the default one is not yet available.
    converter = OcioConverter::Init(doc) iferr_return;
    if (!converter)
    return maxon::NullptrError(MAXON_SOURCE_LOCATION, "Could not init OCIO converter for document."_s);
    }
    // The to be converted color, it has no implicitly defined color space.
    const maxon::Vector64 colorInput{ 1, 0, 0 };
    // Convert the color from sRGB space to render space. With the default OCIO settings of Cinema
    // 4D 2023.1, this will convert to ACEScg space. Doing this is only necessary when computation
    // results or color definitions are explicitly outside of the render space.
    const maxon::Vector64 colorRender = converter->TransformColor(
    // Convert the color from render space to display space, i.e., the space the physical display
    // device operates in. With the default OCIO settings of Cinema 4D 2023.1, this will convert
    // from ACEScg to sRGB space.
    const maxon::Vector64 colorDisplay = converter->TransformColor(
    // Convert a color from render space to view transform (space), i.e., to the value which
    // will be finally shown on the screen of a user. With the default OCIO settings of Cinema 4D
    // 2023.1, this will convert from ACEScg to ACES 1.0 SDR-video space.
    const maxon::Vector64 colorView = converter->TransformColor(
    // There are multiple other conversion paths to be found in #COLORSPACETRANSFORMATION, including
    // inverse operations, as for example converting a color in view space back to the render space.
    const maxon::Vector64 colorRenderViewRender = converter->TransformColor(
    // Print the results.
    ApplicationOutput("\tinput: @", colorInput);
    ApplicationOutput("\tinput->render: @", colorRender);
    ApplicationOutput("\trender->display: @", colorDisplay);
    ApplicationOutput("\trender->view: @", colorView);
    ApplicationOutput("\trender->view->render: @", colorRenderViewRender);
    return maxon::OK;
    }
    OCIO_SRGB_TO_RENDERING
    sRGB to Rendering color space transformation.
    Definition: ge_prepass.h:16
    OCIO_RENDERING_TO_VIEW
    Rendering to view color space transformation.
    Definition: ge_prepass.h:9
    OCIO_VIEW_TO_RENDERING
    View to rendering color space transformation.
    Definition: ge_prepass.h:11
    OCIO_RENDERING_TO_DISPLAY
    Rendering to display color space transformation.
    Definition: ge_prepass.h:14
    maxon::StrongRef< OcioConverter > OcioConverterRef
    Definition: operatingsystem.h:317
    A vector consisting of three components X, Y and Z.
    Definition: vec.h:21

    Convert Colors Arbitrarily

    Convert colors from and to OCIO color spaces using arbitrary in- and output spaces.

    maxon::Result<void> ConvertOcioColorsArbitrarily(BaseDocument* doc)
    {
    return maxon::NullptrError(MAXON_SOURCE_LOCATION, "Invalid document pointer"_s);
    // Make sure that #doc is in OCIO color management mode.
    BaseContainer* bc = doc->GetDataInstance();
    {
    doc->UpdateOcioColorSpaces();
    }
    // Load the "sRGB2014" ICC profile located next to this file.
    const maxon::Url directory = maxon::Url(maxon::String(MAXON_FILE)).GetDirectory();
    const maxon::Url sRgb2014File = (directory + "sRGB2014.icc"_s) iferr_return;
    if (sRgb2014File.IoDetect() == maxon::IODETECT::NONEXISTENT)
    return maxon::IoError(
    MAXON_SOURCE_LOCATION, sRgb2014File, "Could not access sRgb2014File.icc profile."_s);
    const maxon::ColorProfile srgb2014Profile = maxon::ColorProfileInterface::OpenProfileFromFile(
    sRgb2014File) iferr_return;
    // Get the profile for the builtin linear RGB space. This profile is required because
    // conversions with OCIO profiles are only supported between profiles that originate from the
    // same OCIO config and the profiles for the builtin linear or non-linear sRGB space (given that
    // the OCIO config file defines the sRGB space; which is the case for the Cinema 4D profiles).
    // For all other conversions, an intermediate step must be taken, e.g., in our case:
    //
    // sRGB2014 -> lin-RGB -> Render space
    // Render space -> lin-RGB -> sRGB2014
    const maxon::ColorProfile linearRgbSpaceProfile = maxon::ColorSpaces::RGBspace(
    ).GetDefaultLinearColorProfile();
    // Get the profile and name for the active Render space in #doc.
    maxon::ColorProfile renderSpaceProfile, _;
    doc->GetOcioProfiles(renderSpaceProfile, _, _, _);
    maxon::CString renderSpaceName, __;
    doc->GetActiveOcioColorSpacesNames(renderSpaceName, __, __, __);
    // Define the pixel format to operate with and check if it is supported by the profiles.
    const maxon::PixelFormat rgbFormat = maxon::PixelFormats::RGB::F32();
    if (!(srgb2014Profile.CheckCompatiblePixelFormat(rgbFormat) ||
    linearRgbSpaceProfile.CheckCompatiblePixelFormat(rgbFormat) ||
    renderSpaceProfile.CheckCompatiblePixelFormat(rgbFormat)))
    return maxon::UnexpectedError(
    MAXON_SOURCE_LOCATION, "Profile conversion path does not support RGB::F32 pixel format"_s);
    // Construct two converters, one for converting from the ICC profile to the intermediate linear
    // RGB space, and one for converting from that intermediate space to the Render space.
    const maxon::ColorProfileConvert preConverter = maxon::ColorProfileConvertInterface::Init(
    rgbFormat, srgb2014Profile, rgbFormat, linearRgbSpaceProfile,
    const maxon::ColorProfileConvert ocioConverter = maxon::ColorProfileConvertInterface::Init(
    rgbFormat, linearRgbSpaceProfile, rgbFormat, renderSpaceProfile,
    // Initialize the data to convert, an input and an output buffer, as well as two buffer
    // handlers for them. This could also be done by using three buffers (in, intermediate, out) and
    // four handlers (const in, const intermediate, mutable intermediate, mutable out) to avoid
    // having to copy data from the output buffer to the input buffer after the first conversion.
    maxon::Color32 colorData(1, 0, 0);
    maxon::Color32 inputBuffer(colorData);
    maxon::Color32 outputBuffer(0, 0, 0);
    (const maxon::Pix*)&inputBuffer.r, maxon::PixelFormats::RGB::F32());
    (maxon::Pix*)&outputBuffer.r, maxon::PixelFormats::RGB::F32());
    // Carry out the conversion sRGB2014.icc -> linear-RGB -> Render space for the data (1, 0, 0).
    preConverter.Convert(inputBufferHandler, outputBufferHandler, 1) iferr_return;
    ApplicationOutput("\tIn (@): @, Out (@): @",
    srgb2014Profile, colorData, linearRgbSpaceProfile, outputBuffer);
    inputBuffer = outputBuffer;
    ocioConverter.Convert(inputBufferHandler, outputBufferHandler, 1) iferr_return;
    ApplicationOutput("\tIn (@): @, Out (@): @",
    srgb2014Profile, colorData, renderSpaceName, outputBuffer);
    return maxon::OK;
    }
    static MAXON_METHOD Result< ColorProfileConvert > Init(const PixelFormat &srcPixelFormat, const ColorProfile &srcProfile, const PixelFormat &dstPixelFormat, const ColorProfile &dstProfile, COLORCONVERSIONINTENT intent, COLORCONVERSIONFLAGS flags)
    static MAXON_METHOD Result< ColorProfile > OpenProfileFromFile(const Url &fn)
    Definition: string.h:1287
    Definition: url.h:936
    ImageBufferTemplate< PixelConstBuffer > ImageConstBuffer
    Definition: gfx_image_pixelformat.h:186
    UChar Pix
    unspecified pixel format depth.
    Definition: gfx_image_imagechannel.h:17
    ImageBufferTemplate< PixelMutableBuffer > ImageMutableBuffer
    Definition: gfx_image_pixelformat.h:187
    #define MAXON_FILE
    Definition: compilerdetection.h:518
    @ NONEXISTENT
    Url doesn't exist.
    A color consisting of three components R, G and B.
    Definition: col.h:16
    Several functions use this helper structure to pass the image data to functions.
    Definition: gfx_image_pixelformat.h:524

    Get and Set Color Parameters

    Read and write color parameters in an OCIO document either in the native Render space of the document or other spaces.

    maxon::Result<void> GetSetColorValuesInOcioDocuments(BaseDocument* doc)
    {
    return maxon::NullptrError(MAXON_SOURCE_LOCATION, "Invalid document pointer"_s);
    // Ensure that the document is in OCIO color management mode.
    BaseContainer* bc = doc->GetDataInstance();
    {
    doc->UpdateOcioColorSpaces();
    }
    // Get the names of the active OCIO spaces in #doc for #ApplicationOutput calls invoked below.
    maxon::CString renderSpace, viewTransform, _;
    doc->GetActiveOcioColorSpacesNames(renderSpace, _, viewTransform, _);
    // When a document is in OCIO mode, all color parameters of scene elements are implicitly in
    // Render space. When for example the default color for objects is being retrieved from a
    // document, the value is expressed in Render space.
    GeData data;
    const Vector defaultColor = data.GetVector();
    ApplicationOutput("\tdefaultColor(@): @", renderSpace, defaultColor);
    // Unlike in the color chooser GUI, there is no direct way to read color values in any other
    // space, as an sRGB value for example. Such conversions must be carried out with the type
    // OcioConverter manually. The argument #doc to OcioConverter::Init must be a document in OCIO
    // mode.
    const OcioConverter* converter = OcioConverter::Init(doc) iferr_return;
    if (!converter)
    return maxon::NullptrError(MAXON_SOURCE_LOCATION, "Could not init OCIO converter for document."_s);
    // Transform #defaultColor from Render space to sRGB space.
    const Vector colorSrgb = converter->TransformColor(
    ApplicationOutput("\tdefaultColor(@): @", "sRGB"_s, colorSrgb);
    // Allocate three materials to write color values to.
    BaseMaterial* m1 = BaseMaterial::Alloc(Mmaterial);
    BaseMaterial* m2 = BaseMaterial::Alloc(Mmaterial);
    BaseMaterial* m3 = BaseMaterial::Alloc(Mmaterial);
    if (MAXON_UNLIKELY(!(m1 && m2 && m3)))
    return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION, "Could not allocate materials."_s);
    // Analogously, when color values are written, they are interpreted as Render space values by
    // default, and all other input spaces must be converted first.
    const Vector color{ 1, 0, 0 };
    const DescID colorChannel = ConstDescID(DescLevel(MATERIAL_COLOR_COLOR));
    // Write the color channel color of m1 as (1, 0, 0) in Render space.
    m1->SetParameter(colorChannel, GeData(color), DESCFLAGS_SET::NONE);
    // Write the color channel color of m2 as (1, 0, 0) in sRGB space.
    Vector fromSrgb = converter->TransformColor(color, COLORSPACETRANSFORMATION::OCIO_SRGB_TO_RENDERING);
    m2->SetParameter(colorChannel, GeData(fromSrgb), DESCFLAGS_SET::NONE);
    // Write the color channel color of m3 as (1, 0, 0) in View space, i.e., what the color chooser
    // does in its Display tab.
    Vector fromView = converter->TransformColor(color, COLORSPACETRANSFORMATION::OCIO_VIEW_TO_RENDERING);
    m3->SetParameter(colorChannel, GeData(fromView), DESCFLAGS_SET::NONE);
    ApplicationOutput("\tMATERIAL_COLOR_COLOR(@): @", renderSpace, color);
    ApplicationOutput("\tMATERIAL_COLOR_COLOR(@): @", "sRGB"_s, fromSrgb);
    ApplicationOutput("\tMATERIAL_COLOR_COLOR(@): @", viewTransform, fromView);
    // Set the name of and insert all three materials.
    m1->SetName("Material (Render Space)"_s);
    m2->SetName("Material (sRGB)"_s);
    m3->SetName("Material (View Transform)"_s);
    doc->InsertMaterial(m1);
    doc->InsertMaterial(m2);
    doc->InsertMaterial(m3);
    return maxon::OK;
    }
    @ DOCUMENT_DEFAULTMATERIAL_COLOR
    Definition: ddoc.h:67
    OCIO_RENDERING_TO_SRGB
    Rendering to sRGB color space transformation.
    Definition: ge_prepass.h:17
    #define Mmaterial
    Standard material.
    Definition: ge_prepass.h:1007
    @ MATERIAL_COLOR_COLOR
    Definition: mmaterial.h:56
    maxon::Vec3< maxon::Float64, 1 > Vector
    Definition: ge_math.h:140

    Manage Bitmap OCIO Color Profiles

    Read and write the OCIO color spaces associated with cinema::BaseBitmap instances to change or nullify parts of an OCIO conversion path for them.

    This makes it for example possible to disable the Display and View transform for a singular bitmap when displayed in the Picture Viewer.

    maxon::Result<void> GetSetBitmapOcioProfiles(BaseDocument* doc)
    {
    BaseBitmap* clone;
    finally { BaseBitmap::Free(clone); };
    return maxon::NullptrError(MAXON_SOURCE_LOCATION, "Invalid document pointer"_s);
    // Ensure that the document is in OCIO color management mode.
    BaseContainer* bc = doc->GetDataInstance();
    {
    doc->UpdateOcioColorSpaces();
    }
    // Get the Asset API user preferences repository to get the "HDR004.hdr" texture asset in
    // Textures/HDR/Legacy and retrieve its URL. It is important to use here an HDR image (the
    // dynamic range, not the necessarily the format), as the view transform is disabled for SDR
    // content in the Picture Viewer (as of 2023.1, might change in future releases).
    maxon::AssetRepositoryRef repository = maxon::AssetInterface::GetUserPrefsRepository();
    if (MAXON_UNLIKELY(!repository))
    return maxon::UnexpectedError(MAXON_SOURCE_LOCATION, "Could not retrieve user repository."_s);
    const maxon::Id assetId("file_9748feafc2c00be8");
    const maxon::AssetDescription asset = repository.FindLatestAsset(
    // --- Start of Image API related code ----------------------------------------------------------
    // Allocate a bitmap and load the texture asset.
    AutoAlloc<BaseBitmap> bitmap;
    if (MAXON_UNLIKELY(!bitmap))
    return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION, "Could not allocate bitmap."_s);
    if (bitmap->Init(MaxonConvert(textureUrl)) != IMAGERESULT::OK)
    return maxon::IoError(MAXON_SOURCE_LOCATION, textureUrl, "Could not load image file."_s);
    // Clone the loaded bitmap.
    clone = bitmap->GetClone();
    if (MAXON_UNLIKELY(!clone))
    return maxon::UnexpectedError(MAXON_SOURCE_LOCATION, "Could not clone bitmap."_s);
    // Get the OCIO Render space color profile associated with the bitmap.
    const ColorProfile* const profile = clone->GetColorProfile(BaseBitmap::COLORPROFILE_INDEX_RENDERSPACE);
    // Null the Display color space and the View Transform by overwriting them with the Render space
    // profile, the data will be displayed "raw".
    clone->SetColorProfile(profile, BaseBitmap::COLORPROFILE_INDEX_DISPLAYSPACE);
    clone->SetColorProfile(profile, BaseBitmap::COLORPROFILE_INDEX_VIEW_TRANSFORM);
    // Display both bitmaps in the picture viewer.
    ShowBitmap(bitmap);
    ShowBitmap(clone);
    return maxon::OK;
    }
    static MAXON_METHOD const UpdatableAssetRepositoryRef & GetUserPrefsRepository()
    static MAXON_METHOD Result< Url > GetAssetUrl(const AssetDescription &asset, Bool isLatest)
    Definition: apibaseid.h:243
    OK
    User has selected a font.
    Definition: customgui_fontchooser.h:0
    IMAGERESULT
    Definition: ge_prepass.h:3947
    Bool ShowBitmap(const Filename &fn)
    maxon::Url MaxonConvert(const Filename &fn, MAXONCONVERTMODE convertMode)
    The maxon namespace contains all declarations of the Maxon API.
    Definition: autoweight.h:21
    @ LATEST
    Set this flag to obtain only the latest version of the asset.
    const char const char const char * file
    Definition: object.h:439

    OCIO Aware Render

    Realizes a renderer which manipulates the OCIO profiles of an upcoming rendering.

    void OcioAwareRenderer::GetColorProfileInfo(
    BaseVideoPost* node, VideoPostStruct* vps, ColorProfileInfo& info)
    {
    if (!node)
    return;
    // GetColorProfileInfo allows us to react to or modify the color profiles of an upcoming OCIO
    // rendering.Here we use it to null the display and view transform by overwriting them with the
    // render transform when so indicated, causing the rendered image to be treated as "raw".
    BaseContainer* data = node->GetDataInstance();
    if (data->GetBool(ID_OVERWRITE_OCIO_DISPLAY_SPACE))
    info.displayColorSpace = info.renderingColorSpace;
    if (data->GetBool(ID_OVERWRITE_OCIO_VIEW_TRANSFORM))
    info.viewColorSpace = info.renderingColorSpace;
    }
    RENDERRESULT OcioAwareRenderer::Execute(BaseVideoPost* node, VideoPostStruct* vps)
    {
    {
    };
    // Bail when important data is not accessible, a rendering error did occur, or the user did stop
    // the renderer.
    if (!vps || !vps->doc || !vps->doc->GetDataInstance() || !vps->render)
    if (*vps->error != RENDERRESULT::OK)
    if (vps->thread && vps->thread->TestBreak())
    // Skip all calls except for a full frame being finished.
    if (vps->vp == VIDEOPOSTCALL::FRAME || vps->open)
    // Get the RGBA buffer of the rendering.
    VPBuffer* const rgbaBuffer = vps->render->GetBuffer(VPBUFFER_RGBA, NOTOK);
    if (!rgbaBuffer)
    if (rgbaBuffer->GetBt() != 32)
    // Get the color to "render" from the VideoPost node.
    BaseContainer* nodeData = node->GetDataInstance();
    Vector color = nodeData->GetVector(ID_RENDER_COLOR);
    // By default, just as in other places of the API, all color computations are implicitly in
    // Render space once a document is in OCIO mode. When a video post plugin is not meant to operate
    // in that space, all outputs must be transformed manually.
    BaseContainer* docData = vps->doc->GetDataInstance();
    nodeData->GetBool(ID_PRETRANSFORM_OCIO_OUTPUT))
    {
    const OcioConverter* converter = OcioConverter::Init(vps->doc) iferr_return;
    if (!converter)
    // Convert the color chosen by the user from sRGB to Render space. I.e., the chosen color is
    // always interpreted as an sRGB value which is then converted to and written as a Render space
    // value in the output buffer.
    color = converter->TransformColor(color, COLORSPACETRANSFORMATION::OCIO_SRGB_TO_RENDERING);
    }
    // Fill the whole buffer with the color.
    const Int32 width = rgbaBuffer->GetBw();
    const Int32 height = rgbaBuffer->GetBh();
    const Int32 bytesPerPixel = rgbaBuffer->GetCpp();
    Float32* lineBuffer = NewMemClear(Float32, bytesPerPixel * width).GetPointer();
    for (Int32 ix = 0; ix < width; ix++)
    {
    lineBuffer[ix * bytesPerPixel + 0] = (Float32)color.x;
    lineBuffer[ix * bytesPerPixel + 1] = (Float32)color.y;
    lineBuffer[ix * bytesPerPixel + 2] = (Float32)color.z;
    }
    for (Int32 iy = 0; iy < height; iy++)
    rgbaBuffer->SetLine(0, iy, width, lineBuffer, 32, false);
    DeleteMem(lineBuffer);
    }
    FRAME
    Called when the renderer prepares to render a frame.
    Definition: c4d_videopostdata.h:1
    for(i=0;i< length;i++)
    Definition: unicodeobject.h:61
    #define NewMemClear(T, cnt)
    Definition: defaultallocator.h:216
    USERBREAK
    Thread has been canceled.
    Definition: ge_prepass.h:4
    FAILED
    Generic error if a rendering has failed due to missing license or similar.
    Definition: ge_prepass.h:8
    OUTOFMEMORY
    Not enough memory.
    Definition: ge_prepass.h:1
    COLORSPACETRANSFORMATION
    Definition: ge_prepass.h:502
    RENDERRESULT
    Definition: ge_prepass.h:426
    #define VPBUFFER_RGBA
    RGB and alpha multipass channel.
    Definition: c4d_videopostdata.h:115
    maxon::Float32 Float32
    Definition: ge_sys_math.h:59
    maxon::Int32 Int32
    Definition: ge_sys_math.h:51
    void DeleteMem(T *&p)
    Definition: defaultallocator.h:269
    unsigned long Py_ssize_t width
    Definition: pycore_traceback.h:88
    _Py_clock_info_t * info
    Definition: pytime.h:197
    #define iferr_scope_handler
    Definition: resultbase.h:1414
    Definition: node.h:10

    Initialize Colors of Scene Elements in 2025

    [New in 2025.0.0] Demonstrates the changes made to color initiations for scene elements in 2025.0.0.

    With release 2025, OCIO has been substantially updated in Cinema 4D, leading to changes for how colors are interpreted in NodeData::Init. All colors are now interpreted as colors in sRGB-2.2 space in NodeData::Init, specifically when the document is in OCIO mode. This differs from before where colors were interpreted in the document's render space. Other places in code still interpret colors in the document's render space.

    This change was necessary because OCIO became the default color management mode in Cinema 4D 2025 and we wanted to preserve the colors defined in legacy code. This example demonstrates how to circumvent this behavior in case one wants to interpret colors in the document's Render space. This example can also be applied to pre-2025 frameworks. Although not necessary there, it will have no negative side effects either.

    Bool OcioNode2025::Init(cinema::GeListNode* node, cinema::Bool isCloneInit)
    {
    BaseList2D* const blist = static_cast<BaseList2D*>(node);
    BaseContainer* const bc = blist ? blist->GetDataInstance() : nullptr;
    if (!bc)
    return false;
    // In 2025, all colors set in the Init method are always interpreted as sRGB-2.2, even when the
    // document is in OCIO mode, which is now the default. This differs from before where colors were
    // interpreted as render space colors in that case.
    if (!isCloneInit)
    // Will not stay as (1, 0, 0) when the document is in OCIO mode, as the color will be then
    // transformed from this value interpreted as sRGB-2.2 to the render space, which is ACEScg
    // by default ... unless we handle MSG_MENUPREPARE.
    bc->SetVector(OCIO_NODE_2025_COLOR, Vector(1, 0, 0));
    PreloadTextures() iferr_ignore("this might fail but we cannot do anything about it");
    return true;
    }
    void OcioNode2025::Free(cinema::GeListNode* node)
    {
    // Free does not mind us passing a possible nullptr but we cannot pass a pointer to a const
    // object, so we must remove the const qualifier from the pointer.
    BaseBitmap* bmp = MAXON_REMOVE_CONST(_bitmap);
    BaseBitmap::Free(bmp);
    }
    maxon::Result<void> OcioNode2025::PreloadTextures()
    {
    // Scope handler for this method to free the bitmap in case of an error.
    BaseBitmap* bmp;
    {
    if (bmp)
    BaseBitmap::Free(bmp);
    _bitmap = nullptr;
    return err;
    };
    // We should avoid loading textures inside a Draw() method, as this can lead to performance
    // problems and other issues, this especially applies when we are loading the texture from an
    // asset database.
    // Attempt to get the "UV Test Grid.png" from the default asset database of Cinema 4D.
    return maxon::OK;
    const maxon::Url assetUrl("asset:///file_5b6a5fe03176444c"_s);
    const maxon::AssetDescription asset = maxon::AssetInterface::ResolveAsset(
    if (!asset)
    return maxon::IoError(MAXON_SOURCE_LOCATION, assetUrl,
    "Could not resolve asset for 'UV Test Grid.png'."_s);
    // Load the bitmap from the asset.
    const maxon::Url imgUrl = maxon::AssetInterface::GetAssetUrl(asset, true) iferr_return;
    bmp = BaseBitmap::Alloc();
    if (!bmp)
    return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION, "Could not allocate bitmap."_s);
    if (bmp->Init(Filename(imgUrl.GetUrl())) != IMAGERESULT::OK)
    return maxon::UnexpectedError(MAXON_SOURCE_LOCATION, "Could not init bitmap from file."_s);
    // Setting the color profile of the bitmap currently has no impact on drawing operations, if we
    // wanted to see the bitmap interpreted as a specific color space, we have to manually
    // convert it from that space to sRGB-2.2 and then draw it.
    //
    // const ColorProfile* const profile = ColorProfile::GetDefaultSGray();
    // bmp->SetColorProfile(profile, BaseBitmap::COLORPROFILE_INDEX_IMAGE);
    // bmp->SetColorProfile(profile, BaseBitmap::COLORPROFILE_INDEX_RENDERSPACE);
    // bmp->SetColorProfile(profile, BaseBitmap::COLORPROFILE_INDEX_DISPLAYSPACE);
    // bmp->SetColorProfile(profile, BaseBitmap::COLORPROFILE_INDEX_VIEW_TRANSFORM);
    _bitmap = bmp;
    return maxon::OK;
    }
    Bool OcioNode2025::Message(GeListNode* node, Int32 type, void* data)
    {
    if (!data)
    return SUPER::Message(node, type, data);
    BaseList2D* const blist = static_cast<BaseList2D*>(node);
    BaseContainer* const bc = blist ? blist->GetDataInstance() : nullptr;
    if (!bc)
    return SUPER::Message(node, type, data);
    // To prevent node color values being interpreted as sRGB-2.2, we must overwrite them when
    // MSG_MENUPREPARE is being emitted.
    {
    // Force the color to be (1, 0, 0) in Render space. For documents not in OCIO mode, this has
    // no effect, as this extra conversion does not take place there, and our color is already
    // (1, 0, 0) in these cases.
    bc->SetVector(OCIO_NODE_2025_COLOR, Vector(1, 0, 0));
    return true;
    }
    return SUPER::Message(node, type, data);
    }
    Represents a C4DAtom that resides in a 4D list.
    Definition: c4d_baselist.h:1990
    static MAXON_METHOD Bool WaitForDatabaseLoading()
    static MAXON_METHOD Result< AssetDescription > ResolveAsset(const Url &url, const AssetRepositoryRef &repository)
    Py_ssize_t PyObject * from
    Definition: unicodeobject.h:502
    Vec3< Float, 1 > Vector
    Definition: vector.h:56
    #define MSG_MENUPREPARE
    Allows tags, objects, shaders etc. to do some setup work when called from the menu....
    Definition: c4d_baselist.h:417
    UV
    UV Options.
    Definition: lib_activeobjectmanager.h:18
    Definition: autoweight.h:11
    maxon::Bool Bool
    Definition: ge_sys_math.h:46
    Url GetAssetUrl(const DndAsset &asset)
    struct _node node
    PyObject ** type
    Definition: pycore_pyerrors.h:34
    #define iferr_ignore(...)
    Definition: resultbase.h:1496

    Drawing with OCIO Colors in a Viewport

    [New in 2025.0.0] Demonstrates how to draw into a viewport when OCIO color management is enabled in a document.

    With 2025 it has become more important to correctly draw colors in the viewport when OCIO is enabled. This example demonstrates how to draw colors using the flag SET_PEN_USE_PROFILE_COLOR in a BaseDraw instance. And the special case of drawing colors from the settings of a Cinema 4D instance such as the world axis colors.

    Fig. II: The example draws with a color taken from the node (pure red in this case), a color taken from the world color settings (the y-axis color in this case), and a multiple instances of the same texture to the viewport.
    ocio_node_2025
    DRAWRESULT OcioNode2025::Draw(BaseObject* op, DRAWPASS drawpass, BaseDraw* bd, BaseDrawHelp* bh)
    {
    // Get out when we are in a draw pass we do not want to draw into, or when we are missing data.
    if (drawpass != DRAWPASS::HANDLES && drawpass != DRAWPASS::OBJECT)
    return SUPER::Draw(op, drawpass, bd, bh);
    if (!bd || !bh || !op || !_bitmap)
    // Make sure that there is a polygonal cache and a data container for our node.
    BaseObject* const cache = op ? op->GetCache() : nullptr;
    PolygonObject* const poly = (cache && (cache->GetType() == Opolygon)) ?
    static_cast<PolygonObject*>(cache) : nullptr;
    BaseContainer* const bc = op ? op->GetDataInstance() : nullptr;
    if (!poly || !bc)
    // Get the bounding box radius of the object as we will need it later.
    const Vector bboxRadius = poly->GetRad();
    // Cinema 4D asks us to draw handles for our object, we are going to draw a (non-functional)
    // handle on each point of the object in the color defined by the node data. See other ObjectData
    // examples for more information on how to implement handles.
    if (drawpass == DRAWPASS::HANDLES)
    {
    // When we want to draw a color value from our node's data container, we should draw it
    // with SET_PEN_USE_PROFILE_COLOR. This will be the correct choice in all cases except for:
    //
    // 1. The document is in OCIO mode, and we want explicitly to draw a color interpreted as an
    // sRGB-2.2 value instead of a render space value.
    // 2. The document is in Basic color management mode but linear workflow is enabled and we
    // again want to draw a color as an sRGB-2.2 value.
    //
    // In both cases we must pass the flag 0 to SetPen, the default. #SET_PEN_USE_PROFILE_COLOR
    // on the other hand will draw as a render space color in OCIO mode, and as a linear sRGB
    // in basic color management mode with linear workflow enabled.
    //
    // When a document is in basic color management mode with linear workflow disabled, this flag
    // makes no difference, since both color spaces are then the same.
    bd->SetPen(bc->GetVector(OCIO_NODE_2025_COLOR), SET_PEN_USE_PROFILE_COLOR);
    // Set the drawing matrix the local coordinate system of the object and the point size to 20.
    bd->SetMatrix_Matrix(op, op->GetMg());
    bd->SetPointSize(20);
    // Draw a handle on each point of the object in the color defined by the node's data container.
    const Vector* points = poly->GetPointR();
    const Int32 pointCount = poly->GetPointCount();
    for (Int32 i = 0; i < pointCount; i++)
    bd->DrawHandle(points[i], DRAWHANDLE::CUSTOM, 0);
    // Colors from the world settings should be drawn in this manner, no matter in which color
    // management mode the document is. Here we draw a line along the local y-axis of the object
    // in the color y-axis color from the world settings.
    bd->SetPen(GetViewColor(VIEWCOLOR_WYAXIS), 0);
    bd->DrawLine(Vector(0, -bboxRadius.y, 0), Vector(0, bboxRadius.y, 0), 0);
    }
    // Now we are going to draw a texture in world space, i.e., a texture that pans, rotates, and
    // scales with the active camera. It is important to draw textures which are drawn with
    // #SetMatrix_Matrix in the object #drawpass, other #drawpasses will not work as expected.
    if (drawpass == DRAWPASS::OBJECT && _bitmap)
    {
    // We again set the drawing matrix to the local coordinate system of the object.
    bd->SetMatrix_Matrix(op, op->GetMg());
    // Set up the points and UVs for a texture drawn at 50% of the object's bounding box radius
    // directly onto the object.
    Vector texRadius = bboxRadius * 0.5;
    Vector texPoints[4] = {
    Vector(-texRadius.x, texRadius.y, 0),
    Vector(texRadius.x, texRadius.y, 0),
    Vector(texRadius.x, -texRadius.y, 0),
    Vector(-texRadius.x, -texRadius.y, 0)
    };
    Vector texUVs[4] = {
    Vector(0, 0, 0),
    Vector(1, 0, 0),
    Vector(1, 1, 0),
    Vector(0, 1, 0)
    };
    // Set the z-offset of the following drawing operation so that we draw over polygons (0),
    // points (2), and edges (4) and then draw the texture. We again use here USE_PROFILE_COLOR.
    bd->LineZOffset(5);
    bd->DrawTexture(_bitmap, texPoints, nullptr, nullptr, texUVs, 4,
    }
    // Draw the two textures in screen space to the left of the object. Textures in screen space
    // usually should be drawn in the handles #drawpass, as textures in the object pass are also
    // visible when the object is not selected. And permanently visible textures plus screen space,
    // i.e., textures that do do not pan, rotate, or scale with the camera, would be very distracting.
    // If we would draw in the object draw pass, this would also mean that the handles could overlap
    // with these two screen space textures (which is likely not what we want). When we draw in the
    // handles draw pass, the drawing order will determine if the texture is drawn over or under the
    // handles. Since we draw the handles above, and the textures below, the textures will be drawn
    // over the handles in this case.
    if (drawpass == DRAWPASS::HANDLES && _bitmap)
    {
    // Get the left, top, and bottom safe frame offsets for the viewport (the black bars which are
    // drawn for viewports which do not match the aspect ratio of the render output).
    Int32 topSafeOffset, bottomSafeOffset, leftSafeOffset, _ = 0;
    bd->GetSafeFrame(&leftSafeOffset, &topSafeOffset, &_, &bottomSafeOffset);
    // Calculate where we have to place our two textures so that they fit nicely into the left side
    // of the viewport without overlapping with the safe frame borders.
    const Int32 margin = 25;
    const Int32 safeViewPortHeight = bottomSafeOffset - topSafeOffset - 2 * margin;
    const Int32 textureHeight = Int32(Float64(safeViewPortHeight) * .5) - margin;
    if (textureHeight < 1)
    // The uv coordinates we are going to use for both textures.
    const Vector texUVs[4] = {
    Vector(0, 0, 0),
    Vector(1, 0, 0),
    Vector(1, 1, 0),
    Vector(0, 1, 0)
    };
    // Draws a texture with a label below it, we are going to use this lambda to draw both textures.
    auto drawTextureWithLabel =
    [this, &bd, &textureHeight, &texUVs, &topSafeOffset, &leftSafeOffset, &margin]
    {
    // The four points of the rectangle in which we are going to draw the texture.
    const Int32 xa = leftSafeOffset + margin;
    const Int32 xb = xa + textureHeight;
    const Int32 ya = topSafeOffset + margin + i * (textureHeight + margin);
    const Int32 yb = ya + textureHeight;
    Vector points[4] = {
    Vector(xa, ya, 0),
    Vector(xb, ya, 0),
    Vector(xb, yb, 0),
    Vector(xa, yb, 0)
    };
    // Check if we draw the texture in profile color mode or not.
    // Draw the texture and a label for the flag below it.
    bd->DrawTexture(_bitmap, points, nullptr, nullptr, texUVs, 4, DRAW_ALPHA::NORMAL, flags);
    bd->DrawHUDText(xa, yb, isProfile ? "USE_PROFILE_COLOR"_s : "NONE"_s);
    };
    // Set the drawing matrix to screen space and draw the texture once in profile color mode and
    // once in normal mode. The former is usually the best choice for drawing textures, as it will
    // will draw the tetxure as it would be seen in render output (if the texture would be part of it).
    bd->SetMatrix_Screen();
    drawTextureWithLabel(0, DRAW_TEXTUREFLAGS::USE_PROFILE_COLOR);
    drawTextureWithLabel(1, DRAW_TEXTUREFLAGS::NONE);
    }
    return SUPER::Draw(op, drawpass, bd, bh);
    }
    Py_ssize_t i
    Definition: abstract.h:645
    SKIP
    Definition: asset_browser.h:0
    PyCompilerFlags * flags
    Definition: ast.h:14
    #define SET_PEN_USE_PROFILE_COLOR
    Set if the color is already in the color space of the BaseDraw. Otherwise the color will be converted...
    Definition: c4d_basedraw.h:228
    USE_PROFILE_COLOR
    Use color profile color.
    Definition: ge_prepass.h:8
    HANDLES
    The active objects handles will be drawn.
    Definition: ge_prepass.h:1
    DRAW_TEXTUREFLAGS
    Definition: ge_prepass.h:3013
    DRAWPASS
    Definition: ge_prepass.h:3542
    DRAWRESULT
    Definition: ge_prepass.h:4391
    #define Opolygon
    Polygon - PolygonObject.
    Definition: ge_prepass.h:1041
    #define VIEWCOLOR_WYAXIS
    Definition: ge_prepass.h:3090
    OBJECT
    Object mode.
    Definition: lib_activeobjectmanager.h:2
    NORMAL
    Definition: lib_birender.h:2
    CUSTOM
    Definition: lib_birender.h:6
    Vector GetViewColor(Int32 colid, Vector *defaultColor=nullptr)
    maxon::Float64 Float64
    Definition: ge_sys_math.h:58
    PyObject * op
    Definition: object.h:520