```#mission by nickoe import bpy import csv import math import bmesh def gridGet(grid, u, v): # grid is a sparse rectangular array, a list of lists col = grid[u] if v self.max): self.max = v def toUVCoord(x,y,z, du, dv, minMaxZ): """ return a 2-element list usable as a UV texture coordinate""" return [ (y/dv +x)/du, (z-minMaxZ.min)/(minMaxZ.max-minMaxZ.min) ] def loadBathymetry(fname): """ load bathymetry data from fname. The format is space-separated floating point values (x y z) one triple per line. We assume that the X and Y coordinates are at intervals of 1 and construct a mesh of squares wherever we have all four corners. """ r2 = csv.reader(open(fname, "r"), delimiter=' ') minMaxX = MinMax() minMaxY = MinMax() minMaxZ = MinMax() # scan for min/max values for row in r2: x_,y_,z_ = row z = float(z_) x = float(x_) y = float(y_) minMaxX.load(x) minMaxY.load(y) minMaxZ.load(z) # make a 2nd pass r2 = csv.reader(open(fname, "r"), delimiter=' ') verts = [] grid = [] # build a list of vertices # and memorize the vertex index of each cell # in the sparse matrix (grid) for row in r2: x_,y_,z_ = row z = float(z_) x = float(x_)-minMaxX.min y = float(y_)-minMaxY.min u = math.floor(x) v = math.floor(y) idx = len(verts) verts.append( [ x,y,z] ) # print( "%d %d %f"%(u,v,z) ) gridPut(grid, u, v, idx) faces = [] uvStash = [] du = math.ceil(minMaxX.max-minMaxX.min) dv = math.ceil(minMaxY.max-minMaxY.min) # iterate through all imagined squares in the sparse matrix # and build faces for each one that has all four corners present for u in range(0, du): for v in range(0, dv): # get the vertex indices for the corners zi1 = gridGet(grid, u, v) zi2 = gridGet(grid, u+1, v) zi4 = gridGet(grid, u, v+1) zi3 = gridGet(grid, u+1, v+1) # if all four corners have data if not (zi1 is None or zi2 is None or zi3 is None or zi4 is None): # make a face for it faces.append( [zi1, zi2, zi3, zi4] ) # memorize some UV coordinates for that face as well uvStash.append( [ toUVCoord(u, v, verts[zi1], du, dv, minMaxZ), toUVCoord(u+1, v, verts[zi2], du, dv, minMaxZ), toUVCoord(u+1, v+1, verts[zi3], du, dv, minMaxZ), toUVCoord(u, v+1, verts[zi4], du, dv, minMaxZ), ] ) # build a mesh from the vertex and face list mesh = bpy.data.meshes.new("bathymetry") mesh.from_pydata(verts, [], faces ) # create a new UV layer mesh.uv_textures.new("depth") bm = bmesh.new() bm.from_mesh(mesh) bm.faces.ensure_lookup_table() uv_layer = bm.loops.layers.uv # loop through the faces and set the UV coordinates # according to the values we stashed in the earlier loop. for fi in range(len(bm.faces)): uvs = uvStash[fi] for vi in range(len(uvs)): bm.faces[fi].loops[vi][uv_layer].uv = uvs[vi] # print("face[%d] .uv[%d] = %s" % (fi, vi, uvs[vi]) ) bm.to_mesh(mesh) return mesh def getGradientImage(): """rainbow gradient image""" rval = bpy.data.images.get("gradient") # print(rval) if rval is None: rval = bpy.data.images.new("gradient", 1, 6) rval.pixels = [ #R,G,B,A, 1,0,1,1, # magenta 0,0,1,1, # blue 0,1,1,1, # cyan 0,1,0,1, # green 1,1,0,1, # yellow 1,0,0,1, # red ] # if we don't pack the image into the .blend, it will be lost when you re-load the project rval.pack(True) return rval def getGradientTexture(): """rainbow gradient texture""" rval = bpy.data.textures.get("gradient") # print(rval) if rval is None: rval = bpy.data.textures.new("gradient", 'IMAGE') rval.image = getGradientImage() print(rval.image) return rval def getGradientMaterial(): """rainbow gradient material from UV layer 'depth' """ rval = bpy.data.materials.get("gradient") print(rval) if rval is None: rval = bpy.data.materials.new("gradient") rval.texture_slots.add() ts = rval.texture_slots ts.texture = getGradientTexture() ts.texture_coords='UV' ts.uv_layer = "depth" return rval def set_UV_editor_texture(mesh): """ set the image for the face.tex layer on all the faces so we have a rough idea of what the mesh will look like in the 3D view's Texture render mode""" # load the mesh data into a bmesh object bm = bmesh.new() bm.from_mesh(mesh) bm.faces.ensure_lookup_table() # Get the "tex" layer for the first UV map # If you don't already have a UV map, why are you even calling this function? tex_layer = bm.faces.layers.tex[mesh.uv_layers.name] for i in range(len(bm.faces)): # figure out which material this face uses mi = bm.faces[i].material_index mat = mesh.materials[mi] # Assume that we want to use the image from the first texture slot; # and assume that the material has a texture in that first slot; # and assume that the texture is an image texture instead of a procedural texture. # if any of several assumptions are wrong, this will explode img = mat.texture_slots.texture.image bm.faces[i][tex_layer].image = img # copy the modified data into the mesh bm.to_mesh(mesh) # # if False: # debugging code to blow away old data blocks try: bpy.context.scene.objects.unlink(bpy.data.objects.get("bathymetry")) except: pass try: bpy.data.objects.remove(bpy.data.objects.get("bathymetry")) except: pass try: bpy.data.meshes.remove(bpy.data.meshes.get("bathymetry")) except: pass try: bpy.data.materials.remove(bpy.data.materials.get("gradient")) except: pass try: bpy.data.textures.remove(bpy.data.textures.get("gradient")) except: pass try: bpy.data.images.remove(bpy.data.images.get("gradient")) except: pass # build the mesh and UVs from the CSV data mesh = loadBathymetry("/var/tmp/testdata.csv") # put the gradient material on the mesh mesh.materials.append(getGradientMaterial()) # create the object for the mesh obj = bpy.data.objects.new("bathymetry", mesh) # put an image on the UV layer so we can see the # colors in texture mode of the 3d view set_UV_editor_texture(obj.data) # link the object to the current scene bpy.context.scene.objects.link(obj) obj.select = True bpy.context.scene.objects.active = obj print("done") ```

Syntax highlighting by Pygments.