Difference between revisions of "IC Python API:Transform Math"

From Reallusion Wiki!
Jump to: navigation, search
m (Transform Point)
m
 
(One intermediate revision by the same user not shown)
Line 24: Line 24:
 
     return RLPy.RVector3(point_world_matrix.GetTranslate())
 
     return RLPy.RVector3(point_world_matrix.GetTranslate())
 
</syntaxhighlight>
 
</syntaxhighlight>
 
  
 
=== Transform Point with Specific Rotation ===
 
=== Transform Point with Specific Rotation ===
Line 94: Line 93:
 
     # Return the translation element of the combined matrix4
 
     # Return the translation element of the combined matrix4
 
     return RLPy.RVector3(point_world_matrix.GetTranslate())
 
     return RLPy.RVector3(point_world_matrix.GetTranslate())
 +
</syntaxhighlight>
 +
 +
== Transform Lerp ==
 +
 +
Lerps between two transformational matrices given a point between 0 and 1.
 +
 +
<syntaxhighlight lang="python">
 +
def transform_lerp(from_transform, to_transform, point):
 +
    x = y = z = 0
 +
 +
    # Convert transform quaternion rotations to euler angles (in radians)
 +
    from_rotation = from_transform.R().ToRotationMatrix().ToEulerAngle(RLPy.EEulerOrder_XYZ, x, y, z)
 +
    to_rotation = to_transform.R().ToRotationMatrix().ToEulerAngle(RLPy.EEulerOrder_XYZ, x, y, z)
 +
 +
    # Lerp between the start and end eular angle values
 +
    euler_rotation = RLPy.RVector3(
 +
        (1 - point) * from_rotation[0] + point * to_rotation[0],
 +
        (1 - point) * from_rotation[1] + point * to_rotation[1],
 +
        (1 - point) * from_rotation[2] + point * to_rotation[2]
 +
    )
 +
 +
    # Convert the final euler roation back to a rotation matrix3 (3x3 matrix)
 +
    matrix_rotation = RLPy.RMatrix3().FromEulerAngle(RLPy.EEulerOrder_XYZ, euler_rotation.x, euler_rotation.y, euler_rotation.z)
 +
 +
    # Return an interpolated transform matrix4 (4x4 matrix)
 +
    # The transform entry order is: Scale (Vector3), Rotation (Quaternion), Translation (Vector3)
 +
    return RLPy.RTransform(
 +
        RLPy.RVector3(
 +
            (1 - point) * from_transform.S().x + point * to_transform.S().x,
 +
            (1 - point) * from_transform.S().y + point * to_transform.S().y,
 +
            (1 - point) * from_transform.S().z + point * to_transform.S().z
 +
        ),
 +
        RLPy.RQuaternion().FromRotationMatrix(matrix_rotation[0]),  # Convert matrix3 rotation back to quaternion
 +
        RLPy.RVector3(
 +
            (1 - point) * from_transform.T().x + point * to_transform.T().x,
 +
            (1 - point) * from_transform.T().y + point * to_transform.T().y,
 +
            (1 - point) * from_transform.T().z + point * to_transform.T().z
 +
        )
 +
    )
 +
</syntaxhighlight>
 +
 +
The returned transformation matrix can be applied by setting the value for the '''Transform''' control of a prop:
 +
 +
<syntaxhighlight lang="python">
 +
box = RLPy.RScene.FindObject(RLPy.EObjectType_Prop, "Box")
 +
box.GetControl("Transform").SetValue(RLPy.RGlobal.GetTime(), transform)
 
</syntaxhighlight>
 
</syntaxhighlight>

Latest revision as of 04:03, 18 February 2020

Main article: RL Python Samples.

This article will go some recipes for common 3D transformational math. You'll find this helpful if you need to perform spacial calculations.

Transform Point

Transforms position of a point from local-space to world-space. The returned position is affected by scale.

def transform_point(world_transform, local_position):
    # Get the transform matrix4
    world_matrix = world_transform.Matrix()

    # New matrix4 for the local position
    point_world_matrix = RLPy.RMatrix4()
    point_world_matrix.MakeIdentity()
    point_world_matrix.SetTranslate(local_position)

    # Combine the 2 matrix4s
    point_world_matrix = point_world_matrix * world_matrix

    # Return the translation element of the combined matrix4
    return RLPy.RVector3(point_world_matrix.GetTranslate())

Transform Point with Specific Rotation

