0

I trying to dynamically create meshes using the python API and it seems that coordinates are relative to the cursor location instead of the global zero point?

Is this correct? And if so, is there a way to make blender do it relative to (0, 0, 0)

Code:

_mesh1 = bpy.data.meshes.new(name='testing_mesh1')

vertices1 = [Vector((a, b, c)) ...] edges1 = [(0, 1) ...]

_mesh1.from_pydata(vertices1, edges1, [])

bpy_extras.object_utils.object_data_add(context, _mesh1)

batFINGER
  • 84,216
  • 10
  • 108
  • 233
jed-blip
  • 1
  • 1
  • Please add code to clarify how you are adding objects. If using operators, yes the default setting is to add at scene.cursor location. If location argument is set it is relative to global origin. – batFINGER Mar 22 '21 at 16:45
  • I have added the code that I use – jed-blip Mar 22 '21 at 16:51

1 Answers1

2

Simple test in python console

Run a simple test. Put the cursor at some known scene location, and add an object using the bpy_extras.object_utils.object_data_add method. (Simply pinched a mesh from the active object cube)

>>> C.object
bpy.data.objects['Cube']

>>> me = C.object.data >>> C.scene.cursor.location = (10, 10, 10) >>> import bpy_extras >>> ob = bpy_extras.object_utils.object_data_add(C, me)

>>> ob.location Vector((10.0, 10.0, 10.0))

Hence without any operator passed, uses the scene cursor. btw the python source is readily available, and could check thru scripts/modules/bpy_extras/object_utils.py to confirm

To make it zero location, rotation and unit scale

>>> ob.matrix_world = Matrix()
>>> ob.location
Vector((0.0, 0.0, 0.0))

Check the docstring

For a quick run down check the docstring in the python console

>>> bpy_extras.object_utils.object_data_add(
object_data_add(context, obdata, operator=None, name=None)
Add an object using the view context and preference to initialize the
location, rotation and layer.
:arg context: The context to use.
:type context: :class:`bpy.types.Context`
:arg obdata: the data used for the new object.
:type obdata: valid object data type or None.
:arg operator: The operator, checked for location and rotation properties.
:type operator: :class:`bpy.types.Operator`
:arg name: Optional name
:type name: string
:return: the newly created object in the scene.
:rtype: :class:`bpy.types.Object`

Use in conjunction with an operator

is designed to be used in conjunction with an add object operator in which case transform settings are taken from the instance of the operator. Often also used with AddObjectHelper class, as demonstrated in Text Editor > Python > Templates > Add Object and in this example https://blender.stackexchange.com/a/160995

Using a decorator

An example of wrapping a decorator around the imported method to set the new object created to a transform of our choosing.

import bpy
from bpy_extras.object_utils import object_data_add
from mathutils import Matrix

def location_decorator(matrix=Matrix()): def decorator(f): def g(args, kwargs): ob = f(args, **kwargs) ob.matrix_world = matrix return ob return g return decorator

object_data_add = location_decorator()(object_data_add)

me = bpy.data.meshes.new("Foo")

ob = object_data_add(bpy.context, me)

or if using with an operator that has a location property, but we wish to make it default to scene origin (or another transform) when not set then

def location_decorator(matrix=Matrix()):
    def decorator(f):
        def g(*args, **kwargs):
            op = kwargs.get("operator")
        if op and not op.properties.is_property_set("location"):                    
            op.location = matrix.translation
        return f(*args, **kwargs)
    return g 
return decorator

batFINGER
  • 84,216
  • 10
  • 108
  • 233