Calculate X angle between ImageTarget and ARCamera in Vuforia Unity? - c#

I have one imageTarget, I track that imageTarget with ARCamera, I want to find angle X of imageTarget relative to ARCamera(mobile device), because I need to move my object(imageTarget) towards the camera. I am using Vuforia in Unity. If possible please provide me code sample, as I am new in Unity, don't know much. I am sharing you my effort here. I am using this code for calculating angle, I think it is not correct. Please review it. Please help me.
Transform dummy = new GameObject("Dummy").transform;
dummy.SetParent(trackableEventHandler.transform);
dummy.LookAt(Camera.main.transform, trackableEventHandler.transform.up);
float angle = Mathf.Atan2(dummy.forward.z, dummy.forward.x) - Mathf.Atan2(trackableEventHandler.transform.forward.z, trackableEventHandler.transform.forward.x);
angle *= Mathf.Rad2Deg;
text.text = angle.ToString();

Try this
Transform dummy = new GameObject("Dummy").transform;
dummy.SetParent(trackableEventHandler.transform);
dummy.LookAt(Camera.main.transform, trackableEventHandler.transform.up);
float angle = Vector3.Angle(Camera.main.transform.forward, dummy.position - Camera.main.transform.position);
text.text = angle.ToString();
Edit: For signed angles, use this instead
float angle = Vector3.SignedAngle(Camera.main.transform.forward, dummy.position - Camera.main.transform.position, Vector3.up);
For 2D signed angles, use this instead
float angle = Vector2.SignedAngle(Vector2(Camera.main.transform.forward.x, Camera.main.transform.forward.z), Vector2(dummy.positionx.x - Camera.main.transform.position.x, dummy.positionx.z - Camera.main.transform.position.z));

Related

Quaternion.Lerp not working properly in Unity3d

I'm using Quaternion.Lerp to rotate a joint with a certain angle, but when I use the below code I find the joint rotating very far although I specified it to rotate with only 5. Any thoughts please?
newRot.y += currentTransform.localRotation.y + 5f;
blendWeight = 0;
if ( blendWeight < 1)
{
animationRotation = currentTransform.transform.localRotation;
newRotation = Quaternion.Euler(newRot.x, newRot.y, newRot.z);
blendWeight += Time.deltaTime/0.9f;
currentTransform.transform.localRotation = Quaternion.Lerp (animationRotation,newRotation, blendWeight);
}
where newRot is a Vector3
If you want to add 5 degrees to y, you must use eulerAngles and not directly rotation (which il a quaternion). Generaly speaking you should never set the xyzw components of a quaternion.
If you want y slowly rotates an object, consider using RotateTowards (for a given target orientation) or transform.Rotate (for a given speed).

How can I rotate a vector (centripetal force)?

I'm trying to implement centripetal force in a programming language.
I saw some videos teaching the theory. But I dont know how to apply that in a programming language.
If I understand I have to apply centripetal force ac = v²/r to the velocity vector. But I dont know exactly how to proceed.
I have two game objects, one depicting Earth, other depicting Moon. What I wanted is to translate the moon around earth and using a button to "cut/cancel" the centripetal force in order to the moon get out to the earth's orbit.
I have no clue how to start that.
All I know is to rotate like this:
velocity.x = Mathf.Cos(Time.time) * earth_moon_radius;
velocity.z = Mathf.Sin(Time.time) * earth_moon_radius;
moon.transform.position = velocity;
But how to apply centripetal force as described above?
If you just want to have the moon rotating around earth and some trigger to release the moon, it's easier to use rotation around a center instead of forces. Given the following GameObject hierarchy:
Center (MoonRotator attached)
-- Moon
-- Earth
public class MoonRotator : MonoBehaviour
{
public bool cancelCentripetalForce = false;
public Vector3 angularVelocity = new Vector3 (0f, 0f, 100f);
public GameObject moon;
void Update () {
if (cancelCentripetalForce) {
Vector3 radius = moon.transform.position - transform.position;
Vector3 angularVelocityRadians = Mathf.Deg2Rad * angularVelocity;
moon.rigidbody.velocity = Vector3.Cross (angularVelocityRadians, radius);
moon.transform.parent = null;
Destroy (this);
} else {
Vector3 rot = transform.rotation.eulerAngles + angularVelocity * Time.deltaTime;
transform.rotation = Quaternion.Euler (rot);
}
}
}
If cancelCentripetalForce is set true Moon stops travelling around earth but proceeds with its current tangential velocity. This is given as:
v = ω × r
Earth has localPosition (0, 0, 0) and Moon is in this example located in the x-y plane rotating around the z axis.
If you want to cancel the force, add an opposing force vector that is based on your object's linear velocity and current direction.
So I have an object pointing straight along the Z axis. The object's 'forward' vector is 0, 0, 1. Do 1 - Math.abs(forward.x), same for y and z to get 1, 1, 0 when you're pointing forward along the Z axis. You want the direction you're pointing in to be 0'd so that the inertia from that direction is not damped in any way. Now you can apply a cancellation force in any direction that you are NOT pointed in.
This means that if your object is moving in any direction in world space that it's not facing in you can easily apply a cancellation force that is multiplied by the object's linear velocity to get circular motion that uses forces instead of directly setting velocity.
Another way you can do it is solve for V by manually setting it, then find radius using V=RW. You should know V and R or W. Now you can find the force necessary to keep the orbit stable around a point, rather than adding inertia from every frame.

