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;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}		
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 |