How to convert a position into starting point for app using unity and ARKit? - unity3d

Trying to develop an AR app.When the app is opened,at that point the device location is (0,0,0) that is if I print or display my coordinates it will be (0,0,0).I want to create a starting point like at the entrance of a door.When other users using my app can open the app anywhere.
What I am trying to do is I already kept an AR at the entrance of the door.Users open app at random position which become their starting point, all AR objects will appear.When they pass through the AR object ,I want the coordinates of their device be(0,0,0).But if I run the below code in unity editor it takes the camera to the position where app has started.I am looking to convert the entrance position into App starting point.
Camera.main.transform.position=new Vector3(0,0,0);
From what I understand if we change the position of camera in app it can show glitches

Your question is very unclear -.-
but IF what you try doing is reset the camera to (0,0,0) while keeping all game objects at the same relative position to it you could try:
var localToCamera = Camera.main.transform.worldToLocalMatrix;
var obj = GameObject.FindSceneObjectsOfType(typeof(GameObject));
foreach (var o in obj)
{
var go = (o as GameObject);
go.transform.FromMatrix(localToCamera * go.transform.localToWorldMatrix);
}
_
EDIT:
what the UGLY code above is supposed to do:
it's going to crawl through all GameObjects and reposition them in such a way that if you set the camera to position (0,0,0) and facing (0,0,1), they will remain at the same position and orientation relatively to the camera.
notice that the camera itself WILL get repositioned to (0,0,0) and facing (0,0,1) after this code is executed because
Camera.main.transform.worldToLocalMatrix * localToWorldMatrix == identity
EDIT:
I can't put this code in the comments because it's too long.
try
// code from the top of my head here, syntax or function names might not be exact
var forward = arcamera.transform.forward;
forward.y = 0;
arcamera.transform.rotation = Quaternion.LookDirection(forward);
// now the camera forward should be in the (x,z) plane
UnityARSessionNativeInterface.GetARSessionNativeInterface().SetWorldOrigin(arcamera.transform);
// since you did not tilt the horizontal plane, hopefully the plane detection still detected vertical and horizontal planes

Related

How to make the camera in Unity be able to see my character?

