Jump to content

LookAt / Rotate towards a point using only x and y coordinates


rainerpl
 Share

Recommended Posts

Hi @rainerpl

We can accomplish this by making a function,

we'll simply borrow the 2d rotation parts of the lookAt function, mainly 

var dv = targetPoint.subtract(this.position);
var yaw = -Math.atan2(dv.z, dv.x) - Math.PI / 2;

 

now we insert it in a function..

function lookAt(tM, lAt) {
	/*
	 * tM = mesh to rotate.
	 * lAt = vector3(xyz) of target position to look at
	 */
	 
	lAt = lAt.subtract(tM.position);
	tM.rotation.y = -Math.atan2(lAt.z, lAt.x) - Math.PI/2;
}

and finally we use it like this;

//mesh = Mesh we want to rotate
//target = Target point to make the mesh look at.

lookAt(mesh, target);

 

PG; //Click on the ground to rotate the box :)

http://www.babylonjs-playground.com/#Q4LKP#2

Link to comment
Share on other sites

  • 4 weeks later...

@HenryPeng I am afraid I don't have a good answer. I remember I tried to achieve the same when I played with this here: http://p215008.mittwaldserver.info/space/ if you click at an asteroid the ship is supposed to smoothly align with the target and then shoot. But if I remember right it doesn't always work, so I guess there is a flaw in my way of doing it. I also remember I have tried a lot of things but it was never perfect. Maybe somebody else has a good idea how to achieve the in a way that's more...bulletproof. :-/

I think those where the important functions:

/**
 * @param rotatingObject
 * @param pointToRotateTo
 * @returns {boolean}
 */
function facePoint(rotatingObject, pointToRotateTo) {

	// a directional vector from one object to the other one
	var direction = pointToRotateTo.subtract(rotatingObject.position);
	var distanceToTargetPoint = direction.length();

	if(distanceToTargetPoint > 0.5) {

		var axisVectorY = new BABYLON.Vector3(0, 0, 1);
		var directionAxisForY = 'x';
		var deltaY = calculateRotationDeltaForAxis(rotatingObject, 'y', axisVectorY, direction, directionAxisForY);

		var axisVectorZ = new BABYLON.Vector3(0, 1, 0);
		var directionAxisForZ = 'z';
		var deltaZ = calculateRotationDeltaForAxis(rotatingObject, 'z', axisVectorZ, direction, directionAxisForZ);

		var turnAroundYAxisDone = applyRotationForAxis(rotatingObject, 'y', deltaY);
		var turnAroundZAxisDone = applyRotationForAxis(rotatingObject, 'z', deltaZ);

		return (turnAroundYAxisDone && turnAroundZAxisDone) ? true : false;

	}
}

function faceTarget(rotatingObject, target){
	return facePoint(rotatingObject, target.position);
}

function calculateRotationDeltaForAxis(rotatingObject, axis, axisVector, direction, directionAxis){
	var axisVectorNormalized = axisVector.normalize();
	var directionVectorNormalized = direction.normalize();

	// calculate the angel for the new direction
	var angle = Math.acos(BABYLON.Vector3.Dot(axisVectorNormalized, directionVectorNormalized));

	if (directionAxis == 'x') {
		// decide it the angle has to be positive or negative
		if (direction[directionAxis] < 0) angle *= -1;
		// compensate initial rotation of imported spaceship mesh
		angle += Math.PI / 2;
	} else {
		angle -= Math.PI / 2;
	}

	// calculate both angles in degrees
	var playerRotationOnAxis = rotatingObject.rotation[axis];
	// calculate and return the delta
	return playerRotationOnAxis - angle;
}

function applyRotationForAxis(rotatingObject, axis, delta){
	var pi = Math.PI;

	// check what direction to turn to take the shortest turn
	if (delta > pi) {
		delta -= pi*2;
	} else if (delta < -pi) {
		delta += pi*2;
	}

	var absDelta = Math.abs(delta);
	// rotate until the difference between the object angle and the target angle is no more than 3 degrees
	if (absDelta > pi/360) {

		var rotationSpeed = Math.max(0.2, Math.min(absDelta*absDelta, 1));

		if (delta > 0) {
			rotatingObject.rotation[axis] -= rotationSpeed * 0.1;
			if (rotatingObject.rotation[axis] < -pi) {
				rotatingObject.rotation[axis] = pi;
			}
		}
		if (delta < 0) {
			rotatingObject.rotation[axis] += rotationSpeed * 0.1;
			if (rotatingObject.rotation[axis] > pi) {
				rotatingObject.rotation[axis] = -pi;
			}
		}

		// turn not done yet
		return false;

	} else {

		// turn done
		return true;

	}
}

 

Link to comment
Share on other sites

17 minutes ago, iiceman said:

    /**
     * direction vector x,y,z,
     * @param x
     * @param y
     * @param z
     * @param defaultVec default direction(just you set)
     */
    function getFaceRotation(x, y, z, defaultVec) {
        defaultVec = defaultVec || new BABYLON.Vector3(0,0,1); //forward
        var v1 = new BABYLON.Vector3(x,y,z);
        v1.normalize();

        var v2 = defaultVec;
        var axis = BABYLON.Vector3.Cross(v2, v1);
        axis.normalize();
        var angle = Math.acos(BABYLON.Vector3.Dot(v1, v2));

        var rotation = BABYLON.Quaternion.RotationAxis(axis, angle).toEulerAngles();
        return rotation
    }

@iiceman 

I think it mybe a way:P

 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...