# Create big mathematical object directly from array data bypassing tolist

I would like to create mathemical objects within blender directly from numpy array data (see a small example below). I was able to implemented verts and edges without converting the array into list as required by from_pydata(verts, edges, faces). I suppose that converting a very large number of coordinates into a list from an array is an ineffective coding bottleneck ...

The problem I encounter is that I don't see how to add the faces. Informations I find on the net opens up an ocean of perplexity... Could someone help me to find the simplest possibility for directly construct the faces starting from an array (as done below for verts and edges) ?

# parameters
start = -40
end = 40
density = (end - start)*2

# x y meshgrid
xx, yy = np.meshgrid(np.linspace(start,end,density), np.linspace(start,end,density))

# z computation
R = np.sqrt(xx**2 + yy**2)
zz = 2*np.sin(R)

# coordinate formating
coords = np.stack((xx, yy, zz), axis=2).ravel()

# mesh creation
mesh = bpy.data.meshes.new(name='my_shape_data')
num_vertices = coords.shape[0] // 3
mesh.vertices.foreach_set("co", coords)

# optionally - adding edges seems possible using this
edges = (np.arange(2*num_vertices)+1)//2
num_edges = edges.shape[0] // 2
mesh.edges.foreach_set("vertices", edges)

# # update mesh and do some checks on it

mesh.update()
mesh.validate()
# object creation
obj = bpy.data.objects.new('my_shape', mesh)
# Add object to the scene
scene = bpy.context.scene
# 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


• Do you have any data on the faces? As in, how is the algorithm supposed to know which vertices belong to which faces? Was the code written by you or by chatGPT? GPT can be very misleading in regards to intent... Commented Jun 25 at 13:56
• @MarkusvonBroady Yes, I will do an array grouping faces data. I think there are several ways to generate this array (a bit like you can calculate the nodes and sides in the script in different ways). The problem is how to inject directly this array in the object 'avoiding' from_pydata (and the to_list method). PS: No, I wrote this script by myself... Is that so bad :-) ! Commented Jun 25 at 14:18
• AFAIK from_pydata is the fastest method available to the API to generate meshes from arbitrary data entry. Under the hood it is very optimized. The question is how to generate optimized vertices and face vertices indices arrays. But I seem to remember you can directly feed numpy arrays into from_pydata ? Commented Jun 25 at 17:58
• @AFAIK "But I seem to remember you can directly feed numpy arrays into from_pydata ?" If this is true I would be really interested to know how to do it! So far I have not found an example that demonstrates this possibility. I've seen several time this way to inject array data # Must call tolist() to pass to from_pydata()! mesh.from_pydata(verts.tolist(),[],faces.tolist())  Commented Jun 26 at 8:03

Finally,

this solution works for me:

import bpy
import numpy as np

# parameters
start = -20
end = 20
densite_x = 80
densite_y = 80
# x y z computation
u, v = (densite_x, densite_y)
x = np.linspace(start, end, u)
y = np.linspace(start, end, v)
xx, yy, zz = np.meshgrid(x, y,0)
R = np.sqrt(xx**2 + yy**2)
zz = 2*np.sin(R)

# matrix shaping
coords = np.dstack((xx,yy,zz))
coords = np.vstack(coords)

# optional renaming

vertices = coords

# faces = np.array([((u)*j+i, (u)*j+i+1, (u)*j+i+u+1, (u)*j+i+u) for j in range(v-1) for i in range(u-1)])
# faces = []

v_i = np.arange(u*v).reshape((v, u))

# Inspiration taken from
# https://stackoverflow.com/a/78696530/25574561
faces = np.array([
v_i[:-1, :-1].flatten(),
v_i[:-1, 1:].flatten(),
v_i[1:, 1:].flatten(),
v_i[1:, :-1].flatten(),
]).T

mesh_data = bpy.data.meshes.new("cube_mesh_data")
mesh_data.from_pydata(vertices, [], faces)
mesh_data.update()

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

scene = bpy.context.scene

Meaning that well formatted there's no problem to from_pydata method to accept directly an array even for faces.