PolygonReduction Manual

About

The c4d.utils.PolygonReduction class allows to reduce the polygon count of a given c4d.PolygonObject while retaining its overall shape. The class gives access to the functionality used within the “Polygon Reduction” generator.

Create

c4d.utils.PolygonReduction objects are created with PolygonReduction.__init__() / ().

"""
Copyright: MAXON Computer GmbH
Author: Yannick Puech

Description:
    - Creates a new PolygonReduction object.

Class/method highlighted:
    - c4d.utils.PolygonReduction

Compatible:
    - Win / Mac
    - R19, R20, R21, S22
"""
import c4d

polyReduction = c4d.utils.PolygonReduction()

Init

A c4d.utils.PolygonReduction object has to be initialized. It will pre-process the given c4d.PolygonObject.

The data dictionary argument has these keys:

Note

If it should be possible to abort the reduction operation and to retain the original mesh, it is advised to operate on a copy of the original c4d.PolygonObject.

"""
Copyright: MAXON Computer GmbH
Author: Yannick Puech

Description:
    - Configures the given PolygonReduction object.
    - Reduces the given PolygonObject to 25%.

Class/method highlighted:
    - c4d.utils.PolygonReduction

Compatible:
    - Win / Mac
    - R19, R20, R21, S22
"""
import c4d


def main():
    # Checks if selected object is valid
    if op is None:
        raise ValueError("op is none, please select one object.")

    # Check if it's a polygon object
    if not op.IsInstanceOf(c4d.Opolygon):
        raise TypeError("Selected object is not a polygon Object.")

    # Defines settings for PolygonReduction.PreProcess()
    settings = c4d.BaseContainer()
    settings[c4d.POLYREDUXOBJECT_PRESERVE_3D_BOUNDARY] = True
    settings[c4d.POLYREDUXOBJECT_PRESERVE_UV_BOUNDARY] = True

    # Defines data for PolygonReduction.PreProcess()
    data = dict()
    data['_op'] = op
    data['_doc'] = doc
    data['_settings'] = settings
    data['_thread'] = None

    # Creates PolygonReduction object
    polyReduction = c4d.utils.PolygonReduction()
    if polyReduction is None:
        raise RuntimeError("Failed to create the PolygonReduction.")

    # Pre-process the data
    if not polyReduction.PreProcess(data):
        raise RuntimeError("Failed to Pre-Process the PolygonReduction with data.")

    # Runs the reduce process of the polygon object
    polyReduction.SetReductionStrengthLevel(0.75)

    # Updates original PolygonObject
    op.Message(c4d.MSG_UPDATE)

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


if __name__ == '__main__':
    main()

If the _thread key is set the pre-process is running asynchronously in a background thread.

Note

This asynchronous mode may be used e.g. in a generator object.

After the pre-process the c4d.utils.PolygonReduction object is ready:

Reduce

The linked c4d.PolygonObject can be reduced by defining the overall reduction strength or the target triangle, vertex or edge count.

The triangle count is defined with:

"""
Copyright: MAXON Computer GmbH
Author: Yannick Puech

Description:
    - Reduces the active PolygonObject to the given triangle count.

Class/method highlighted:
    - c4d.utils.PolygonReduction

Compatible:
    - Win / Mac
    - R19, R20, R21, S22
"""
import c4d


def main():
    # Checks if selected object is valid
    if op is None:
        raise ValueError("op is none, please select one object.")

    # Check if it's a polygon object
    if not op.IsInstanceOf(c4d.Opolygon):
        raise TypeError("Selected object is not a polygon Object.")

    # Defines settings for PolygonReduction.PreProcess()
    settings = c4d.BaseContainer()
    settings[c4d.POLYREDUXOBJECT_PRESERVE_3D_BOUNDARY] = True
    settings[c4d.POLYREDUXOBJECT_PRESERVE_UV_BOUNDARY] = True

    # Defines data for PolygonReduction.PreProcess()
    data = dict()
    data['_op'] = op
    data['_doc'] = doc
    data['_settings'] = settings
    data['_thread'] = None

    # Creates PolygonReduction object
    polyReduction = c4d.utils.PolygonReduction()
    if polyReduction is None:
        raise RuntimeError("Failed to create the PolygonReduction.")

    # Pre-process the data
    if not polyReduction.PreProcess(data):
        raise RuntimeError("Failed to Pre-Process the PolygonReduction with data.")

    # Asks for number of triangle level
    while True:
        # Opens a Dialog where user can enter a text
        userInput = c4d.gui.InputDialog("Enter number of triangle level:")

        # Checks if operation was cancelled
        if userInput == "":
            return

        # Tries to convert to integer
        try:
            triangleLevel = int(userInput)
            break
        except ValueError:
            c4d.gui.MessageDialog("Please enter a number.")

    # Checks entered number of triangle level is valid
    if not polyReduction.GetMinTriangleLevel() < triangleLevel < polyReduction.GetMaxTriangleLevel():
        raise RuntimeError("Entered value is not valid.")

    # Sets the triangle level
    polyReduction.SetTriangleLevel(triangleLevel)

    # Gets triangle level count after reduction
    realTriangleResult = polyReduction.GetTriangleLevel()
    print("Triangle Result: ".format(realTriangleResult))

    # Updates original PolygonObject
    op.Message(c4d.MSG_UPDATE)

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


