metaforce/hecl/blender/addon/hmdl/HMDLTxtr.py

100 lines
3.1 KiB
Python

'''
HMDL Export Blender Addon
By Jack Andersen <jackoalan@gmail.com>
This file provides the means to generate an RGBA TXTR resource
buffer for packaging into an .hlpk (yes, I know this is slow,
but it's very flexible and supports Blender's procedural textures)
'''
from mathutils import Vector
import struct
def count_bits(num):
accum = 0
index = 0
for i in range(32):
if ((num >> i) & 1):
accum += 1
index = i
return accum, index
def make_txtr(tex, size=(512,512)):
if tex.type == 'IMAGE':
size = tex.image.size
# Validate image for mipmapping
can_mipmap = False
w_bits, w_idx = count_bits(size[0])
h_bits, h_idx = count_bits(size[1])
if w_bits == 1 and h_bits == 1 and tex.use_mipmap:
can_mipmap = True
# Main image 2D array
main_array = []
for y in range(size[1]):
row = []
main_array.append(row)
for x in range(size[0]):
texel = tex.evaluate((x * 2 / size[0] - 1.0, y * 2 / size[1] - 1.0, 0))
row.append(texel)
# Count potential mipmap levels
series_count = 1
if can_mipmap:
if size[0] > size[1]:
series_count = w_idx + 1
else:
series_count = h_idx + 1
# Make header
tex_bytes = struct.pack('IHHI', 0, size[0], size[1], series_count)
# Initial mipmap level
for y in main_array:
for x in y:
tex_bytes += struct.pack('BBBB',
min(255, int(x[0]*256)),
min(255, int(x[1]*256)),
min(255, int(x[2]*256)),
min(255, int(x[3]*256)))
# Prepare mipmap maker
if can_mipmap:
# Box filter
prev_array = main_array
for i in range(series_count - 1):
new_array = []
for y in range(max(len(prev_array) // 2, 1)):
y1 = prev_array[y*2]
if len(prev_array) > 1:
y2 = prev_array[y*2+1]
else:
y2 = prev_array[y*2]
new_row = []
new_array.append(new_row)
for x in range(max(len(y1) // 2, 1)):
texel_val = Vector((0,0,0,0))
texel_val += y1[x*2]
texel_val += y2[x*2]
if len(y1) > 1:
texel_val += y1[x*2+1]
texel_val += y2[x*2+1]
else:
texel_val += y1[x*2]
texel_val += y2[x*2]
texel_val /= 4
new_row.append(texel_val)
tex_bytes += struct.pack('BBBB',
min(255, int(texel_val[0]*256)),
min(255, int(texel_val[1]*256)),
min(255, int(texel_val[2]*256)),
min(255, int(texel_val[3]*256)))
prev_array = new_array
return tex_bytes