In order to assign a specific rotation, use the following instead:

def transform_point(world_transform, specific_rotation, local_position):
    # Get the transform matrix4
    world_matrix = world_transform.Matrix()
    world_matrix.SetSR(specific_rotation)

    # New matrix4 for the local position
    point_world_matrix = RLPy.RMatrix4()
    point_world_matrix.MakeIdentity()
    point_world_matrix.SetTranslate(local_position)

    # Combine the 2 matrix4
    point_world_matrix = point_world_matrix * world_matrix

    # Return the translation element of the combined matrix4
    return RLPy.RVector3(point_world_matrix.GetTranslate())

Inverse Transform Point

Transforms a position point from world-space to local-space. This function is the opposite of Transform Point, which is used to convert local to world-space.

def inverse_transform_point(world_transform, world_point):
    transform_matrix = world_transform.Matrix()
    local_position = world_point - transform_matrix.GetTranslate()  # Can also use transform.T()
    transform_matrix.SetTranslate(RLPy.RVector3.ZERO)  # Zero out transform matrix translation

    # New matrix4 for the local position
    point_world_matrix = RLPy.RMatrix4()
    point_world_matrix.MakeIdentity()
    point_world_matrix.SetTranslate(local_position)

    # Convert local space to transform space
    point_transform_matrix = point_world_matrix * transform_matrix.Inverse()

    # Return the translation element of the combined matrix4
    return point_transform_matrix.GetTranslate()

Transform Direction

Transforms direction of a vector from local-space to world-space. The returned vector has the same length as the direction.

def transform_direction(world_transform, local_position):
    # Get the transform rotation 3x3 matrix
    world_rot_matrix = world_transform.Rotate()

    # New matrix4 for world direction
    world_dir = RLPy.RMatrix4()
    world_dir.MakeIdentity()
    world_dir.SetSR(world_rot_matrix)

    # New matrix for the local position
    point_world_matrix = RLPy.RMatrix4()
    point_world_matrix.MakeIdentity()
    point_world_matrix.SetTranslate(local_position)

    # Combine the 2 matrix4
    point_world_matrix = point_world_matrix * world_dir

    # Return the translation element of the combined matrix4
    return RLPy.RVector3(point_world_matrix.GetTranslate())

Transform Lerp

Lerps between two transformational matrices given a point between 0 and 1.

def transform_lerp(from_transform, to_transform, point):
    x = y = z = 0

    # Convert transform quaternion rotations to euler angles (in radians)
    from_rotation = from_transform.R().ToRotationMatrix().ToEulerAngle(RLPy.EEulerOrder_XYZ, x, y, z)
    to_rotation = to_transform.R().ToRotationMatrix().ToEulerAngle(RLPy.EEulerOrder_XYZ, x, y, z)

    # Lerp between the start and end eular angle values
    euler_rotation = RLPy.RVector3(
        (1 - point) * from_rotation[0] + point * to_rotation[0],
        (1 - point) * from_rotation[1] + point * to_rotation[1],
        (1 - point) * from_rotation[2] + point * to_rotation[2]
    )

    # Convert the final euler roation back to a rotation matrix3 (3x3 matrix)
    matrix_rotation = RLPy.RMatrix3().FromEulerAngle(RLPy.EEulerOrder_XYZ, euler_rotation.x, euler_rotation.y, euler_rotation.z)

    # Return an interpolated transform matrix4 (4x4 matrix)
    # The transform entry order is: Scale (Vector3), Rotation (Quaternion), Translation (Vector3)
    return RLPy.RTransform(
        RLPy.RVector3(
            (1 - point) * from_transform.S().x + point * to_transform.S().x,
            (1 - point) * from_transform.S().y + point * to_transform.S().y,
            (1 - point) * from_transform.S().z + point * to_transform.S().z
        ),
        RLPy.RQuaternion().FromRotationMatrix(matrix_rotation[0]),  # Convert matrix3 rotation back to quaternion
        RLPy.RVector3(
            (1 - point) * from_transform.T().x + point * to_transform.T().x,
            (1 - point) * from_transform.T().y + point * to_transform.T().y,
            (1 - point) * from_transform.T().z + point * to_transform.T().z
        )
    )

The returned transformation matrix can be applied by setting the value for the Transform control of a prop:

box = RLPy.RScene.FindObject(RLPy.EObjectType_Prop, "Box")
box.GetControl("Transform").SetValue(RLPy.RGlobal.GetTime(), transform)