1
$\begingroup$

I have a xyz file containing coordinates of spheres. My goal is to draw something like Figure 2.2 in this link: http://www.fgarciasanchez.es/thesisrocio/node21.html

On this forum I found a script that it can be used for that (Object made of large number of spheres). See below.

What I want to do now is to modify the code in order to:

  • remove any material (i prefer to assign the material manually)
  • replace the "data" matrix with an external file which contains only the xyz coordinates and no info about the material and the radius of the sphere (since they will all be the same). The file can be either a .txt, .csv or .xyz. It will contain 3 columns (x, y, z coordinates) and each row represent a sphere.

Is there an easy way to do so? Thanks!

Blockquote

import bpy
import bmesh
import mathutils

# create the materials used
# simple BI materials used
MatAu = bpy.data.materials.new('Mat.Au')
MatAu.diffuse_color = (0.8,0.7,0.2,1.0)
MatC  = bpy.data.materials.new('Mat.C')
MatC.diffuse_color = (0.1,0.1,0.1,1.0)
MatH  = bpy.data.materials.new('Mat.H')
MatH.diffuse_color = (0.8,0.7,0.2,1.0)

# create an empty mesh object and add it to the scene
sphereMesh = bpy.data.meshes.new('AllSpheres')
sphereObj  = bpy.data.objects.new('AllSpheres', sphereMesh)
bpy.context.collection.objects.link(sphereObj)
bpy.context.view_layer.objects.active = sphereObj

# create slots for each material then add each material to the object
while len(sphereObj.material_slots) < 3:
    bpy.ops.object.material_slot_add()
sphereObj.material_slots[0].material = MatAu
sphereObj.material_slots[1].material = MatC
sphereObj.material_slots[2].material = MatH

# test data to be swapped for data in file
# type, location, scale
data = [('C', (1.0, 1.0, 1.0), 0.2),
        ('H', (2.0, 2.0, 2.0), 0.4),
        ('Au',(3.0, 3.0, 3.0), 0.8),
        ('C', (4.0, 4.0, 4.0), 1.2),
        ('H', (5.0, 5.0, 5.0), 0.2),
        ('Au',(6.0, 6.0, 6.0), 0.8),
        ('C', (7.0, 7.0, 7.0), 0.4),
        ('H', (8.0, 8.0, 8.0), 0.8),
        ('Au',(9.0, 9.0, 9.0), 1.2),
]

bm = bmesh.new()
for i in data:
    locMatrix = mathutils.Matrix.Translation(i[1])
    scaleMatrix = mathutils.Matrix.Scale(i[2], 4)
    mesh = bmesh.ops.create_uvsphere(bm, u_segments=8, v_segments=8,
                    diameter=1.0, matrix=locMatrix @ scaleMatrix)
    for v in mesh['verts']:
        for f in v.link_faces:
            if i[0] == 'Au':
                f.material_index = 0 # material_index matches material_slots[x]
            elif i[0] == 'C':
                f.material_index = 1
            elif i[0] == 'H':
                f.material_index = 2

bm.to_mesh(sphereMesh)
bm.free()
$\endgroup$

Your Answer

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

Browse other questions tagged or ask your own question.