Esempio n. 1
0
        /// <summary>
        /// Returns best placement position in local space to the plane
        /// </summary>
        /// <param name="plane">The <see cref="SpatialAwarenessMeshObject"/> who's plane will be used for placement</param>
        /// <param name="objExtents">Total width and height of object to be placed in meters.</param>
        /// <param name="placementPosOnPlane">Base position on plane in local space.</param>
        /// <returns>returns <see cref="false"/> if API returns null.</returns>
        public bool TryFindCentermostPlacement(Guid quadGuid, Vector2 objExtents, out Vector3 placementPosOnPlane)
        {
            Tuple <SceneQuad, SceneObject> result;

            if (!cachedSceneQuads.TryGetValue(quadGuid, out result))
            {
                placementPosOnPlane = Vector2.zero;
                return(false);
            }

            SceneQuad   quad        = result.Item1;
            SceneObject sceneObject = result.Item2;

            System.Numerics.Vector2 ext            = new System.Numerics.Vector2(objExtents.x, objExtents.y);
            System.Numerics.Vector2 centerPosition = new System.Numerics.Vector2();

            quad.FindCentermostPlacement(ext, out centerPosition);

            // best placement origin is top left (2d sheet of paper)
            centerPosition -= quad.Extents / new System.Numerics.Vector2(2.0f);

            var centerUnity = new Vector3(centerPosition.X, centerPosition.Y, 0);

            placementPosOnPlane = (sceneObject.GetLocationAsMatrix() * sceneToWorldXformSystem * correctOrientation).ToUnity().MultiplyPoint(centerUnity);

            return(true);
        }
Esempio n. 2
0
        /// <summary>
        /// Orients the root game object, such that the Scene Understanding floor lies on the Unity world's X-Z plane.
        /// The floor type with the largest area is choosen as the reference.
        /// If no floor is found....???
        /// </summary>
        /// <param name="scene">Scene Understanding scene.</param>
        private System.Numerics.Vector3 ToUpFromBiggestFloor(IReadOnlyList <SceneObject> sasos)
        {
            float       areaForlargestFloorSoFar = 0;
            SceneObject floorSceneObject         = null;
            SceneQuad   floorQuad = null;

            var result = System.Numerics.Vector3.Zero;

            // Find the largest floor quad.
            var count = sasos.Count;

            for (var i = 0; i < count; ++i)
            {
                if (sasos[i].Kind == SceneObjectKind.Floor)
                {
                    var quads = sasos[i].Quads;

                    Assert.IsNotNull(quads);

                    var qcount = quads.Count;
                    for (int j = 0; j < qcount; j++)
                    {
                        float quadArea = quads[j].Extents.X * quads[j].Extents.Y;

                        if (quadArea > areaForlargestFloorSoFar)
                        {
                            areaForlargestFloorSoFar = quadArea;
                            floorSceneObject         = sasos[i];
                            floorQuad = quads[j];
                        }
                    }
                }
            }

            if (floorQuad != null)
            {
                // Compute the floor quad's normal.
                float halfWidthMeters  = floorQuad.Extents.X * .5f;
                float halfHeightMeters = floorQuad.Extents.Y * .5f;

                System.Numerics.Vector3 point1 = new System.Numerics.Vector3(-halfWidthMeters, -halfHeightMeters, 0);
                System.Numerics.Vector3 point2 = new System.Numerics.Vector3(halfWidthMeters, -halfHeightMeters, 0);
                System.Numerics.Vector3 point3 = new System.Numerics.Vector3(-halfWidthMeters, halfHeightMeters, 0);

                System.Numerics.Matrix4x4 objectToSceneOrigin = floorSceneObject.GetLocationAsMatrix();

                objectToSceneOrigin = RightToLeftHanded(objectToSceneOrigin);

                System.Numerics.Vector3 tPoint1 = System.Numerics.Vector3.Transform(point1, objectToSceneOrigin);
                System.Numerics.Vector3 tPoint2 = System.Numerics.Vector3.Transform(point2, objectToSceneOrigin);
                System.Numerics.Vector3 tPoint3 = System.Numerics.Vector3.Transform(point3, objectToSceneOrigin);

                System.Numerics.Vector3 p21 = tPoint2 - tPoint1;
                System.Numerics.Vector3 p31 = tPoint3 - tPoint1;

                result = System.Numerics.Vector3.Cross(p21, p31);
            }

            return(result);
        }
