Log in or register to post comments

Rotation and PoseMatrix

July 23, 2012 - 1:26pm #1

I am wondering first how to get the pose matrix (using unity3d) and how to then figure out its position to use for rotation.

I have a model that i move with my finger. when it is head on Everything looks ok, swipe finger left model rotates left along the x axis. move right and model rotates along right axis. Move up and also moves properly. The bad stuff happens when i change the angle of the phone/tablet. I want it so that for instace if the phone is at a 45 degree angle than swiping across left to right have not the local x axis of model be transformed but its axis in relation to the world.

I have tried object.transform.rotate(vector3, Space.World) but the transformations are exactly the same in space.self and space.world.

I do not know how i would go about basically transformation with respect to world and current target pose.

Rotation and PoseMatrix

August 14, 2012 - 9:07am #12

Are you sure. Because this code looks to me as if it would rotate the object around the objects y axis regardless of what angle the camera is at.

Also David your below code suffers from gimble lock if i want to rotate around both x and y.

Rotation and PoseMatrix

August 14, 2012 - 9:03am #11

My previous post had a single bug when turned sideways it didnt work. But i accidentaly found a better way when trying for two finger rotation.

Here is my new Rotate code (single finger)

public void Rotate(float rotateLeftRight, float rotateUpDown)

{

Camera cam = Camera.mainCamera;

 

//Gets the world vector space for cameras up vector 

Vector3 relativeUp = cam.transform.TransformDirection(Vector3.up);

//Gets world vector for space cameras right vector

Vector3 relativeRight = cam.transform.TransformDirection(Vector3.right);

 

//Turns relativeUp vector from world to objects local space

Vector3 objectRelativeUp = transform.InverseTransformDirection(relativeUp);

//Turns relativeRight vector from world to object local space

Vector3 objectRelaviveRight = transform.InverseTransformDirection(relativeRight);

 

rotateBy = Quaternion.AngleAxis(-rotateLeftRight, objectRelativeUp)

* Quaternion.AngleAxis(rotateUpDown, objectRelaviveRight);

 

newDeltaObtained = true;

}

 

Hope others find this useful.

Rotation and PoseMatrix

August 10, 2012 - 12:13pm #10

My final code for rotation. This is part of a script that is a component to my 3dmodel. I called the script ModelBehavior.cs

public void Rotate(float RotateLeftRight, float RotateUpDown)

{

float angleX = Camera.mainCamera.transform.localEulerAngles.x;

float angleY = Camera.mainCamera.transform.localEulerAngles.y;

//Debug.Log(angleX + " , " + angleY);

//Camera's angle at z is not needed.

 

float percentAngleX = (float)angleX / 90.0f;

float percentAngleY = 0.0f;

 

float x = 0.0f;

float y = 0.0f;

float z = 0.0f;

 

 

if(angleY < 90)

{

//Only worry about x and z for up down

percentAngleY = angleY /90.0f;

x += RotateUpDown * (1 - percentAngleY);

z += RotateUpDown * percentAngleY;

 

y += RotateLeftRight * (1- percentAngleX);

x += RotateLeftRight * (percentAngleX) * (percentAngleY);

z += RotateLeftRight * (percentAngleX) * (1 - percentAngleY);

}

 

else if(angleY < 180)

{

percentAngleY = (angleY - 90.0f) / 90.0f;

 

z += RotateUpDown * (1 - percentAngleY);

x -= RotateUpDown * (percentAngleY);

 

y += RotateLeftRight * (1- percentAngleX);

z -= RotateLeftRight * (percentAngleX) * (percentAngleY);

x += RotateLeftRight * (percentAngleX) * (1 - percentAngleY);

 

 

}

else if(angleY < 270)

{

percentAngleY = (angleY - 180.0f) / 90.0f;

x -= RotateUpDown * (1 - percentAngleY);

z -= RotateUpDown * (percentAngleY);

 

y += RotateLeftRight * (1- percentAngleX);

x -= RotateLeftRight * (percentAngleX) * (percentAngleY);

z -= RotateLeftRight * (percentAngleX) * (1 - percentAngleY);

}

else if(angleY < 360)

{

percentAngleY = (angleY - 270.0f) / 90.0f;

 

z -= RotateUpDown * (1 - percentAngleY);

x += RotateUpDown * (percentAngleY);

 

y += RotateLeftRight * (1- percentAngleX);

z -= RotateLeftRight * (percentAngleX) * (percentAngleY);

x += RotateLeftRight * (percentAngleX) * (1 - percentAngleY);

}

 

Vector3 relativeUp = transform.InverseTransformDirection(Vector3.down);

Vector3 relativeRight = transform.InverseTransformDirection(Vector3.left);

Vector3 relativeForeward = transform.InverseTransformDirection(Vector3.forward);

 

rotateBy = Quaternion.AngleAxis(z, relativeForeward)

* Quaternion.AngleAxis(y , relativeUp)

* Quaternion.AngleAxis(x , relativeRight);

 

newDeltaObtained = true;

 

}

