218 lines
6.1 KiB
Haxe
218 lines
6.1 KiB
Haxe
|
package iron.object;
|
||
|
|
||
|
import iron.object.Animation.ActionSampler;
|
||
|
|
||
|
import kha.arrays.Float32Array;
|
||
|
import kha.FastFloat;
|
||
|
import kha.arrays.Uint32Array;
|
||
|
import iron.math.Vec4;
|
||
|
import iron.math.Mat4;
|
||
|
import iron.math.Quat;
|
||
|
import iron.data.SceneFormat;
|
||
|
|
||
|
class ObjectAnimation extends Animation {
|
||
|
|
||
|
public var object: Object;
|
||
|
public var oactions: Array<TSceneFormat>;
|
||
|
var oaction: TObj;
|
||
|
var s0: FastFloat = 0.0;
|
||
|
var bezierFrameIndex = -1;
|
||
|
|
||
|
var updateAnimation: Map<String, FastFloat> -> Void;
|
||
|
|
||
|
public var transformArr: Float32Array;
|
||
|
|
||
|
public var transformMap: Map<String, FastFloat>;
|
||
|
|
||
|
public static var trackNames: Array<String> = [ "xloc", "yloc", "zloc",
|
||
|
"xrot", "yrot", "zrot",
|
||
|
"qwrot", "qxrot", "qyrot", "qzrot",
|
||
|
"xscl", "yscl", "zscl",
|
||
|
"dxloc", "dyloc", "dzloc",
|
||
|
"dxrot", "dyrot", "dzrot",
|
||
|
"dqwrot", "dqxrot", "dqyrot", "dqzrot",
|
||
|
"dxscl", "dyscl", "dzscl"];
|
||
|
|
||
|
public function new(object: Object, oactions: Array<TSceneFormat>) {
|
||
|
this.object = object;
|
||
|
this.oactions = oactions;
|
||
|
isSkinned = false;
|
||
|
super();
|
||
|
}
|
||
|
|
||
|
function getAction(action: String): TObj {
|
||
|
for (a in oactions) if (a != null && a.objects[0].name == action) return a.objects[0];
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
override public function play(action = "", onComplete: Void->Void = null, blendTime = 0.0, speed = 1.0, loop = true) {
|
||
|
super.play(action, onComplete, blendTime, speed, loop);
|
||
|
if (this.action == "" && oactions[0] != null) this.action = oactions[0].objects[0].name;
|
||
|
oaction = getAction(this.action);
|
||
|
if (oaction != null) {
|
||
|
isSampled = oaction.sampled != null && oaction.sampled;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
override public function update(delta: FastFloat) {
|
||
|
if (!object.visible || object.culled) return;
|
||
|
|
||
|
#if lnx_debug
|
||
|
Animation.beginProfile();
|
||
|
#end
|
||
|
|
||
|
if(transformMap == null) transformMap = new Map();
|
||
|
transformMap = initTransformMap();
|
||
|
|
||
|
super.update(delta);
|
||
|
if (paused) return;
|
||
|
if(updateAnimation == null) return;
|
||
|
if (!isSkinned) updateObjectAnimation();
|
||
|
|
||
|
#if lnx_debug
|
||
|
Animation.endProfile();
|
||
|
#end
|
||
|
}
|
||
|
|
||
|
public override function getTotalFrames(sampler: ActionSampler): Int {
|
||
|
var track = getAction(sampler.action).anim.tracks[0];
|
||
|
return Std.int(track.frames[track.frames.length - 1] - track.frames[0]);
|
||
|
}
|
||
|
|
||
|
public function initTransformMap(){
|
||
|
|
||
|
var map = new Map<String, Null<FastFloat>>();
|
||
|
for (name in trackNames){
|
||
|
map.set(name, null);
|
||
|
}
|
||
|
|
||
|
return map;
|
||
|
|
||
|
}
|
||
|
|
||
|
public function animationLoop(f: Map<String, FastFloat>->Void){
|
||
|
|
||
|
updateAnimation = f;
|
||
|
}
|
||
|
|
||
|
function updateObjectAnimation() {
|
||
|
updateAnimation(transformMap);
|
||
|
updateTransform(transformMap, object.transform);
|
||
|
object.transform.buildMatrix();
|
||
|
}
|
||
|
|
||
|
override public function updateActionTrack(sampler: ActionSampler) {
|
||
|
if(sampler.paused) return;
|
||
|
|
||
|
if(! sampler.actionDataInit) {
|
||
|
var objanim = getAction(sampler.action);
|
||
|
sampler.setObjectAction(objanim);
|
||
|
}
|
||
|
|
||
|
oaction = sampler.getObjectAction();
|
||
|
updateTrack(oaction.anim, sampler);
|
||
|
|
||
|
}
|
||
|
|
||
|
function updateAnimSampled(anim: TAnimation, transformMap: Map<String, FastFloat>, sampler: ActionSampler) {
|
||
|
|
||
|
for (track in anim.tracks) {
|
||
|
var sign = sampler.speed > 0 ? 1 : -1;
|
||
|
|
||
|
var t = sampler.time;
|
||
|
//t = t < 0 ? 0.1 : t;
|
||
|
|
||
|
var ti = sampler.offset;
|
||
|
//ti = ti < 0 ? 1 : ti;
|
||
|
|
||
|
var t1 = track.frames[ti] * frameTime;
|
||
|
var t2 = track.frames[ti + sign] * frameTime;
|
||
|
var v1 = track.values[ti];
|
||
|
var v2 = track.values[ti + sign];
|
||
|
|
||
|
var value = interpolateLinear(t, t1, t2, v1, v2);
|
||
|
|
||
|
if(value == null) continue;
|
||
|
|
||
|
transformMap.set(track.target, value);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public function sampleAction(sampler: ActionSampler, transformMap: Map<String, FastFloat>){
|
||
|
|
||
|
if(! sampler.actionDataInit) {
|
||
|
var objanim = getAction(sampler.action);
|
||
|
sampler.setObjectAction(objanim);
|
||
|
}
|
||
|
|
||
|
var objanim = sampler.getObjectAction();
|
||
|
updateAnimSampled(objanim.anim, transformMap, sampler);
|
||
|
}
|
||
|
|
||
|
public function blendActionObject(transformMap1: Map<String, FastFloat>, transformMap2: Map<String, FastFloat>, transformMapRes: Map<String, FastFloat>, factor: FastFloat ) {
|
||
|
|
||
|
for(track in transformMapRes.keys()){
|
||
|
|
||
|
var v1 = transformMap1.get(track);
|
||
|
var v2 = transformMap2.get(track);
|
||
|
|
||
|
if(v1 == null || v2 == null) continue;
|
||
|
|
||
|
var maxVal: FastFloat = 1.0;
|
||
|
var tempValue = (maxVal - factor) * v1 + factor * v2;
|
||
|
transformMapRes.set(track, tempValue);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
inline function interpolateLinear(t: FastFloat, t1: FastFloat, t2: FastFloat, v1: FastFloat, v2: FastFloat): Null<FastFloat> {
|
||
|
var s = (t - t1) / (t2 - t1);
|
||
|
return (1.0 - s) * v1 + s * v2;
|
||
|
}
|
||
|
|
||
|
@:access(iron.object.Transform)
|
||
|
function updateTransform(transformMap: Map<String, FastFloat>, transform: Transform) {
|
||
|
|
||
|
var t = transform;
|
||
|
t.resetDelta();
|
||
|
|
||
|
for (track in transformMap.keys()){
|
||
|
|
||
|
var value = transformMap.get(track);
|
||
|
|
||
|
if(value == null) continue;
|
||
|
|
||
|
switch (track) {
|
||
|
|
||
|
case "xloc": transform.loc.x = value;
|
||
|
case "yloc": transform.loc.y = value;
|
||
|
case "zloc": transform.loc.z = value;
|
||
|
case "xrot": transform.setRotation(value, transform._eulerY, transform._eulerZ);
|
||
|
case "yrot": transform.setRotation(transform._eulerX, value, transform._eulerZ);
|
||
|
case "zrot": transform.setRotation(transform._eulerX, transform._eulerY, value);
|
||
|
case "qwrot": transform.rot.w = value;
|
||
|
case "qxrot": transform.rot.x = value;
|
||
|
case "qyrot": transform.rot.y = value;
|
||
|
case "qzrot": transform.rot.z = value;
|
||
|
case "xscl": transform.scale.x = value;
|
||
|
case "yscl": transform.scale.y = value;
|
||
|
case "zscl": transform.scale.z = value;
|
||
|
// Delta
|
||
|
case "dxloc": transform.dloc.x = value;
|
||
|
case "dyloc": transform.dloc.y = value;
|
||
|
case "dzloc": transform.dloc.z = value;
|
||
|
case "dxrot": transform._deulerX = value;
|
||
|
case "dyrot": transform._deulerY = value;
|
||
|
case "dzrot": transform._deulerZ = value;
|
||
|
case "dqwrot": transform.drot.w = value;
|
||
|
case "dqxrot": transform.drot.x = value;
|
||
|
case "dqyrot": transform.drot.y = value;
|
||
|
case "dqzrot": transform.drot.z = value;
|
||
|
case "dxscl": transform.dscale.x = value;
|
||
|
case "dyscl": transform.dscale.y = value;
|
||
|
case "dzscl": transform.dscale.z = value;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|