0
$\begingroup$

I'd like to use knowuh's script on converting an image to voxels. there's the script: https://gist.github.com/knowuh/48136d7a17387e7cf6c3

I have tried to run it, but the file I loaded into the UV editor and saved on my desktop cannot be found. I'll always get this error:

File "\Text", line 46, in <module>
File "\Text", line 43, in cubify
File "\Text", line 23, in draw_pix
File "\Text", line 17, in make_material KeyError:
'bpy_prop_collection[key]: key "Diffuse BSDF" not found'

So, is this a problem by blender 2.92 handling things differently then 7 years ago when the script is written or? what does the key error mean, blenders api descriptions is too cryptic for me to understand properly

$\endgroup$
3
  • 1
    $\begingroup$ Hi and welcome. Please use the edit link at the bottom of your question to add more details. Comments aren't indexed in search engines, and we just use comments for suggestions, light discussion, and requests for clarification. $\endgroup$ Commented Apr 14, 2021 at 21:26
  • $\begingroup$ Also any edits made will bump this back into active questions. $\endgroup$ Commented Apr 14, 2021 at 21:26
  • $\begingroup$ Hi, sry for any mistakes I made. This is my first post ever in any forums. $\endgroup$
    – Monti
    Commented Apr 15, 2021 at 9:18

1 Answer 1

2
$\begingroup$

What does it do?

In 2.92 If you add a new material and select "use nodes" you are presented with two nodes, neither of which has name "Diffuse BSDF" ... so one imagines that this was the case back when the script was written.

The Python console.

The expectation isn't that you will be a python wizard overnight. The beauty of python is it doesn't need to be compiled, hence can take lines of code and run them in the console and see what happens.

When assigning a variable like, below, no feedback is good news, it worked.

>>> color = D.materials.new("Color")
>>> color.use_nodes = True

Can test in UI to see that there is a new material named "Color" or "Color.001" if run again.. etc etc and it is to use nodes...

Next line, uh oh have seen this before.

blenders api descriptions is too cryptic for me to understand properly

>>> Diffuse_BSDF = color.node_tree.nodes['Diffuse BSDF']
Traceback (most recent call last):
  File "<blender_console>", line 1, in <module>
KeyError: 'bpy_prop_collection[key]: key "Diffuse BSDF" not found'

Or in lay-mans terms there is no node named "Diffuse BSDF", if only cryptic crosswords were as simple.

Let's see what nodes this newly created material does have, hmmm they look familiar.

>>> color.node_tree.nodes.keys()
['Principled BSDF', 'Material Output']

Can be sure that if a new material is added, use nodes it has these two nodes, in same order.

Ok then lets have a go at making the make_material function work, paste this in text editor and run script..

import bpy


def make_material(color):
    alpha = 1.0
    red, green, blue, alpha = color
    color_name = '%(red)03d_%(green)03d_%(blue)03d' % {"red": red, "green": green, "blue": blue}
    color = bpy.data.materials.new(color_name)
    color.use_nodes = True
    bsdf, output = color.node_tree.nodes
    bsdf.inputs[0].default_value = [red, green, blue, alpha]
    return color

make_material((1, 0, 0, 1))

And there it is

enter image description here

IMO a little confusing passing a color list, then making a material with same variable name, so let's refine this further, by instead calling the new material mat

import bpy


def make_material(color):
    red, green, blue, alpha = color
    color_name = '%(red)03d_%(green)03d_%(blue)03d' % {"red": red, "green": green, "blue": blue}
    mat = bpy.data.materials.new(color_name)
    mat.use_nodes = True
    bsdf, output = mat.node_tree.nodes
    bsdf.inputs[0].default_value = color
    return mat

make_material((1, 0, 0, 1))

_Note: haven't tested to see if any other changes are needed, or amended to instead use a "Diffuse BSDF" node.+

Optimizing.

The script is going to be sloooooooooooooooooooow.

Object creation slows over time

Python performance with Blender operators

As it is to create each cube for an image on M x N pixels the script is calling 2 x M x N operators.

Instead Create one object and duplicate it. Even if this lone object is created with operator, it will be one call. Can be done with none. Consider even using the array mnodifier to very quickly make N x M grid of cubes then separate

How can I create many objects quickly?

Copying an object with python without actually creating a new object

Use numpy to read the image pixels. See Read pixel color with foreach_get() on image data (looping is one almost always a rate determining step.)

Make one material. Randomly coloring with script doesn't work correctly which if used in conjunction with this would mean making one material, and assigning pixel color to material color of the voxel.

Vertex colors. Another option is to have no materials and set vertex colors to pixel color.

You can export it from blender as an FBX and then import to Unity. Unity will create a materials file from the vertex colors you don't need to do anything special.

How to get random color variation on a single mesh?

(Suggest array method here to create object NxM array of cubes, apply array, use the order to set the vertex colors en masse with numpy, separate into multiple objects.)

Making these changes will see huge improvement in speed gain.

$\endgroup$
5
  • $\begingroup$ Thanks a lot mate, the script is running and burning my cpu. You even described your solution's path, thumbs up :) $\endgroup$
    – Monti
    Commented Apr 15, 2021 at 14:42
  • $\begingroup$ is there a way to run the script faster? I know it's a hell lot of calculation, but... $\endgroup$
    – Monti
    Commented Apr 15, 2021 at 23:22
  • $\begingroup$ With only one material I'd loose the difference in color. Creating multiple colored voxels from a source or reference image is the key aspect of my program. Otherwise I'd just create blank voxels in untiy and recolour them there. @batFINGER $\endgroup$
    – Monti
    Commented May 12, 2021 at 11:22
  • $\begingroup$ Not sure if object color is exported to unity, can certainly export as a vertex color. As with object color only require one material to display vertex color. $\endgroup$
    – batFINGER
    Commented May 12, 2021 at 15:25
  • $\begingroup$ with the exported file .fbx I get every cube with its unique color as a material $\endgroup$
    – Monti
    Commented May 20, 2021 at 9:21

You must log in to answer this question.

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