What the above does is give me a quaternion that allows me to rotate my model by a path traced by my finger reguardless of how I am looking at the model (top, stright, left, right, topright, topleft, and anywhere in between).

Then i update update my models new position in my update function

void Update()

{

     if(newDeltaObtained)

     {

           this.gameObject.transform.localRotation *= rotateBy; 

          newDeltaObtained = false;

     }

 }

 

DavidBeard please look it over and tell me what you think.

Rotation and PoseMatrix

August 10, 2012 - 11:31am #9

I have figured out how to rotate my model up down from any angle and it works: here is the code.

public void Rotate(float RotateLeftRight, float RotateUpDown)

{

float angleX = Camera.mainCamera.transform.localEulerAngles.x;

float angleY = Camera.mainCamera.transform.localEulerAngles.y;

//Debug.Log(angleX + " , " + angleY);

//Camera's angle at z is not needed.

 

float percentAngleX = (float)angleX / 90.0f;

float percentAngleY = 0.0f;

 

float x = 0.0f;

float y = 0.0f;

float z = 0.0ff

if(angleY < 90)

{

//Only worry about x and z for up down

percentAngleY = angleY /90.0f;

x += RotateUpDown * (1 - percentAngleY);

z += RotateUpDown * percentAngleY;

 

 

}

 

else if(angleY < 180)

{

percentAngleY = (angleY - 90.0f) / 90.0f;

 

z += RotateUpDown * (1 - percentAngleY);

x -= RotateUpDown * (percentAngleY);

 

}

else if(angleY < 270)

{

percentAngleY = (angleY - 180.0f) / 90.0f;

x -= RotateUpDown * (1 - percentAngleY);

z -= RotateUpDown * (percentAngleY);

}

else if(angleY < 360)

{

percentAngleY = (angleY - 270.0f) / 90.0f;

 

z -= RotateUpDown * (1 - percentAngleY);

x += RotateUpDown * (percentAngleY);

 

}

 

Vector3 relativeUp = transform.InverseTransformDirection(Vector3.down);

Vector3 relativeRight = transform.InverseTransformDirection(Vector3.left);

Vector3 relativeForeward = transform.InverseTransformDirection(Vector3.forward);

 

rotateBy = Quaternion.AngleAxis(z, relativeForeward)

* Quaternion.AngleAxis(y , relativeUp)

* Quaternion.AngleAxis(x , relativeRight);

 

newDeltaObtained = true;

 

}

Then in my update function:

void Update()

{

if(newDeltaObtained)

{

this.gameObject.transform.localRotation *= rotateBy;

 

newDeltaObtained = false;

}

}

 

 

I am still working on left right rotation

Rotation and PoseMatrix

August 10, 2012 - 7:45am #8

The thing is, you really shouldn't have to take the camera perspective into account to simply rotate the model. Here's a script that will rotate a model in the direction of a touch stroke along the screen's x axis..

 

using UnityEngine;
using System.Collections;

public class RotationStroke : MonoBehaviour {

    public GameObject rotationTarget;

    public float rotationSpeed = 10.0f;

    void FixedUpdate () {

        if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Moved) {

            Vector2 touchDeltaPosition = Input.GetTouch(0).deltaPosition;

            Debug.Log( rotationTarget.transform.rotation.y + ":"+touchDeltaPosition.x );

            rotationTarget.transform.Rotate(Vector3.up * -touchDeltaPosition.x  * Time.deltaTime * rotationSpeed );

        }
    }
}