Unity C# Quaternion Rotation Correcting orientation

IHi I've been working on a camera rotation method.
I'm trying to rotate a camera using the mouse inputs.
I need the horizontal rotation to be parallel to a x,y plane(my board) and the vertical rotation to be limited to certain angle(something like 40 degree to -40).
I use quaternions to rotate the camera.
Here my code so far
float angle = (mouseX_Current - mouseX_ActionStart) * 0.25f;
Quaternion horizontalRotationQuat = Quaternion.AngleAxis(angle, Vector3.up);
angle = (mouseY_Current - mouseY_ActionStart) * 0.25f;
Quaternion verticalRotationQuat = Quaternion.AngleAxis(angle, Vector3.right);
Camera.main.transform.rotation *= (horizontalRotationQuat * verticalRotationQuat);
My problem is that by adding those mouse related rotations to my current camera orientation quaternion the camera is no more parallel to the plane(x,y) which it s looking at.
I' ve been trying to create a correction quaternion to add to the camera quaternion after adding those mouse related rotations but I can't seem to find the right one.
Quaternion currentOrientationQuat = Camera.main.transform.rotation;
Quaternion corretionQuat = new Quaternion(0.0f, 0.0f, - currentOrientationQuat.z, currentOrientationQuat.w);
Camera.main.transform.rotation *= corretionQuat;
If someone could help me out on this I would be very grateful.
Thanks.
Sorry for the English, not my primary language.
Solved this using another method
float angle = (mouseX_Current - mouseX_ActionStart) * 0.25f;
Camera.main.transform.Rotate(0.0f, 0.0f, angle, Space.World);
angle = (mouseY_Current - mouseY_ActionStart) * 0.25f;
Camera.main.transform.Rotate(angle, 0.0f, 0.0f, Space.Self);
Feeling dumb after seeing how easy it was to do it.
Did'nt even needed the quaternions for this one.

C# XNA Mouse position projected to 3D plane

I'm working on a 3D XNA project, and I've been thinking about this problem for like 2 weeks.
So I just decided to ask you.
Basically I have a flat plane and i want to project the mouse position to that plane, but how?
I tried many ways to do it, calculated angles...
But i figured out, that the distance must effect on the X position, maybe some math is needed what I've never heard before.
I did some code few years ago which returns the position as Vector3(x,y,z), given mouse state:
private Vector3 FindWhereClicked(MouseState ms)
{
Vector3 nearScreenPoint = new Vector3(ms.X, ms.Y, 0);
Vector3 farScreenPoint = new Vector3(ms.X, ms.Y, 1);
Vector3 nearWorldPoint = device.Viewport.Unproject(nearScreenPoint, cam.projectionMatrix, cam.viewMatrix, Matrix.Identity);
Vector3 farWorldPoint = device.Viewport.Unproject(farScreenPoint, cam.projectionMatrix, cam.viewMatrix, Matrix.Identity);
Vector3 direction = farWorldPoint - nearWorldPoint;
float zFactor = -nearWorldPoint.Y / direction.Y;
Vector3 zeroWorldPoint = nearWorldPoint + direction * zFactor;
return zeroWorldPoint;
}
device is an instance of GraphicsDevice.
Hope it works for you.

