Skip to content

Instantly share code, notes, and snippets.

@z0w0 z0w0/bls2obj.py
Created Mar 18, 2011

Embed
What would you like to do?
A python program for converting a Blockland save file (.bls) to a 3d wavefront model (.obj). @blockland.us
import sys,decimal,os,math,Image
def convert(input,output,offset,angle,brickName,color):
global posCount,uvCount,normalCount,posCache,uvCache,normalCache,brickCache,currentTex
try:
input = open(input,"r")
lines = input.readlines()
input.close()
except:
return
offset = str(str(decimal.Decimal(offset[0]) * 2) + " " + str(decimal.Decimal(offset[1]) * 2) + " " + str(decimal.Decimal(offset[2]) * decimal.Decimal("1.668"))).split()
linecount = -1
for line in lines:
linecount = linecount + 1
if len(line) >= 4:
if line[0:4] == "TEX:" and len(lines)-linecount >= 15:
if currentTex != line[4:].strip() + "_" + str(color) and line[4:].strip() != "PRINT":
currentTex = line[4:].strip() + "_" + str(color)
output.write("usemtl " + currentTex + "\n")
if lines[linecount+1][0:9].strip() == "POSITION:":
lines[linecount+2] = lines[linecount+2].strip().split()
arrayone = [str(decimal.Decimal(lines[linecount+2][0]) + decimal.Decimal(offset[0])) + " " + str(decimal.Decimal(lines[linecount+2][1]) + decimal.Decimal(offset[1])) + " " + str((decimal.Decimal(lines[linecount+2][2]) / 3) + decimal.Decimal(offset[2])),
str(decimal.Decimal(lines[linecount+2][1]) + decimal.Decimal(offset[0])) + " " + str(decimal.Decimal(offset[1]) - decimal.Decimal(lines[linecount+2][0])) + " " + str((decimal.Decimal(lines[linecount+2][2]) / 3) + decimal.Decimal(offset[2])),
str(decimal.Decimal(offset[0]) - decimal.Decimal(lines[linecount+2][0])) + " " + str(decimal.Decimal(offset[1]) - decimal.Decimal(lines[linecount+2][1])) + " " + str((decimal.Decimal(lines[linecount+2][2]) / 3) + decimal.Decimal(offset[2])),
str(decimal.Decimal(offset[0]) - decimal.Decimal(lines[linecount+2][1])) + " " + str(decimal.Decimal(offset[1]) + decimal.Decimal(lines[linecount+2][0])) + " " + str((decimal.Decimal(lines[linecount+2][2]) / 3) + decimal.Decimal(offset[2]))]
lines[linecount+2] = arrayone[angle]
posOne = posCount + 1
posOneAdd = 1
if lines[linecount+2] in posCache:
posOneAdd = 0
posOne = posCache[lines[linecount+2]]
else:
output.write("v " + lines[linecount+2] + "\n")
posCache[lines[linecount+2]] = posOne
lines[linecount+3] = lines[linecount+3].strip().split()
arraytwo = [str(decimal.Decimal(lines[linecount+3][0]) + decimal.Decimal(offset[0])) + " " + str(decimal.Decimal(lines[linecount+3][1]) + decimal.Decimal(offset[1])) + " " + str((decimal.Decimal(lines[linecount+3][2]) / 3) + decimal.Decimal(offset[2])),
str(decimal.Decimal(lines[linecount+3][1]) + decimal.Decimal(offset[0])) + " " + str(decimal.Decimal(offset[1]) - decimal.Decimal(lines[linecount+3][0])) + " " + str((decimal.Decimal(lines[linecount+3][2]) / 3) + decimal.Decimal(offset[2])),
str(decimal.Decimal(offset[0]) - decimal.Decimal(lines[linecount+3][0])) + " " + str(decimal.Decimal(offset[1]) - decimal.Decimal(lines[linecount+3][1])) + " " + str((decimal.Decimal(lines[linecount+3][2]) / 3) + decimal.Decimal(offset[2])),
str(decimal.Decimal(offset[0]) - decimal.Decimal(lines[linecount+3][1])) + " " + str(decimal.Decimal(offset[1]) + decimal.Decimal(lines[linecount+3][0])) + " " + str((decimal.Decimal(lines[linecount+3][2]) / 3) + decimal.Decimal(offset[2]))]
lines[linecount+3] = arraytwo[angle]
posTwo = posCount + (1 + posOneAdd)
posTwoAdd = 1
if lines[linecount+3] in posCache:
posTwoAdd = 0
posTwo = posCache[lines[linecount+3]]
else:
output.write("v " + lines[linecount+3] + "\n")
posCache[lines[linecount+3]] = posTwo
lines[linecount+4] = lines[linecount+4].strip().split()
arraythree = [str(decimal.Decimal(lines[linecount+4][0]) + decimal.Decimal(offset[0])) + " " + str(decimal.Decimal(lines[linecount+4][1]) + decimal.Decimal(offset[1])) + " " + str((decimal.Decimal(lines[linecount+4][2]) / 3) + decimal.Decimal(offset[2])),
str(decimal.Decimal(lines[linecount+4][1]) + decimal.Decimal(offset[0])) + " " + str(decimal.Decimal(offset[1]) - decimal.Decimal(lines[linecount+4][0])) + " " + str((decimal.Decimal(lines[linecount+4][2]) / 3) + decimal.Decimal(offset[2])),
str(decimal.Decimal(offset[0]) - decimal.Decimal(lines[linecount+4][0])) + " " + str(decimal.Decimal(offset[1]) - decimal.Decimal(lines[linecount+4][1])) + " " + str((decimal.Decimal(lines[linecount+4][2]) / 3) + decimal.Decimal(offset[2])),
str(decimal.Decimal(offset[0]) - decimal.Decimal(lines[linecount+4][1])) + " " + str(decimal.Decimal(offset[1]) + decimal.Decimal(lines[linecount+4][0])) + " " + str((decimal.Decimal(lines[linecount+4][2]) / 3) + decimal.Decimal(offset[2]))]
lines[linecount+4] = arraythree[angle]
posThree = posCount + (1 + posOneAdd + posTwoAdd)
posThreeAdd = 1
if lines[linecount+4] in posCache:
posThreeAdd = 0
posThree = posCache[lines[linecount+4]]
else:
output.write("v " + lines[linecount+4] + "\n")
posCache[lines[linecount+4]] = posThree
lines[linecount+5] = lines[linecount+5].strip().split()
arrayfour = [str(decimal.Decimal(lines[linecount+5][0]) + decimal.Decimal(offset[0])) + " " + str(decimal.Decimal(lines[linecount+5][1]) + decimal.Decimal(offset[1])) + " " + str((decimal.Decimal(lines[linecount+5][2]) / 3) + decimal.Decimal(offset[2])),
str(decimal.Decimal(lines[linecount+5][1]) + decimal.Decimal(offset[0])) + " " + str(decimal.Decimal(offset[1]) - decimal.Decimal(lines[linecount+5][0])) + " " + str((decimal.Decimal(lines[linecount+5][2]) / 3) + decimal.Decimal(offset[2])),
str(decimal.Decimal(offset[0]) - decimal.Decimal(lines[linecount+5][0])) + " " + str(decimal.Decimal(offset[1]) - decimal.Decimal(lines[linecount+5][1])) + " " + str((decimal.Decimal(lines[linecount+5][2]) / 3) + decimal.Decimal(offset[2])),
str(decimal.Decimal(offset[0]) - decimal.Decimal(lines[linecount+5][1])) + " " + str(decimal.Decimal(offset[1]) + decimal.Decimal(lines[linecount+5][0])) + " " + str((decimal.Decimal(lines[linecount+5][2]) / 3) + decimal.Decimal(offset[2]))]
lines[linecount+5] = arrayfour[angle]
posFour = posCount + (1 + posOneAdd + posTwoAdd + posThreeAdd)
posFourAdd = 1
if lines[linecount+5] in posCache:
posFourAdd = 0
posFour = posCache[lines[linecount+5]]
else:
output.write("v " + lines[linecount+5] + "\n")
posCache[lines[linecount+5]] = posFour
posCount = posCount + (posOneAdd + posTwoAdd + posThreeAdd + posFourAdd)
if lines[linecount+6][0:10].strip() == "UV COORDS:":
uvOne = uvCount + 1
uvOneAdd = 1
if lines[linecount+7].strip() in uvCache:
uvOneAdd = 0
uvOne = uvCache[lines[linecount+7].strip()]
else:
output.write("vt " + lines[linecount+7].strip() + "\n")
uvCache[lines[linecount+7].strip()] = uvOne
uvTwo = uvCount + (1 + uvOneAdd)
uvTwoAdd = 1
if lines[linecount+8].strip() in uvCache:
uvTwoAdd = 0
uvTwo = uvCache[lines[linecount+8].strip()]
else:
output.write("vt " + lines[linecount+8].strip() + "\n")
uvCache[lines[linecount+8].strip()] = uvTwo
uvThree = uvCount + (1 + uvOneAdd + uvTwoAdd)
uvThreeAdd = 1
if lines[linecount+9].strip() in uvCache:
uvThreeAdd = 0
uvThree = uvCache[lines[linecount+9].strip()]
else:
output.write("vt " + lines[linecount+9].strip() + "\n")
uvCache[lines[linecount+9].strip()] = uvThree
uvFour = uvCount + (1 + uvOneAdd + uvTwoAdd + uvThreeAdd)
uvFourAdd = 1
if lines[linecount+10].strip() in uvCache:
uvFourAdd = 0
uvFour = uvCache[lines[linecount+10].strip()]
else:
output.write("vt " + lines[linecount+10].strip() + "\n")
uvCache[lines[linecount+10].strip()] = uvFour
uvCount = uvCount + (uvOneAdd + uvTwoAdd + uvThreeAdd + uvFourAdd)
if lines[linecount+11][0:8].strip() == "NORMALS:":
normalOne = normalCount + 1
normalOneAdd = 1
if lines[linecount+12].strip() in normalCache:
normalOneAdd = 0
normalOne = normalCache[lines[linecount+12].strip()]
else:
output.write("vn " + lines[linecount+12].strip() + "\n")
normalCache[lines[linecount+12].strip()] = normalOne
normalTwo = normalCount + (1 + normalOneAdd)
normalTwoAdd = 1
if lines[linecount+13].strip() in normalCache:
normalTwoAdd = 0
normalTwo = normalCache[lines[linecount+13].strip()]
else:
output.write("vn " + lines[linecount+13].strip() + "\n")
normalCache[lines[linecount+13].strip()] = normalTwo
normalThree = normalCount + (1 + normalOneAdd + normalTwoAdd)
normalThreeAdd = 1
if lines[linecount+14].strip() in normalCache:
normalThreeAdd = 0
normalThree = normalCache[lines[linecount+14].strip()]
else:
output.write("vn " + lines[linecount+14].strip() + "\n")
normalCache[lines[linecount+14].strip()] = normalThree
normalFour = normalCount + (1 + normalOneAdd + normalTwoAdd + normalThreeAdd)
normalFourAdd = 1
if lines[linecount+15].strip() in normalCache:
normalFourAdd = 0
normalFour = normalCache[lines[linecount+15].strip()]
else:
output.write("vn " + lines[linecount+15].strip() + "\n")
normalCache[lines[linecount+15].strip()] = normalFour
normalCount = normalCount + (normalOneAdd + normalTwoAdd + normalThreeAdd + normalFourAdd)
try:
output.write("f " + str(posOne) + "/" + str(uvOne) + "/" + str(normalOne) + " " + str(posTwo) + "/" + str(uvTwo) + "/" + str(normalTwo) + " " + str(posThree) + "/" + str(uvThree) + "/" + str(normalThree) + " " + str(posFour) + "/" + str(uvFour) + "/" + str(normalFour) + "\n")
except:
continue
if len(sys.argv) > 1:
try:
print "Converting..."
try:
runningDirectory = os.path.abspath(os.path.dirname(sys.argv[0])) + "\\"
outputDirectory = os.path.abspath(os.path.dirname(sys.argv[0])) + "\\" + os.path.basename(sys.argv[1][0:sys.argv[1].find(".")]) + "\\"
if not os.path.isdir(outputDirectory):
os.mkdir(outputDirectory)
except:
sys.exit()
posCount = 0
uvCount = 0
normalCount = 0
posCache = {}
uvCache = {}
normalCache = {}
brickCache = {}
currentTex = ""
input = open(sys.argv[1],"r")
lines = input.readlines()
input.close()
output = open(outputDirectory + os.path.basename(sys.argv[1]).replace(".bls","") + ".obj","w")
material = open(outputDirectory + os.path.basename(sys.argv[1]).replace(".bls","") + ".mtl","w")
outputtedMaterial = 0
currentLine = 0
percent = 0
output.write("#Exported by BLSOBJ (zack0wack0.com)\nmtllib " + os.path.basename(sys.argv[1]).replace(".bls","") + ".mtl\n")
colorCount = -1
colorLoaded = {}
for line in lines:
currentLine = currentLine + 1
pos = line.find("\"")
if pos > -1 and line.find("+-") == -1:
brick = line[0:pos]
line = line[pos+2:]
file = os.path.abspath(os.path.dirname(sys.argv[0])) + "\library\\" + brick + ".blb"
if os.path.isfile(file):
line = line.strip().split()
if line[10] == "0":
continue
if colorLoaded[int(line[5])] == 0:
continue
convert(file,output,line[0:3],int(line[3]),brick,int(line[5]))
if decimal.Decimal(str(percent + 1)) < decimal.Decimal(str(math.floor((decimal.Decimal(str(currentLine)) / len(lines)) * 100))):
percent = percent + 1
print str(percent) + "%"
continue
else:
print "No such brick in the library: " + file
elif line.find("Linecount ") > -1:
outputtedMaterial = 1
material.close()
elif not outputtedMaterial:
color = line.split()
if len(color) == 4:
colorCount = colorCount + 1
colorIndex = str(colorCount)
if decimal.Decimal(color[3]) == 0:
colorLoaded[colorCount] = 0
continue
colorDataIndex = -1
for colorData in color:
colorDataIndex = colorDataIndex + 1
test = decimal.Decimal(colorData)
if test <= 1:
color[colorDataIndex] = str(test * 255)
colorLoaded[colorCount] = 1
print "Generating a material for the color " + str(colorCount + 1) + " on the colorset..."
colorTop = Image.new("RGB",(512,512),(decimal.Decimal(color[0]),decimal.Decimal(color[1]),decimal.Decimal(color[2])))
colorTop = Image.blend(colorTop,Image.open(runningDirectory + "brickTOP.png"),0.25)
colorTop.save(outputDirectory + "TOP_" + colorIndex + ".png",bits=24)
colorBottomLoop = Image.new("RGB",(512,512),(decimal.Decimal(color[0]),decimal.Decimal(color[1]),decimal.Decimal(color[2])))
colorBottomLoop = Image.blend(colorBottomLoop,Image.open(runningDirectory + "brickBOTTOMLOOP.png"),0.25)
colorBottomLoop.save(outputDirectory + "BOTTOMLOOP_" + colorIndex + ".png",bits=24)
colorBottomEdge = Image.new("RGB",(512,512),(decimal.Decimal(color[0]),decimal.Decimal(color[1]),decimal.Decimal(color[2])))
colorBottomEdge = Image.blend(colorBottomEdge,Image.open(runningDirectory + "brickBOTTOMEDGE.png"),0.25)
colorBottomEdge.save(outputDirectory + "BOTTOMEDGE_" + colorIndex + ".png",bits=24)
colorSide = Image.new("RGB",(512,512),(decimal.Decimal(color[0]),decimal.Decimal(color[1]),decimal.Decimal(color[2])))
colorSide = Image.blend(colorSide,Image.open(runningDirectory + "brickSIDE.png"),0.25)
colorSide.save(outputDirectory + "SIDE_" + colorIndex + ".png",bits=24)
colorRamp = Image.new("RGB",(512,512),(decimal.Decimal(color[0]),decimal.Decimal(color[1]),decimal.Decimal(color[2])))
colorRamp = Image.blend(colorRamp,Image.open(runningDirectory + "brickRAMP.png"),0.25)
colorRamp.save(outputDirectory + "RAMP_" + colorIndex + ".png",bits=24)
material.write("newmtl TOP_" + colorIndex + "\nd " + color[3] + "\nmap_Kd TOP_" + colorIndex + ".png\n\nnewmtl BOTTOMLOOP_" + colorIndex + "\nd " + color[3] + "\nmap_Kd BOTTOMLOOP_" + colorIndex + ".png\n\nnewmtl BOTTOMEDGE_" + colorIndex + "\nd " + color[3] + "\nmap_Kd BOTTOMEDGE_" + colorIndex + ".png\n\nnewmtl SIDE_" + colorIndex + "\nd " + color[3] + "\nmap_Kd SIDE_" + colorIndex + ".png\n\nnewmtl RAMP_" + colorIndex + "\nd " + color[3] + "\nmap_Kd RAMP_" + colorIndex + ".png\n\n")
output.close()
print "Complete"
os.system("pause")
except Exception,error:
print error
os.system("pause")
@ittehgeps

This comment has been minimized.

Copy link

ittehgeps commented Feb 11, 2018

sooo, how do i use it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.