1

I attempting to import a regular grid database into a 3D scene for visualization/simulation. The easiest way to do this I believe is to convert the Regular Grid Database into a format (e.g., wavefront .obj) that can be imported into Blender for example. The Regular Grid Data base has the following format: first line has three integers for example 3072 3072 10 The first line has three integers, denoting the dimensions of the grid. In the example above, the grid is 3072 x 3072 x 10 boxes. Assume 1 meter voxel cubes

The reminder of the file has six columns

3072 3072 10
1437    1437    1   500 314.781433  4.82E-05
1437    1438    1   500 314.781433  4.82E-05
1437    1439    1   500 314.781433  4.82E-05
1437    1440    1   500 314.781433  4.82E-05
1437    1441    1   500 314.781433  4.82E-05
1437    1442    1   500 314.781433  4.82E-05
1437    1443    1   500 314.781433  4.82E-05
1437    1444    1   500 314.781433  4.82E-05 ....

where The remainder of the file consists of lines with six columns of data. The first three columns indicate the voxel index (counting from 0). The fourth column indicates a material ID corresponding to an entry in a separate Material Database file (.mat). The fifth column indicates temperature in Kelvin. The final column indicates concentration in parts per million (ppm).

To simplify the problem lets assume that we have a single material (material ID 500). If I can get this into a .obj file format then I can write a code to update other materials.

Does anyone know of a way to do this other than by brute force? I can do it by brute force by generating a 3D grid then stepping through the regular grid file and checking to see if it is populated with a material property or not but this still does not solve the problem of getting it into a wavefront .obj file format. I grateful for your counsel here.

Sambler offered some code to generate the grid in Blender directly. I was unable to get this to run in blender so I have modified it. This code runs in blender and produces outputs to the console. However I have not been successful in getting it to produce a visible grid in Blender. Any help would be appreciated.

import bpy, bmesh
import csv
import os
import glob
import pdb; pdb.set_trace()
from pdb import set_trace as bp
from bpy import context
import csv
import os
import glob
import pdb; pdb.set_trace()
from pdb import set_trace as bp

scale_fac = 0.1
bm = bmesh.new()

filename = 'data.csv'

directory = r'c:\\test\\'
fullpath = os.path.join(directory, filename)
d=[]
with open(fullpath, 'r', newline='') as csvfile:
    data = csv.reader(csvfile, delimiter=' ', quoting=csv.QUOTE_NONE)
    count=0
    for d in data:
        #bp()
        for elements in d:
            parts=elements.split(',')
            if count==0:
                grid_x = int(parts[0].strip(""))
                print(grid_x)
                grid_y = int(parts[1])
                print(grid_y)
                grid_z = int(parts[2])
                print(grid_z)
                count+=1
                #print(count)
            else:
                x = int(parts[0])
                y = int(parts[1])
                z = int(parts[2])
                print(x,y,z)    
        continue
        res = bmesh.ops.create_cube(bm,size=scale_fac)
        bmesh.ops.translate(bm, verts=res['verts'],
                vec=(x*scale_fac , y*scale_fac, z*scale_fac))
        for v in res['verts']:
            for f in v.link_faces:
                f.material_index = int(parts[3])
                print(f.material_index)    
obj_data = bpy.data.meshes.new('gridmesh')
gridobj = bpy.data.objects.new('gridobj', obj_data)
bpy.context.scene.objects.link(gridobj)
bm.to_mesh(gridobj.data)
bm.free()
print("Mesh Complete")
thiirane
  • 45
  • 11
  • Iterate through each voxel and create unit cube around it (8 vertices, 6 quads). All that remains is to remove duplicating vertices, if needed. Group by materials if needed. – keltar Jan 07 '18 at 05:59

1 Answers1

1

Instead of manually creating an .obj file, you can read the data and generate the mesh directly in blender. You can then export it as an .obj if you want to transfer the mesh elsewhere.

Performance wise, blender works better with one object with one million verts than one thousand objects with one thousand verts each, so I would suggest building the mesh as one object. See this answer for a test I performed a while back. It is simple, though time consuming, to separate by loose parts when you are finished if you want multiple objects.

Each disconnected mesh piece (or each face) in the object can be assigned a different material. Note that the material index assigned here is an index to the materials assigned to the object, which are found in obj.material_slots. See this answer for a simple example of also creating BI materials.

import bpy, bmesh
import csv

scale_fac = 0.1

bm = bmesh.new()
grid_x , grid_y, grid_z = (0,0,0) # grid limits
with open('data.csv') as csvfile:
    data = csv.reader(csvfile, delimiter=' ', quoting=csv.QUOTE_NONE)
    for d in data:
        if len(d) == 3:
            grid_x = int(d[0])
            grid_y = int(d[1])
            grid_z = int(d[2])
            continue
        x = int(d[0])
        y = int(d[1])
        z = int(d[2])
        res = bmesh.ops.create_cube(bm,size=scale_fac)
        bmesh.ops.translate(bm, verts=res['verts'],
                vec=(x*scale_fac , y*scale_fac, z*scale_fac))
        for v in res['verts']:
            for f in v.link_faces:
                f.material_index = int(d[3])

obj_data = bpy.data.meshes.new('gridmesh')
gridobj = bpy.data.objects.new('gridobj', obj_data)
bpy.context.scene.objects.link(gridobj)
bm.to_mesh(gridobj.data)
bm.free()
sambler
  • 6,917
  • 1
  • 16
  • 23