1
0
Fork 0
mirror of https://git.coom.tech/drummyfish/small3dlib.git synced 2024-11-21 20:39:57 +01:00
small3dlib/tools/obj2array.py

220 lines
5.7 KiB
Python
Raw Normal View History

2019-05-23 19:42:12 +02:00
# Python tool to convert a 3D model from the text obj format to C arrays to be
# used with small3dlib.
#
2019-05-25 19:57:05 +02:00
# by drummyfish
2019-05-23 19:42:12 +02:00
# released under CC0 1.0.
import sys
2019-05-25 13:34:43 +02:00
def printHelp():
print("Convert 3D model in OBJ format (text, triangulated) to C array for small3dlib.")
print("usage:\n")
print(" python obj2array.py [-c -sX -uY -vZ -n] file\n")
print(" -c compact format (off by default)")
2019-05-25 19:57:05 +02:00
print(" -t use direct instead of indexed UV coords (off by default)")
2019-05-26 16:42:55 +02:00
print(" -h include header guards (for model per file)")
2019-06-24 18:00:26 +02:00
print(" -m include a material array (per-triangle)")
2019-05-25 19:57:05 +02:00
print(" -nS use the name S for the model (defaut: \"model\")")
2019-05-25 13:34:43 +02:00
print(" -sX scale the model by X (default: 512)")
print(" -uY scale the U texture coord by Y (default: 512)")
print(" -vZ scale the V texture coord by Z (default: 512)")
print("");
print("by Miloslav \"drummyfish\" Ciz")
print("released under CC0 1.0")
2019-05-23 19:42:12 +02:00
2019-05-25 13:34:43 +02:00
if len(sys.argv) < 2:
printHelp()
quit()
2019-05-25 19:57:05 +02:00
FILENAME = ""
2019-05-23 19:42:12 +02:00
VERTEX_SCALE = 512
U_SCALE = 512
V_SCALE = 512
NAME = "model"
2019-05-26 16:42:55 +02:00
GUARDS = False
2019-05-25 13:34:43 +02:00
COMPACT = False
INDEXED_UVS = True
2019-06-24 18:00:26 +02:00
MATERIALS = False
2019-05-25 13:34:43 +02:00
for s in sys.argv:
if s == "-c":
COMPACT = True
2019-05-25 19:57:05 +02:00
elif s == "-t":
2019-05-25 13:34:43 +02:00
INDEXED_UVS = False
2019-05-26 16:42:55 +02:00
elif s == "-h":
GUARDS = True
2019-06-24 18:00:26 +02:00
elif s == "-m":
MATERIALS = True
2019-05-25 13:34:43 +02:00
elif s[:2] == "-s":
VERTEX_SCALE = int(s[2:])
elif s[:2] == "-u":
U_SCALE = int(s[2:])
elif s[:2] == "-v":
V_SCALE = int(s[2:])
2019-05-25 19:57:05 +02:00
elif s[:2] == "-n":
NAME = s[2:]
2019-05-25 13:34:43 +02:00
else:
2019-05-25 19:57:05 +02:00
FILENAME = s
2019-05-23 19:42:12 +02:00
2019-05-25 19:57:05 +02:00
objFile = open(FILENAME)
2019-05-23 19:42:12 +02:00
vertices = []
uvs = []
triangles = []
triangleUVs = []
2019-06-24 18:00:26 +02:00
materials = []
materialNames = []
currentMatrial = 0
def getMaterialIndex(materialName):
try:
return materialNames.index(materialName)
except Exception:
materialNames.append(materialName)
return len(materialNames) - 1
2019-05-23 19:42:12 +02:00
# parse the file:
for line in objFile:
if line[:2] == "v ":
coords = line[2:].split()
vertex = [float(coords[i]) for i in range(3)]
2019-06-06 23:37:41 +02:00
vertex[2] *= -1
2019-05-23 19:42:12 +02:00
vertices.append(vertex)
elif line[:3] == "vt ":
coords = line[3:].split()
vertex = [float(coords[i]) for i in range(2)]
2019-06-01 22:28:12 +02:00
vertex[1] = 1.0 - vertex[1]
2019-05-23 19:42:12 +02:00
uvs.append(vertex)
elif line[:2] == "f ":
indices = line[2:].split()
if len(indices) != 3:
raise(Exception("The model is not triangulated!"))
t = []
u = []
for i in indices:
components = i.split("/")
t.append(int(components[0]) - 1)
2021-08-01 21:13:16 +02:00
try:
u.append(int(components[1]) - 1)
except Exception as e:
u.append(int(components[2]) - 1)
2019-05-23 19:42:12 +02:00
triangles.append(t)
2019-06-01 22:28:12 +02:00
triangleUVs.append(u)
2019-06-24 18:00:26 +02:00
materials.append([currentMatrial])
elif line[:7] == "usemtl ":
currentMatrial = getMaterialIndex(line[7:])
2019-05-23 19:42:12 +02:00
# print the result:
2019-06-06 16:38:29 +02:00
def arrayString(name, array, components, scales, align, short, dataType, sizeStr):
result = "const " + dataType + " " + name + "[" + sizeStr + "] = {\n"
2019-05-23 19:42:12 +02:00
if COMPACT:
lineLen = 0
first = True
n = 0
for v in array:
for c in v:
item = ""
if first:
first = False
else:
result += ","
lineLen += 1
if lineLen >= 80:
result += "\n"
lineLen = 0
num = c * scales[n % len(scales)]
if short:
item += str(num)
else:
item += ("" if num >= 0 else "-") + "0x%x" % abs(num)
2019-06-28 02:17:30 +02:00
if lineLen + len(item) >= 80:
2019-05-23 19:42:12 +02:00
result += "\n"
lineLen = 0
result += item
lineLen += len(item)
n += 1
2019-05-26 16:42:55 +02:00
result += "};\n"
2019-05-23 19:42:12 +02:00
else: # non-compact
n = 0
endIndex = len(array) - 1
for v in array:
line = " " + ", ".join([str(int(v[c] * scales[c % len(scales)])).rjust(align) for c in range(components)])
if n < endIndex:
line += ","
line = line.ljust((components + 2) * (align + 1)) + "// " + str(n * components) + "\n"
result += line
n += 1
2019-05-26 16:42:55 +02:00
result += "}; // " + name + "\n"
2019-05-23 19:42:12 +02:00
return result
result = ""
2019-05-26 16:42:55 +02:00
if GUARDS:
2019-06-02 20:22:42 +02:00
print("#ifndef " + NAME.upper() + "_MODEL_H")
print("#define " + NAME.upper() + "_MODEL_H\n")
2019-05-26 16:42:55 +02:00
2019-06-06 16:38:29 +02:00
print("#define " + NAME.upper() + "_VERTEX_COUNT " + str(len(vertices)))
print(arrayString(NAME + "Vertices",vertices,3,[VERTEX_SCALE],5,False,"S3L_Unit",NAME.upper() + "_VERTEX_COUNT * 3"))
print("#define " + NAME.upper() + "_TRIANGLE_COUNT " + str(len(triangles)))
print(arrayString(NAME + "TriangleIndices",triangles,3,[1],5,True,"S3L_Index",NAME.upper() + "_TRIANGLE_COUNT * 3"))
2019-05-23 19:42:12 +02:00
2019-06-24 18:00:26 +02:00
if MATERIALS:
print(arrayString(NAME + "Materials",materials,1,[1],5,True,"uint8_t",NAME.upper() + "_TRIANGLE_COUNT"))
2019-05-23 19:42:12 +02:00
if INDEXED_UVS:
2019-06-06 16:38:29 +02:00
print("#define " + NAME.upper() + "_UV_COUNT " + str(len(uvs)))
print(arrayString(NAME + "UVs",uvs,2,[U_SCALE,V_SCALE],5,False,"S3L_Unit",NAME.upper() + "_UV_COUNT * 2"))
print("#define " + NAME.upper() + "_UV_INDEX_COUNT " + str(len(triangleUVs)))
print(arrayString(NAME + "UVIndices",triangleUVs,3,[1],5,True,"S3L_Index",NAME.upper() + "_UV_INDEX_COUNT * 3"))
2019-05-23 19:42:12 +02:00
else:
uvs2 = []
for item in triangleUVs:
uvs2.append([
uvs[item[0]][0],
uvs[item[0]][1],
uvs[item[1]][0],
uvs[item[1]][1],
uvs[item[2]][0],
uvs[item[2]][1]])
2019-06-06 16:38:29 +02:00
print("#define " + NAME.upper() + "_DIRECT_UV_COUNT " + str(len(uvs2)))
print(arrayString(NAME + "DirectUVs",uvs2,6,[U_SCALE,V_SCALE],5,False,"S3L_Unit",NAME.upper() + "_DIRECT_UV_COUNT * 6"))
2019-05-23 19:42:12 +02:00
2019-06-17 21:51:23 +02:00
print("S3L_Model3D " + NAME + "Model;\n")
print("void " + NAME + "ModelInit()")
print("{")
2021-12-28 23:25:22 +01:00
print(" S3L_model3DInit(")
2019-06-17 21:51:23 +02:00
print(" " + NAME + "Vertices,")
print(" " + NAME.upper() + "_VERTEX_COUNT,")
print(" " + NAME + "TriangleIndices,")
print(" " + NAME.upper() + "_TRIANGLE_COUNT,")
print(" &" + NAME + "Model);")
print("}")
2019-05-26 16:42:55 +02:00
if GUARDS:
print("\n#endif // guard")