forked from LeenkxTeam/LNXSDK
Consolidate and update
This commit is contained in:
@ -40,11 +40,6 @@ class Animation {
|
||||
public var paused = false;
|
||||
var frameTime: FastFloat = 1 / 60;
|
||||
|
||||
var blendTime: FastFloat = 0.0;
|
||||
var blendCurrent: FastFloat = 0.0;
|
||||
var blendFactor: FastFloat = 0.0;
|
||||
|
||||
var lastFrameIndex = -1;
|
||||
var markerEvents: Map<ActionSampler, Map<String, Array<Void->Void>>> = null;
|
||||
|
||||
public var activeActions: Map<String, ActionSampler> = null;
|
||||
@ -63,8 +58,6 @@ class Animation {
|
||||
|
||||
public function play(action = "", onComplete: Void->Void = null, blendTime = 0.0, speed = 1.0, loop = true) {
|
||||
if (blendTime > 0) {
|
||||
this.blendTime = blendTime;
|
||||
this.blendCurrent = 0.0;
|
||||
frameIndex = 0;
|
||||
time = 0.0;
|
||||
}
|
||||
@ -93,6 +86,7 @@ class Animation {
|
||||
}
|
||||
|
||||
public function update(delta: FastFloat) {
|
||||
if (paused) return;
|
||||
if(activeActions == null) return;
|
||||
|
||||
for(sampler in activeActions){
|
||||
@ -160,24 +154,25 @@ class Animation {
|
||||
while (checkFrameIndex(track.frames, time, frameIndex, speed)) frameIndex += sign;
|
||||
|
||||
// Marker events
|
||||
if (markerEvents != null && anim.marker_names != null && frameIndex != lastFrameIndex) {
|
||||
if(markerEvents.get(sampler) != null){
|
||||
if (markerEvents != null && anim.marker_names != null && frameIndex != sampler.offsetOld) {
|
||||
var markerListeners = markerEvents.get(sampler);
|
||||
if (markerListeners != null) {
|
||||
var fromFrame = sampler.offsetOld < 0 ?
|
||||
(speed > 0 ? -1 : track.frames[track.frames.length - 1] + 1) :
|
||||
track.frames[sampler.offsetOld];
|
||||
var toFrame = track.frames[frameIndex];
|
||||
for (i in 0...anim.marker_frames.length) {
|
||||
if (frameIndex == anim.marker_frames[i]) {
|
||||
var markerAct = markerEvents.get(sampler);
|
||||
var ar = markerAct.get(anim.marker_names[i]);
|
||||
if (ar != null) for (f in ar) f();
|
||||
} else {
|
||||
for (j in 0...(frameIndex - lastFrameIndex)) {
|
||||
if (lastFrameIndex + j + 1 == anim.marker_frames[i]) {
|
||||
var markerAct = markerEvents.get(sampler);
|
||||
var ar = markerAct.get(anim.marker_names[i]);
|
||||
if (ar != null) for (f in ar) f();
|
||||
}
|
||||
}
|
||||
var markerFrame = anim.marker_frames[i];
|
||||
var crossed =
|
||||
(speed > 0 && toFrame >= fromFrame && markerFrame > fromFrame && markerFrame <= toFrame) ||
|
||||
(speed < 0 && toFrame <= fromFrame && markerFrame <= fromFrame && markerFrame > toFrame) ||
|
||||
(speed > 0 && toFrame < fromFrame && (markerFrame > fromFrame || markerFrame <= toFrame)) ||
|
||||
(speed < 0 && toFrame > fromFrame && (markerFrame >= toFrame || markerFrame < fromFrame));
|
||||
if (crossed) {
|
||||
var listeners = markerListeners.get(anim.marker_names[i]);
|
||||
if (listeners != null) for (listener in listeners) listener();
|
||||
}
|
||||
}
|
||||
lastFrameIndex = frameIndex;
|
||||
}
|
||||
}
|
||||
|
||||
@ -191,8 +186,8 @@ class Animation {
|
||||
else {
|
||||
frameIndex -= sign;
|
||||
sampler.paused = true;
|
||||
if (sampler.onComplete != null) for(func in sampler.onComplete){ func();};
|
||||
}
|
||||
if (sampler.onComplete != null) for(func in sampler.onComplete){ func();};
|
||||
sampler.trackEnd = true;
|
||||
}
|
||||
|
||||
|
||||
@ -112,6 +112,10 @@ class BoneAnimation extends Animation {
|
||||
this.data = mo != null ? mo.data : null;
|
||||
this.isSkinned = data != null ? data.isSkinned : false;
|
||||
if (this.isSkinned) {
|
||||
if (armature != null && data.geom.skeletonBoneRefs != null
|
||||
&& data.geom.actions.keys().hasNext() == false) {
|
||||
data.geom.addArmature(armature);
|
||||
}
|
||||
var boneSize = 12; // Dual-quat skinning + scaling
|
||||
this.skinBuffer = new Float32Array(skinMaxBones * boneSize);
|
||||
for (i in 0...this.skinBuffer.length) this.skinBuffer[i] = 0;
|
||||
@ -205,18 +209,37 @@ class BoneAnimation extends Animation {
|
||||
}
|
||||
|
||||
function setAction(action: String) {
|
||||
if (armature == null) return;
|
||||
armature.initMats();
|
||||
var a = armature.getAction(action);
|
||||
if (a == null) return;
|
||||
skeletonBones = a.bones;
|
||||
skeletonMats = a.mats;
|
||||
if(! rootMotionCacheInit) skeletonMats.push(Mat4.identity());
|
||||
if (isSkinned) {
|
||||
skeletonBones = data.geom.actions.get(action);
|
||||
var geomMats = data.geom.mats.get(action);
|
||||
if (geomMats != null) {
|
||||
skeletonMats = [];
|
||||
for (i in 0...geomMats.length) {
|
||||
var m = Mat4.identity();
|
||||
m.setFrom(geomMats[i]);
|
||||
skeletonMats.push(m);
|
||||
}
|
||||
}
|
||||
else skeletonMats = null;
|
||||
}
|
||||
if (skeletonBones == null) {
|
||||
if (armature == null) return;
|
||||
armature.initMats();
|
||||
var a = armature.getAction(action);
|
||||
if (a == null) return;
|
||||
skeletonBones = a.bones;
|
||||
skeletonMats = a.mats;
|
||||
}
|
||||
if (skeletonMats.length == skeletonBones.length) skeletonMats.push(Mat4.identity()); // Root motion cache
|
||||
rootMotionCacheInit = true;
|
||||
setMats();
|
||||
}
|
||||
|
||||
function getAction(action: String): Array<TObj> {
|
||||
if (isSkinned) {
|
||||
var bones = data.geom.actions.get(action);
|
||||
if (bones != null) return bones;
|
||||
}
|
||||
if (armature == null) return null;
|
||||
armature.initMats();
|
||||
var a = armature.getAction(action);
|
||||
@ -251,15 +274,91 @@ class BoneAnimation extends Animation {
|
||||
updateAnimation = f;
|
||||
}
|
||||
|
||||
var blendSampler1: ActionSampler = null;
|
||||
var blendSampler2: ActionSampler = null;
|
||||
var blendMats: Array<Mat4> = null;
|
||||
|
||||
public function blend(action1: String, action2: String, factor: FastFloat) {
|
||||
var actionName1: String = getName(action1);
|
||||
var actionName2: String = getName(action2);
|
||||
if (blendSampler1 == null || blendSampler1.action != actionName1) {
|
||||
blendSampler1 = new ActionSampler(actionName1);
|
||||
registerAction("blendSampler1", blendSampler1);
|
||||
}
|
||||
if (blendSampler2 == null || blendSampler2.action != actionName2) {
|
||||
blendSampler2 = new ActionSampler(actionName2);
|
||||
registerAction("blendSampler2", blendSampler2);
|
||||
}
|
||||
blendSampler1.paused = false;
|
||||
blendSampler2.paused = false;
|
||||
if (transitionSampler != null) {
|
||||
transitionSampler.paused = true;
|
||||
transitionSampler = null;
|
||||
}
|
||||
if (currentPlaySampler != null) currentPlaySampler.paused = true;
|
||||
currentPlaySampler = blendSampler1;
|
||||
if (skeletonMats == null) setAction(actionName1);
|
||||
if (skeletonMats == null) return;
|
||||
if (blendMats == null) blendMats = initMatsEmpty();
|
||||
updateAnimation = function(mats) {
|
||||
sampleAction(blendSampler1, mats);
|
||||
sampleAction(blendSampler2, blendMats);
|
||||
blendAction(mats, blendMats, mats, factor);
|
||||
}
|
||||
}
|
||||
|
||||
var playSamplers: Map<String, ActionSampler> = [];
|
||||
var currentPlaySampler: ActionSampler = null;
|
||||
var transitionSampler: ActionSampler = null;
|
||||
var transitionMats: Array<Mat4> = null;
|
||||
var transitionTime: FastFloat = 0.0;
|
||||
var transitionDuration: FastFloat = 0.0;
|
||||
|
||||
override public function play(action = "", onComplete: Void->Void = null, blendTime = 0.2, speed = 1.0, loop = true) {
|
||||
var actionName: String = getName(action);
|
||||
if (actionName != "") {
|
||||
setAction(actionName);
|
||||
super.play(actionName, onComplete, blendTime, speed, loop);
|
||||
var tempAnimParam = new ActionSampler(actionName);
|
||||
registerAction("tempAction", tempAnimParam);
|
||||
var sampler = playSamplers.get(actionName);
|
||||
if (sampler == null) {
|
||||
if (activeActions != null) sampler = activeActions.get(actionName);
|
||||
if (sampler == null) sampler = new ActionSampler(actionName);
|
||||
playSamplers.set(actionName, sampler);
|
||||
}
|
||||
if (transitionSampler != null) {
|
||||
transitionSampler.paused = true;
|
||||
transitionSampler = null;
|
||||
}
|
||||
if (blendTime > 0 && currentPlaySampler != null && currentPlaySampler != sampler && skeletonMats != null) {
|
||||
transitionSampler = currentPlaySampler;
|
||||
if (transitionMats == null) transitionMats = initMatsEmpty();
|
||||
transitionTime = 0.0;
|
||||
transitionDuration = blendTime;
|
||||
if (blendSampler1 != null && blendSampler1 != transitionSampler) blendSampler1.paused = true;
|
||||
if (blendSampler2 != null && blendSampler2 != transitionSampler) blendSampler2.paused = true;
|
||||
}
|
||||
else if (currentPlaySampler != null) currentPlaySampler.paused = true;
|
||||
currentPlaySampler = sampler;
|
||||
sampler.speed = speed;
|
||||
sampler.loop = loop;
|
||||
sampler.onComplete = onComplete != null ? [onComplete] : null;
|
||||
sampler.restartAction();
|
||||
registerAction(actionName, sampler);
|
||||
updateAnimation = function(mats){
|
||||
sampleAction(tempAnimParam, mats);
|
||||
if (transitionSampler != null) {
|
||||
sampleAction(transitionSampler, transitionMats);
|
||||
sampleAction(sampler, mats);
|
||||
var f = transitionTime / transitionDuration;
|
||||
if (f > 1.0) f = 1.0;
|
||||
f = f * f * (3.0 - 2.0 * f); // Smoothstep
|
||||
blendAction(transitionMats, mats, mats, f, -1, 0.0);
|
||||
transitionTime += delta;
|
||||
if (transitionTime >= transitionDuration) {
|
||||
transitionSampler.paused = true;
|
||||
transitionSampler = null;
|
||||
}
|
||||
}
|
||||
else sampleAction(sampler, mats);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -279,6 +378,7 @@ class BoneAnimation extends Animation {
|
||||
#end
|
||||
|
||||
super.update(delta);
|
||||
if (paused) return;
|
||||
if(updateAnimation != null) {
|
||||
updateAnimation(skeletonMats);
|
||||
}
|
||||
@ -540,12 +640,14 @@ class BoneAnimation extends Animation {
|
||||
|
||||
|
||||
inline function interpolateSample(track: TTrack, m: Mat4, t: FastFloat, ti: Int, sign: Int) {
|
||||
var tj = ti + sign;
|
||||
if (tj < 0 || tj >= track.frames.length) tj = ti;
|
||||
var t1 = track.frames[ti] * frameTime;
|
||||
var t2 = track.frames[ti + sign] * frameTime;
|
||||
var s: FastFloat = (t - t1) / (t2 - t1); // Linear
|
||||
var t2 = track.frames[tj] * frameTime;
|
||||
var s: FastFloat = t2 != t1 ? (t - t1) / (t2 - t1) : 0.0; // Linear
|
||||
|
||||
m1.setF32(track.values, ti * 16); // Offset to 4x4 matrix array
|
||||
m2.setF32(track.values, (ti + sign) * 16);
|
||||
m2.setF32(track.values, tj * 16);
|
||||
|
||||
// Decompose
|
||||
m1.decompose(vpos, q1, vscl);
|
||||
@ -643,7 +745,7 @@ class BoneAnimation extends Animation {
|
||||
return actionMats != null ? actionMats[getBoneIndex(bone)] : null;
|
||||
}
|
||||
|
||||
function getWorldMat(actionMats: Array<Mat4>, bone: TObj): Mat4 {
|
||||
public function getWorldMat(actionMats: Array<Mat4>, bone: TObj): Mat4 {
|
||||
if (applyParent == null) {
|
||||
applyParent = [];
|
||||
for (m in actionMats) applyParent.push(true);
|
||||
@ -728,7 +830,7 @@ class BoneAnimation extends Animation {
|
||||
// Skip if root motion is disabled
|
||||
if(j < 0) continue;
|
||||
// Use Action 2
|
||||
if(skeletonBones[j].bone_layers[layerMask] || layerMask < 0){
|
||||
if(layerMask < 0 || skeletonBones[j].bone_layers[layerMask]){
|
||||
resultMat[i].setFrom(actionMats2[i]);
|
||||
}
|
||||
// Use Action 1 if not in layer
|
||||
@ -744,7 +846,7 @@ class BoneAnimation extends Animation {
|
||||
// Skip if root motion is disabled
|
||||
if(j < 0) continue;
|
||||
// Blend
|
||||
if(skeletonBones[j].bone_layers[j] || layerMask < 0) {
|
||||
if(layerMask < 0 || skeletonBones[j].bone_layers[layerMask]) {
|
||||
// Decompose
|
||||
m.setFrom(actionMats1[i]);
|
||||
m1.setFrom(actionMats2[i]);
|
||||
@ -786,8 +888,10 @@ class BoneAnimation extends Animation {
|
||||
}
|
||||
else{
|
||||
for(i in 0...baseActionMats.length){
|
||||
var j = i == skeletonBones.length ? rootMotionIndex : i;
|
||||
if(j < 0) continue;
|
||||
|
||||
if(skeletonBones[i].bone_layers[layerMask] || layerMask < 0) {
|
||||
if(layerMask < 0 || skeletonBones[j].bone_layers[layerMask]) {
|
||||
// Decompose
|
||||
m.setFrom(baseActionMats[i]);
|
||||
m1.setFrom(addActionMats[i]);
|
||||
|
||||
@ -13,7 +13,10 @@ class Constraint {
|
||||
}
|
||||
|
||||
public function apply(transform: Transform) {
|
||||
if (target == null && raw.target != null) target = Scene.active.getChild(raw.target).transform;
|
||||
if (target == null && raw.target != null) {
|
||||
var o = Scene.active.getChild(raw.target);
|
||||
if (o != null) target = o.transform;
|
||||
}
|
||||
|
||||
if (target == null && raw.type != "LIMIT_LOCATION" && raw.type != "LIMIT_ROTATION" && raw.type != "LIMIT_SCALE") return;
|
||||
|
||||
|
||||
@ -48,7 +48,6 @@ class MeshObject extends Object {
|
||||
#if lnx_morph_target
|
||||
public var morphTarget: MorphTarget = null;
|
||||
#end
|
||||
public var vertexGroups: Map<String, Array<Vec4>> = null;
|
||||
|
||||
#if lnx_veloc
|
||||
public var prevMatrix = Mat4.identity();
|
||||
@ -240,6 +239,7 @@ class MeshObject extends Object {
|
||||
return setCulled(isShadow, true);
|
||||
}
|
||||
|
||||
#if rp_shadowmap
|
||||
if (isShadow && light.data.raw.type == "sun") {
|
||||
var frame = RenderPath.active.frame;
|
||||
if (shadowCameraCullFrame == frame && shadowCameraCullCamera == camera &&
|
||||
@ -270,10 +270,8 @@ class MeshObject extends Object {
|
||||
}
|
||||
}
|
||||
}
|
||||
#end
|
||||
}
|
||||
|
||||
//culled = false;
|
||||
//return culled;
|
||||
return setCulled(isShadow, false);
|
||||
}
|
||||
|
||||
|
||||
@ -15,6 +15,7 @@ class Object {
|
||||
public var transform: Transform;
|
||||
public var constraints: Array<Constraint> = null;
|
||||
public var traits: Array<Trait> = [];
|
||||
public var vertexGroups: Map<String, Array<iron.math.Vec4>> = null;
|
||||
|
||||
public var parent: Object = null;
|
||||
public var children: Array<Object> = [];
|
||||
|
||||
@ -17,6 +17,7 @@ class ObjectAnimation extends Animation {
|
||||
public var oactions: Array<TSceneFormat>;
|
||||
var oaction: TObj;
|
||||
var s0: FastFloat = 0.0;
|
||||
var delta: FastFloat = 0;
|
||||
var bezierFrameIndex = -1;
|
||||
|
||||
var updateAnimation: Map<String, FastFloat> -> Void;
|
||||
@ -26,7 +27,11 @@ class ObjectAnimation extends Animation {
|
||||
public var transformMap: Map<String, FastFloat>;
|
||||
|
||||
var defaultSampler: ActionSampler = null;
|
||||
static inline var DEFAULT_SAMPLER_ID = "__object_default_action__";
|
||||
var playSamplers: Map<String, ActionSampler> = [];
|
||||
var transitionSampler: ActionSampler = null;
|
||||
var transitionMap: Map<String, FastFloat> = null;
|
||||
var transitionTime: FastFloat = 0.0;
|
||||
var transitionDuration: FastFloat = 0.0;
|
||||
|
||||
public static var trackNames: Array<String> = [ "xloc", "yloc", "zloc",
|
||||
"xrot", "yrot", "zrot",
|
||||
@ -67,27 +72,59 @@ class ObjectAnimation extends Animation {
|
||||
oaction = getAction(this.action);
|
||||
if (oaction != null) {
|
||||
isSampled = oaction.sampled != null && oaction.sampled;
|
||||
if (defaultSampler != null) {
|
||||
deRegisterAction(DEFAULT_SAMPLER_ID);
|
||||
var sampler = playSamplers.get(this.action);
|
||||
if (sampler == null) {
|
||||
if (activeActions != null) sampler = activeActions.get(this.action);
|
||||
if (sampler == null) sampler = new ActionSampler(this.action);
|
||||
playSamplers.set(this.action, sampler);
|
||||
}
|
||||
var callbacks = onComplete != null ? [onComplete] : null;
|
||||
defaultSampler = new ActionSampler(this.action, speed, loop, false, callbacks);
|
||||
registerAction(DEFAULT_SAMPLER_ID, defaultSampler);
|
||||
if (paused) defaultSampler.paused = true;
|
||||
if (transitionSampler != null) {
|
||||
transitionSampler.paused = true;
|
||||
transitionSampler = null;
|
||||
}
|
||||
if (blendTime > 0 && defaultSampler != null && defaultSampler != sampler) {
|
||||
transitionSampler = defaultSampler;
|
||||
transitionMap = initTransformMap();
|
||||
transitionTime = 0.0;
|
||||
transitionDuration = blendTime;
|
||||
}
|
||||
else if (defaultSampler != null) defaultSampler.paused = true;
|
||||
defaultSampler = sampler;
|
||||
sampler.speed = speed;
|
||||
sampler.loop = loop;
|
||||
sampler.onComplete = onComplete != null ? [onComplete] : null;
|
||||
sampler.restartAction();
|
||||
registerAction(this.action, sampler);
|
||||
updateAnimation = function(map: Map<String, FastFloat>) {
|
||||
sampleAction(defaultSampler, map);
|
||||
if (transitionSampler != null) {
|
||||
sampleAction(transitionSampler, transitionMap);
|
||||
sampleAction(sampler, map);
|
||||
var f = transitionTime / transitionDuration;
|
||||
if (f > 1.0) f = 1.0;
|
||||
f = f * f * (3.0 - 2.0 * f); // Smoothstep
|
||||
blendActionObject(transitionMap, map, map, f);
|
||||
transitionTime += delta;
|
||||
if (transitionTime >= transitionDuration) {
|
||||
transitionSampler.paused = true;
|
||||
transitionSampler = null;
|
||||
}
|
||||
}
|
||||
else sampleAction(sampler, map);
|
||||
};
|
||||
}
|
||||
else {
|
||||
if (defaultSampler != null) {
|
||||
deRegisterAction(DEFAULT_SAMPLER_ID);
|
||||
defaultSampler = null;
|
||||
if (transitionSampler != null) {
|
||||
transitionSampler.paused = true;
|
||||
transitionSampler = null;
|
||||
}
|
||||
if (defaultSampler != null) defaultSampler.paused = true;
|
||||
defaultSampler = null;
|
||||
updateAnimation = null;
|
||||
}
|
||||
}
|
||||
|
||||
override public function update(delta: FastFloat) {
|
||||
this.delta = delta;
|
||||
if (!object.visible || object.culled) return;
|
||||
|
||||
#if lnx_debug
|
||||
@ -98,7 +135,6 @@ class ObjectAnimation extends Animation {
|
||||
transformMap = initTransformMap();
|
||||
|
||||
super.update(delta);
|
||||
if (defaultSampler != null) defaultSampler.paused = paused;
|
||||
if (paused) return;
|
||||
if (updateAnimation == null) return;
|
||||
if (!isSkinned) updateObjectAnimation();
|
||||
@ -160,11 +196,13 @@ class ObjectAnimation extends Animation {
|
||||
|
||||
var ti = sampler.offset;
|
||||
//ti = ti < 0 ? 1 : ti;
|
||||
var tj = ti + sign;
|
||||
if (tj < 0 || tj >= track.frames.length) tj = ti;
|
||||
|
||||
var t1 = track.frames[ti] * frameTime;
|
||||
var t2 = track.frames[ti + sign] * frameTime;
|
||||
var t2 = track.frames[tj] * frameTime;
|
||||
var v1 = track.values[ti];
|
||||
var v2 = track.values[ti + sign];
|
||||
var v2 = track.values[tj];
|
||||
|
||||
var value = interpolateLinear(t, t1, t2, v1, v2);
|
||||
|
||||
@ -202,6 +240,7 @@ class ObjectAnimation extends Animation {
|
||||
}
|
||||
|
||||
inline function interpolateLinear(t: FastFloat, t1: FastFloat, t2: FastFloat, v1: FastFloat, v2: FastFloat): Null<FastFloat> {
|
||||
if (t2 == t1) return v1;
|
||||
var s = (t - t1) / (t2 - t1);
|
||||
return (1.0 - s) * v1 + s * v2;
|
||||
}
|
||||
|
||||
@ -131,13 +131,20 @@ class Transform {
|
||||
dscale = new Vec4().set(1, 1, 1);
|
||||
}
|
||||
|
||||
static var _cdLoc = new Vec4();
|
||||
static var _cdRot = new Quat();
|
||||
static var _cdScale = new Vec4();
|
||||
|
||||
function composeDelta() {
|
||||
// Delta transform
|
||||
dloc.addvecs(loc, dloc);
|
||||
dscale.addvecs(dscale, scale);
|
||||
drot.fromEuler(_deulerX, _deulerY, _deulerZ);
|
||||
drot.multquats(rot, drot);
|
||||
local.compose(dloc, drot, dscale);
|
||||
// Delta transform: additive location, multiplicative rotation and scale
|
||||
_cdLoc.addvecs(loc, dloc);
|
||||
_cdScale.x = scale.x * dscale.x;
|
||||
_cdScale.y = scale.y * dscale.y;
|
||||
_cdScale.z = scale.z * dscale.z;
|
||||
_cdRot.fromEuler(_deulerX, _deulerY, _deulerZ);
|
||||
_cdRot.multquats(_cdRot, drot);
|
||||
_cdRot.multquats(rot, _cdRot);
|
||||
local.compose(_cdLoc, _cdRot, _cdScale);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user