diff --git a/Mat4.py b/Mat4.py index 9948936..79d0b75 100644 --- a/Mat4.py +++ b/Mat4.py @@ -26,113 +26,165 @@ import math class Mat4: - #constructor - def __init__(self): - self.mtx = self.identity() + #constructor + def __init__(self): + self.mtx = self.identity() - # return matrix - def getMatrix(self): - return self.mtx + # return matrix + def getMatrix(self): + return self.mtx - # create identity - def identity(self): - return [ - [1, 0, 0, 0], - [0, 1, 0, 0], - [0, 0, 1, 0], - [0, 0, 0, 1] - ] + # create identity + def identity(self): + return [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [0, 0, 0, 1] + ] - # mutliply by 4x4 matrix - def multiply(self, factor): - tmp = self.identity() + # mutliply by 4x4 matrix + def multiply(self, factor): + tmp = self.identity() - for i in range(4): - for j in range(4): - t = 0.0 - for k in range(4): - t = t + (self.mtx[i][k] * factor[k][j]) - tmp[i][j] = t + for i in range(4): + for j in range(4): + t = 0.0 + for k in range(4): + t = t + (self.mtx[i][k] * factor[k][j]) + tmp[i][j] = t - self.mtx = tmp + self.mtx = tmp - # apply matrix to vec3 - def apply(self, vec3): - vec3.append(1) - res = [0,0,0,0] - for i in range(4): - t = 0.0 - for j in range(4): - t = t + (vec3[j] * self.mtx[j][i]) - res[i] = t - x = res[0] / res[3]; - y = res[1] / res[3]; - z = res[2] / res[3]; - return [x, y, z] + # apply matrix to vec3 + def apply(self, vec3): + vec3.append(1) + res = [0,0,0,0] + for i in range(4): + t = 0.0 + for j in range(4): + t = t + (vec3[j] * self.mtx[j][i]) + res[i] = t + x = res[0] / res[3]; + y = res[1] / res[3]; + z = res[2] / res[3]; + return [x, y, z] - # scale by vec3 - def scale(self, vec3): - tmp = self.identity() - # x - tmp[0][0] = vec3[0] - # y - tmp[1][1] = vec3[1] - # z - tmp[2][2] = vec3[2] - self.multiply(tmp) + # scale by vec3 + def scale(self, vec3): + tmp = self.identity() + # x + tmp[0][0] = vec3[0] + # y + tmp[1][1] = vec3[1] + # z + tmp[2][2] = vec3[2] + self.multiply(tmp) - # translate by vec3 - def translate(self, vec3): - tmp = self.identity() - # x - tmp[3][0] = vec3[0] - # y - tmp[3][1] = vec3[1] - # z - tmp[3][2] = vec3[2] - self.multiply(tmp) + # translate by vec3 + def translate(self, vec3): + tmp = self.identity() + # x + tmp[3][0] = vec3[0] + # y + tmp[3][1] = vec3[1] + # z + tmp[3][2] = vec3[2] + self.multiply(tmp) - # rotate by vec3 - def rotate(self, vec3, zxy_order = False): + # rotate by vec3 + def rotate(self, vec3): - if zxy_order: - z = vec3[0] - x = vec3[1] - y = vec3[2] - else: - x = vec3[0] - y = vec3[1] - z = vec3[2] + 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.multiply(tmp) + # 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.multiply(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.multiply(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.multiply(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.multiply(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.multiply(tmp) + + def toQuat(self): + + m11 = self.mtx[0][0] + m21 = self.mtx[1][0] + m31 = self.mtx[2][0] + + m12 = self.mtx[0][1] + m22 = self.mtx[1][1] + m32 = self.mtx[2][1] + + m13 = self.mtx[0][2] + m23 = self.mtx[1][2] + m33 = self.mtx[2][2] + + trace = m11 + m22 + m33; + + x = 0 + y = 0 + z = 0 + w = 1 + + if (trace > 0): + + s = 0.5 / math.sqrt( trace + 1.0 ) + w = 0.25 / s + x = ( m32 - m23 ) * s + y = ( m13 - m31 ) * s + z = ( m21 - m12 ) * s + + elif ( m11 > m22 and m11 > m33 ): + + s = 2.0 * math.sqrt( 1.0 + m11 - m22 - m33 ) + w = ( m32 - m23 ) / s + x = 0.25 * s + y = ( m12 + m21 ) / s + z = ( m13 + m31 ) / s + + elif (m22 > m33) : + + s = 2.0 * math.sqrt( 1.0 + m22 - m11 - m33 ) + + w = ( m13 - m31 ) / s + x = ( m12 + m21 ) / s + y = 0.25 * s + z = ( m23 + m32 ) / s + + else: + + s = 2.0 * math.sqrt( 1.0 + m33 - m11 - m22 ) + + w = ( m21 - m12 ) / s + x = ( m13 + m31 ) / s + y = ( m23 + m32 ) / s + z = 0.25 * s + + return [x, y, z, w] #============================================================== """ diff --git a/NinjaBone.py b/NinjaBone.py index 961416a..2261dce 100644 --- a/NinjaBone.py +++ b/NinjaBone.py @@ -37,6 +37,9 @@ class NinjaBone: # { self.world = Mat4() self.parent = None self.children = [] + self.rotation = [ 0, 0, 0 ] + self.position = [ 0, 0, 0 ] + self.scale = [ 1, 1, 1] return None def getIndex(self): @@ -45,6 +48,15 @@ class NinjaBone: # { def getWorld(self): return self.world.mtx + def getScale(self): + return self.scale + + def getPosition(self): + return self.position + + def getRotation(self): + return self.rotation + def setName(self, num): self.index = num self.name = 'bone_%03d' % num @@ -62,16 +74,31 @@ class NinjaBone: # { return None def setScale(self, vec3): + self.scale = vec3 self.local.scale(vec3) self.world.scale(vec3) return None - def setRotation(self, vec3, zxy_order): - self.local.rotate(vec3, zxy_order) - self.world.rotate(vec3, zxy_order) + def setRotation(self, vec3, zxy_order = False): + + if zxy_order: + z = vec3[0] + x = vec3[1] + y = vec3[2] + else: + x = vec3[0] + y = vec3[1] + z = vec3[2] + + rot = [ x, y, z ] + self.rotation = rot + + self.local.rotate(vec3) + self.world.rotate(vec3) return None def setPosition(self, vec3): + self.position = vec3 self.local.translate(vec3) self.world.translate(vec3) return None @@ -80,7 +107,6 @@ class NinjaBone: # { return self.world.apply(vec3) def createDmfEntry(self, file): - # 0x00 Name name = self.name while len(name) < 0x20: diff --git a/NinjaModel.py b/NinjaModel.py index 1a75095..4a714e6 100644 --- a/NinjaModel.py +++ b/NinjaModel.py @@ -433,6 +433,7 @@ class NinjaModel: 'rot' : p[2] & 0x02, 'scl' : p[2] & 0x04 } + factor_count = p[3] & 0x03 spline_interpolation = p[3] & 0x40 user_function_interpolation = p[3] & 0x80 @@ -443,22 +444,12 @@ class NinjaModel: anim.setSkeleton(self.bones) self.anim_list.append(anim) - print("READING ANIMTION!!!!") - print(motion_type) - - print("FRAME COUNT: %d" % frame_count) - print("Factor Count %d" % factor_count) - print("Spline Function %d" % spline_interpolation) - # Read Motion Table anim_vals = [] - print("Table Offset: 0x%08x" % table_ofs) self.file.seek(table_ofs, 0) for i in range(len(self.bones)): - print("Current Offset: 0x%08x" % self.file.tell()) - entry = { 'bone_index' : i, 'pos_ofs' : 0, @@ -496,13 +487,13 @@ class NinjaModel: bytes = self.file.read(4) p = struct.unpack('I', bytes) entry['scl_num'] = p[0] - anim_vals.append(entry) c = 2 * 3.141592 / 0x10000; for entry in anim_vals: - + boneIndex = entry['bone_index'] + print("Bone Index: %d" % boneIndex) self.file.seek(entry['pos_ofs'], 0) for i in range(entry['pos_num']): @@ -514,8 +505,8 @@ class NinjaModel: self.file.seek(entry['rot_ofs'], 0) for i in range(entry['rot_num']): - bytes = self.file.read(16) - p = struct.unpack('Ifff', bytes) + bytes = self.file.read(8) + p = struct.unpack('Hhhh', bytes) frame = p[0] vec3 = [ p[1]*c, p[2]*c, p[3]*c ] anim.appendKeyFrame(boneIndex, frame, vec3, 'rot') @@ -527,7 +518,7 @@ class NinjaModel: frame = p[0] vec3 = [ p[1], p[2], p[3] ] anim.appendKeyFrame(boneIndex, frame, vec3, 'scl') - + anim.save(boneIndex) return None def export(self): diff --git a/NinjaMotion.py b/NinjaMotion.py index 5c29afe..fb618e0 100644 --- a/NinjaMotion.py +++ b/NinjaMotion.py @@ -42,7 +42,7 @@ class NinjaMotion: return None def setSkeleton(self, bones): - self.seleton = bones + self.skeleton = bones for i in range(len(bones)): self.keyFrames.append([]) return None @@ -67,5 +67,50 @@ class NinjaMotion: keyFrames.append(keyFrame) return None + + def save(self, boneIndex): + bone = self.skeleton[boneIndex] + keyFrames = self.keyFrames[boneIndex] + + if len(keyFrames) == 0: + keyFrames.append({ + 'frame' : 0 + }) + keyFrames.append({ + 'frame' : self.frames - 1 + }) + + if 'scl' not in keyFrames[0].keys(): + keyFrames[0]['scl'] = bone.getScale() + + if 'pos' not in keyFrames[0].keys(): + keyFrames[0]['pos'] = bone.getPosition() + + if 'rot' not in keyFrames[0].keys(): + keyFrames[0]['rot'] = bone.getRotation() + + lastIndex = len(keyFrames) - 1 + + if 'scl' not in keyFrames[lastIndex].keys(): + keyFrames[lastIndex]['scl'] = bone.getScale() + + if 'pos' not in keyFrames[lastIndex].keys(): + keyFrames[lastIndex]['pos'] = bone.getPosition() + + if 'rot' not in keyFrames[lastIndex].keys(): + keyFrames[lastIndex]['rot'] = bone.getRotation() + + for keyFrame in keyFrames: + + if 'rot' not in keyFrame.keys(): + continue + + mat4 = Mat4() + mat4.rotate(keyFrame['rot']) + keyFrame['quat'] = mat4.toQuat() + print(keyFrame['quat']) + + + return None