Example #1
0
def fix_cube_rotation(obj: bpy.types.Object):
    '''
    Rotate the bounding box of a cuboid so  it's aligned with
    the cube rotation. The scale and rotation of the object must
    be in default position for this function to work.

    :param obj: blender object with cuboid mesh.
    '''
    # Get coordinates of 3 points (a,b and c) from any polygon
    # I'm assuming this is a cuboid so I also can assume that
    # vectors u and v are not planar:
    # u = vector(b, a) and v = (b, c)
    poly = obj.data.polygons[0]

    vertices = obj.data.vertices
    a = vertices[poly.vertices[0]].co
    b = vertices[poly.vertices[1]].co
    c = vertices[poly.vertices[2]].co

    # Calculate the normal vector of the surface with points
    # a, b and c
    u: mathutils.Vector = (a-b).normalized()
    v: mathutils.Vector = (c-b).normalized()

    # The cross product creates the 3rd vector that defines
    # the rotated space
    w = u.cross(v).normalized()
    # Recalculate V to make sure that all of the vectors are at
    # the right angle (even though they should be)
    v = w.cross(u).normalized()

    # Create rotation matrix (unit vectors x, y, z in columns)
    rotation_matrix = mathutils.Matrix((w, v, -u))
    # (w, v, -u) - this order of normals in rotation matrix is set up in
    # such way that applying the operator to the default cube (without
    # rotations) will not change its rotation and won't flip its scale to -1.
    # It will have no effect.


    # Rotate the mesh
    for vertex in obj.data.vertices:
        vertex.co = rotation_matrix @ vertex.co

    # Counter rotate object around its origin
    counter_rotation = rotation_matrix.to_4x4().inverted()

    loc, rot, scl = obj.matrix_local.decompose()
    loc_mat = mathutils.Matrix.Translation(loc)
    rot_mat = rot.to_matrix().to_4x4()
    scl_mat =  (
        mathutils.Matrix.Scale(scl[0],4,(1,0,0)) @
        mathutils.Matrix.Scale(scl[1],4,(0,1,0)) @
        mathutils.Matrix.Scale(scl[2],4,(0,0,1)))

    obj.matrix_local = loc_mat @ counter_rotation @ rot_mat @ scl_mat
Example #2
0
def apply_obj_transform_keep_origin(obj: bpy.types.Object):
    '''
    Apply object transformations but keep the origin in place. Resets object
    rotation and scale but keeps location the same.
    '''
    # Decompose object transformations
    loc, rot, scl = obj.matrix_local.decompose()
    loc_mat = mathutils.Matrix.Translation(loc)
    rot_mat = rot.to_matrix().to_4x4()
    scl_mat =  (
        mathutils.Matrix.Scale(scl[0],4,(1,0,0)) @
        mathutils.Matrix.Scale(scl[1],4,(0,1,0)) @
        mathutils.Matrix.Scale(scl[2],4,(0,0,1)))
    obj.matrix_local = loc_mat

    for vertex in obj.data.vertices:
        vertex.co =  rot_mat @ scl_mat @ vertex.co