3

The cube is composed of 1 million voxels (100x100x100) having the same size (1 unit). Voxel information is saved in this .txt file having the format: (4 columns x 1 million lines).

The first 3 columns represent x, y, z of each voxel, while the 4th column has the values: {0, 1, 2, 7, 8, 9, 10, 12, 13, 16, 17}. Each number represents a color in the model (eg: {black, yellow, green, blue, cyan, lawngreen, pink, magenta, white, gray, orange})

Because of the high number of voxels, I tried to pass by creating instances by adapting a code that I found here. the script worked for representing all voxels as instances. However, I'm unable to find a solution to color each voxel based on data in the 4th column within the voxels file.

I tried to use instancing and arrays by geometry nodes but it is still challenging for me as it's just my 2nd application using Blender.

Here is the script representing the voxels:

import bpy
import numpy as np
import mathutils as mt

bpy.ops.object.select_all(action="SELECT") bpy.ops.object.delete()

C = bpy.context

#open text file rawfile = open("/Users/test/Documents/voxels.txt","r") data=np.loadtxt( rawfile, delimiter=' ' ) rawfile.close()

#Create and arrange mesh data verts = [ mt.Vector( data[i,:3] ) for i in range(data.shape[0]) ] m = bpy.data.meshes.new('pc') m.from_pydata(verts, [], [])

Create mesh object and link to scene collection

o = bpy.data.objects.new('pc', m) C.scene.collection.objects.link( o )

#Add primitive cube

bpy.ops.mesh.primitive_cube_add( size = 1) isobj = bpy.data.objects[C.object.name]

Set instancing props

for ob in [ isobj, o]: ob.instance_type = 'VERTS' ob.show_instancer_for_viewport = True ob.show_instancer_for_render = True

Set instance parenting (parent cube to verts)

o.select_set(True) C.view_layer.objects.active = o

bpy.ops.object.parent_set( type = 'VERTEX', keep_transform = True )

voxel file

Blender result

Harry McKenzie
  • 10,995
  • 8
  • 23
  • 51

1 Answers1

2

I'm unsure about storing colors for individual instances. But latest blender comes with point cloud feature for cycles, so you can try that way also.

Here the script create vertices and stores color attribute. The vertices are then converted to point cloud using geometry nodes.

import bpy
import numpy as np
import mathutils as mt

bpy.ops.object.select_all(action="SELECT") bpy.ops.object.delete()

C = bpy.context

#open text file rawfile = open("/home/hari/Desktop/voxels.txt","r") data=np.loadtxt( rawfile, delimiter=' ' ) rawfile.close()

color dict

colordict = {0:[0.000000, 0.000000, 0.000000, 1.000000], 1:[1.000000, 1.000000, 0.000000, 1.000000], 2:[0.000000, 1.000000, 0.000000, 1.000000], 7:[0.000000, 0.000000, 1.000000, 1.000000], 8:[0.000000, 0.750000, 1.000000, 1.000000], 9:[0.929871, 0.302988, 0.571237, 1.000000], 10:[1.000000, 0.527115, 0.597202, 1.000000], 12:[1.000000, 0.000000, 1.000000, 1.000000], 13:[1.000000, 1.000000, 1.000000, 1.000000], 16:[0.500000, 0.500000, 0.500000, 1.000000], 17:[1.000000, 0.250000, 0.000000, 1.000000]}

#Create and arrange mesh data verts = [ mt.Vector( data[i,:3] ) for i in range(data.shape[0]) ]

create voxel object

obj_name = "Voxels" mesh_data = bpy.data.meshes.new(obj_name + "_data") obj = bpy.data.objects.new(obj_name, mesh_data) bpy.context.scene.collection.objects.link(obj) mesh_data.from_pydata(verts, [], [])

store color attribute

colors = np.array([colordict.get(i,[0,0,0,1]) for i in data[:,-1]]).ravel()
obj.data.attributes.new(name='col', type='FLOAT_COLOR', domain='POINT') obj.data.attributes['col'].data.foreach_set('color', colors)

enter image description here

Instancing cubes on points enter image description here

Harisreedhar
  • 3,054
  • 7
  • 11