skeletons-cd2025/scripts/generate_node_box.py

228 lines
6.1 KiB
Python
Executable File

#!/bin/python
import sys
import lupa
if (len(sys.argv)!=3) and (len(sys.argv)!=4):
print("Usage: generate_node_box.py schema_file output_file [usemtl]")
exit();
schema_file = open(sys.argv[1], "r");
schema = schema_file.read();
schema_file.close();
if schema.startswith("5:return {"):
schema = schema[9:];
else:
print("schema_file format is not supported.")
exit();
usemtl = False;
if (len(sys.argv)==4) and (sys.argv[3]=="usemtl"):
usemtl = True;
print("Use different boxes for different materials into one box.");
lua = lupa.LuaRuntime(unpack_returned_tuples=True)
schema = dict(lua.eval(schema))
min_x = None
max_x = None
min_y = None
max_y = None
min_z = None
max_z = None
for node in schema.values():
x = node["x"];
if (not min_x) or (x<min_x):
min_x = x;
if (not max_x) or (x>max_x):
max_x = x;
y = node["y"];
if (not min_y) or (y<min_y):
min_y = y;
if (not max_y) or (y>max_y):
max_y = y;
z = node["z"];
if (not min_z) or (z<min_z):
min_z = z;
if (not max_z) or (z>max_z):
max_z = z;
size_x = max_x - min_x + 1;
size_y = max_y - min_y + 1;
size_z = max_z - min_z + 1;
print("Schema size is: {}x{}x{}".format(size_x, size_y, size_z));
def fit_to_16_min(value):
rem = value % 16;
return value - rem;
def fit_to_16_max(value):
if value==0:
value = 1;
rem = value % 16;
if rem!=0:
rem = 16 - rem;
return value + rem;
min_x = fit_to_16_min(min_x);
max_x = fit_to_16_max(max_x)-1;
min_y = fit_to_16_min(min_y);
max_y = fit_to_16_max(max_y)-1;
min_z = fit_to_16_min(min_z);
max_z = fit_to_16_max(max_z)-1;
size_x = max_x - min_x + 1;
size_y = max_y - min_y + 1;
size_z = max_z - min_z + 1;
print("Schema size is: {}x{}x{}".format(size_x, size_y, size_z));
nodes_x = (size_x)//16;
nodes_y = (size_y)//16;
nodes_z = (size_z)//16;
print("Nodes size is: {}x{}x{}".format(nodes_x, nodes_y, nodes_z));
node_boxes = "";
def check_names_in_area(schema, name, from_x, to_x, from_y, to_y, from_z, to_z):
checked = [];
for z in range(from_z, to_z+1):
for y in range(from_y, to_y+1):
for x in range(from_x, to_x+1):
index = z*256+y*16+x;
if usemtl and (schema[index]!=name):
return None;
if (not usemtl) and (schema[index]==None):
return None;
checked.append(index);
return checked;
class Box_Area:
def __init__(self, schema, b_x, b_y, b_z):
index = b_z*256+b_y*16+b_x;
name = schema[index];
self.indexes = [index];
self.from_x = self.to_x = b_x;
self.from_y = self.to_y = b_y;
self.from_z = self.to_z = b_z;
# first try x direction
x = self.from_x-1;
while x>=0:
index = b_z*256+b_y*16+x;
# only filled nodes can be merged
if (schema[index]==None):
break;
# only same materials can be merged
if usemtl and (schema[index]!=name):
break;
self.from_x = x;
self.indexes.append(index);
x = self.from_x - 1;
x = self.to_x + 1;
while x<16:
index = b_z*256+b_y*16+x;
# only filled nodes can be merged
if (schema[index]==None):
break;
# only same materials can be merged
if usemtl and (schema[index]!=name):
break;
self.to_x = x;
self.indexes.append(index);
x = self.to_x + 1;
# second try y direction
y = self.from_y-1;
while y>=0:
checked = check_names_in_area(schema, name, self.from_x, self.to_x, y, y, self.from_z, self.to_z);
# if check failed, break
if not checked:
break;
self.from_y = y;
self.indexes.extend(checked);
y = self.from_y - 1;
y = self.to_y+1;
while y<16:
checked = check_names_in_area(schema, name, self.from_x, self.to_x, y, y, self.from_z, self.to_z);
# if check failed, break
if not checked:
break;
self.to_y = y;
self.indexes.extend(checked);
y = self.to_y + 1;
# last try z direction
z = self.from_z-1;
while z>=0:
checked = check_names_in_area(schema, name, self.from_x, self.to_x, self.from_y, self.to_y, z, z);
# if check failed, break
if not checked:
break;
self.from_z = z;
self.indexes.extend(checked);
z = self.from_z - 1;
z = self.to_z+1;
while z<16:
checked = check_names_in_area(schema, name, self.from_x, self.to_x, self.from_y, self.to_y, z, z);
# if check failed, break
if not checked:
break;
self.to_z = z;
self.indexes.extend(checked);
z = self.to_z + 1;
def generate_node_box(node_x, node_y, node_z, schema):
node_box = " -- node box {{x={}, y={}, z={}}}\n".format(node_x, node_y, node_z);
node_box = node_box + " node_box = {\n";
node_box = node_box + " type = \"fixed\",\n";
node_box = node_box + " fixed = {\n";
for z in range(16):
for y in range(16):
for x in range(16):
node = schema[z*256+y*16+x];
if node:
box_area = Box_Area(schema, x, y, z);
box_x = (box_area.from_x/16)-0.5;
box_y = (box_area.from_y/16)-0.5;
box_z = (box_area.from_z/16)-0.5;
node_box = node_box + " {{{},{},{},".format(box_x, box_y, box_z);
box_x = ((box_area.to_x+1)/16)-0.5;
box_y = ((box_area.to_y+1)/16)-0.5;
box_z = ((box_area.to_z+1)/16)-0.5;
node_box = node_box + "{},{},{}}},\n".format(box_x, box_y, box_z);
for index in box_area.indexes:
schema[index] = None;
node_box = node_box + " },\n";
node_box = node_box + " },\n";
return node_box;
for box_x in range(nodes_x):
min_x = box_x*16;
for box_y in range(nodes_y):
min_y = box_y*16;
for box_z in range(nodes_z):
min_z = box_z*16;
box_schema = [None] * (16*16*16);
for node in schema.values():
x = node["x"] - min_x;
y = node["y"] - min_y;
z = node["z"] - min_z;
if (x>=0) and (x<16) and (y>=0) and (y<16) and (z>=0) and (z<16):
box_schema[z*256+y*16+x] = node["name"];
node_boxes = node_boxes + generate_node_box(box_x, box_y, box_z, box_schema);
output_file = open(sys.argv[2], "w");
output_file.write(node_boxes);
output_file.close();