Files
dusk/tools/assetstool/processmap.py
2025-11-11 12:25:46 -06:00

124 lines
4.0 KiB
Python

import struct
import sys
import os
import json
from args import args
from assetcache import assetCache, assetGetCache
from assethelpers import getAssetRelativePath
CHUNK_WIDTH = 16
CHUNK_HEIGHT = 16
CHUNK_DEPTH = 32
CHUNK_TILE_COUNT = CHUNK_WIDTH * CHUNK_HEIGHT * CHUNK_DEPTH
TILE_SIZE = 16.0
def createQuadForTile(model, tileIndex, x=0, y=0, z=0):
# Only append vertices if z == 0
if z != 0:
return
# Determine color for checkerboard pattern
color = (255,255,255) if (x + y) % 2 == 0 else (0,0,0)
# Use TILE_SIZE for positions
px = x * TILE_SIZE
py = y * TILE_SIZE
pz = z * TILE_SIZE
quad_vertices = [
{'position': (px, py, pz), 'color': color, 'uv': (0,0)}, # 0,0
{'position': (px + TILE_SIZE, py, pz), 'color': color, 'uv': (1,0)}, # 1,0
{'position': (px + TILE_SIZE, py + TILE_SIZE, pz), 'color': color, 'uv': (1,1)}, # 1,1
{'position': (px, py, pz), 'color': color, 'uv': (0,0)}, # 0,0 (repeat)
{'position': (px + TILE_SIZE, py + TILE_SIZE, pz), 'color': color, 'uv': (1,1)}, # 1,1 (repeat)
{'position': (px, py + TILE_SIZE, pz), 'color': color, 'uv': (0,1)} # 0,1
]
base = len(model['vertices'])
quad_indices = [base, base+1, base+2, base+3, base+4, base+5]
model['vertices'].extend(quad_vertices)
model['indices'].extend(quad_indices)
model['vertexCount'] = len(model['vertices'])
model['indexCount'] = len(model['indices'])
def processMap(asset):
cache = assetGetCache(asset['path'])
if cache is not None:
return cache
# Read input file as JSON
with open(asset['path'], 'r') as f:
inData = json.load(f)
tileIndexes = inData['tiles']
# Create output object 'map' with default tile indexes and models array
map = {
'tiles': [0] * CHUNK_TILE_COUNT,
'models': []
}
# Create a simple 3D model object
model = {
'vertices': [],
'indices': [],
'vertexCount': 0,
'indexCount': 0
}
# Append the model to map.models
map['models'].append(model)
for i, tile in enumerate(tileIndexes):
# Calculate x, y, z from i
x = i % CHUNK_WIDTH
y = (i // CHUNK_WIDTH) % CHUNK_HEIGHT
z = i // (CHUNK_WIDTH * CHUNK_HEIGHT)
createQuadForTile(model, tile, x, y, z)
# Generate binary buffer for efficient output
buffer = bytearray()
buffer.extend(b'DMF')# Header
buffer.extend(len(map['tiles']).to_bytes(4, 'little')) # Number of tiles
buffer.extend(len(map['models']).to_bytes(1, 'little')) # Number of models
# Buffer tile data as array of uint8_t
for tileIndex in map['tiles']:
buffer.append(tileIndex.to_bytes(1, 'little')[0])
# For each model
for model in map['models']:
# Write vertex count and index count
buffer.extend(model['vertexCount'].to_bytes(4, 'little'))
# buffer.extend(model['indexCount'].to_bytes(4, 'little'))
# For each vertex
for vertex in model['vertices']:
# This is not tightly packed in memory.
# R G B A U V X Y Z
# Color is 4 bytes (RGBA)
# Rest is floats
r, g, b = vertex['color']
a = 255
buffer.extend(r.to_bytes(1, 'little'))
buffer.extend(g.to_bytes(1, 'little'))
buffer.extend(b.to_bytes(1, 'little'))
buffer.extend(a.to_bytes(1, 'little'))
u, v = vertex['uv']
buffer.extend(bytearray(struct.pack('<f', u)))
buffer.extend(bytearray(struct.pack('<f', v)))
x, y, z = vertex['position']
buffer.extend(bytearray(struct.pack('<f', x)))
buffer.extend(bytearray(struct.pack('<f', y)))
buffer.extend(bytearray(struct.pack('<f', z)))
# Write out map file
relative = getAssetRelativePath(asset['path'])
fileNameWithoutExt = os.path.splitext(os.path.basename(asset['path']))[0]
outputFileRelative = os.path.join(os.path.dirname(relative), f"{fileNameWithoutExt}.dmf")
outputFilePath = os.path.join(args.output_assets, outputFileRelative)
os.makedirs(os.path.dirname(outputFilePath), exist_ok=True)
with open(outputFilePath, "wb") as f:
f.write(buffer)
outMap = {
'files': [ outputFilePath ],
'map': map
}
return assetCache(asset['path'], outMap)