Open Search
    BaseObject Manual

    About

    BaseObject is the base class of all scene objects of Cinema 4D. These objects can be polygon objects, splines, generators, deformers, effectors, cameras, lights or objects like the "Sky" or "Background" object.

    BaseObject objects are an instance of Obase.

    A BaseObject may be also a:

    See also Flags.

    Access

    BaseObject objects are typically stored in and accessed from a BaseDocument:

    See BaseDocument Objects and Selections.

    // This example searches for an object named "Cube".
    // If it cannot be found a new cube with that name will be created.
    BaseObject* const object = doc->SearchObject("Cube"_s);
    if (object != nullptr)
    {
    ApplicationOutput("found \"Cube\""_s);
    return maxon::OK;
    }
    BaseObject* const cubeObject = BaseObject::Alloc(Ocube);
    if (cubeObject == nullptr)
    return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION);
    cubeObject->SetName("Cube"_s);
    doc->InsertObject(cubeObject, nullptr, nullptr);
    void SetName(const maxon::String &name)
    Definition: c4d_baselist.h:2369
    Definition: c4d_baseobject.h:225
    static BaseObject * Alloc(Int32 type)
    return OK
    Definition: apibase.h:2667
    #define Ocube
    Cube.
    Definition: ge_prepass.h:1095
    #define MAXON_SOURCE_LOCATION
    Definition: memoryallocationbase.h:67
    #define ApplicationOutput(formatString,...)
    Definition: debugdiagnostics.h:210
    const char * doc
    Definition: pyerrors.h:226

    Allocation/Deallocation

    BaseObject objects are created with the usual tools:

    The object IDs of many build-in object types are defined in Object Types.

    // This example shows how to create a new "Cube" object and how to insert it into the document.
    BaseDocument* const document = GetActiveDocument();
    if (document == nullptr)
    return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
    BaseObject* const cubeObject = BaseObject::Alloc(Ocube);
    if (cubeObject == nullptr)
    return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION);
    cubeObject->SetName("This is a new object"_s);
    document->InsertObject(cubeObject, nullptr, nullptr);
    BaseDocument * GetActiveDocument(void)
    void EventAdd(EVENT eventflag=EVENT::NONE)
    Definition: c4d_basedocument.h:498
    void InsertObject(BaseObject *op, BaseObject *parent, BaseObject *pred, Bool checknames=false)

    Primitive objects can also be created with these dedicated functions:

    New objects are typically added to a BaseDocument that takes ownership:

    // This example accesses the currently active object.
    // If an object is found a new Sphere is created and inserted under the found object.
    BaseObject* const parentObject = doc->GetActiveObject();
    if (parentObject == nullptr)
    return maxon::IllegalArgumentError(MAXON_SOURCE_LOCATION);
    BaseObject* const newSphere = BaseObject::Alloc(Osphere);
    if (newSphere == nullptr)
    return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION);
    newSphere->InsertUnder(parentObject);
    void InsertUnder(GeListNode *bl)
    Definition: c4d_baselist.h:1880
    #define Osphere
    Sphere.
    Definition: ge_prepass.h:1096

    Remove

    A BaseObject can be removed from the host BaseDocument:

    // The example removes the active object from the document.
    BaseObject* object = doc->GetActiveObject();
    if (object == nullptr)
    return maxon::IllegalArgumentError(MAXON_SOURCE_LOCATION);
    object->Remove();
    static void Free(BaseObject *&bl)

    Navigate

    BaseObject elements are organized in a tree. The usual functions can be used to navigate in that tree:

    See also Navigation in Lists and Trees.

    // This example function iterates through all objects
    // of the object tree defined by the given BaseObject.
    static void CheckObjects(BaseObject* obj)
    {
    while (obj != nullptr)
    {
    ApplicationOutput("Object Name: " + obj->GetName());
    CheckObjects(obj->GetDown());
    obj = obj->GetNext();
    }
    }
    PyObject * obj
    Definition: complexobject.h:60

    Read-Only Properties

    Bounding Box

    The bounding box defines the dimensions of a BaseObject.

    // This example creates a cube with the size of the bounding box.
    const Vector bbCenter = object->GetMp();
    const Vector bbRadius = object->GetRad();
    if (cube == nullptr)
    return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION);
    cube->InsertUnder(object);
    Bool SetParameter(const DescID &id, const GeData &t_data, DESCFLAGS_SET flags)
    Definition: lib_description.h:330
    @ ID_BASEOBJECT_REL_POSITION
    Definition: obase.h:15
    @ PRIM_CUBE_LEN
    Definition: ocube.h:6

    Cache

    Generator objects store virtual child objects in a cache. If a deformer is applied, the deformed child objects are found in the deform cache.

    // This function can be used to recursively search the cache
    // of a given BaseObject for polygon objects.
    static void DoRecursion(BaseObject* op)
    {
    // Check the deform cache
    BaseObject* tp = op->GetDeformCache();
    if (tp)
    {
    DoRecursion(tp);
    }
    else
    {
    // check the cache
    tp = op->GetCache(nullptr);
    if (tp)
    {
    DoRecursion(tp);
    }
    else
    {
    // check if generator
    if (!op->GetBit(BIT_CONTROLOBJECT))
    {
    // check if polygon object
    if (op->IsInstanceOf(Opolygon))
    {
    ApplicationOutput("Found polygon data"_s);
    }
    }
    }
    }
    // loop through child objects
    for (tp = op->GetDown(); tp; tp = tp->GetNext())
    {
    DoRecursion(tp);
    }
    }
    BaseObject * GetNext(void)
    Definition: c4d_baseobject.h:256
    #define BIT_CONTROLOBJECT
    Internal bit set by generators.
    Definition: ge_prepass.h:892
    #define Opolygon
    Polygon - PolygonObject.
    Definition: ge_prepass.h:1026
    PyObject * op
    Definition: object.h:520

    See also Generating.

    Miscellaneous

    Further functions are:

    // This example casts the given BaseObject into SplineObject
    // if it is a spline or if it is a spline generator.
    SplineObject* spline = nullptr;
    // check if the object is a "Spline" object
    if (object->IsInstanceOf(Ospline))
    spline = ToSpline(object);
    // check if the object is a spline generator
    else if (object->GetInfo() & OBJECT_ISSPLINE)
    spline = object->GetRealSpline();
    if (spline != nullptr)
    ApplicationOutput("Spline Object: " + spline->GetName());
    #define ToSpline(op)
    Casts a BaseObject* to a SplineObject*.
    Definition: c4d_baseobject.h:2209
    String GetName() const
    Definition: c4d_baselist.h:2363
    SplineObject * GetRealSpline(void)
    Represents a spline object.
    Definition: c4d_baseobject.h:2042
    #define OBJECT_ISSPLINE
    Spline object.
    Definition: ge_prepass.h:937
    #define Ospline
    Spline - SplineObject.
    Definition: ge_prepass.h:1027
    Definition: object.h:105

    Properties

    Parameters

    The basic parameters IDs of a BaseObject are defined in obase.h. They can be changed using C4DAtom::SetParameter() and C4DAtom::GetParameter(). For several properties dedicated functions exist.

    PSR

    The placement of an object is defined by its position, scale and rotation (PSR). Freeze Transformations allow to define a default or reset value. In short, the absolute value is the frozen value plus the relative value.

    Note
    The "absolute" values are not the world space values.

    These functions give access to the "absolute" values:

    These functions give access to the "frozen" values:

    These functions give access to the "relative" values:

    These functions are used to access the local and global Matrix of an object:

    // This example reads the global matrix of the given object
    // and applies it to the newly created BaseObject.
    const Matrix mg = object->GetMg();
    if (cube == nullptr)
    return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION);
    doc->InsertObject(cube, nullptr, nullptr);
    cube->SetMg(mg);
    void SetMg(const Matrix &m)
    Definition: c4d_baseobject.h:488

    See also Vector Manual (Classic) and Matrix Manual (Classic).

    Visibility

    A BaseObject may or may not be visible in the editor and rendered output.

    The modes are:

    • MODE_ON: The object is enabled regardless of the state of any parent object.
    • MODE_OFF: The object is disabled regardless of the state of any parent object.
    • MODE_UNDEF: The object is enabled by default, but the state of any parent object is used if it is enabled or disabled.
    // This example synchronizes editor and render mode if the render mode is off.
    const Int32 mode = object->GetRenderMode();
    if (mode == MODE_OFF)
    object->SetEditorMode(MODE_OFF);
    const wchar_t * mode
    Definition: fileutils.h:96
    maxon::Int32 Int32
    Definition: ge_sys_math.h:60
    #define MODE_OFF
    The object is disabled regardless of the state of any parent object.
    Definition: c4d_baseobject.h:36
    Note
    CheckEditorVisibility() checks the editor mode effect and layer settings of the given object, see Utility.

    Generator / Deformer enabled

    If an object is a generator or deformer it can be enabled or disabled:

    // This example checks if the given object is a SDS.
    // If so it gets disabled.
    // check if the object is a
    // "Subdivision Surface"
    if (object->IsInstanceOf(Osds))
    {
    object->SetDeformMode(false);
    }
    #define Osds
    SDS (HyperNURBS) - SDSObject.
    Definition: ge_prepass.h:1134

    Tags

    A BaseObject can host a variable number of tags. These tags add additional functionality and data to the object.

    See also BaseTag and VariableTag Manual.

    Warning
    Since R17 the Take System can add and own tags. See Take System Overview.

    Existing tags can be accessed with:

    // This example loops through the tags of the given object.
    BaseTag* tag = object->GetFirstTag();
    while (tag != nullptr)
    {
    ApplicationOutput("Tag: " + tag->GetName());
    tag = tag->GetNext();
    }
    Definition: c4d_basetag.h:48
    BaseTag * GetNext(void)
    Definition: c4d_basetag.h:79

    New tags can be created:

    // This example checks if the given object owns a "Protection" tag.
    // If not, the "Protection" tag is created.
    BaseTag* protectionTag = object->GetTag(Tprotection);
    if (protectionTag == nullptr)
    {
    protectionTag = object->MakeTag(Tprotection);
    if (protectionTag == nullptr)
    return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION);
    }
    #define Tprotection
    Protection.
    Definition: ge_prepass.h:1386

    and

    // This example adds a Phong tag to the given object.
    object->SetPhong(true, true, DegToRad(60.0));
    Float32 DegToRad(Float32 r)
    Definition: apibasemath.h:247

    Further tag related functionality:

    // This example removes all "Annotation" tags from the given object.
    // loop until no "Annotation" tag can be found anymore
    while (object->GetTag(Tannotation))
    {
    object->KillTag(Tannotation);
    }
    #define Tannotation
    Annotation.
    Definition: ge_prepass.h:1390

    Color

    A BaseObject can have an assigned color and can be displayed in xray mode:

    The settings are:

    // This example reads the color settings of the given object.
    object->GetColorProperties(&objColor);
    static String VectorToString(const Vector32 &v, Int32 nnk=-1)
    Definition: c4d_string.h:571
    Data structure for object color properties.
    Definition: c4d_baseobject.h:168
    Vector color
    The color.
    Definition: c4d_baseobject.h:170
    Note
    To set the color of virtual objects in ObjectData::GetVirtualObjects() a generator must be registered with OBJECT_USECACHECOLOR, see Flags and Generating.

    Modeling Axis

    In certain modeling modes a modeling axis is presented as the result of the current selection.

    // This example creates a new cube object using the modeling axis of the given object.
    const Matrix mat = object->GetModelingAxis(doc);
    if (cube == nullptr)
    return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION);
    cube->SetMg(mat);
    doc->InsertObject(cube, nullptr, nullptr);
    Note
    The axis of a multiselection can be obtained from the document, see BaseDocument Axis and Plane.

    Generating

    A generator object creates virtual and cached BaseObject elements in its ObjectData::GetVirtualObjects() function. The following BaseObject member functions are only used in this context.

    While creating the cache one should typically check if the cache is already build:

    // This code checks if the cache or the object is dirty.
    // If not, the existing cache is returned.
    Bool dirty = op->CheckCache(hh) || op->IsDirty(DIRTYFLAGS::DATA);
    if (!dirty)
    return op->GetCache(hh);
    maxon::Bool Bool
    Definition: ge_sys_math.h:55
    @ DATA
    Container changed.

    See also Cache.

    Generators can use child objects as input objects (see flag OBJECT_INPUT). A generator can check if these child objects are dirty and it can hide them in the viewport. The most simple way is to handle the child objects manually:

    // This example checks if the child object is dirty and "touches" it so it will be hidden.
    Bool dirty = false;
    BaseObject* const childObject = op->GetDown();
    if (childObject != nullptr)
    {
    dirty = childObject->IsDirty(DIRTYFLAGS::MATRIX | DIRTYFLAGS::DATA);
    childObject->Touch();
    }
    Bool IsDirty(DIRTYFLAGS flags)
    Definition: c4d_baseobject.h:902
    void Touch(void)
    Marks object to be used by generator. Automatically resets dirty values for use with IsDirty().
    @ MATRIX
    Matrix changed.

    To handle multiple child objects a dependence list can be used:

    // This example adds only the cube child objects to the dependencies list.
    op->NewDependenceList();
    BaseObject* child = op->GetDown();
    while (child != nullptr)
    {
    // check if the child object is a "Cube" object
    if (child->GetType() == Ocube)
    {
    op->AddDependence(hh, child);
    }
    child = child->GetNext();
    }
    if (!dirty)
    dirty = !op->CompareDependenceList();
    op->TouchDependenceList();
    Int32 GetType() const
    Definition: c4d_baselist.h:1393

    But the most simple way is to use one of these two functions: They will return polygon versions of the child objects and hide them:

    Note
    In some special cases (eg, Matrix Object) these functions don't work as expected (eg, wrong dirtiness). In these cases, a custom cache handling is needed.
    // This example gets a polygon clone of the first child object.
    // If the child object is not dirty, the returned object is the cache.
    Bool dirty = false;
    BaseObject* const childObject = op->GetDown();
    if (childObject != nullptr)
    {
    BaseObject* const clone = op->GetAndCheckHierarchyClone(hh, childObject, flags, &dirty, nullptr, false);
    if (!dirty)
    return clone;
    // Fill the cache based on the polygon clone.
    // ...
    PyCompilerFlags * flags
    Definition: ast.h:14
    HIERARCHYCLONEFLAGS
    Definition: ge_prepass.h:3389
    @ ASPOLY
    Objects cloned as polygons. (Used by e.g. HyperNURBS.)

    If a generator creates multiple child objects each object must be uniquely identifiable. If the flag OBJECT_UNIQUEENUMERATION is set each object can receive an unique IP number.

    Note
    The unique IP must not be zero.
    // This example creates some cube objects with a unique IP.
    Vector pos = Vector(0, 0, 0);
    for (Int32 i = 1; i < 11; ++i)
    {
    if (cube != nullptr)
    {
    cube->InsertUnder(parent);
    cube->SetAbsPos(pos);
    cube->SetUniqueIP(i);
    pos.x += 250.0;
    }
    }
    Py_ssize_t i
    Definition: abstract.h:645
    void SetUniqueIP(Int32 ip)
    void SetAbsPos(const Vector &v)
    Definition: c4d_baseobject.h:304
    void Py_ssize_t * pos
    Definition: dictobject.h:50
    maxon::Vec3< maxon::Float64, 1 > Vector
    Definition: ge_math.h:145

    Isoparm lines can be used to display and accentuate certain lines in the viewport.

    // This example creates a simple Line object and assigns it to the given polygon object.
    LineObject* const lineObject = LineObject::Alloc(2, 1);
    if (lineObject != nullptr)
    {
    Segment* const segments = lineObject->GetSegmentW();
    Vector* const linePoints = lineObject->GetPointW();
    // check pointers
    if (segments && linePoints)
    {
    segments[0].cnt = 2;
    linePoints[0] = Vector(0, 0, 0);
    linePoints[1] = Vector(0, 1000, 0);
    lineObject->Message(MSG_UPDATE);
    polyObject->SetIsoparm(lineObject);
    }
    }
    Bool Message(Int32 type, void *data=nullptr)
    Definition: c4d_baselist.h:1439
    Definition: c4d_baseobject.h:1524
    static LineObject * Alloc(Int32 pcnt, Int32 scnt)
    Segment * GetSegmentW(void)
    Definition: c4d_baseobject.h:1562
    Vector * GetPointW(void)
    Definition: c4d_baseobject.h:1464
    #define MSG_UPDATE
    Must be sent if the bounding box has to be recalculated. (Otherwise use MSG_CHANGE....
    Definition: c4d_baselist.h:341
    Represents a Spline segment data.
    Definition: c4d_baseobject.h:159
    Int32 cnt
    The number of points in the segment.
    Definition: c4d_baseobject.h:160

    Rotation Order

    In Cinema 4D the rotation of an object is stored as a Vector. Each component of this vector corresponds to a rotation axis. The rotation result depends on the order in which the rotation is executed. For values see ROTATIONORDER.

    // This example simply sets the default rotation order.
    object->SetRotationOrder(ROTATIONORDER::DEFAULT);
    @ DEFAULT
    Default order (HPB).
    Note
    Typically used with MatrixToHPB() and HPBToMatrix(). See Matrix Manual (Classic).

    The rotation values of an animation can be optimized:

    // This example checks the rotation tracks of the given object.
    // FindBestEulerAngle() will modify the existing keys to find the best angles.
    obj->FindBestEulerAngle(ID_BASEOBJECT_REL_ROTATION, true, false);
    // animate the object so it uses the new key values
    doc->AnimateObject(obj, doc->GetTime(), ANIMATEFLAGS::NONE);
    @ ID_BASEOBJECT_REL_ROTATION
    Definition: obase.h:16

    Quaternion Rotation Mode

    The (animated) rotation values of an object can be interpolated using quaternions.

    // This example checks if the given object uses quaternion interpolation.
    // If not quaternion interpolation is enabled.
    // check if the object uses quaternion interpolation
    if (obj->IsQuaternionRotationMode() == false)
    {
    // turn on quaternion interpolation.
    // this will update the rotation animation tracks
    obj->SetQuaternionRotationMode(true, false);
    }

    The use of quaternion interpolation can be forced with:

    Animation Tracks

    These utility functions allow fast access to the animation tracks and curves of an animated Vector parameter. See Animation Overview.

    Note
    This is typically used with synchronized tracks, see CTrack Synchronisation.
    // This example accesses the subtracks of the object's position track.
    const DescID positionTrack { DescLevel { ID_BASEOBJECT_REL_POSITION, DTYPE_VECTOR, 0 } };
    CTrack* trackX = nullptr;
    CTrack* trackY = nullptr;
    CTrack* trackZ = nullptr;
    // access track for each vector component
    if (obj->GetVectorTracks(positionTrack, trackX, trackY, trackZ))
    {
    if (trackX != nullptr)
    ApplicationOutput("Track X: " + trackX->GetName());
    if (trackY != nullptr)
    ApplicationOutput("Track Y: " + trackY->GetName());
    if (trackZ != nullptr)
    ApplicationOutput("Track Z: " + trackZ->GetName());
    }
    Definition: c4d_canimation.h:671
    @ DTYPE_VECTOR
    Vector
    Definition: lib_description.h:70
    Represents a level within a DescID.
    Definition: lib_description.h:289

    This function is used to handle keys on a Vector parameter:

    Animate

    An object can be animated using the host BaseDocument:

    Note
    This function only animates the object based on its keyframes but does not care about expressions or other objects.

    See also BaseDocument Animate.

    Convert

    Generators create and own virtual child objects. To access these child object one can read the cache of the generator (see Cache). Another way is to apply the "Current State to Object" command to the given generator object.

    // This example creates a torus object and converts it to a polygon object.
    if (tempDoc == nullptr)
    return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION);
    if (object == nullptr)
    return maxon::OutOfMemoryError(MAXON_SOURCE_LOCATION);
    // insert it into the temp doc.
    tempDoc->InsertObject(object, nullptr, nullptr);
    // modify object
    object->SetParameter(PRIM_TORUS_INNERRAD, 100.0, DESCFLAGS_SET::NONE);
    mcd.doc = tempDoc;
    mcd.op = object;
    // execute the "Current State to Object" modeling command
    return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
    BaseObject* const res = static_cast<BaseObject*>(atom);
    // check if the result object is a polygon object
    if (res && (res->GetType() == Opolygon))
    {
    doc->InsertObject(res, nullptr, nullptr);
    }
    PyObject * object
    Definition: asdl.h:7
    Bool SendModelingCommand(Int32 command, ModelingCommandData &data)
    C4DAtom * GetIndex(Int32 idx) const
    Definition: c4d_baselist.h:1679
    Definition: ge_autoptr.h:37
    Definition: c4d_baselist.h:1377
    Py_UCS4 * res
    Definition: unicodeobject.h:1113
    #define atom
    Definition: graminit.h:72
    #define MCOMMAND_CURRENTSTATETOOBJECT
    Current state to object (returns object): MDATA_CURRENTSTATETOOBJECT.
    Definition: ge_prepass.h:1612
    #define Otorus
    Torus.
    Definition: ge_prepass.h:1099
    @ PRIM_TORUS_INNERRAD
    Definition: otorus.h:7
    A helper object for SendModelingCommand().
    Definition: operatingsystem.h:815
    AtomArray * result
    Definition: operatingsystem.h:837
    BaseObject * op
    The input object. Use arr for multiple objects.
    Definition: operatingsystem.h:828
    BaseDocument * doc
    Definition: operatingsystem.h:826

    Bits

    A BaseObject can be hidden in the Object Manager or viewport using these bits:

    // This example hides the given object in the Object Manager.
    object->ChangeNBit(NBIT::OHIDE, NBITCONTROL::SET);
    @ SET
    Set bit.
    @ OHIDE
    Hide object/tag in Object Manager or material in Material Manager.

    Flags

    The flags of a BaseObject can be accessed with GeListNode::GetInfo(). These flags inform about the type of object and its behavior.

    Object type:

    // This example casts the given BaseObject into SplineObject
    // if it is a spline or if it is a spline generator.
    SplineObject* spline = nullptr;
    // check if the object is a "Spline" object
    if (object->IsInstanceOf(Ospline))
    spline = ToSpline(object);
    // check if the object is a spline generator
    else if (object->GetInfo() & OBJECT_ISSPLINE)
    spline = object->GetRealSpline();
    if (spline != nullptr)
    ApplicationOutput("Spline Object: " + spline->GetName());

    Generator related flags:

    Other flags:

    Utility

    These utility functions can return the name of the object type or return the object type based on that name.

    // This example prints the name of the object type of the given object.
    const Int32 type = obj->GetType();
    const String typeName = GetObjectName(type);
    ApplicationOutput("Object Type: " + typeName);
    String GetObjectName(Int32 type)
    Definition: c4d_string.h:39
    PyObject ** type
    Definition: pycore_pyerrors.h:34

    These functions can be used to check if the given BaseObject is visible in the Editor:

    // This example checks if the given BaseObject is visible in the active editor view.
    BaseDraw* const bd = doc->GetActiveBaseDraw();
    if (bd == nullptr)
    return maxon::UnexpectedError(MAXON_SOURCE_LOCATION);
    const DISPLAYFILTER filter = bd->GetDisplayFilter();
    const Bool displayFilter = CheckDisplayFilter(object, filter);
    // check editor visibility
    const Bool editorVisibiliy = CheckEditorVisibility(object);
    // check if the object is visible in the viewport
    if (displayFilter && editorVisibiliy)
    {
    ApplicationOutput("The object is visible in the Editor"_s);
    }
    else
    {
    ApplicationOutput("The object is not visible in the Editor"_s);
    }
    Bool CheckDisplayFilter(BaseObject *op, DISPLAYFILTER filter)
    Bool CheckEditorVisibility(BaseObject *op)
    Definition: c4d_basedraw.h:754
    DISPLAYFILTER GetDisplayFilter() const
    Definition: c4d_basedraw.h:1594
    DISPLAYFILTER
    Definition: ge_prepass.h:4537

    Further Reading