Camera flip problem

I'm programming a game in C# using the XNA3.1 engine. However I'm having a small issue with my camera, basically my camera tends to "flip" when it rotates more than 180 degrees on its roll (when the camera reaches 180 degrees, it seems to flip back to 0 degrees). The code for obtaining the view matrix is as follows:
Globals.g_GameProcessingInfo.camera.viewMat = Matrix.CreateLookAt(Globals.g_GameProcessingInfo.camera.target.pos, Globals.g_GameProcessingInfo.camera.LookAt, up); //Calculate the view matrix
The Globals.g_GameProcessingInfo.camera.LookAt variable the position 1 unit directly in front of the camera, relative to the rotation of the camera, and the "up" variable is obtained with the following function:
static Vector3 GetUp() //Get the up Vector of the camera
{
Vector3 up = Vector3.Zero;
Quaternion quat = Quaternion.Identity;
Quaternion.CreateFromYawPitchRoll(Globals.g_GameProcessingInfo.camera.target.rot.Y, Globals.g_GameProcessingInfo.camera.target.rot.X, Globals.g_GameProcessingInfo.camera.target.rot.Z, out quat);
up.X = 2 * quat.X * quat.Y - 2 * quat.W * quat.Z; //Set the up x-value based on the orientation of the camera
up.Y = 1 - 2 * quat.X * quat.Z - 2 * quat.Z * quat.Z; //Set the up y-value based on the orientation of the camera
up.Z = 2 * quat.Z * quat.Y + 2 * quat.W * quat.X; //Set the up z-value based on the orientation of the camera
return up; //Return the up Vector3
}
I got same problems in OpenGL with gluLookAt. I fixed that problem with my own camera class:
void Camera::ComputeVectors()
{
Matrix4x4 rotX, rotZ;
Quaternion q_x, q_y, q_z;
Quaternion q_yx, q_yz;
q_x.FromAngleAxis(radians.x, startAxisX);
q_y.FromAngleAxis(radians.y, startAxisY);
q_z.FromAngleAxis(radians.z, startAxisZ);
q_yx = q_y * q_x;
q_yx.ToMatrix(rotZ);
q_yz = q_y * q_z;
q_yz.ToMatrix(rotX);
axisX = startAxisX;
axisZ = startAxisZ;
axisX.Transform(rotX);
axisZ.Transform(rotZ);
axisY = axisX.Cross(axisZ);
position = startPosition;
position -= center;
position.Transform(q_yx);
position += center;
}
It is maybe overcomplicated, but working. axisY is your up vector.
Full code listing is at:
http://github.com/filipkunc/opengl-editor-cocoa/blob/master/PureCpp/MathCore/Camera.cpp
Hope it helps.
This is probably slower but the only way I know to do with would be the with the rotation matrix for 3D. Wikipedia Link
Where
and U = (Camera.position - Camera.lookat).norm
... Now, I believe that would give you the rotation part of the view matrix. However, I'm not 100% on it. I'm still looking into this though.
meh was hoping to see a tan in there somewhere.
can you link to where you got your equation from please?
(am at work and really don;t want to sit down myself and derive it)
how are you setting your camera rotation? are you sure nothing is going on there?
I'm a bit unsure about the math in your GetUp method. Could you elaborate on the math behind it?
In my lookat camera I initialize my up-vector once and then rotate that vector using a quaternion. This removes the possibility of trying to do a cross-product on parallel vectors in order to calculate the up vector.
Some semicode to clarify perhaps:
var up = Vector3.Up;
var target = <some point in space>;
var rotation = <current rotation quaternion>;
var forward = target - position;
forward = Vector3.Transform(forward, rotation);
var updatedPosition = target - forward;
var updatedUp = Vector3.Transform(up, rotation);
var view = Matrix.CreateLookAt(updatedPosition, target, updatedUp);
Since I wasn't satisfied with the answers here already, I had to figure this out myself.
What I discovered is it's actually quite simple. Just do this:
Matrix ypr = Matrix.CreateFromYawPitchRoll(yaw, pitch, roll);
Vector3 up = Vector3.Transform(Vector3.Up, ypr);
"up" is the direction you want.

Categories