forked from LeenkxTeam/LNXSDK
		
	
		
			
				
	
	
		
			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;
 | |
| 			}
 | |
| 		}		
 | |
| 	}
 | |
| }
 |