How to Modify the Axis of a Point Object?

Hello,
Here is the short scenario:
I have many objects that have different rotation values. some of them have 45 degree H, some of them -90 B etc. If I reset them from object manager Coordinate tab, naturaly object change its rotations visually. I needed to. fix them without changing their appearance. So I found a way like below:

  • 1- Select an object has -90 degree rotation for example
  • 2- turn on Enable Axis mode
  • 3- In the "Coordinate Manager" panel (not object manager. By the way for a single mesh object object manager can be used but this method can't work for Null objects) reset that value by entering 0

with this method I could fix the object gizmo without changing its current appearance but also I realized that I can't do this operation for more than one object by selecting multiple objects.
So I have to select them one by one and apply above steps. I need to use script I guess.

how can I do this by Python? I've done many research but 2. and 3. steps were confusing me, I couldn't achieve those.

thank you

edited by @ferdinand
Replaced title 'How can I do this with Python' with 'How to Modify the Axis of a Point Object?'

Probably need to modify your thread title. Too generic. Too vague.

Anyhow, I think what you are looking for is what I was trying to achieve in this thread:
https://plugincafe.maxon.net/topic/14259/reset-rotate-with-compensate-points/4

Hello @delizade,

Thank you for reaching out to us. @bentraje was right on both points. Your topic title was a bit too broad, I have fixed that for you, and also the topic by @bentraje was closely related.

In the public Cinema 4D API there is no such concept as an axis gizmo. While you can call the command to enable or disable the axis tool, you are still operating on a lower level, which makes the state of the tool meaningless. Tranforming the axis of a point object means transforming its coordinate system (a.k.a., "global matrix") and then applying the inverse transform to all its points. This will result in the origin and frame, what you see as "the axis" in the editor, to be changed but the points to stay in place as you undid to them what you did to "the axis".

We have 27 pages of search results for 'move axis' related questions on Plugin Café, as this is one of the most commonly asked things. Last year I also added operation_transfer_axis_s26.py, a Python script which tackles one of the commonly requested use cases. Otherwise, I would recommend the Matrix Manual, as each specific use case tends to be slightly different than others.

Cheers,
Ferdinand

Hello,
thank you so much @bentraje and @ferdinand for your time and help.
also sorry for the title.

and omg yes there were literally same trouble posts here but I guess I didn't know what to search for (and akso I wrote that weird title)
I will check your solutions, thank you.

as far as I understand those scripts only for polygon meshes. How can I made it for null objects too? and scripts does not reset scales too. it works for only rotations.

sorry for this I am not a programmer. I just need to reset tons of objects and nulls and trying to understand tose script to achieve that.

I wrote a strange script that works for both types. I will share it soon to get your feedbacks I hope

Hey @delizade,

The script works for anything that is a c4d.PointObject, i.e., editable polygon and spline objects. But not for generators, e.g., the Cube object or the Circle spline, as you cannot edit their points and therefore have no control over the placement of their "axis" in relation to their vertices.

When you want to set the transform of any BaseObject, e.g., a PointObject, a generator, or a null object, you must simply set either its local or global matrix. But this will not keep vertices 'in place' as generators and a null object have no vertices one could edit, and the vertices of PointObject instances must be corrected manually to achieve the 'move the axis idea'.

But you can of course just set the global or local matrix (a.k.a. transform) of a BaseObject. Find an example below. For more detailled information, I would recommend having a look at the Matrix Manual.

Cheers,
Ferdinand

The result, the two cubes are not at the same location because combining two transforms is not commutative, i.e., the order matters. A * B is not always the same as B * A for matrices:
8392f997-7526-4a6d-b00b-e020d7669c59-image.png

The code:

"""Demonstrates the basic concept of transformations as realized by Cinema 4D.
"""

import c4d

def main() -> None:
    """Constructs two transforms and applies them in the global coordinate system to two cube
    objects.
    """
    # Construct a transform that translates by 500 units on the y-axis and one that rotates by 
    # 45° on the x-axis.
    move: c4d.Matrix = c4d.utils.MatrixMove(c4d.Vector(0, 500, 0))
    rotate: c4d.Matrix = c4d.utils.MatrixRotX(c4d.utils.DegToRad(45))

    # Combine both transforms into a singular one by multiplying them. Note that matrix 
    # multiplication, combining transforms, is not commutative. I.e., the order matters opposed
    # to numbers; move * rotate is not the same as rotate * move.
    tMoveRotate: c4d.Matrix = move * rotate
    tRotateMove: c4d.Matrix = rotate * move

    # Allocate two cube objects.
    cubeMoveRotate: c4d.BaseObject = c4d.BaseObject(c4d.Ocube)
    cubeRotateMove: c4d.BaseObject = c4d.BaseObject(c4d.Ocube)
    if None in (cubeMoveRotate, cubeRotateMove):
        raise MemoryError("Could not allocate cube object.")

    # And set their global matrix, i.e., the absolute transform in the global coordinate system.
    cubeMoveRotate.SetMg(tMoveRotate)
    cubeRotateMove.SetMg(tRotateMove)

    # Name both null objects, set their display color, insert them into the active document, and 
    # push an update event.
    cubeMoveRotate.SetName("Cube: Move -> Rotate")
    cubeRotateMove.SetName("Cube: Rotate -> Move")
    cubeMoveRotate[c4d.ID_BASEOBJECT_USECOLOR] = c4d.ID_BASEOBJECT_USECOLOR_ALWAYS
    cubeRotateMove[c4d.ID_BASEOBJECT_USECOLOR] = c4d.ID_BASEOBJECT_USECOLOR_ALWAYS
    cubeMoveRotate[c4d.ID_BASEOBJECT_COLOR] = c4d.Vector(1, 0, 0)
    cubeRotateMove[c4d.ID_BASEOBJECT_COLOR] = c4d.Vector(0, 0, 1)
    doc.InsertObject(cubeMoveRotate)
    doc.InsertObject(cubeRotateMove)
    c4d.EventAdd()

if __name__ == '__main__':
    main()