ikaruga/NinjaMotion.py
Benjamin Collins bf94f20bac normals
2020-08-24 22:58:21 +09:00

208 lines
5.3 KiB
Python

"""
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.
"""
import math
import struct
from Mat4 import Mat4
class NinjaMotion:
def __init__(self):
self.debug = False
self.index = -1
self.name = "";
self.skeleton = []
self.frames = 0
self.fps = 30
self.keyFrames = []
self.count = 0
return None
def setName(self, index):
self.index = index
self.name = "anim_%03d" % index
return None
def setSkeleton(self, bones):
self.skeleton = bones
for i in range(len(bones)):
self.keyFrames.append([])
return None
def setFrames(self, frames):
self.frames = frames
return None
def appendKeyFrame(self, boneIndex, frame, vec3, type):
keyFrames = self.keyFrames[boneIndex]
if self.debug:
print("Adding %s type frame to bone %d" % (type, boneIndex))
for keys in keyFrames:
if keys['frame'] != frame:
continue
keys[type] = vec3
return None
keyFrame = {
'frame' : frame,
type : vec3
}
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:
self.count += 1
if 'rot' not in keyFrame.keys():
continue
c1 = math.cos( keyFrame['rot'][0] / 2 );
c2 = math.cos( keyFrame['rot'][1] / 2 );
c3 = math.cos( keyFrame['rot'][2] / 2 );
s1 = math.sin( keyFrame['rot'][0] / 2 );
s2 = math.sin( keyFrame['rot'][1] / 2 );
s3 = math.sin( keyFrame['rot'][2] / 2 );
x = s1 * c2 * c3 + c1 * s2 * s3
y = c1 * s2 * c3 - s1 * c2 * s3
z = c1 * c2 * s3 + s1 * s2 * c3
w = c1 * c2 * c3 - s1 * s2 * s3
keyFrame['quat'] = [ x, y, z, w ]
return None
def generateDmfEntry(self, file):
name = self.name
while len(name) < 0x20:
name += '\0'
bytes = name.encode()
file.write(bytes)
bytes = struct.pack('hh', self.index, self.fps)
file.write(bytes)
self.pos = file.tell()
file.write(struct.pack('I', 0))
file.write(struct.pack('I', self.count))
duration = (self.frames - 1) / self.fps
file.write(struct.pack('f', duration))
return None
def writeDmfAnimation(self, file):
offset = file.tell()
file.seek(self.pos, 0)
file.write(struct.pack('I', offset))
file.seek(0, 2)
for i in range(len(self.keyFrames)):
keyFrames = self.keyFrames[i]
for keyFrame in keyFrames:
skipFlags = 0
if 'pos' in keyFrame.keys():
skipFlags |= 0x01
if 'rot' in keyFrame.keys():
skipFlags |= 0x02
if 'scl' in keyFrame.keys():
skipFlags |= 0x04
file.write(struct.pack('hh', i, skipFlags))
file.write(struct.pack('f', keyFrame['frame'] / self.fps))
if 'pos' in keyFrame.keys():
file.write(struct.pack('f', keyFrame['pos'][0]))
file.write(struct.pack('f', keyFrame['pos'][1]))
file.write(struct.pack('f', keyFrame['pos'][2]))
else:
file.write(struct.pack('f', 0))
file.write(struct.pack('f', 0))
file.write(struct.pack('f', 0))
if 'quat' in keyFrame.keys():
file.write(struct.pack('f', keyFrame['quat'][0]))
file.write(struct.pack('f', keyFrame['quat'][1]))
file.write(struct.pack('f', keyFrame['quat'][2]))
file.write(struct.pack('f', keyFrame['quat'][3]))
else:
file.write(struct.pack('f', 0))
file.write(struct.pack('f', 0))
file.write(struct.pack('f', 0))
file.write(struct.pack('f', 1))
if 'scl' in keyFrame.keys():
file.write(struct.pack('f', keyFrame['scl'][0]))
file.write(struct.pack('f', keyFrame['scl'][1]))
file.write(struct.pack('f', keyFrame['scl'][2]))
else:
file.write(struct.pack('f', 1))
file.write(struct.pack('f', 1))
file.write(struct.pack('f', 1))
return None