4
$\begingroup$

Background: Hello, I'm a researcher looking into the supply chain. A few years ago I was creating a static visualisation of vessels across the globe. I discovered Blender and using several tutorials was able to create a realistic map and using Python place glowing/emissive rods on the map. However, I needed more data and therefore left the project till now.

However, in that time things have changed in Blender and my script no longer work (not even on old versions).

Task: I'd like to run a For Loop, which parses through a preprepared csv file (I have this) and then creates a rod at many specific locations and then later applies colour and emissive properties to that particular rod (not necessarily in that order).

Current situation: When this was working, I was able to perform tasks in Blender (manually) and then copy the Python code for those steps from the console (this is still the case, but it's not working for me). As I recall, I had to add a step by giving each rod a "name", so that it could be assigned a material property (emissiveness and colour).

My old code (for the previous Blender version) looked like this:

import bpy, csv, random, os
fp = _file_path1_
cp = _file_path2_

with open( cp ) as csvfile:
    rdr = csv.reader(csvfile, delimiter=';')
    for i, row in enumerate( rdr):
        if i == 0: continue # Skip column title
        material = bpy.data.materials.new(name=str(row[0]))
        material.use_nodes = True
        material.node_tree.nodes.remove(material.node_tree.nodes.get('Diffuse BSDF'))
        material_output = material.node_tree.nodes.get('Material Output')
        emission = material.node_tree.nodes.new('ShaderNodeEmission')
        emission.inputs['Strength'].default_value = 15.0
        emission.inputs['Color'].default_value = (float(row[1]), float(row[2]), float(row[3]), float(1.0))
        material.node_tree.links.new(material_output.inputs[0], emission.outputs[0])

rands_list = random.sample(range(35000), 2000)

with open( fp ) as csvfile:
    rdr = csv.reader(csvfile, delimiter=';')
    for i, row in enumerate( rdr ):
        # if i >= 30000 and i < 30050:
        if i in rands_list:
            # Add spheres
            bpy.ops.mesh.primitive_cylinder_add(
                        vertices=5,
                        radius= 0.005, 
                        location = (float(row[1]), float(row[2]), float(0.045)),
                        depth = 0.01
                        )
            bpy.context.object.active_material = bpy.data.materials[str(row[0])]

I'm a bit discouraged now. So would really appreciate help with this task.

$\endgroup$
3
  • $\begingroup$ Hello, could you elaborate on what exactly is the error when running the script ? You can see it by going window > toggle system console $\endgroup$
    – Gorgious
    Jun 24 at 8:50
  • $\begingroup$ can you provide a small csv file, so we can check it out? $\endgroup$
    – Chris
    Jun 24 at 11:11
  • $\begingroup$ Consider adding print statements as a debug option. A quick look at this shows a 2000 integers chosen randomly from 0..34999 and relies on a number in range of length of input file to be in it. Could be the script is adding materials and materials on each run but never a cylinder. $\endgroup$
    – batFINGER
    Jun 24 at 15:33
1
$\begingroup$

This codes now worked on my computer, but since you didn't provide your csv ...i had to make my own. Of course the csv must also be correct so that the code works. I wrote in comments after the code where i had to change things.

import bpy, csv, random, os

fp = # must be right path here
cp = # must be right path here

with open( cp ) as csvfile:
    rdr = csv.reader(csvfile, delimiter=';')
    for i, row in enumerate( rdr):
    #        if i == 0: continue # Skip column title -> i had no title...
        material = bpy.data.materials.new(name=str(row[0]))
        print ("new material:", material.name)
        material.use_nodes = True
        material.node_tree.nodes.remove(material.node_tree.nodes.get('Principled BSDF')) # changed to Principled -> this is not necessary because if you create an object via python it has no default material -> looks like this is left "garbage" from older code...
        material_output = material.node_tree.nodes.get('Material Output')
        emission = material.node_tree.nodes.new('ShaderNodeEmission')
        print("new shader node", emission)
        emission.inputs['Strength'].default_value = 15.0
        emission.inputs['Color'].default_value = (float(row[1]), float(row[2]), float(row[3]), float(1.0))
        material.node_tree.links.new(material_output.inputs[0], emission.outputs[0])

rands_list = random.sample(range(35000), 2000)

with open( fp ) as csvfile:
    print("fp case", "*"*100)
    rdr = csv.reader(csvfile, delimiter=';')
    for i, row in enumerate( rdr ):
        print (i, row, "#"*30)
        # if i >= 30000 and i < 30050:
   #     if i in rands_list: # commented this out because sometimes this code wasn't called at all here ...
            # Add spheres
        bpy.ops.mesh.primitive_cylinder_add(
                    vertices=5,
                    radius= 20, # change, so that i "saw" something 
                    location = (float(row[1]), float(row[2]), float(0.045)),
                    depth = 0.01
                    )
        print("cylinder created")
        bpy.context.object.active_material = bpy.data.materials[str(row[0])]
        
       

result with "my" csv data:

enter image description here

but honestly: if you don't provide csv next time...i will downvote your question....

$\endgroup$
2
  • $\begingroup$ Appologies for not including a csv file. $\endgroup$
    – Tanxs
    Jun 28 at 13:55
  • $\begingroup$ It's ok. Just make it better next time, then i am happy! ;) $\endgroup$
    – Chris
    Jun 28 at 13:56

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.