To test this, attach it to your ImageTarget and add your model to it's Rotation Target field in the inspector. You can do the same for the y axis by using the delta of 'y'. Something to keep in mind is that the screen coordinate space is defined for a given orientation w/ the origin at the bottom left. If you rotate the device, the stroke is still goiing to be measured according that origin, unless you use auto-rotation. And for overhead perspectives, a stroke along the top edge of the screen will appear to rotate the model in the opposite direction. This is where the pose matrix could come in handy, to recognize this perpective and change the sign of the delta for touches past the screen height / 2.

Rotation and PoseMatrix

August 9, 2012 - 2:15pm #7

At this point only just trying to get it so that if i swipe my finger to the left then depending on the angle the model will move left left to right or top to bottom or some combination of them. Although I think i might have figured it out, just trying to understan quaternion multiplication or addition.

 

Edit: I see that the camera is never still, It constantly updates its position relative to the target object (using trackables pose information) so that localSpace rotation and world space rotations are exactly the same( since its xyz are pointing in the exact same direction in both world space and local space)

Now that i understand this, I might be able to change my approach, maybe somehow change how swipes work with angles. Still getting closer to figuring it out. If i do I will post my solution here. (but please if someone else finds it before me help me)

 

Edit2:

I have got it working but only when facing foreward. If I am looking from front and anywhere up the y axis then i can fully change the models rotation relative to the camera. Here is my code for it so far

 

float angleX = Camera.mainCamera.transform.localEulerAngles.x;

float angleY = Camera.mainCamera.transform.localEulerAngles.y;

Debug.Log(angleX + " , " + angleY);

//Camera's angle at z is not needed.

 

float percentAngleX = (float)angleX / 90.0f;

 

float z = RotateLeftRight * percentAngleX;

float y = RotateLeftRight * (1 - percentAngleX);

 

float x = RotateUpDown;

 

rotateBy = Quaternion.AngleAxis(z, Vector3.back)

* Quaternion.AngleAxis(y , Vector3.up)

* Quaternion.AngleAxis(x , Vector3.right);

 

                this.gameObject.transform.rotation *= rotateBy;

 

The above code allows me to side swipe and change position with no problem. Now I am working trying to swip at different y angles (looking at model from size or back), if anyone can look at the above code and help me that would be great.

Rotation and PoseMatrix

August 8, 2012 - 9:16am #6

Please do. This seems to be a popular request, so I'll look into solutions.

Are you attempting to rotate the object proportionally to the stroke length?

Rotation and PoseMatrix

August 8, 2012 - 9:05am #5

The thing is that no way actually works for me. I have tried model.transform.Rotate(rotateByVector3, Space.world) but that doesn't work. The only thing i can think of is getting the pose and somehow using that to change how it rotates (eg rotate relative to how it looks, if im looking at the model from the top and I swip left the the model follows my finger, unlike now if i swipe left then just the x axis is changed (whihc makes it looks like I'm spinning it like a top)).

Ill try to make a smaller project or just upload the 3 scripts that i use for all this.

Rotation and PoseMatrix

August 8, 2012 - 8:44am #4

Can you post a sample project?  I think you may be overthinking this one and it's possible that it can be accomplished without digging into QCAR too deeply.

Rotation and PoseMatrix

August 8, 2012 - 7:37am #3

Sorry it took so long ot answer this but I was swamped with other portions of the app (and having to rewrite huge portions because something about the code either kept freezing or looked completely wrong on ANdroid device)

So how would i go about using those poses to obtain (in on tracked) what andle I am looking at an image target from or how it is changed;

This is for basically changin rotation in world space not local space (eg swipe left and no matter how the image target lays and from what angle i will rotate the model to the left in world space not in local space (where it turns left relative to its image target)

Edit: I have been at this for a while now but i still cannot figure out how to get Pose data in the TrackableEventHandler.

Thanks for all your help so far.

Rotation and PoseMatrix

July 23, 2012 - 3:09pm #2

The pose orientation is an element of the PoseData struct, which is an element of the TrackableData struct. You can obtain these with the ImageTracker's updates on the trackable and camera in ImageTracker.css lines 233 and 274.

 

e.g.

 

    public struct PoseData
    {
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
        public Vector3 position;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
        public Quaternion orientation;
    }

    // This struct stores general Trackable data like its 3D pose, its status
    // and its unique id.
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct TrackableData
    {
        public PoseData pose;
        public TrackableBehaviour.Status status;
        public int id;
    }

Log in or register to post comments