Esempio n. 3
0
    /// <summary>
    /// Apply Region mask to a Scene Object
    /// </summary>
    private void ApplyQuadRegionMask(SceneQuad quad, GameObject gameobject, Color color)
    {
        if (quad == null || gameobject == null)
        {
            Debug.LogWarning("SceneUnderstandingManager.ApplyQuadRegionMask: One or more arguments are null.");
            return;
        }

        // Resolution of the mask.
        ushort width  = 256;
        ushort height = 256;

        byte[] mask = new byte[width * height];
        quad.GetSurfaceMask(width, height, mask);

        MeshRenderer meshRenderer = gameobject.GetComponent <MeshRenderer>();

        if (meshRenderer == null || meshRenderer.sharedMaterial == null || meshRenderer.sharedMaterial.HasProperty("_MainTex") == false)
        {
            Debug.LogWarning("SceneUnderstandingManager.ApplyQuadRegionMask: Mesh renderer component is null or does not have a valid material.");
            return;
        }

        // Create a new texture.
        Texture2D texture = new Texture2D(width, height);

        texture.filterMode = FilterMode.Bilinear;
        texture.wrapMode   = TextureWrapMode.Clamp;

        // Transfer the invalidation mask onto the texture.
        Color[] pixels = texture.GetPixels();
        for (int i = 0; i < pixels.Length; ++i)
        {
            byte value = mask[i];

            if (value == (byte)SceneRegionSurfaceKind.NotSurface)
            {
                pixels[i] = Color.clear;
            }
            else
            {
                pixels[i] = color;
            }
        }

        texture.SetPixels(pixels);
        texture.Apply(true);

        // Set the texture on the material.
        meshRenderer.sharedMaterial.mainTexture = texture;
    }
    private GameObject CreateOrUpdateQuad(Transform sceneObjectTransform, SceneQuad quad)
    {
        GameObject quadObj;

        if (sceneGeometries.ContainsKey(quad.Id))
        {
            quadObj = sceneGeometries[quad.Id];
        }
        else
        {
            quadObj = GameObject.CreatePrimitive(PrimitiveType.Quad);
            quadObj.transform.SetParent(sceneObjectTransform, false);
            quadObj.name = $"Quad-{quad.Id}";
            sceneGeometries.Add(quad.Id, quadObj);
        }
        quadObj.transform.localScale = new Vector3(quad.Extents.X, quad.Extents.Y, 1);
        return(quadObj);
    }
Esempio n. 5
0
    /// <summary>
    /// Create a Unity Mesh from a Scene Understanding Quad
    /// </summary>
    /// <param name="suQuad">The Scene Understanding quad to generate in Unity</param>
    private Mesh GenerateUnityMeshFromSceneObjectQuad(SceneQuad suQuad)
    {
        if (suQuad == null)
        {
            Debug.LogWarning("SceneUnderstandingManager.GenerateUnityMeshForSceneObjectQuad: Quad is null.");
            return(null);
        }

        float widthInMeters  = suQuad.Extents.X;
        float heightInMeters = suQuad.Extents.Y;

        // Bounds of the quad.
        List <Vector3> vertices = new List <Vector3>()
        {
            new Vector3(-widthInMeters / 2, -heightInMeters / 2, 0),
            new Vector3(widthInMeters / 2, -heightInMeters / 2, 0),
            new Vector3(-widthInMeters / 2, heightInMeters / 2, 0),
            new Vector3(widthInMeters / 2, heightInMeters / 2, 0)
        };

        List <int> triangles = new List <int>()
        {
            1, 3, 0,
            3, 2, 0
        };

        List <Vector2> uvs = new List <Vector2>()
        {
            new Vector2(0, 0),
            new Vector2(1, 0),
            new Vector2(0, 1),
            new Vector2(1, 1)
        };

        Mesh unityMesh = new Mesh();

        unityMesh.SetVertices(vertices);
        unityMesh.SetIndices(triangles.ToArray(), MeshTopology.Triangles, 0);
        unityMesh.SetUVs(0, uvs);

        return(unityMesh);
    }
