Display speed of a unity vuforia tracking target - c#

I just finished a Vuforia Unity AR project which successfully tracks a target and moves a unity object.
I have done this using AR camera prefab and ImageTrack prefabs.
I have added a 3d sphere with the ImageTrack object. Upon detecting a marker, the sphere is displayed and faithfully follows target where ever it goes.
I want to display the position or speed of this moving sphere which appears and follows the target.
To start with that I have attached a gui textbox with sphere with screenoverlay property.
I set transform.position to this text box and it shows the initial coordinates of ImageTrack when run. As the sphere moves upon marker moving, I want the current position of the sphere to be displayed.
Now it just shows initial position of the ImageTrack even though I placed the code under update(){}
I need latest current position because I need to calculate velocity, acceleration of this moving sphere.
Any help plz

For anyone who may come here, the following code works for me:
private void Update()
{
float x = Camera.main.WorldToScreenPoint(transform.position).x / Screen.width;
float y = Camera.main.WorldToScreenPoint(transform.position).y / Screen.height;
var tString = "x = " + System.Math.Round(x, 4);
var tString2 = "y = " + System.Math.Round(y, 4);
winText.text = tString;
win2Text.text = tString2;
}

Related

How to make panel show up in front of camera

I have this project where I click on an object and a canvas will show up to the player select an option inside the canvas. I needed the canvas to be world space so the player can move its head and the canvas will stay static in front. The problem is, there is a ton of objects around the scene and I need to update the position of the canvas everytime the player clicks an object.
I've tried to use "transform.position" but it doesn't work the way I wanted.
obs:
painel_escolha = canvas with panel;
transform_tela = camera.
painel_escolha.transform.position = transform_tela.transform.position;
Use this to move the canvas/panel in front of the camera and make it face the camera
// move the canvas distance meters in front of the camera
painel_escolha.transform.position = transform_tela.position + transform_tela.transform.forward * distance;
// make the canvas point in the same direction as the camera
painel_escolha.transform.rotation = transform_tela.transform.rotation;
Doing this in LateUpdate(! so after User input and position and rotation changes are processed) makes your panel absolutely head stable meaning it always stays in front of the user and he can't look away basically.
Often you rather want to use some kind of smoothed lerping instead e.g. doing
[Range(0,1)]
public float interpolationRatePosition = 0.5f;
[Range(0,1)]
public float interpolationRateRotation = 0.5f;
privtae Vector3 lastPosition;
private Quaternion lastRotation;
privtae void LateUpdate()
{
painel_escolha.transform.position = Vector3.Lerp(painel_escolha.transform.position, transform_tela.position, interpolationRatePosition);
painel_escolha.transform.rotation = Quaterinon.Lerp(painel_escolha.transform.rotation, transform_tela.rotation, interpolationRateRotation);
}
this resuts basically in the same end position but makes it looking a bit smoother.
Canvas positions are basically 2D screen positions. You could get the clicked objects world position with transform.position but for a canvas element to point to that (be on top of it) you need to transform that world position to the screen position via https://docs.unity3d.com/ScriptReference/Camera.WorldToScreenPoint.html

Unity - Camera ScreenToWorldPoint returning odd values

