Browse Source

LookAt: Add lock axis

trethaller 6 years ago
parent
commit
b1b7541d62
1 changed files with 54 additions and 12 deletions
  1. 54 12
      hide/prefab/fx/LookAt.hx

+ 54 - 12
hide/prefab/fx/LookAt.hx

@@ -1,16 +1,22 @@
 package hide.prefab.fx;
 
 
+@:access(hide.prefab.fx.LookAt)
 class LookAtInstance {
 	var object: h3d.scene.Object;
 	var target: h3d.scene.Object;
-	public function new(obj, target) {
+	var definition: LookAt;
+
+	public function new(def, obj, target) {
+		this.definition = def;
 		this.object = obj;
 		this.target = target;
 	}
 
 	static var tmpMat = new h3d.Matrix();
-	static var tmpVec = new h3d.Vector();
+	static var deltaVec = new h3d.Vector();
+	static var lockAxis = new h3d.Vector();
+	static var invParentQ = new h3d.Quat();
 	public function apply() {
 		if(object == null || object.getScene() == null)
 			return;
@@ -21,27 +27,58 @@ class LookAtInstance {
 			else
 				object.getScene().camera.pos;
 
-		tmpVec.load(lookAtPos.sub(object.getAbsPos().getPosition()));
-		if(tmpVec.lengthSq() < 0.001)
+		deltaVec.load(lookAtPos.sub(object.getAbsPos().getPosition()));
+		if(deltaVec.lengthSq() < 0.001)
 			return;
-		h3d.Matrix.lookAtX(tmpVec, tmpMat);
+
+		tmpMat.load(object.parent.getAbsPos());
+		tmpMat.invert();
+		invParentQ.initRotateMatrix(tmpMat);
+
+		if(definition.lockAxis != null) {
+			lockAxis.set(definition.lockAxis[0], definition.lockAxis[1], definition.lockAxis[2]);
+			if(lockAxis.lengthSq() > 0.001) {
+				var targetOnPlane = h3d.col.Plane.fromNormalPoint(lockAxis.toPoint(), new h3d.col.Point()).project(deltaVec.toPoint()).toVector();
+				targetOnPlane.normalize();
+				var frontAxis = new h3d.Vector(1, 0, 0);
+				var angle = hxd.Math.acos(frontAxis.dot3(targetOnPlane));
+
+				var cross = frontAxis.cross(deltaVec);
+				if(lockAxis.dot3(cross) < 0)
+					angle = -angle;
+
+				var q = object.getRotationQuat();
+				q.initRotateAxis(lockAxis.x, lockAxis.y, lockAxis.z, angle);
+				q.multiply(invParentQ, q);
+				object.setRotationQuat(q);
+				return;
+			}
+		}
+
+		// Default look at
+		h3d.Matrix.lookAtX(deltaVec, tmpMat);
 		var q = object.getRotationQuat();
 		q.initRotateMatrix(tmpMat);
 		object.setRotationQuat(q);
 	}
 }
 
+@:allow(hide.prefab.fx.LookAt.LookAtInstance)
 class LookAt extends Prefab {
 
-	public var target(default,null) : String;
+	var target(default,null) : String;
+	var lockAxis: Array<Float> = [0,0,0];
 
 	override public function load(v:Dynamic) {
 		target = v.target;
+		if(v.lockAxis != null)
+			lockAxis = v.lockAxis;
 	}
 
 	override function save() {
 		return {
-			target : target
+			target : target,
+			lockAxis: lockAxis
 		};
 	}
 
@@ -49,7 +86,7 @@ class LookAt extends Prefab {
 		var targetObj = null;
 		if(target != "camera")
 			targetObj = ctx.locateObject(target);
-		ctx.custom = new LookAtInstance(ctx.local3d, targetObj);
+		ctx.custom = new LookAtInstance(this, ctx.local3d, targetObj);
 	}
 
 	override function makeInstance( ctx : Context ) {
@@ -69,13 +106,18 @@ class LookAt extends Prefab {
 	}
 
 	override function edit(ctx:EditContext) {
-		var props = ctx.properties.add(new hide.Element('
+		var group = new hide.Element('
+		<div class="group" name="LookAt">
 			<dl>
-				<dt>Target</dt><dd><select field="target"><option value="">-- Choose --</option></select>
+				<dt>Target</dt><dd><select field="target"><option value="">-- Choose --</option></select></dd>
 			</dl>
-		'),this, function(_) {
+		</div>');
+
+		group.append(hide.comp.PropsEditor.makePropsList([
+			{ name: "lockAxis", t: PVec(3), def: [1,0,0] }
+		]));
 
-		});
+		var props = ctx.properties.add(group ,this, function(_) { trace(this.lockAxis); });
 
 		var select = props.find("select");
 		var opt = new hide.Element("<option>").attr("value", "camera").html("Camera");