if __name__ == '__main__':
    main()

The vertex count is defined with:

"""
Copyright: MAXON Computer GmbH
Author: Yannick Puech

Description:
    - Reduces the active PolygonObject to the given vertex count.

Class/method highlighted:
    - c4d.utils.PolygonReduction

Compatible:
    - Win / Mac
    - R19, R20, R21, S22
"""
import c4d


def main():
    # Checks if selected object is valid
    if op is None:
        raise ValueError("op is none, please select one object.")

    # Check if it's a polygon object
    if not op.IsInstanceOf(c4d.Opolygon):
        raise TypeError("Selected object is not a polygon Object.")

    # Defines settings for PolygonReduction.PreProcess()
    settings = c4d.BaseContainer()
    settings[c4d.POLYREDUXOBJECT_PRESERVE_3D_BOUNDARY] = True
    settings[c4d.POLYREDUXOBJECT_PRESERVE_UV_BOUNDARY] = True

    # Defines data for PolygonReduction.PreProcess()
    data = dict()
    data['_op'] = op
    data['_doc'] = doc
    data['_settings'] = settings
    data['_thread'] = None

    # Creates PolygonReduction object
    polyReduction = c4d.utils.PolygonReduction()
    if polyReduction is None:
        raise RuntimeError("Failed to create the PolygonReduction.")

    # Pre-process the data
    if not polyReduction.PreProcess(data):
        raise RuntimeError("Failed to Pre-Process the PolygonReduction with data.")

    # Asks for number of vertex level
    while True:
        # Opens a Dialog where user can enter a text
        userInput = c4d.gui.InputDialog("Enter number of vertex level:")

        # Checks if operation was cancelled
        if userInput == "":
            return

        # Tries to convert to integer
        try:
            vertexLevel = int(userInput)
            break
        except ValueError:
            c4d.gui.MessageDialog("Please enter a number.")

    # Checks entered number of vertex level is valid
    if not polyReduction.GetMinVertexLevel() < vertexLevel < polyReduction.GetMaxVertexLevel():
        raise RuntimeError("Entered value is not valid.")

    # Sets the vertex level
    polyReduction.SetVertexLevel(vertexLevel)

    # Gets vertex level count after reduction
    realVertexResult = polyReduction.GetVertexLevel()
    print("Vertex Result: {0}".format(realVertexResult))

    # Updates original PolygonObject
    op.Message(c4d.MSG_UPDATE)

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


if __name__ == '__main__':
    main()

Finally the edge count can be defined with:

"""
Copyright: MAXON Computer GmbH
Author: Yannick Puech

Description:
    - Reduces the active PolygonObject to the given edge count.

Class/method highlighted:
    - c4d.utils.PolygonReduction

Compatible:
    - Win / Mac
    - R19, R20, R21, S22
"""
import c4d


def main():
    # Checks if selected object is valid
    if op is None:
        raise ValueError("op is none, please select one object.")

    # Check if it's a polygon object
    if not op.IsInstanceOf(c4d.Opolygon):
        raise TypeError("Selected object is not a polygon Object.")

    # Defines settings for PolygonReduction.PreProcess()
    settings = c4d.BaseContainer()
    settings[c4d.POLYREDUXOBJECT_PRESERVE_3D_BOUNDARY] = True
    settings[c4d.POLYREDUXOBJECT_PRESERVE_UV_BOUNDARY] = True

    # Defines data for PolygonReduction.PreProcess()
    data = dict()
    data['_op'] = op
    data['_doc'] = doc
    data['_settings'] = settings
    data['_thread'] = None

    # Creates PolygonReduction object
    polyReduction = c4d.utils.PolygonReduction()
    if polyReduction is None:
        raise RuntimeError("Failed to create the PolygonReduction.")

    # Pre-process the data
    if not polyReduction.PreProcess(data):
        raise RuntimeError("Failed to Pre-Process the PolygonReduction with data.")

    # Asks for number of edges level
    while True:
        # Opens a Dialog where user can enter a text
        userInput = c4d.gui.InputDialog("Enter number of edges level:")

        # Checks if operation was cancelled
        if userInput == "":
            return

        # Tries to convert to integer
        try:
            edgesLevel = int(userInput)
            break
        except ValueError:
            c4d.gui.MessageDialog("Please enter a number.")

    # Sets edges level number
    polyReduction.SetRemainingEdgesLevel(min(edgesLevel, polyReduction.GetMaxRemainingEdgesLevel()))
    polyReduction.SetRemainingEdgesLevel(min(edgesLevel, polyReduction.GetMaxRemainingEdgesLevel()))

    # Retrieves edges level count after reduction
    realEdgeResult = polyReduction.GetRemainingEdgesLevel()
    print("Edge Result: {0}".format(realEdgeResult))

    # Updates the original PolygonObject
    op.Message(c4d.MSG_UPDATE)

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


if __name__ == '__main__':
    main()