This commit is contained in:
Benjamin Collins 2020-08-21 21:06:39 +09:00
parent 45a58a1eee
commit 1d3e6372e5
4 changed files with 228 additions and 114 deletions

240
Mat4.py
View File

@ -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]
#==============================================================
"""

View File

@ -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:

View File

@ -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):

View File

@ -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