0
$\begingroup$

I need some help with my script. The main task is to move the origin to the position of a certain vertex. In theory this works quite well, but unfortunately the meshes are always moved after i run the script. Since I am a complete beginner in python/scripting in general, I have absolutely no idea where to start to fix this problem.

Before: before:

After running the script after:

On this screenshot I have displayed the meshes before and after the script, the ones after the script are marked. As you can see, the origin is in the desired position, but unfortunately the meshes are no longer there. origin

This is what my humble script currently looks like. I am grateful for any help.

import bpy

def move_origin_to_second_vertex(obj):
    mesh = obj.data
    for face in mesh.polygons:
        second_vertex_index = face.vertices[1]
        obj.location = mesh.vertices[second_vertex_index].co

bpy.ops.object.select_all(action='DESELECT')
bpy.ops.object.select_by_type(type='MESH')

for obj in bpy.context.selected_objects:
    move_origin_to_second_vertex(obj)
$\endgroup$
2
  • $\begingroup$ Not an answer but realize that the first vertex is face.vertices[0] (zero indexed) $\endgroup$
    – james_t
    Commented May 26 at 21:34
  • $\begingroup$ Yes, that's right. It turned out that vertex Id 1 is the correct one, I did not change the name. I have edited it to avoid further confusion. Thanks anyway! :) $\endgroup$
    – Knudsen
    Commented May 26 at 21:38

2 Answers 2

1
$\begingroup$

A bit of a delay, but had to sign off last night...

You would do this similar to how it's done in the 3d editor, which is:

  1. set object as selected
  2. edit:mode select a vertex
  3. move cursor to selected
  4. set origin to cursor

so in python:

import bpy

def move_origin_to_second_vertex(obj):
    # when using interface 'ops' methods, one object needs to be selected at a time
    obj.select_set(True)
    print(obj.name)
    # be sure to have vertex locations in sync with scale    
    bpy.ops.object.transform_apply()
    # move view/scene cursor to first vertex
    bpy.context.scene.cursor.location = obj.data.vertices[1].co
    print( bpy.context.scene.cursor.location )
    bpy.ops.object.origin_set(type='ORIGIN_CURSOR')
    obj.select_set(False)

bpy.ops.object.select_all(action='DESELECT')
bpy.ops.object.select_by_type(type='MESH')
mesh_objs = bpy.context.selected_objects
bpy.ops.object.select_all(action='DESELECT')

for obj in mesh_objs:
    move_origin_to_second_vertex(obj)
$\endgroup$
3
  • $\begingroup$ Thank you very much! Yours works just as I imagine! I'm still at the very beginning and am slowly working my way into the topic. So if you have any tips on the subject, I'm always thankful! $\endgroup$
    – Knudsen
    Commented May 27 at 20:16
  • 1
    $\begingroup$ @Knudsen -- tip#1: avoid calls to bpy.ops.... at all costs! $\endgroup$
    – james_t
    Commented May 27 at 21:10
  • $\begingroup$ thanks for the tip, I wasn't aware of that. $\endgroup$
    – Knudsen
    Commented May 28 at 11:54
1
$\begingroup$

Try this.

How to perform at low level

import bpy
from mathutils import Matrix, Vector

def set_mesh_origin(ob, pos):
    '''Given a mesh object, set its origin to a given position.'''
    # Create a translation matrix from the position
    mat = Matrix.Translation(pos - ob.location)
    # Update the object's location
    ob.location = pos
    # Transform the object's data using the inverse of the translation matrix
    ob.data.transform(mat.inverted())
    ob.data.update()

for obj in bpy.context.selected_objects:
    # Check if the object is a mesh
    if obj.type == 'MESH':
        # Get the local coordinates of vertex 1
        vloc_local = obj.data.vertices[1].co
        # Convert local coordinates to world coordinates
        vloc_world = obj.matrix_world @ vloc_local
        # Set the object's origin to the world coordinates
        set_mesh_origin(obj, vloc_world)

enter image description here

As james_t said, avoiding the use of OPS as much as possible and running the API at a low level provides stability in scripting.

This script is originally a method to move to world coordinates, The application used it as it is in the function. The function is executed after converting the local coordinates of vertex 1 to world coordinates in a FOR loop.

Reference URL

https://blenderartists.org/t/modifying-object-origin-with-python/507305/7?u=makorin

Extra snooping

If you want to make the position of the bottom vertex of an object the origin, you can use the script below.

import bpy
from mathutils import Matrix, Vector

def set_mesh_origin(ob, pos):
    '''Given a mesh object, set its origin to a given position.'''
    # Create a translation matrix from the position
    mat = Matrix.Translation(pos - ob.location)
    # Update the object's location
    ob.location = pos
    # Transform the object's data using the inverse of the translation matrix
    ob.data.transform(mat.inverted())
    ob.data.update()

def get_lowest_z_vertex(obj):
    '''Find the vertex with the lowest Z value in the given object.'''
    lowest_vertex = None
    lowest_z = float('inf') # Initialize to positive infinity
    # Iterate through the vertices to find the lowest Z
    for vertex in obj.data.vertices:
        # Convert local vertex coordinates to world coordinates
        world_coord = obj.matrix_world @ vertex.co
        if world_coord.z < lowest_z:
            lowest_z = world_coord.z
            lowest_vertex = world_coord
    return lowest_vertex

for obj in bpy.context.selected_objects:
    # Check if the object is a mesh
    if obj.type == 'MESH':
        # Find the vertex with the lowest Z value
        lowest_vertex = get_lowest_z_vertex(obj)
        if lowest_vertex:
            # Set the object's origin to the lowest vertex's world coordinates
            set_mesh_origin(obj, lowest_vertex)

enter image description here

Objects do not take rotation into account, so prior apply of rotation is required enter image description here

$\endgroup$
1
  • 1
    $\begingroup$ Thank you very mutch for your detailed explanation! $\endgroup$
    – Knudsen
    Commented May 28 at 11:54

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .