1
$\begingroup$

I'm trying to create one object from scratch using numpy (in the example, in order to make it very simple, only two vertices and one edge).

The code below works (Hurray!) but ... Could anyone give me some advice on how to approach the problem.

Is there a shorter version, or more efficient way to create object from a numpy array ?

Thank you !

import bpy
import numpy as np

# Vertices and edges (straightforward)
vertices = np.array([
        0, 0, 0,
        1, 1, 1
    ], dtype=np.float32)

edges = np.array([
        0, 1
    ], dtype=np.int32)

# vertices and edges number (general way)

num_vertices = vertices.shape[0] // 3
num_edges = edges.shape[0] // 2

# Create mesh object based on the arrays above

mesh = bpy.data.meshes.new(name='mesh')
mesh.vertices.add(num_vertices)
mesh.vertices.foreach_set("co", vertices)

mesh.edges.add(num_edges)
mesh.edges.foreach_set("vertices", edges)
    
# update mesh object 

mesh.update()
mesh.validate()

# create object

obj = bpy.data.objects.new('created object', mesh)

# Add obj to the scene
scene = bpy.context.scene
scene.collection.objects.link(obj)

# Select the new object and make it active
bpy.ops.object.select_all(action='DESELECT')
obj.select_set(True)
bpy.context.view_layer.objects.active = obj
$\endgroup$

1 Answer 1

1
$\begingroup$

yes there is ! I've finally find a way to build all parts (even faces) with from_pydata! more details here

# Vertices and edges (straightforward)
vertices = np.array([
        [0, 0, 0],
        [1, 1, 1],
        [1, 0, 0]
    ], dtype=np.float32)

# edges are built when faces are generated
# but it is possible to directly implement edges
# edges = np.array([[0, 1]], dtype=np.int32)
edges = []
faces = [[0,1,2]]

# build mesh data, object and do some check-up

mesh_data = bpy.data.meshes.new("my_object_data")
mesh_data.from_pydata(vertices, edges, faces)
mesh_data.update()
mesh_data.validate()      

obj = bpy.data.objects.new("my_object", mesh_data)

# add the object to the scene      
scene = bpy.context.scene
scene.collection.objects.link(obj)

# activate the object
obj.select_set(True)
bpy.context.view_layer.objects.active = obj 
$\endgroup$

You must log in to answer this question.

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