Esempio n. 6
0
        public bool TryGetOcclusionMask(Guid quadId, ushort textureWidth, ushort textureHeight, out byte[] mask)
        {
            Tuple <SceneQuad, SceneObject> result;

            if (!cachedSceneQuads.TryGetValue(quadId, out result))
            {
                mask = null;
                return(false);
            }

            SceneQuad   quad        = result.Item1;
            SceneObject sceneObject = result.Item2;

            var maskResult = new byte[textureWidth * textureHeight];

            quad.GetSurfaceMask(textureWidth, textureHeight, maskResult);

            mask = maskResult;

            return(true);
        }
Esempio n. 7
0
        private SpatialAwarenessSceneObject ConvertSceneObject(SceneObject sceneObject)
        {
            int quadCount = sceneObject.Quads.Count;
            int meshCount = sceneObject.Meshes.Count;

            List <SpatialAwarenessSceneObject.Quad>     quads  = new List <SpatialAwarenessSceneObject.Quad>(quadCount);
            List <SpatialAwarenessSceneObject.MeshData> meshes = new List <SpatialAwarenessSceneObject.MeshData>(meshCount);

            if (RequestPlaneData)
            {
                SceneQuad sceneQuad = null;

                for (int i = 0; i < quadCount; ++i)
                {
                    sceneQuad = sceneObject.Quads[i];

                    var quadIdKey = sceneQuad.Id;

                    byte[] occlusionMaskBytes = null;

                    if (RequestOcclusionMask)
                    {
                        occlusionMaskBytes = new byte[OcclusionMaskResolution.x * OcclusionMaskResolution.y];
                        sceneQuad.GetSurfaceMask((ushort)OcclusionMaskResolution.x, (ushort)OcclusionMaskResolution.y, occlusionMaskBytes);
                    }

                    var extents = new UnityEngine.Vector2(sceneQuad.Extents.X, sceneQuad.Extents.Y);

                    var quad = new SpatialAwarenessSceneObject.Quad(quadIdKey, extents, occlusionMaskBytes);

                    quads.Add(quad);

                    // Store a cache so we can retrieve best position on plane later.

                    if (!cachedSceneQuads.ContainsKey(quadIdKey))
                    {
                        cachedSceneQuads.Add(quadIdKey, new Tuple <SceneQuad, SceneObject>(sceneQuad, sceneObject));
                    }
                }
            }

            if (RequestMeshData)
            {
                SceneMesh sceneMesh = null;

                for (int i = 0; i < meshCount; ++i)
                {
                    sceneMesh = sceneObject.Meshes[i];
                    var meshData = MeshData(sceneMesh);
                    meshes.Add(meshData);
                }
            }

            // World space conversion

            System.Numerics.Matrix4x4 worldXformSystem = sceneObject.GetLocationAsMatrix() * sceneToWorldXformSystem * correctOrientation;

            System.Numerics.Vector3    worldTranslationSystem;
            System.Numerics.Quaternion worldRotationSytem;
            System.Numerics.Vector3    localScale;

            System.Numerics.Matrix4x4.Decompose(worldXformSystem, out localScale, out worldRotationSytem, out worldTranslationSystem);

            var result = new SpatialAwarenessSceneObject(
                sceneObject.Id,
                SpatialAwarenessSurfaceType(sceneObject.Kind),
                worldTranslationSystem.ToUnityVector3(),
                worldRotationSytem.ToUnityQuaternion(),
                quads,
                meshes);

            return(result);
        }