private void UpdateForDisplayImmediatelyGroundOnly()
    {
        long      activeSurfaceId = xr.GetActiveSurfaceId();
        XRSurface activeSurface   = xr.GetSurface(activeSurfaceId);

        bool activeSurfaceIsValidGround = activeSurface != XRSurface.NO_SURFACE &&
                                          activeSurface.type == XRSurface.Type.HORIZONTAL_PLANE;

        if (!activeSurfaceIsValidGround)
        {
            return;
        }

        Vector3 centerVertex = GetVertexCenter(activeSurface.mesh);

        if (surfaceFound)
        {
            if (centerVertex.y < groundHeightGuess)
            {
                groundHeightGuess = centerVertex.y;
                SetHeight(groundHeightGuess);
            }
        }
        else
        {
            if (centerVertex.y < Camera.main.transform.position.y - MIN_GROUND_DISTANCE_FROM_PHONE)
            {
                groundHeightGuess = centerVertex.y;
                SetHeight(groundHeightGuess);
                onSurfaceAttach.Invoke();
                surfaceFound = true;
            }
        }
    }
Example #2
0
    public override bool Equals(object o)
    {
        if (!(o is XRSurface))
        {
            return(false);
        }
        XRSurface s = (XRSurface)o;

        return(id == s.id && type == s.type && rotation == s.rotation && mesh == s.mesh);
    }
    private bool IsValidGroundSurface(XRSurface surface)
    {
        if (surface.type != XRSurface.Type.HORIZONTAL_PLANE)
        {
            return(false);
        }

        Vector3 centerVertex = GetVertexCenter(surface.mesh);
        // New ground surface must be:
        //   -below a certain cutoff
        //   -lowest surface seen so far (and at least MIN_GROUND_CHANGE_DISTANCE lower)
        bool surfaceIsGroundHeight  = centerVertex.y < Camera.main.transform.position.y - MIN_GROUND_DISTANCE_FROM_PHONE;
        bool surfaceIsLowestSurface = !surfaceFound || centerMap[surfaceId].y - centerVertex.y > MIN_GROUND_CHANGE_DISTANCE;

        return(surfaceIsGroundHeight && surfaceIsLowestSurface);
    }
    /** This method doesn't cache its result.
     */
    private Dictionary <long, XRSurface> GetSurfacesFromXRResponse()
    {
        var r = GetCurrentReality();

        var surfaceSet        = r.getXRResponse().getSurfaces().getSet();
        var surfaces          = surfaceSet.getSurfaces();
        var faces             = surfaceSet.getFaces();
        var vertexList        = surfaceSet.getVertices();
        var textureCoordsList = surfaceSet.getTextureCoords();
        // Boundary vertices are available but not used right now

        var surfacesToRemove = new HashSet <long>(xrSurfaceMap_.Keys);

        foreach (var surface in surfaces)
        {
            long id = surface.getId().getEventTimeMicros();
            surfacesToRemove.Remove(id);

            var quat = surface.getNormal().getRotation();

            // Extract basic info about this mesh.
            int beginFaceIndex     = surface.getFacesBeginIndex();
            int endFaceIndex       = surface.getFacesEndIndex();
            int beginVerticesIndex = surface.getVerticesBeginIndex();
            int endVerticesIndex   = surface.getVerticesEndIndex();

            // Support texture coords when the device has it (e.g. ARKit >1.5)
            int  beginTextureCoordsIndex = 0;
            bool hasTextureCoords        = false;
            if (surface.getTextureCoordsEndIndex() > 0)
            {
                hasTextureCoords        = true;
                beginTextureCoordsIndex = surface.getTextureCoordsBeginIndex();
            }

            // Build the vertex and normal arrays.
            int       nVertices = endVerticesIndex - beginVerticesIndex;
            Vector3[] vertices  = new Vector3[nVertices];
            Vector3[] normals   = new Vector3[nVertices];
            Vector2[] uvs       = new Vector2[nVertices];

            for (int j = 0; j < nVertices; ++j)
            {
                int vertexIndex = beginVerticesIndex + j;
                vertices[j] = new Vector3(
                    vertexList.get(vertexIndex).getX(),
                    vertexList.get(vertexIndex).getY(),
                    vertexList.get(vertexIndex).getZ());
                normals[j] = Vector3.up;

                float u = vertices[j][0];
                float v = vertices[j][2];
                if (hasTextureCoords)
                {
                    int textureIndex = beginTextureCoordsIndex + j;
                    u = textureCoordsList.get(textureIndex).getU();
                    v = textureCoordsList.get(textureIndex).getV();
                }
                uvs[j] = new Vector2(u, v);
            }

            // We can just directly copy over the triangles (they are stored in consecutive sets of three
            // vertex indices) as long as we offset the vertex indices.
            int   nFaces    = endFaceIndex - beginFaceIndex;
            int[] triangles = new int[nFaces * 3];
            for (int j = 0; j < nFaces; ++j)
            {
                int v0 = faces.get(j + beginFaceIndex).getV0() - beginVerticesIndex;
                int v1 = faces.get(j + beginFaceIndex).getV1() - beginVerticesIndex;
                int v2 = faces.get(j + beginFaceIndex).getV2() - beginVerticesIndex;
                triangles[3 * j]     = v0;
                triangles[3 * j + 1] = v1;
                triangles[3 * j + 2] = v2;
            }

            var surfaceType     = GetSurfaceType(surface.getSurfaceType());
            var surfaceRotation = new Quaternion(quat.getX(), quat.getY(), quat.getZ(), quat.getW());

            Mesh mesh = null;
            if (xrSurfaceMap_.ContainsKey(id))
            {
                XRSurface existingSurface = xrSurfaceMap_[id];
                mesh = existingSurface.mesh;
                mesh.Clear();
            }
            else
            {
                mesh = new Mesh();
            }
            mesh.vertices     = vertices;
            mesh.normals      = normals;
            mesh.uv           = uvs;
            mesh.triangles    = triangles;
            xrSurfaceMap_[id] = new XRSurface(id, surfaceType, surfaceRotation, mesh);
        }

        // Remove surfaces we no longer receive from the map
        foreach (long surfaceId in surfacesToRemove)
        {
            xrSurfaceMap_.Remove(surfaceId);
        }

        return(xrSurfaceMap_);
    }
    // Returns true if surface was updated
    private bool UpdateSurface()
    {
        long      activeSurfaceId = xr.GetActiveSurfaceId();
        XRSurface activeSurface   = xr.GetSurface(activeSurfaceId);

        if (activeSurface.mesh == null)
        {
            return(false);
        }

        // Update center map height if already in map
        if (centerMap.ContainsKey(activeSurfaceId))
        {
            Vector3 centerVertex   = GetVertexCenter(activeSurface.mesh);
            Vector3 previousCenter = centerMap[activeSurfaceId];
            Vector3 normal         = Vector3.Cross(
                activeSurface.mesh.vertices[0] - activeSurface.mesh.vertices[1],
                activeSurface.mesh.vertices[0] - activeSurface.mesh.vertices[2]
                );
            normal.Normalize();
            Vector3 newCenter = previousCenter + normal * Vector3.Dot(centerVertex - previousCenter, normal);
            centerMap[activeSurfaceId] = newCenter;
        }

        if (surfaceId == activeSurfaceId)
        {
            return(false);
        }

        if (groundOnly && !IsValidGroundSurface(activeSurface))
        {
            return(false);
        }

        if (surfaceFound && lockToFirstSurface)
        {
            return(false);
        }

        if (!centerMap.ContainsKey(activeSurfaceId))
        {
            centerMap.Add(activeSurfaceId, GetVertexCenter(activeSurface.mesh));
        }

        bool triggerReady  = !displayImmediately && !surfaceFound;
        bool triggerAttach = !surfaceFound;

        SetHidden(false);
        transform.position = centerMap[activeSurfaceId];
        surfaceId          = activeSurfaceId;
        surfaceFound       = true;
        if (rotatePlaneWithDetectedNormal)
        {
            transform.localRotation = originalRotation_;
            transform.Rotate(activeSurface.rotation.eulerAngles);
        }

        if (deformToSurface)
        {
            DeformMesh(activeSurface.mesh);
        }

        if (triggerReady)
        {
            if (onSurfaceReady != null)
            {
                onSurfaceReady.Invoke();
            }
        }
        if (triggerAttach)
        {
            if (onSurfaceAttach != null)
            {
                onSurfaceAttach.Invoke();
            }
        }
        else
        {
            if (onSurfaceSwitch != null)
            {
                onSurfaceSwitch.Invoke();
            }
        }

        return(true);
    }