Skip to content

Instantly share code, notes, and snippets.

@itherunder
Last active April 12, 2022 04:22
Show Gist options
  • Save itherunder/16ca714327bafc94b897379dc8d5a424 to your computer and use it in GitHub Desktop.
Save itherunder/16ca714327bafc94b897379dc8d5a424 to your computer and use it in GitHub Desktop.
change .obj color by program!

readme

  1. 将脚本文件放到obj,png同目录下即可,python3 script.py,命令行中的输出为obj中平面的数量,与1.中的decimal设置有关

结果图(lenOfRGBs == 50):

image image

  1. 可调参数,懒得写在命令行了,直接在py文件改

a. decimal(Line 32),越小,平面数量越少 b. lenOfRGBs(Line 91),越小,使用的png中的颜色越少,注释的话使用png中全部颜色

  1. 问题

如何对应平面和png中的颜色,暂无办法 因此目前修改后的obj不好看

.obj example: obj&color.zip

from unicodedata import decimal
from PIL import Image
objFilePath = "obj&color/monu1.vox.obj"
pngFilePath = "obj&color/monu1.vox.png"
mtlFilePath = "obj&color/monu1.vox.mtl"
def loadPng():
image = Image.open(pngFilePath)
pixels = image.load()
rgbs = []
for x in range(image.size[0]):
rgbs.append(pixels[x, 0])
return rgbs
def writeMtl():
rgbs = loadPng()
with open(mtlFilePath, "w") as w:
for i, rgb in enumerate(rgbs):
w.write("newmtl mtl{}\n".format(i))
w.write("Kd {} {} {}\n".format(rgb[0], rgb[1], rgb[2]))
w.write("Ks 0.50 0.50 0.50\n")
w.write("\n")
return len(rgbs)
def calSurface(v1, v2, v3):
a = (v2[1] - v1[1]) * (v3[2] - v1[2]) - (v2[2] - v1[2]) * (v3[1] - v1[1])
b = (v2[2] - v1[2]) * (v3[0] - v1[0]) - (v2[0] - v1[0]) * (v3[2] - v1[2])
c = (v2[0] - v1[0]) * (v3[1] - v1[1]) - (v2[1] - v1[1]) * (v3[0] - v1[0])
d = -(a * v1[0] + b * v1[1] + c * v1[2])
# remained decimal digits, the less decimal the less surfaces
decimal = 2
a, b, c, d = round(a, decimal), round(b, decimal), round(c, decimal), round(d, decimal)
if a == -0.0: a = 0.0
if b == -0.0: b = 0.0
if c == -0.0: c = 0.0
if d == -0.0: d = 0.0
return "#".join([str(a), str(b), str(c), str(d)])
def readObj():
fs, vs, fcnt, vcnt = {}, {}, 0, 1 # vcnt is the number of vertices, start with 1
surfaces, revSurfaces = {}, {} # a*x + b*y + c*z = d => <i, str(a#b#c#d)>
with open(objFilePath, "r") as r:
for i, line in enumerate(r.readlines()):
strs = line.split(" ")
if strs[0] == "f":
v1, v2, v3 = int(strs[1].split("/")[0]), int(strs[2].split("/")[0]), int(strs[3].split("/")[0])
fs[i] = [fcnt, v1, v2, v3]
fcnt += 1
if strs[0] == "v":
vs[vcnt] = (float(strs[1]), float(strs[2]), float(strs[3]))
vcnt += 1
newFs = {}
for i, ps in fs.items():
v1, v2, v3 = vs[ps[1]], vs[ps[2]], vs[ps[3]]
surface = calSurface(v1, v2, v3)
surfaces[i] = surface
if surface not in revSurfaces: revSurfaces[surface] = [i]
else: revSurfaces[surface].append(i)
newFs[i] = [ps[0], surface]
print(len(revSurfaces))
return fs, newFs, surfaces, revSurfaces
def rewriteObj(lenOfRGBs):
fs, newFs, surfaces, revSurfaces = readObj()
# gap = len(fs) // lenOfRGBs
gap_ = len(revSurfaces) // lenOfRGBs
surface2mtlindex = {}
for i, (fcnt, surface) in newFs.items():
if surface not in surface2mtlindex:
l = len(surface2mtlindex)
if l // gap_ < lenOfRGBs:
surface2mtlindex[surface] = l // gap_
else:
surface2mtlindex[surface] = lenOfRGBs - 1
with open(objFilePath, "r") as r:
with open("obj&color/monu1.vox.new.obj", "w") as w:
for i, line in enumerate(r.readlines()):
# if i in fs and fs[i][0] % gap == 0 and fs[i][0] // gap < lenOfRGBs:
# w.write("usemtl mtl{}\n".format(fs[i][0] // gap))
if i in newFs:
# printfile(i, newFs[i], surface2mtlindex[newFs[i][1]])
with open("surface.txt", "a") as a:
a.write("{} {} {}\n".format(i, newFs[i], surface2mtlindex[newFs[i][1]]))
w.write("usemtl mtl{}\n".format(surface2mtlindex[newFs[i][1]]))
w.write(line)
if __name__ == "__main__":
lenOfRGBs = writeMtl() # total colors of .png
lenOfRGBs = 50 # how many RGBs used in one mtl file, options, to make your obj less color...
rewriteObj(lenOfRGBs)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment