diff --git a/NinjaBone.py b/NinjaBone.py index 2812e66..48dc330 100644 --- a/NinjaBone.py +++ b/NinjaBone.py @@ -147,7 +147,6 @@ class NinjaBone: # { return None def apply(self, vertex): - print(vertex.pos) vec3 = [ vertex.pos['x'], vertex.pos['y'], diff --git a/NinjaFace.py b/NinjaFace.py index 2c1b5c6..63c5917 100644 --- a/NinjaFace.py +++ b/NinjaFace.py @@ -50,22 +50,26 @@ class NinjaFace: return None def setIndexes(self, a, b, c): - self.index[0] = a - self.index[1] = b - self.index[2] = c + self.index = ( a, b, c ) return None def setNormals(self, a, b, c): - self.norm[0] = a - self.norm[1] = b - self.norm[2] = c + self.norm = ( a, b, c ) return None - def setDiffuseUv(self, a, b, c): - self.diffuse_uv[0] = a - self.diffuse_uv[1] = b - self.diffuse_uv[2] = c + def setColors(self, a, b, c): + self.color = (a, b, c) return None + def setDiffuseUv(self, a, b, c): + self.diffuse_uv = ( a, b, c ) + return None + def __repr__(self): + return "Material Id: %d, Indices: %d %d %d" % ( + self.mat_index, + self.index[0], + self.index[1], + self.index[2] + ) diff --git a/NinjaMaterial.py b/NinjaMaterial.py new file mode 100644 index 0000000..d769b63 --- /dev/null +++ b/NinjaMaterial.py @@ -0,0 +1,75 @@ +""" + + MIT License + + Copyright (c) 2020 Benjamin Collins (kion @ dashgl.com) + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + +""" + +class NinjaMaterial: + + def __init__(self): + self.tex_index = -1 + self.diffuse = { + 'r' : 255, + 'g' : 255, + 'b' : 255, + 'a' : 255 + } + return None + + def setTexIndex(self, index): + self.tex_index = index + return None + + def setDiffuseColor(self, r, g, b, a): + self.diffuse['r'] = r + self.diffuse['g'] = g + self.diffuse['b'] = b + self.diffuse['a'] = a + return None + + def clone(self): + other = NinjaMaterial() + other.tex_index = self.tex_index + other.diffuse['r'] = self.diffuse['r'] + other.diffuse['g'] = self.diffuse['g'] + other.diffuse['b'] = self.diffuse['b'] + other.diffuse['a'] = self.diffuse['a'] + return other + + def __eq__ (self, other): + if self.tex_index != other.tex_index: + return False + + if self.diffuse['r'] == other.diffuse['r']: + return False + + if self.diffuse['b'] == other.diffuse['b']: + return False + + if self.diffuse['g'] == other.diffuse['g']: + return False + + if self.diffuse['a'] == other.diffuse['a']: + return False + + return True + diff --git a/NinjaModel.py b/NinjaModel.py index 7dae886..ddc836d 100644 --- a/NinjaModel.py +++ b/NinjaModel.py @@ -25,6 +25,7 @@ import os import struct +from NinjaMaterial import NinjaMaterial from NinjaVertex import NinjaVertex from NinjaFace import NinjaFace from NinjaBone import NinjaBone @@ -256,7 +257,7 @@ class NinjaModel: # { print("Chunk: Material") bytes = self.file.read(2) short_len = struct.unpack('H', bytes) - self.material = {} + self.material = NinjaMaterial() dst_alpha = chunk_flag & 0x07 src_alpha = chunk_flag >> 3 @@ -264,32 +265,28 @@ class NinjaModel: # { if chunk_head & 0x01: bytes = self.file.read(4) c = struct.unpack('BBBB', bytes) - self.material['diffuse'] = { - 'b' : c[0] / 255.0, - 'g' : c[1] / 255.0, - 'r' : c[2] / 255.0, - 'a' : c[3] / 255.0 - } + b = c[0] / 255.0 + g = c[1] / 255.0 + r = c[2] / 255.0 + a = c[3] / 255.0 + self.material.setDiffuseColor(r, g, b, a) if chunk_head & 0x02: bytes = self.file.read(4) c = struct.unpack('BBBB', bytes) - self.material['ambient'] = { - 'b' : c[0] / 255.0, - 'g' : c[1] / 255.0, - 'r' : c[2] / 255.0, - 'a' : c[3] / 255.0 - } + b = c[0] / 255.0, + g = c[1] / 255.0, + r = c[2] / 255.0, + a = c[3] / 255.0 if chunk_head & 0x04: bytes = self.file.read(4) c = struct.unpack('BBBB', bytes) - self.material['specular'] = { - 'b' : c[0] / 255.0, - 'g' : c[1] / 255.0, - 'r' : c[2] / 255.0, - 'coef' : c[3] / 255.0 - } + b = c[0] / 255.0, + g = c[1] / 255.0, + r = c[2] / 255.0, + coef = c[3] / 255.0 + elif chunk_head >= 8 and chunk_head <= 9: print("Chunk: Tiny") bytes = self.file.read(2) @@ -299,9 +296,11 @@ class NinjaModel: # { clamp_v = chunk_flag & 0x10 flip_u = chunk_flag & 0x20 flip_v = chunk_flag & 0x40 - self.material['tex_id'] = chunk_body & 0x1fff + tex_id = chunk_body & 0x1fff super_sample = chunk_body >> 13 & 0x01 filter_sample = chunk_body >> 14 & 0x03 + self.material = self.material.clone() + self.material.setTexIndex(tex_id) elif chunk_head >= 64 and chunk_head <= 66: print("Chunk Strip!!!") @@ -310,6 +309,17 @@ class NinjaModel: # { chunk_len = h[0] * 2 chunk_body = h[1] + mat_index = -1 + for i in range(len(self.mat_list)): + if self.material != self.mat_list[i]: + continue + mat_index = i + break + + if mat_index == -1: + mat_index = len(self.mat_list) + self.mat_list.append(self.material) + ignore_light = chunk_flag & 0x01 ignore_specular = chunk_flag & 0x02 ignore_ambient = chunk_flag & 0x04 @@ -322,7 +332,7 @@ class NinjaModel: # { user_offset = chunk_body >> 14 print("Strip count: %d" % strip_count) - for i in range (strip_count): + for i in range (strip_count): # { print("Strip Start: 0x%08x" % self.file.tell()) bytes = self.file.read(2) @@ -332,7 +342,7 @@ class NinjaModel: # { strip_len = abs(strip_len) strip = [] - for k in range (strip_len): + for k in range (strip_len): # { bytes = self.file.read(2) index = struct.unpack('H', bytes)[0] index = self.index_lookup[index] @@ -357,9 +367,10 @@ class NinjaModel: # { strip.append({ 'index' : index, - 'uv' : [ u, v ] + 'uv' : { 'u' : u, 'v' : v } }) + # } for i in range(len(strip) - 2): #{ if i % 2 == 0 and counter_clockwise: @@ -371,27 +382,23 @@ class NinjaModel: # { b = strip[i + 0] c = strip[i + 2] + ai = a['index'] + bi = b['index'] + ci = c['index'] + va = self.vertex_list[a['index']] vb = self.vertex_list[a['index']] vc = self.vertex_list[a['index']] + + face = NinjaFace() + face.setMatIndex(mat_index) + face.setIndexes(ai, bi, ci) + face.setNormals(va.norm, vb.norm, vc.norm) + face.setDiffuseUv(a['uv'], b['uv'], c['uv']) + self.face_list.append(face) + print(face) + # } - self.face_list.append({ - 'index' : ( - a['index'], - b['index'], - b['index'] - ), - 'norm' : ( - va.norm, - vb.norm, - vc.norm - ), - uv : ( - a['uv'], - b['uv'], - c['uv'] - ) - }) # } print("Strip End: 0x%08x" % self.file.tell())