start on shape commands

This commit is contained in:
red031000 2023-07-11 10:31:28 +01:00
parent 53f8dc0034
commit db40db6ef7
No known key found for this signature in database
GPG Key ID: D27E50C050AE0CE1
4 changed files with 242 additions and 3 deletions

View File

@ -5,7 +5,7 @@ all: nitrog3d
nitrog3d:
mkdir -p io_scene_g3d
cp __init__.py import_nsbmd.py utils.py io_scene_g3d
cp __init__.py import_nsbmd.py utils.py g3_commands.py io_scene_g3d
zip -r nitrog3d.zip io_scene_g3d
rm -rf io_scene_g3d

191
g3_commands.py Normal file
View File

@ -0,0 +1,191 @@
from .utils import error, read32, np_fixed_to_float, fixed_to_float, to_rgb, vec10_to_vec
from enum import IntEnum
import numpy as np
def parse_dl(data, size, report_func):
offset = 0
display_list = []
while offset < size:
commandData = read32(data, offset)
offset += 4
commands, offset = parse_dl_command(data, offset, commandData, report_func)
display_list.append(commands)
return display_list
def parse_dl_command(data, offset, commandData, report_func):
commands = []
for i in range(4):
command = (commandData >> i * 8) & 0xFF
if command == 0x00:
commands.append(DLCommandNoop())
elif command == 0x10:
mode = MatrixMode(read32(data, offset))
offset += 4
commands.append(DLCommandMtxMode(mode))
elif command == 0x11:
commands.append(DLCommandPushMtx())
elif command == 0x12:
matrixId = read32(data, offset)
offset += 4
commands.append(DLCommandPopMtx(matrixId))
elif command == 0x13:
matrixId = read32(data, offset)
offset += 4
commands.append(DLCommandStoreMtx(matrixId))
elif command == 0x14:
matrixId = read32(data, offset)
offset += 4
commands.append(DLCommandRestoreMtx(matrixId))
elif command == 0x15:
commands.append(DLCommandIdentity())
elif command == 0x16:
matrix = np_fixed_to_float(np.frombuffer(data[offset:offset + 64], dtype=np.dtype('uint32').newbyteorder('<')).reshape((4, 4)))
offset += 64
commands.append(DLCommandLoadMtx44(matrix))
elif command == 0x17:
matrix = np_fixed_to_float(np.frombuffer(data[offset:offset + 48], dtype=np.dtype('uint32').newbyteorder('<')).reshape((4, 3)))
offset += 48
commands.append(DLCommandLoadMtx43(matrix))
elif command == 0x18:
matrix = np_fixed_to_float(np.frombuffer(data[offset:offset + 64], dtype=np.dtype('uint32').newbyteorder('<')).reshape((4, 4)))
offset += 64
commands.append(DLCommandMultMtx44(matrix))
elif command == 0x19:
matrix = np_fixed_to_float(np.frombuffer(data[offset:offset + 48], dtype=np.dtype('uint32').newbyteorder('<')).reshape((4, 3)))
offset += 48
commands.append(DLCommandMultMtx43(matrix))
elif command == 0x1A:
matrix = np_fixed_to_float(np.frombuffer(data[offset:offset + 36], dtype=np.dtype('uint32').newbyteorder('<')).reshape((3, 3)))
offset += 36
commands.append(DLCommandMultMtx33(matrix))
elif command == 0x1B:
x = fixed_to_float(read32(data, offset))
y = fixed_to_float(read32(data, offset + 4))
z = fixed_to_float(read32(data, offset + 8))
matrix = np.identity(4)
matrix[0, 0] = x
matrix[1, 1] = y
matrix[2, 2] = z
offset += 12
commands.append(DLCommandScale(matrix))
elif command == 0x1C:
x = fixed_to_float(read32(data, offset))
y = fixed_to_float(read32(data, offset + 4))
z = fixed_to_float(read32(data, offset + 8))
matrix = np.identity(4)
matrix[0, 3] = x
matrix[1, 3] = y
matrix[2, 3] = z
offset += 12
commands.append(DLCommandTranslate(matrix))
elif command == 0x20:
color = read32(data, offset)
rgb = to_rgb(color)
offset += 4
commands.append(DLCommandColor(rgb))
elif command == 0x21:
normal = vec10_to_vec(read32(data, offset))
offset += 4
commands.append(DLCommandNormal(normal))
elif command == 0x22:
texcoord = read32(data, offset)
s = fixed_to_float((texcoord & 0xFFFF) << 8) # unsure if this shift is correct
t = fixed_to_float(((texcoord >> 16) & 0xFFFF) << 8)
offset += 4
commands.append(DLCommandTexcoord(s, t))
#todo more commands
return commands, offset
class MatrixMode(IntEnum):
PROJECTION = 0
POSITION = 1
POSITION_VECTOR = 2
TEXTURE = 3
class DLCommand:
def __init__(self, commandId):
self.commandId = commandId
class DLCommandNoop(DLCommand):
def __init__(self):
super().__init__(0x00)
class DLCommandMtxMode(DLCommand):
def __init__(self, mode):
super().__init__(0x10)
self.mode = mode
class DLCommandPushMtx(DLCommand):
def __init__(self):
super().__init__(0x11)
class DLCommandPopMtx(DLCommand):
def __init__(self, matrixId):
super().__init__(0x12)
self.matrixId = matrixId
class DLCommandStoreMtx(DLCommand):
def __init__(self, matrixId):
super().__init__(0x13)
self.matrixId = matrixId
class DLCommandRestoreMtx(DLCommand):
def __init__(self, matrixId):
super().__init__(0x14)
self.matrixId = matrixId
class DLCommandIdentity(DLCommand):
def __init__(self):
super().__init__(0x15)
class DLCommandLoadMtx44(DLCommand):
def __init__(self, matrix):
super().__init__(0x16)
self.matrix = matrix
class DLCommandLoadMtx43(DLCommand):
def __init__(self, matrix):
super().__init__(0x17)
self.matrix = matrix
class DLCommandMultMtx44(DLCommand):
def __init__(self, matrix):
super().__init__(0x18)
self.matrix = matrix
class DLCommandMultMtx43(DLCommand):
def __init__(self, matrix):
super().__init__(0x19)
self.matrix = matrix
class DLCommandMultMtx33(DLCommand):
def __init__(self, matrix):
super().__init__(0x1A)
self.matrix = matrix
class DLCommandScale(DLCommand):
def __init__(self, matrix):
super().__init__(0x1B)
self.matrix = matrix
class DLCommandTranslate(DLCommand):
def __init__(self, matrix):
super().__init__(0x1C)
self.matrix = matrix
class DLCommandColor(DLCommand):
def __init__(self, color):
super().__init__(0x20)
self.color = color
class DLCommandNormal(DLCommand):
def __init__(self, normal):
super().__init__(0x21)
self.normal = normal
class DLCommandTexcoord(DLCommand):
def __init__(self, s, t):
super().__init__(0x22)
self.s = s
self.t = t

View File

@ -1,6 +1,7 @@
from enum import IntEnum, IntFlag
from os.path import isfile
from .utils import read8, read16, read32, read_str, log, debug, parse_dictionary, fixed_to_float, to_rgb
from .g3_commands import parse_dl
import numpy as np
class ScalingRule(IntEnum):
@ -393,6 +394,33 @@ class NSBMDMaterial():
def add_palette_mat_data(self, palette_mat_data):
self.paletteMatData.append(palette_mat_data)
class ShapeFlags(IntFlag):
USE_NORMAL = 0x0001
USE_COLOR = 0x0002
USE_TEXCOORD = 0x0004
USE_RESTOREMTX = 0x0008
class NSBMDShape():
def __init__(self, name):
self.name = name
self.useNormal = False
self.useColor = False
self.useTexCoord = False
self.useRestoreMtx = False
def parse_flags(self, flags, report_func):
self.useNormal = (flags & ShapeFlags.USE_NORMAL) != 0
log('Use normal: %s' % self.useNormal, report_func)
self.useColor = (flags & ShapeFlags.USE_COLOR) != 0
log('Use color: %s' % self.useColor, report_func)
self.useTexCoord = (flags & ShapeFlags.USE_TEXCOORD) != 0
log('Use tex coord: %s' % self.useTexCoord, report_func)
self.useRestoreMtx = (flags & ShapeFlags.USE_RESTOREMTX) != 0
log('Use restore mtx: %s' % self.useRestoreMtx, report_func)
class NSBMDModel():
def __init__(self, name):
self.name = name
@ -541,11 +569,12 @@ class NSBMDImporter():
if material_value < matIdxDataEnd:
matIdxDataEnd = material_value
dict_size = read16(materialset_data[offsetDictPlttToMat:], 2)
dict_size = read16(materialset_data[offsetDictPlttToMat:], 0x2)
model.matIdxData = materialset_data[offsetDictPlttToMat + dict_size:matIdxDataEnd].tobytes() # no idea how this is used, but essential
log('Material id data: %s' % model.matIdxData.hex(" "), self.report)
for material_key, material_value in materialset_dictionary.items():
log('%s: %08X' % (material_key, material_value), self.report)
material = NSBMDMaterial(material_key)
material_data = materialset_data[material_value:]
diffAmb = read32(material_data, 0x04)
@ -646,8 +675,18 @@ class NSBMDImporter():
material_id = read8(pltt_mat_data, i)
pltt_mat = NSBMDPaletteMaterialData(pltt_mat_key, material_id, pltt_mat_bound)
model.materials[material_id].add_palette_mat_data(pltt_mat)
shape_data = data[shape_offset:]
shape_dictionary = parse_dictionary(shape_data)
for shape_key, shape_value in shape_dictionary.items():
log('%s: %08X' % (shape_key, shape_value), self.report)
shape = NSBMDShape(shape_key)
shape_item_data = shape_data[shape_value:]
shape_flags = read32(shape_item_data, 0x04)
shape.parse_flags(shape_flags, self.report)
shape_dl_offset = read32(shape_item_data, 0x08)
shape_dl_size = read32(shape_item_data, 0x0C)
shape.dlData = parse_dl(shape_data[shape_dl_offset:], shape_dl_size, self.report)
#todo
return nsbmd

View File

@ -24,6 +24,9 @@ def read_dict_string(data, offset):
def log(string, report_func):
report_func(type={"INFO"}, message=string)
def error(string, report_func):
report_func(type={"ERROR"}, message=string)
def debug(string, report_func):
report_func(type={"DEBUG"}, message=string)
@ -53,3 +56,9 @@ def fixed_to_float(value):
def to_rgb(color):
return (color & 0x1F, (color >> 5) & 0x1F, (color >> 10) & 0x1F)
def np_fixed_to_float(value):
return (value / 4096.0).astype('float')
def vec10_to_vec(value):
return (value & 0x3FF, (value >> 10) & 0x3FF, (value >> 20) & 0x3FF)