4
\$\begingroup\$

I'm working on a game in which cards are placed on a table and then rendered in augmented reality. These objects have 3D physics attached to them which doesn't work as well if they are either rotated or if the system mistakes them for being higher or lower then they really are.

Is there a good method to force Vuforia/Unity to place all items in the same 2D plane and keep all of them upright compared to that plane?

I currently have the following code:

using UnityEngine;
using System.Collections;

public class projectioncode : MonoBehaviour {
    Vector3 p1;
    Vector3 p2;
    Vector3 p3;
    Vector3 v1;
    Vector3 v2;
    Vector3 normal;    

    /*
     *use a plane with the following 3 coordinates 
     */ 
    public void setPlaneByPoints(Vector3 point1,Vector3 point2, Vector3 point3){
        p1 = point1;
        p2 = point2;
        p3 = point3;

        v1=p2-p1;
        v2=p3-p1;
        normal=getNormal(v1,v2);
    }

    public Transform projectTransform(Transform input){
        input.position = projectPoint (input.position);
        return input;
    }
    /*
     *  projects a 3d point into space; 
     */
    Vector3 projectPoint(Vector3 point){
        Vector3 vOToPoint = point - p1;//vector between origin and point 
        float dist = Vector3.Dot (vOToPoint, normal); //distance plane to point 
        return point - dist * normal;
    }

    /*
     * caclulates the normal of 2 vectors
     */ 
    Vector3 getNormal(Vector3 v1,Vector3 v2){
        Vector3 res= (Vector3.Cross (v1, v2));
        res.Normalize();
        return res;
    }
}

This seems to project objects onto a plane but the results tend to be inaccurate and result in weird movements, particularly when moving the camera around.

This is what it looks like: 4 markers

3 markers 2 recognised

\$\endgroup\$
  • \$\begingroup\$ Are you doing everything in the camera frame, or in the world frame? The reason I ask is because some of your other comments seem to be confusing a rotating object and a moving camera. \$\endgroup\$ – mklingen May 4 '15 at 21:47
  • \$\begingroup\$ World frame. However the default starting positions (i.e. what is down?) depends on the initial camera position for in real life (down will be what the game thinks is "down" from that which might not be down compared to this plane) \$\endgroup\$ – Thijser May 5 '15 at 5:35
  • \$\begingroup\$ Can you add pictures of what you're seeing? Also, it will help you a lot to initialize your camera pose such that the table's normal points along a world axis. Then, Lefty's answer will work just fine. \$\endgroup\$ – mklingen May 5 '15 at 15:23
  • \$\begingroup\$ Note that vuforia also does not seem to respect locking a given axis/rotation \$\endgroup\$ – Thijser May 6 '15 at 7:48
  • \$\begingroup\$ I have also added in some extra screenshots \$\endgroup\$ – Thijser May 6 '15 at 8:06
1
\$\begingroup\$

I manage to get this to work by separating the target and the model so that the model is NOT a child of the target in the scene. I let Vuforia handle the calculation of where the target is located, and then created a script to calculate the transform of the model based upon the transform of the target. In this script, I forced the y-position, x-rotation, and z-rotation to zero.

Note: This script assumes the xz-plane is aligned with the tabletop. You could also determine this by placing a "stationary target" on the tabletop and setting everything in the scene relative to the x and z components of the stationary target's transform.

using UnityEngine;
using System.Collections;

public class VuforiaFixToPlane : MonoBehaviour  {
    public Transform target;

    private Rigidbody rb;

    void Start()  {
        rb = GetComponent<Rigidbody>();
    }

    void FixedUpdate()  {
        Vector3 positionInPlane = target.position;
        positionInPlane.y = 0.0f;
        rb.position = positionInPlane;

        Vector3 rotInPlane = target.rotation.eulerAngles;
        rotInPlane.x = 0.0f;
        rotInPlane.z = 0.0f;
        rb.rotation = Quaternion.Euler(rotInPlane);
    }
}
| improve this answer | |
\$\endgroup\$
-1
\$\begingroup\$

you can "lock" the axis for a rigidbody so it cannot move/rotate/whatever around/along specific axis. Check the inspector options for the rigidbody component.

http://docs.unity3d.com/Manual/class-Rigidbody.html

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Well the problem is that the view can rotate around this plane. The user would not always be looking straight from above the table but sometimes from an angle to the table, so just stoping rotation wouldn't work. \$\endgroup\$ – Thijser May 1 '15 at 8:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.