Skip to content

Instantly share code, notes, and snippets.

@kythyria
Created January 22, 2017 17:39
Show Gist options
  • Save kythyria/9accae4f6239808293046734c4e660e6 to your computer and use it in GitHub Desktop.
Save kythyria/9accae4f6239808293046734c4e660e6 to your computer and use it in GitHub Desktop.
Blender reader for SL sculpts
import bmesh
import bmesh.ops
import bpy
import bpy.ops
import itertools
def chunks(l, n):
return [l[i:i+n] for i in range(0, len(l), n)]
def sculpt_mesh_from_coords_wiki_64(data, name, sculpttype, mirror, invert):
if mirror:
invert = not invert
template = list(itertools.chain(range(0,64,2), [63]))
# [[(x,y,u,v), ...], ...]
coordinates = []
for v,y in enumerate(template):
row = []
for u,x in enumerate(template):
row.append((x,y,u,v))
coordinates.append(row)
if sculpttype == "SPHERE":
row = coordinates[0]
for i, v in enumerate(row):
row[i] = (32, v[1], v[2], v[3])
row = coordinates[len(coordinates) - 1]
for i, v in enumerate(row):
row[i] = (32, v[1], v[2], v[3])
if sculpttype == "CYLINDER" or sculpttype == "TORUS" or sculpttype == "SPHERE":
for i, row in enumerate(coordinates):
v = row[32]
row[32] = (0, v[1], v[2], v[3])
if sculpttype == "TORUS":
for i, v in enumerate(coordinates[31]):
coordinates[32][i] = (v[0], 0, v[2], v[3])
me = bpy.data.meshes.new(name)
me.uv_textures.new("UVMap")
bm = bmesh.new()
bm.from_mesh(me)
uv_layer = bm.loops.layers.uv[0]
vertices = []
vcache = {}
for row in coordinates:
vr = []
for c in row:
if mirror:
px = data[c[1]][63 - c[0]]
else:
px = data[c[1]][c[0]]
pos = (px[0] - 0.5, px[1] - 0.5, px[2] - 0.5)
xy = c[0:2]
existing = vcache.get(xy)
if existing != None:
vr.append(existing)
else:
v = bm.verts.new(pos)
vr.append(v)
vcache[xy] = v
vertices.append(vr)
def get_verts(coll,x,y):
a = coll[y][x]
b = coll[y][x+1]
c = coll[y+1][x]
d = coll[y+1][x+1]
return a,b,c,d
def set_face_uv(face, vertex, uv):
loops = [l for l in face.loops if l.vert == vertex]
if len(loops) == 0:
return
loop = loops[0]
u = uv[0] / 32
v = uv[1] / 32
loop[uv_layer].uv = (u,v)
for y, row in enumerate(coordinates):
if y == len(coordinates) - 1:
break
for x, c in enumerate(row):
if x == len(row) - 1:
break
#
# p1---p2
# | |
# | |
# p3---p4
c1, c2, c3, c4 = get_verts(coordinates, x, y)
p1, p2, p3, p4 = get_verts(vertices, x, y)
if invert:
face = bm.faces.new(dedup((p1,p3,p4,p2)))
else:
face = bm.faces.new(dedup((p1,p2,p4,p3)))
face.smooth = True
set_face_uv(face, p1, c1[2:4])
set_face_uv(face, p2, c2[2:4])
set_face_uv(face, p3, c3[2:4])
set_face_uv(face, p4, c4[2:4])
#for vrow, crow in zip(vertices,coordinates):
# for vert, c in zip(vrow,crow):
# u = c[2] / 32
# v = c[3] / 32
# for loop in vert.link_loops:
# loop[uv_layer].uv = (u,v)
bm.to_mesh(me)
me.update()
return me
def sculpt_mesh_from_file(name, stype, imagepath, mirror, invert):
oname = name
if mirror or invert:
oname = name + "."
if mirror:
oname += "m"
if invert:
oname += "i"
idx = bpy.data.meshes.find(oname)
if idx != -1:
mdata = bpy.data.meshes[idx]
else:
image = bpy.data.images.load(imagepath)
pxlist = chunks(chunks(image.pixels, 4),64)
mdata = sculpt_mesh_from_coords_wiki_64(pxlist, oname, stype, mirror, invert)
return mdata
def sculpt_from_file(name, sculpt_type, imagepath, mirror, invert):
me = sculpt_mesh_from_file(name, stype, fn, mirror, invert)
ob = bpy.data.objects.new(name, me)
bpy.context.scene.objects.link(ob)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment