7
$\begingroup$

Last year I discovered here that blender is sensitive to the type of integer used to create faces. Now I want to do this with NumPy and I am at a loss for how to do this. I CAN NOT use the previous answer face = (int(iv1),int(iv2),int(iv3),int(iv4)), since my faces will not have a fixed number of vertices, and the source of integers may be other NumPy methods as well.

Question: how in general can I make my vertex list generated by np.arange or other NumPy integer type arrays the "right kind of int" for me.from_pydata(verts, [], faces)?

(Optional question: Is this sensitivity to the type of integer protective - for example, does it make sure the integers aren't too big or something like that?)

If dtype is not specified:

TypeError: bpy_struct: item.attr = val: expected sequence items of type int, not numpy.int64

If dtype = int:

TypeError: bpy_struct: item.attr = val: expected sequence items of type int, not numpy.int64

If dtype = int8:

TypeError: bpy_struct: item.attr = val: expected sequence items of type int, not numpy.int8

import bpy
import numpy as np

def make_7_seg(hw, hl, gapxy, slant_factor):

    xnom = np.array([-hl, -hl+hw, hl-hw, hl, hl-hw, -hl+hw])
    ynom = np.array([0.0, -hw, -hw, 0.0, hw, hw])
    znom = np.array([0.0, 0.0, 0.0, 0.0, 0.0, 0.0])

    xoffs = (hl+gapxy) * np.array([0, 1, 1, 0, -1, -1, 0])
    yoffs = (hl+gapxy) * np.array([2, 1, -1, -2, -1, 1, 0])
    rots  = 0.5 * np.pi * np.array([0, 1, 1, 0, 1, 1, 0])
    sinrot, cosrot = np.sin(rots), np.cos(rots)

    X = cosrot[:,None]*xnom[None,:] - sinrot[:,None]*ynom[None,:] + xoffs[:,None]
    Y = sinrot[:,None]*xnom[None,:] + cosrot[:,None]*ynom[None,:] + yoffs[:,None]
    Z = np.zeros_like(X, dtype='float')        

    X = X + slant_factor*Y   

    a = np.arange(7*6).reshape(7,6)
    b = np.arange(7*6,dtype='int').reshape(7,6)    # try some stuff
    c = np.arange(7*6,dtype='int8').reshape(7,6)
    d = np.arange(7*6,dtype='int16').reshape(7,6)

    faces = [tuple(thing) for thing in a]

    verts = [tuple(thing) for thing in zip(X.flatten(), Y.flatten(), Z.flatten())]

    me = bpy.data.meshes.new('digit')
    ob = bpy.data.objects.new('digit', me)
    bpy.context.scene.objects.link(ob)
    me.from_pydata(verts, [], faces)

    return ob

digity = make_7_seg(0.5, 2.0, 0.1, 0.15)
#
#  ---A---
# |       |
# F       B
# |       |
#  ---G---
# |       |
# E       C
# |       |
#  ---D---
#
#      A  B  C  D  E  F  G
# "0"  X  X  X  X  X  X  -
# "1"  -  X  X  -  -  -  -
# "2"  X  X  -  X  X  -  X
# "3"  X  X  X  X  -  -  X
# "4"  -  X  X  -  -  X  X
# "5"  X  -  X  X  -  X  X
# "6"  X  -  X  X  X  X  X
# "7"  X  X  X  -  -  -  -
# "8"  X  X  X  X  X  X  X
# "9"  X  X  X  X  -  X  X
$\endgroup$
5
  • 1
    $\begingroup$ any chance you could link to a script that also generates X, Y, Z so It can be tested? $\endgroup$
    – zeffii
    Commented Aug 9, 2015 at 12:18
  • $\begingroup$ I just pasted what I'm using now. Need to go home to recharge batteries, will come back later - thanks! $\endgroup$
    – uhoh
    Commented Aug 9, 2015 at 12:28
  • 2
    $\begingroup$ Use tolist? $\endgroup$ Commented Aug 9, 2015 at 12:34
  • $\begingroup$ Thanks @pinkvertex, I'm still confused why I can not make the right kind of bpy-friendly integers with NumPy directly. $\endgroup$
    – uhoh
    Commented Aug 9, 2015 at 13:04
  • $\begingroup$ Additional background info on NumPy int types in Python Stack Overflow here $\endgroup$
    – uhoh
    Commented Aug 10, 2015 at 1:08

2 Answers 2

5
$\begingroup$

Pretty cool script btw, doing this worked:

faces = [ [int(i) for i in thing] for thing in a]
verts = [ thing for thing in zip(X.flatten(), Y.flatten(), Z.flatten())]

or

faces = np.arange(7*6).reshape(7,6).tolist()
verts = [ thing for thing in zip(X.flatten(), Y.flatten(), Z.flatten())]

But I imagine there's a faster way to cast down to regular python ints from Numpy -- That is however really a Numpy/Python problem and not BPY/Blender. I doubt that in this scenario speed is of the utmost importance.

$\endgroup$
5
  • $\begingroup$ Wow! So you got to see it run in Blender before I did! (I wrote it using Matplotlib first, will have more questions about this thing soon) OK, so I have also learned that I didn't need to tuple() them, lists of lists are OK too. Just saw your 2nd code snippet, eexxxxxcelent! But I don't understand exactly what kind of int BPY is looking for, and why I can't produce it with NumPy, but tolist() does. $\endgroup$
    – uhoh
    Commented Aug 9, 2015 at 12:53
  • 1
    $\begingroup$ yeah, mind you... now numpy is bundled with Blender, it might be a good idea to update the from_pydata or provide a secondary convenience function. Not a crazy request.... $\endgroup$
    – zeffii
    Commented Aug 9, 2015 at 12:57
  • 1
    $\begingroup$ yes - lists or iterable types, except generators. $\endgroup$
    – zeffii
    Commented Aug 9, 2015 at 12:58
  • $\begingroup$ I mean, if I were to ask elsewhere, I wouldn't know how to explain that I want NumPy to make "blender's kind of integers". I wouldn't know how to make such a request either. Assistance welcome. (can't imagine life before NumPy - might have to use a mouse and draw something - shudder) $\endgroup$
    – uhoh
    Commented Aug 9, 2015 at 13:11
  • $\begingroup$ ...added slant_factor to script, looks nicer. $\endgroup$
    – uhoh
    Commented Aug 9, 2015 at 14:37
3
$\begingroup$

Anyone here getting the error “TypeError: incorrect sequence item type: d” or “TypeError: incorrect sequence item type: 1” make sure your numpy array dtype is float32 (see link) https://pastebin.com/sP8ykmDM

$\endgroup$

You must log in to answer this question.

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