I'm creating a 2D project.
The Camera is a child of the character. This is the second camera. The main camera is able to see the whole thing. The only thing that the second camera shows is the blue background.
This picture shows the hierarchal and inspector of the Object:
hierarchal and inspector
This picture shows the inspector of the second camera:
Camera Inspector
This shows the position of camera:
position
I'm expecting a way to make the camera be able to see my character and the map.
The problem is the camera position ... It's child for the character and I see it's z is 0 which that mean it is in the same depth of 2D Layer .. so you have to move it back.. you can change the view to 3D mode to see it more clearly ..
Conculotion : switch to 3D mode and change the Z position in the camera .
Hope it help..
Better solution : make a script to get the transform of the character and then set the camera to that position (((( with offset )))
public Transform character;
public Vector3 offset;
void Update(){
transform.position = character.position+offset;
}
Put Script like this in the camera and get it out from the character and set the offset for something like (0,0,-2) and try diffrent z values untill get you want

Unity AR Rotate Scene to match reference point

How to Match a reference point in 2 different AR scenes by position and rotation?
Here are some details about my project:
I have 2 scenes: "new scan" and "load scan". In the "new scan" scene I instantiate a 3d cube and make all the other points relative to it. This is my reference point. Then I instantiate some more points and finally save all the data to the device (my phone).
Next, in "load scan" I load the scene again and instantiate the cube in the exact same world position. For now, I managed to set the right position for each point but the axis is rotated because I start the scene from a different real-world location and different phone rotation.
Based on the cubes which are instantiated in the same place, I need to match the rotation and the position of the scene so the points will appear in the same relative position as the first cube.
Note: one can assume that the cube will instantiate with the user standing in the same direction as the desired position. But Do NOT assume that the user starts the "load scan" scene in the same direction as the "new scan" scene (which effect the whole scene rotation).
Here is a visualization of the problem:
Image of New Scan:
Image of Load Scan:
Thanks
If you want to make sure that the cube will appear in the same position/rotation in every AR session you have several options:
Use an Image marker
Use ARWorldMap (iOS exclusive)
Use a Cloud Tracking solution (google cloud anchors / Azure spatial anchors)
Of course you can also try to make the user place the cube correctly themselves, or redesign your app to work without these restrictions.
So I've found a solution but this is not the ultimate solution:
First, make a class with public static parameter so we can pass it through other scripts and scenes. Something like that:
public static class SceneStage
{
public static int ResetScene = 0;
}
Now, every time the camera turns on, check the SceneStage.ResetScene state. If value == 0 don't do anything, otherwise ask the user to stand facing the desire direction and then press a button, which call the function ResetScene:
private void ResetScene(int _scene)
{
var xrManagerSettings = UnityEngine.XR.Management.XRGeneralSettings.Instance.Manager;
xrManagerSettings.DeinitializeLoader();
SceneManager.LoadScene(_scene); // reload current scene
xrManagerSettings.InitializeLoaderSync();
}
Here I send the scene build index to the function with:
ResetScene(SceneManager.GetActiveScene().buildIndex);
So basically, the flow is like that: for the first time we open the scene (when SceneStage.ResetScene = 1) -> change the value to 0, and reset the scene. The second time don't do anything, but when we leave the scene set the value back to 1 so the next scene will reset too (because the ARPose driver still tracking the environment).

How to smoothly move a node in an ARkit Scene View based off device motion?

Swift beginner struggling with moving a scene node in ARkit in response to the device motion.
What I want to achieve is: First detect the floor plane, then place a sphere on the floor. From that point onwards depending on the movement of the device, I want to move the sphere along its x and z axis to move it around the floor of the room. (The sphere once created needs to be in the center of the device screen and locked to that view)
So far I can detect the floor and place a node no problem. I can use device motion to obtain the device attitude (pitch, roll and yaw) but how to translate these values into meaningful x, y, z positions that I can update my node with?
Are there any formulas or methods that are used to calculate such information or is this the wrong approach? I would appreciate a link to some info or an explanation of how to go about this. Also I am unsure how to ensure the node would be always at the center of the device screen.
so, as far as I understood you want to have a following workflow:
Step 1. You create a sphere on a plane (which is already done)
Step 2. Move the sphere with respect to the camera's horizontal plane (i.e. along its x and z axis to move it around the floor of the room depending on the movement of the device)
Assuming that the Step 1 is done, what you can do:
Get the position of the camera and the sphere
This should be first called within the function that is invoked after sphere creation (be it a tapGestureRecognizer(), touchesBegan(), etc.).
You can do it by calling position property of SCNNode for sphere and for camera position and/or orientation by calling sceneView.session.currentFrame's .camera.transform which contains all necessary parameters about current position of the camera
Move the sphere as camera moves
Having the sphere position on the Scene and the transformation matrix of the camera, you can find the distance relation between them. Here you can find a good explanation of how exactly you can do it
After you get those things you should implement a proper logic within renderer(_:didUpdate:for:) to obtain continuous lock of the ball with respect to the camera position
If you are interested about the math behind it, you can kick off by reading more about transformation matrices which is a big part of Image Processing and many other areas
Hope that this will help!

Unity How To Get The Camera borders as a vector3?

i need to get the camera borders as a vector3 to store it and use it later in the game .
as the image show you , i need to get this positions , so whatever camera move anywhere , i can determine the borders of my game.
you can use Camera.ScreenPointToRay(Vector3 pixelPosition) to get a given ray from the camera that crosses a given pixel coordinate (z position is ignored), than if you multiply by distance (your end plane distance?) you'll get coortinates of your points

Check if camera if facing a specific direction

I'm working to let a character push objects around. The problem is that as soon as he touches an object he starts moving it, even when the touch was accidental and the character isn't facing the direction of the object.
What I want to do is get the direction the object when a collision happens, and if the camara is really facing that direction allow the player to move it.
Right now I only managed to get the direction of the object, but I don't know how to compare that with the direction of the camera.
This is what I'm trying now:
void OnCollisionEnter(Collision col) {
float maxOffset = 1f;
if (col.gameObject.name == "Sol") {
// Calculate object direction
Vector3 direction = (col.transform.position - transform.position).normalized;
// Check the offset with the camera rotation (this doesn't work)
Vector3 offset = direccion - Camera.main.transform.rotation.eulerAngles.normalized;
if(offset.x + offset.y + offset.z < maxOffset) {
// Move the object
}
}
You can try to achieve this in several different ways. And it is a bit dependent on how precise you mean facing the box.
You can get events when an object is visible within a certain camera, and when it enters or leaves using the following functions. With these commands from the moment the box gets rendered with that camera (so even if just a edge is visible) your collision will trigger.
OnWillRenderObject, Renderer.isVisible Renderer.OnBecameVisible, OnBecameInvisible
Or you could attempt to calculate whether and objects bounding box falls within the camera's view frustum, there for you could use the following geometry commands
GeometryUtility.CalculateFrustumPlanes, GeometryUtility.TestPlanesAABB
Or if you rather have a very precise facing you could also go for a Physics.Raycast So then you will only trigger the event when the ray is hitting the object.
Hope this helps ya out.
Take a compass obj and align it to ur device sorry object than when you move it you can always know where it points to.
theoretically it should work but maybe your object just moves around because of a bug in your simulator motion engine.