5
$\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$
  • 1
    $\begingroup$ any chance you could link to a script that also generates X, Y, Z so It can be tested? $\endgroup$ – zeffii Aug 9 '15 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 Aug 9 '15 at 12:28
  • 2
    $\begingroup$ Use tolist? $\endgroup$ – pink vertex Aug 9 '15 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 Aug 9 '15 at 13:04
  • $\begingroup$ Additional background info on NumPy int types in Python Stack Overflow here $\endgroup$ – uhoh Aug 10 '15 at 1:08
3
$\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$
  • $\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 Aug 9 '15 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 Aug 9 '15 at 12:57
  • 1
    $\begingroup$ yes - lists or iterable types, except generators. $\endgroup$ – zeffii Aug 9 '15 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 Aug 9 '15 at 13:11
  • $\begingroup$ ...added slant_factor to script, looks nicer. $\endgroup$ – uhoh Aug 9 '15 at 14:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.