diff --git a/matrix_44.py b/Mat4.py similarity index 100% rename from matrix_44.py rename to Mat4.py diff --git a/NinjaBone.py b/NinjaBone.py index 52d8290..e20fc9b 100644 --- a/NinjaBone.py +++ b/NinjaBone.py @@ -24,143 +24,56 @@ """ import math +from Mat4 import Mat4 class NinjaBone: # { def __init__(self): self.name = ""; - self.localMatrix = self.identity() - self.worldMatrix = self.identity() + self.index = -1 + self.parentIndex = -1 + self.local = Mat4() + self.world = Mat4() self.parent = None self.children = [] return None - def identity(self): - return [ - [ 1, 0, 0, 0 ], - [ 0, 1, 0, 0 ], - [ 0, 0, 1, 0 ], - [ 0, 0, 0, 1 ] - ] + def getIndex(self): + return self.index - def multiply(self, a, b): - tmp = self.identity() - for i in range(4): - for j in range(4): - t = 0.0 - for k in range(4): - t = t + (b[i][k] * a[k][j]) - tmp[i][j] = t - return tmp - - def multiplyLocal(self, factor): - a = self.localMatrix - b = factor - tmp = self.multiply(a, b) - self.localMatrix = tmp - return None - - def multiplyWorld(self, factor): - a = self.worldMatrix - b = factor - tmp = self.multiply(a, b) - self.worldMatrix = tmp - return None + def getWorld(self): + return self.world.mtx def setName(self, num): - self.save() - self.id = num + self.index = num self.name = 'bone_%03d' % num return None - def save(self): - for i in range(4): - for k in range(4): - self.worldMatrix[i][k] = self.localMatrix[i][k] - return None - def setParent(self, parent): self.parent = parent + self.parentIndex = parent.getIndex() + self.world.multiply(parent.getWorld()) return None def add(self, child): - child.multiplyWorld(self.worldMatrix) self.children.append(child) child.setParent(self) return None def setScale(self, vec3): - tmp = self.identity() - tmp[0][0] = vec3[0] - tmp[1][1] = vec3[1] - tmp[2][2] = vec3[2] - self.multiplyLocal(tmp) + self.local.scale(vec3) + self.world.scale(vec3) return None def setRotation(self, vec3, zxy_order): - if zxy_order: - z = vec3[0] - x = vec3[1] - y = vec3[2] - else: - x = vec3[0] - y = vec3[1] - z = vec3[2] - - # rotate x-axis - tmp = self.identity() - c = math.cos(x) - s = math.sin(x) - tmp[1][1] = c; - tmp[1][2] = s; - tmp[2][1] = -s; - tmp[2][2] = c; - self.multiplyLocal(tmp) - - # rotate y-axis - tmp = self.identity() - c = math.cos(y) - s = math.sin(y) - tmp[0][0] = c; - tmp[0][2] = -s; - tmp[2][0] = s; - tmp[2][2] = c; - self.multiplyLocal(tmp) - - # rotate z-axis - tmp = self.identity() - c = math.cos(z) - s = math.sin(z) - tmp[0][0] = c; - tmp[0][1] = s; - tmp[1][0] = -s; - tmp[1][1] = c; - self.multiplyLocal(tmp) + self.local.rotate(vec3, zxy_order) + self.world.rotate(vec3, zxy_order) return None def setPosition(self, vec3): - tmp = self.identity() - tmp[0][0] = vec3[0] - tmp[1][1] = vec3[1] - tmp[2][2] = vec3[2] - self.multiplyLocal(tmp) + self.local.translate(vec3) + self.world.translate(vec3) return None - def apply(self, vertex): - vec3 = [ - vertex.pos['x'], - vertex.pos['y'], - vertex.pos['z'], - 1 - ] - res = [0,0,0,0] - for i in range(4): - t = 0.0 - for j in range(4): - t = t + (vec3[j] * self.worldMatrix[j][i]) - res[i] = t - x = res[0] / res[3] - y = res[1] / res[3] - z = res[2] / res[3] - vertex.setPosition(x, y, z) - return vertex + def apply(self, vec3): + return self.world.apply(vec3) diff --git a/NinjaModel.py b/NinjaModel.py index a986b7a..d1cf20c 100644 --- a/NinjaModel.py +++ b/NinjaModel.py @@ -32,7 +32,6 @@ from NinjaMaterial import NinjaMaterial from NinjaVertex import NinjaVertex from NinjaFace import NinjaFace from NinjaBone import NinjaBone -from matrix_44 import Mat4 class NinjaModel: # { @@ -88,7 +87,7 @@ class NinjaModel: # { len = struct.unpack('I', bytes)[0] pos = self.file.tell() + len self.pof = self.file.tell() - self.readNjcm(None, None) + self.readNjcm(None) self.file.seek(pos, 0) elif (bytes == b'NMDM') : print('Found Ninja Direct Motion') @@ -118,7 +117,7 @@ class NinjaModel: # { name += ch.decode() return None - def readNjcm(self, parentBone, ptx): + def readNjcm(self, parentBone): bytes = self.file.read(52) b = struct.unpack('IIfffiiifffII', bytes) @@ -144,25 +143,15 @@ class NinjaModel: # { print("Flags: %d" % flags); print(pos) - mtx = Mat4() - if ( (flags & 0x04) == 0): - mtx.scale(scl) self.bone.setScale(scl) if ( (flags & 0x02) == 0): - mtx.rotate(rot) self.bone.setRotation(rot, flags & 0x20) if ( (flags & 0x01) == 0): - mtx.translate(pos) self.bone.setPosition(pos) - if ptx is not None: - mtx.multiply(ptx.getMatrix()) - - self.mtx = mtx - if parentBone: parentBone.add(self.bone) @@ -173,11 +162,11 @@ class NinjaModel: # { if child_ofs: self.file.seek(child_ofs + self.pof, 0) - self.readNjcm(self.bone, mtx) + self.readNjcm(self.bone) if sibling_ofs: self.file.seek(sibling_ofs + self.pof, 0) - self.readNjcm(parentBone, ptx) + self.readNjcm(parentBone) return None @@ -220,16 +209,12 @@ class NinjaModel: # { v = struct.unpack('ffffff', bytes) pos = [ v[0], v[1], v[2] ] - pos = self.mtx.apply(pos) + pos = self.bone.apply(pos) vertex = NinjaVertex() vertex.setPosition( pos[0], pos[1], pos[2] ) vertex.setNormal( v[3], v[4], v[5] ) - vertex.setSkinWeight(0, self.bone.id, 1.0) - - #print("vertex in: %s" % vertex) - #vertex = self.bone.apply(vertex) - #print("vertex out: %s" % vertex) + vertex.setSkinWeight(0, self.bone.index, 1.0) while len(self.index_lookup) < vertex_ofs + 1: self.index_lookup.append(None) @@ -249,7 +234,6 @@ class NinjaModel: # { print("End Chunk Head: %d" % chunk_head) print("End Chunk Flag: %d" % chunk_flag) - return None def readChunkList(self):