The main camera's output is set to a render texture, which is applied to a material, which is applied to a quad that's scaled up to 128x72. The secondary camera is set to only see what is rendered to the child quad, who has the material with the render texture on it.
However Camera.main.ScreenToWorldPoint(Input.mousePosition) is returning values that aren't even close to the GameObject. I.E. The GameObject is instantiated at (0, 0, 0), and hovering over it shows the mouse at (307, 174). Moving the Rotating Object to the right edge of the screen will only return an x position of 64 (half of the 128px wide quad) so I'm not sure where the 300+ is coming from. Not sure if the quad/camera set up is responsible for this.
EDIT: Using a single orthographic camera, all properties the same except for using a render texture, instead of the setup I have now results in accurate ScreenToWorldPoint output.
The Input.mousePosition property will only return the x and y axis of the mouse position in pixels.
ScreenToWorldPoint requires the z axis too which Input.mousePosition doesn't provide. The z-axis value supposed to be the nearClipPlane of the camera. It will give you a position that's right in front of the camera.
Depending on the size of the 3D object you want to instantiate where mouse button is pressed, you will need to apply an offset to it to make it totally visible to the screen. For a simple cube created in Unity, an offset of 2 is fine. Anything bigger than that, you will need to increase the offset.
Below is a complete example of how to properly use ScreenToWorldPoint with Camera.nearClipPlane and an offset to instantiate a 3D object where mouse is clicked:
public GameObject prefab;
public float offset = 2f;
void Update()
{
if (Input.GetMouseButtonDown(0))
{
Camera cam = Camera.main;
Vector2 mousePos = Vector3.zero;
mousePos.x = Input.mousePosition.x;
mousePos.y = Input.mousePosition.y;
Vector3 worldPoint = cam.ScreenToWorldPoint(new Vector3(mousePos.x, mousePos.y, cam.nearClipPlane + offset));
Instantiate(prefab, worldPoint, Quaternion.identity);
}
}
You may not be calling the Camera.ScreenToWorldPoint method correctly. In particular, the z position of the screen position parameter that's passed to this method should be defined as world units from the camera. See the Unity documentation on Camera.ScreenToWorldPoint.
Instead of Camera.main.ScreenToWorldPoint(Input.mousePosition), I think this is the correct way to call Camera.ScreenToWorldPoint:
var cameraPosition = Camera.main.transform.position;
// assuming `transform` is the transform "Virtual Screen Quad"...
float zWorldDistanceFromCamera = transform.position.z - cameraPosition.z;
var screenPoint = new Vector3(Input.mousePosition.x, Input.mousePosition.y, zWorldDistanceFromCamera);
var worldPoint = Camera.main.ScreenToWorldPoint(screenPoint);
Debug.LogFormat("mousePosition: {0} | zWorldDistanceFromCamera: {1} | worldPoint: {2}",
Input.mousePosition,
zWorldDistanceFromCamera,
worldPoint.ToString("F3"));
(If this isn't working, could you update your question or reply to this post with a comment with details showing the values that are logged at each step?)
I was just struggling with this problem and this question helped me find the answer, so thank you for posting it!
The issue has nothing to do with the z axis or how you're calling Camera.ScreenToWorldPoint. The issue is that the camera you're calling it on is rendering to a RenderTexture, and the dimensions of the RT don't match the dimensions of your game window. I wasn't able to find the implementation of the method in the reference source, but whatever it's doing is dependent on the resolution of the RenderTexture.
To test this, click the stats button in the game window to display the game window's screen size. The coordinates you get will match the ratio between that and the RenderTexture resolution.
Solutions:
Don't call this method on a camera targeting a rendertexture, either target the screen (none) or create a child camera that matches the position of the camera you need
Match the RT resolution to the screen. Obviously this may have performance implications, or cause issues if the screen size changes.
Don't use Camera.ScreenToWorldPoint. Depending on the use case, using a raycast may be simpler or more reliable.
Since using a default camera was returning the correct values, I simply added another one to detect the mouse position independent of the render texture/quad setup.

Get mouse position in world space

I'm making a game using Unity and I have a little issue, I need to know the mouse position in world space, for that I try to set a GameObject at the mouse position using this code :
Vector3 p = Input.mousePosition;
Vector3 pos = Camera.main.ScreenToWorldPoint( p);
testGameObject.transform.position = pos;
It works like a charm in Editor but in exe / apk, the GameObject dosn't follow the mouse:
Example 1
Example 2
The GameObject that is supposed to follow the mouse is the "1" inside a circle
If it's works in editor like a charm, then it should in build to.
I see it already working in build, maybe what you want is to exactly place yor object to match the screen click point, but your object is far too close to the camera so that you can't see it.
maybe there's a problem with the depth of the position from the camera.
try adding something like
Vector3 p = Input.mousePosition;
p.z = 20;
Vector3 pos = Camera.main.ScreenToWorldPoint(p);
testGameObject.transform.position = pos;
To add depth to the mouse position. try to change 20 to -20 if it's still doesn't work

Unity Hololens cursor following users gaze off center?

I'm essentially trying to use my own code to accomplish what the BasicCursor and its corresponding script, Cursor.cs, does for gaze following using the Microsoft Toolkit. I believe its UpdateCursorTransform() method is what I'm trying to emulate, but I'm confused.
At the moment right now I have the cursor following the users gaze but it appears to be off center. The cursor is lower and to the left of where the users actual gaze is. What gives?
Here is my code..
// Do a raycast into the world based on the user's
// head position and orientation.
var headPosition = Camera.main.transform.position;
var gazeDirection = Camera.main.transform.forward;
RaycastHit hitInfo;
Ray ray;
Camera c = Camera.main;
ray = c.ScreenPointToRay(headPosition);
if (Physics.Raycast(headPosition, gazeDirection, out hitInfo))
{
// If the raycast hit a hologram...
objHit = hitInfo.transform;
// Move the cursor to the point where the raycast hit.
this.transform.position = hitInfo.point;
// Rotate the cursor to hug the surface of the hologram.
this.transform.rotation = Quaternion.FromToRotation(Vector3.up, hitInfo.normal);
}
Unity units are supposed to be 1 meter.
Mind, if your hololens camera's field of view is very wide or very narrow, that'll artificially influence what you see (things will seem closer/farther). In a project I was working on, my coworker had put the objects that were to be the holograms 500 units away from the camera, then set the FOV to 10, which made them not sit in space where the real-world walls and floor were. If you tried to walk around the object, you couldn't.
Set the field of view to 60 degrees for the best experience, I believe the prefab hololens camera has a field of view of 51.
I am not sure why trying to convert from meters to inches is giving you a value that's off by a power of 10 (should be a multiplier of ~39.37)

Unity Camera Maintain perspective while rotating

I'm trying to write a camera script which will maintain the perspective point which I'm looking at while rotating.
public void RegisterRotationControls()
{
var horizontal = CrossPlatformInputManager.GetAxis(InputAxisName.Horizontal.ToString());
offsetX = Quaternion.AngleAxis(horizontal * turnSpeed, Vector3.up) * offsetX;
transform.position = player.position + offsetX;
transform.LookAt(player.position + PlayerOffset);
}
Currently this script is only working properly when the camera is looking at the player, however the camera has freedom to move position yet the rotation should maintain relativity to the center.
The top row dipicts the current behavior, while the bottom depicts what should be occuring
Manually calculating the rotation to move a camera in a circle while retaining its original (relative) facing is somewhat cumbersome, and requires you to do a lot more math than you need to.
A popular solution is to parent the camera under an empty GameObject, and centering that GameObject on the point/object you want the camera to rotate around. (This basically internalizes a lot of the calculations, letting the engine do the heavy lifting.) Then, you can locally translate the camera as needed and then rotate the container GameObject to move the camera in a circle.

Categories