The SurfacePlane class is used by SurfaceMeshesToPlanes to create different types of planes (walls, floors, tables, etc.) based on the Spatial Mapping data returned by the SpatialMappingManager's source. This script should be a component on the SufacePlane prefab, which is used by SurfaceMeshesToPlanes.
Inheritance: MonoBehaviour
Beispiel #1
0
    private GameObject FindGazeTarget(out RaycastHit hit, float distance, int layerMask)
    {
        //TODO: This code assumes that the collider is in a child object. If this is not the case,
        //      the code fails.
        if (Physics.Raycast(Camera.main.transform.position, Camera.main.transform.forward, out hit, distance, layerMask))
        {
            if (hit.collider.gameObject.CompareTag(Layers.Instance.surfacePlaneTag))
            {
                HoloToolkit.Unity.SpatialMapping.SurfacePlane p = hit.collider.gameObject.GetComponent <HoloToolkit.Unity.SpatialMapping.SurfacePlane>();
                if (p.PlaneType == HoloToolkit.Unity.SpatialMapping.PlaneTypes.Wall && Input.GetButtonDown("Fire2"))
                {
                    Debug.Log("hit point=" + hit.point);
                    ParticleEffectsManager.Instance.CreateBulletHole(hit.point, hit.normal, p);
                }
            }

            /*
             * GameObject target = hit.collider.transform.parent.gameObject;
             * m_gazeTarget = target;
             * if (target == null)
             * {
             * Debug.Log("ERROR: CANNOT IDENTIFY RAYCAST OBJECT");
             * return null;
             * }
             * cursor1.transform.position = hit.point + hit.normal * 0.01f;
             * cursor1.transform.forward = hit.normal;
             * return target.activeSelf ? target : null;
             */
        }
        return(null);
    }
        /// <summary>
        /// Gets all active planes of the specified type(s).
        /// </summary>
        /// <param name="planeTypes">A flag which includes all plane type(s) that should be returned.</param>
        /// <returns>A collection of planes that match the expected type(s).</returns>
        public List <GameObject> GetActivePlanes(PlaneTypes planeTypes)
        {
            List <GameObject> typePlanes = new List <GameObject>();

            foreach (GameObject plane in ActivePlanes)
            {
                SurfacePlane surfacePlane = plane.GetComponent <SurfacePlane>();

                if (surfacePlane != null)
                {
                    if ((planeTypes & surfacePlane.PlaneType) == surfacePlane.PlaneType)
                    {
                        if (surfacePlane.PlaneType == PlaneTypes.Table)
                        {
                            plane.tag = "Table";
                        }
                        if (surfacePlane.PlaneType == PlaneTypes.Ceiling)
                        {
                            plane.tag = "Ceiling";
                        }
                        if (surfacePlane.PlaneType == PlaneTypes.Wall)
                        {
                            plane.tag = "Wall";
                        }
                        if (surfacePlane.PlaneType == PlaneTypes.Floor)
                        {
                            plane.tag = "Floor";
                        }
                        typePlanes.Add(plane);
                    }
                }
            }

            return(typePlanes);
        }
 public Task(HoloToolkit.Unity.SpatialMapping.SurfacePlane pPlane, GameObject pMarginVolume, Vector3 pCenterPointOnFrontPlane, Vector3 pCenterPointOnBackPlane, GameObject pEmbedded)
 {
     plane                   = pPlane;
     marginVolume            = pMarginVolume;
     centerPointOnFrontPlane = pCenterPointOnFrontPlane;
     centerPointOnBackPlane  = pCenterPointOnBackPlane;
     embedded                = pEmbedded;
 }
    private bool HasSufficientMargin(HoloToolkit.Unity.SpatialMapping.SurfacePlane plane, MeshFilter meshFilter, float requiredMargin)
    {
        Tuple <HoloToolkit.Unity.SpatialMapping.SurfacePlane, MeshFilter> key = new Tuple <HoloToolkit.Unity.SpatialMapping.SurfacePlane, MeshFilter>(plane, meshFilter);
        //Debug.Log("hash key " + plane.GetInstanceID() + "," + meshFilter.GetInstanceID() + " = " + key.GetHashCode());
        float currentMargin;

        if (m_marginByPlaneAndSpatialMesh.TryGetValue(key, out currentMargin))
        {
            return(currentMargin >= requiredMargin);
        }
        return(false);
    }
        /// <summary>
        /// Creates and positions a collection of Placeable space objects on SurfacePlanes in the environment.
        /// </summary>
        /// <param name="terminalObjects">Collection of prefab GameObjects that have the Placeable component.</param>
        /// <param name="surfaces">Collection of SurfacePlane objects in the world.</param>
        private void CreateTerminalObjects(List <GameObject> terminalObjects, List <GameObject> surfaces)
        {
            List <int> UsedPlanes = new List <int>();

            // Sort the planes by distance to user.
            surfaces.Sort((lhs, rhs) =>
            {
                Vector3 headPosition   = Camera.main.transform.position;
                Collider rightCollider = rhs.GetComponent <Collider>();
                Collider leftCollider  = lhs.GetComponent <Collider>();

                // This plane is big enough, now we will evaluate how far the plane is from the user's head.
                // Since planes can be quite large, we should find the closest point on the plane's bounds to the
                // user's head, rather than just taking the plane's center position.
                Vector3 rightSpot = rightCollider.ClosestPointOnBounds(headPosition);
                Vector3 leftSpot  = leftCollider.ClosestPointOnBounds(headPosition);

                return(Vector3.Distance(leftSpot, headPosition).CompareTo(Vector3.Distance(rightSpot, headPosition)));
            });

            foreach (GameObject item in terminalObjects)
            {
                int      index    = -1;
                Collider collider = item.GetComponent <Collider>();

                index = FindNearestPlane(surfaces, collider.bounds.size, UsedPlanes, false);

                // If we can't find a good plane we will put the object floating in space.
                Vector3    position = Camera.main.transform.position + Camera.main.transform.forward * 2.0f + Camera.main.transform.right * (Random.value - 1.0f) * 2.0f;
                Quaternion rotation = Quaternion.identity;

                // If we do find a good plane we can do something smarter.
                if (index >= 0)
                {
                    UsedPlanes.Add(index);
                    GameObject   surface = surfaces[index];
                    SurfacePlane plane   = surface.GetComponent <SurfacePlane>();
                    position = surface.transform.position + (plane.PlaneThickness * plane.SurfaceNormal);
                    position = AdjustPositionWithSpatialMap(position, plane.SurfaceNormal);
                    rotation = Camera.main.transform.localRotation;

                    // Horizontal objects should face the user.
                    rotation   = Quaternion.LookRotation(Camera.main.transform.position);
                    rotation.x = 0f;
                    rotation.z = 0f;
                }

                //Vector3 finalPosition = AdjustPositionWithSpatialMap(position, surfaceType);
                GameObject terminalObject = Instantiate(item, position, rotation) as GameObject;
                terminalObject.transform.parent         = gameObject.transform;
                terminalObject.transform.localPosition += new Vector3(0.0f, item.GetComponent <MeshRenderer>().bounds.size.y / 2, 0.0f);
            }
        }
Beispiel #6
0
    private void CreateSurfaceHitFX(GameObject hitObject, Vector3 hitPoint, Vector3 hitNormal)
    {
        if (hitObject.CompareTag(Layers.Instance.surfacePlaneTag))
        {
            ParticleEffectsManager.Instance.CreateBulletImpact(hitPoint, hitNormal);
            HoloToolkit.Unity.SpatialMapping.SurfacePlane plane = hitObject.GetComponent <HoloToolkit.Unity.SpatialMapping.SurfacePlane>();
            switch (plane.PlaneType)
            {
            case HoloToolkit.Unity.SpatialMapping.PlaneTypes.Wall:
                ParticleEffectsManager.Instance.CreateBulletImpactDebris(hitPoint, hitNormal, 0.1f, 3, 0);
                ParticleEffectsManager.Instance.CreateBulletHole(hitPoint, hitNormal, plane);
                break;

            case HoloToolkit.Unity.SpatialMapping.PlaneTypes.Floor:
                ParticleEffectsManager.Instance.CreateLingeringFireball(hitPoint, hitNormal, 0);
                ParticleEffectsManager.Instance.CreateCrater(hitPoint, hitNormal);
                break;

            default:
                break;
            }
        }
        else
        {
            ParticleEffectsManager.Instance.CreateBulletImpact(hitPoint, hitNormal);
            float cos80 = 0.1736f;
            if (Mathf.Abs(Vector3.Dot(hitNormal, Vector3.right)) > cos80 &&
                Mathf.Abs(Vector3.Dot(hitNormal, Vector3.up)) > cos80 &&
                Mathf.Abs(Vector3.Dot(hitNormal, Vector3.forward)) > cos80)
            {
                PlayRicochetSound();
            }
        }

        /*
         * if (Vector3.Angle(hitNormal, Vector3.up) < 10)
         * {
         * // Lingering fireball only when hitting the ground
         * ParticleEffectsManager.Instance.CreateLingeringFireball(hitPoint, hitNormal, 0);
         * }
         * else if (Mathf.Abs(90 - Vector3.Angle(hitNormal, Vector3.up)) < 10)
         * {
         * // Debris when hitting walls
         * //TODO: wall detection should actually involve testing against detected wall planes
         * ParticleEffectsManager.Instance.CreateBulletImpactDebris(hitPoint, hitNormal, 0.1f, 3, 0);
         * }
         */
    }
Beispiel #7
0
        /// <summary>
        /// Gets all active planes of the specified type(s).
        /// </summary>
        /// <param name="planeTypes">A flag which includes all plane type(s) that should be returned.</param>
        /// <returns>A collection of planes that match the expected type(s).</returns>
        public List <GameObject> GetActivePlanes(PlaneTypes planeTypes)
        {
            List <GameObject> typePlanes = new List <GameObject>();

            foreach (GameObject plane in ActivePlanes)
            {
                SurfacePlane surfacePlane = plane.GetComponent <SurfacePlane>();

                if (surfacePlane != null)
                {
                    if ((planeTypes & surfacePlane.PlaneType) == surfacePlane.PlaneType)
                    {
                        typePlanes.Add(plane);
                    }
                }
            }

            return(typePlanes);
        }
    public void Embed(GameObject embedded, HoloToolkit.Unity.SpatialMapping.SurfacePlane plane)
    {
        if (null == plane)
        {
            return;
        }

        // Temporarily make the embedded object render in front of spatial mesh
        MakeHighPriorityRenderOrder(embedded);

        // Create an object describing the margin volume required for embedded
        // object placement
        GameObject marginVolume;
        Vector3    centerPointOnFrontPlane;
        Vector3    centerPointOnBackPlane;

        if (CreateMarginVolumeObject(out marginVolume, out centerPointOnFrontPlane, out centerPointOnBackPlane, embedded, plane))
        {
            return;
        }

        // Deform the spatial mesh to create a margin volume large enough for the
        // embedded object
        m_taskQueue.Enqueue(new Task(plane, marginVolume, centerPointOnFrontPlane, centerPointOnBackPlane, embedded));
        if (!m_working)
        {
            m_working = true;
            StartCoroutine(DeformSurfaceCoroutine());
        }

        if (debugMarginVolumes)
        {
            Debug.Log("pos=" + marginVolume.transform.position + ", obbpos = " + marginVolume.GetComponent <BoxCollider>().transform.position);
            GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
            cube.transform.parent                         = null;
            cube.transform.localScale                     = marginVolume.transform.localScale;
            cube.transform.position                       = marginVolume.transform.position;
            cube.transform.transform.rotation             = marginVolume.transform.rotation;
            cube.GetComponent <Renderer>().material       = debugMaterial;
            cube.GetComponent <Renderer>().material.color = Color.green;
            cube.SetActive(true);
        }
    }
Beispiel #9
0
    //TODO: move this function into Bullet.cs
    //TODO: anchors should be embedded into the SurfacePlane and then the bullet holes attached to that plane
    public void CreateBulletHole(Vector3 position, Vector3 normal, HoloToolkit.Unity.SpatialMapping.SurfacePlane plane)
    {
        //m_bulletHoleBuffer.Insert(position + normal * .005f, normal);


        GameObject bulletHole = Instantiate(bulletHolePrefab, position + normal * .005f, Quaternion.LookRotation(normal)) as GameObject;

        bulletHole.AddComponent <WorldAnchor>();
        bulletHole.transform.parent = this.transform;
        //SpatialMeshDeformationManager.Instance.Embed(bulletHole);
        SurfacePlaneDeformationManager.Instance.Embed(bulletHole, plane);
        //TODO: logic for objects to self destruct after not being gazed at for long enough?
        m_bulletHoles.Enqueue(bulletHole);
        while (m_bulletHoles.Count > maxBulletHoles)
        {
            GameObject oldBulletHole = m_bulletHoles.Dequeue();
            if (oldBulletHole) // if hasn't destroyed itself already
            {
                Destroy(oldBulletHole);
            }
        }
    }
Beispiel #10
0
 /// <summary>
 /// Sets visibility of planes based on their type.
 /// </summary>
 /// <param name="surfacePlane"></param>
 private void SetPlaneVisibility(SurfacePlane surfacePlane)
 {
     surfacePlane.IsVisible = ((drawPlanesMask & surfacePlane.PlaneType) == surfacePlane.PlaneType);
 }
Beispiel #11
0
        /// <summary>
        /// Iterator block, analyzes surface meshes to find planes and create new 3D cubes to represent each plane.
        /// </summary>
        /// <returns>Yield result.</returns>
        private IEnumerator MakePlanesRoutine()
        {
            // Remove any previously existing planes, as they may no longer be valid.
            for (int index = 0; index < ActivePlanes.Count; index++)
            {
                Destroy(ActivePlanes[index]);
            }

            // Pause our work, and continue on the next frame.
            yield return(null);

            float start = Time.realtimeSinceStartup;

            ActivePlanes.Clear();

            // Get the latest Mesh data from the Spatial Mapping Manager.
            List <PlaneFinding.MeshData> meshData = new List <PlaneFinding.MeshData>();
            List <MeshFilter>            filters  = SpatialMappingManager.Instance.GetMeshFilters();

            for (int index = 0; index < filters.Count; index++)
            {
                MeshFilter filter = filters[index];
                if (filter != null && filter.sharedMesh != null)
                {
                    // fix surface mesh normals so we can get correct plane orientation.
                    filter.mesh.RecalculateNormals();
                    meshData.Add(new PlaneFinding.MeshData(filter));
                }

                if ((Time.realtimeSinceStartup - start) > FrameTime)
                {
                    // Pause our work, and continue to make more PlaneFinding objects on the next frame.
                    yield return(null);

                    start = Time.realtimeSinceStartup;
                }
            }

            // Pause our work, and continue on the next frame.
            yield return(null);

#if !UNITY_EDITOR && UNITY_METRO
            // When not in the unity editor we can use a cool background task to help manage FindPlanes().
            Task <BoundedPlane[]> planeTask = Task.Run(() => PlaneFinding.FindPlanes(meshData, snapToGravityThreshold, MinArea));

            while (planeTask.IsCompleted == false)
            {
                yield return(null);
            }

            BoundedPlane[] planes = planeTask.Result;
#else
            // In the unity editor, the task class isn't available, but perf is usually good, so we'll just wait for FindPlanes to complete.
            BoundedPlane[] planes = PlaneFinding.FindPlanes(meshData, snapToGravityThreshold, MinArea);
#endif

            // Pause our work here, and continue on the next frame.
            yield return(null);

            start = Time.realtimeSinceStartup;

            float maxFloorArea   = 0.0f;
            float maxCeilingArea = 0.0f;
            FloorYPosition   = 0.0f;
            CeilingYPosition = 0.0f;
            float upNormalThreshold = 0.9f;

            if (SurfacePlanePrefab != null && SurfacePlanePrefab.GetComponent <SurfacePlane>() != null)
            {
                upNormalThreshold = SurfacePlanePrefab.GetComponent <SurfacePlane>().UpNormalThreshold;
            }

            // Find the floor and ceiling.
            // We classify the floor as the maximum horizontal surface below the user's head.
            // We classify the ceiling as the maximum horizontal surface above the user's head.
            for (int i = 0; i < planes.Length; i++)
            {
                BoundedPlane boundedPlane = planes[i];
                if (boundedPlane.Bounds.Center.y < 0 && boundedPlane.Plane.normal.y >= upNormalThreshold)
                {
                    maxFloorArea = Mathf.Max(maxFloorArea, boundedPlane.Area);
                    if (maxFloorArea == boundedPlane.Area)
                    {
                        FloorYPosition = boundedPlane.Bounds.Center.y;
                    }
                }
                else if (boundedPlane.Bounds.Center.y > 0 && boundedPlane.Plane.normal.y <= -(upNormalThreshold))
                {
                    maxCeilingArea = Mathf.Max(maxCeilingArea, boundedPlane.Area);
                    if (maxCeilingArea == boundedPlane.Area)
                    {
                        CeilingYPosition = boundedPlane.Bounds.Center.y;
                    }
                }
            }

            // Create SurfacePlane objects to represent each plane found in the Spatial Mapping mesh.
            for (int index = 0; index < planes.Length; index++)
            {
                GameObject   destPlane;
                BoundedPlane boundedPlane = planes[index];

                // Instantiate a SurfacePlane object, which will have the same bounds as our BoundedPlane object.
                if (SurfacePlanePrefab != null && SurfacePlanePrefab.GetComponent <SurfacePlane>() != null)
                {
                    destPlane = Instantiate(SurfacePlanePrefab);
                }
                else
                {
                    destPlane = GameObject.CreatePrimitive(PrimitiveType.Cube);
                    destPlane.AddComponent <SurfacePlane>();
                    destPlane.GetComponent <Renderer>().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
                }

                destPlane.transform.parent = planesParent.transform;
                SurfacePlane surfacePlane = destPlane.GetComponent <SurfacePlane>();

                // Set the Plane property to adjust transform position/scale/rotation and determine plane type.
                surfacePlane.Plane = boundedPlane;

                SetPlaneVisibility(surfacePlane);

                if ((destroyPlanesMask & surfacePlane.PlaneType) == surfacePlane.PlaneType)
                {
                    DestroyImmediate(destPlane);
                }
                else
                {
                    // Set the plane to use the same layer as the SpatialMapping mesh.
                    destPlane.layer = SpatialMappingManager.Instance.PhysicsLayer;
                    ActivePlanes.Add(destPlane);
                }

                // If too much time has passed, we need to return control to the main game loop.
                if ((Time.realtimeSinceStartup - start) > FrameTime)
                {
                    // Pause our work here, and continue making additional planes on the next frame.
                    yield return(null);

                    start = Time.realtimeSinceStartup;
                }
            }

            Debug.Log("Finished making planes.");

            // We are done creating planes, trigger an event.
            EventHandler handler = MakePlanesComplete;
            if (handler != null)
            {
                handler(this, EventArgs.Empty);
            }

            makingPlanes = false;
        }
Beispiel #12
0
        /// <summary>
        /// Creates and positions a collection of Placeable space objects on SurfacePlanes in the environment.
        /// </summary>
        /// <param name="spaceObjects">Collection of prefab GameObjects that have the Placeable component.</param>
        /// <param name="surfaces">Collection of SurfacePlane objects in the world.</param>
        /// <param name="surfaceType">Type of objects and planes that we are trying to match-up.</param>
        private void CreateSpaceObjects(List <GameObject> spaceObjects, List <GameObject> surfaces, PlacementSurfaces surfaceType)
        {
            List <int> UsedPlanes = new List <int>();

            // Sort the planes by distance to user.
            surfaces.Sort((lhs, rhs) =>
            {
                Vector3 headPosition   = Camera.main.transform.position;
                Collider rightCollider = rhs.GetComponent <Collider>();
                Collider leftCollider  = lhs.GetComponent <Collider>();

                // This plane is big enough, now we will evaluate how far the plane is from the user's head.
                // Since planes can be quite large, we should find the closest point on the plane's bounds to the
                // user's head, rather than just taking the plane's center position.
                Vector3 rightSpot = rightCollider.ClosestPointOnBounds(headPosition);
                Vector3 leftSpot  = leftCollider.ClosestPointOnBounds(headPosition);

                return(Vector3.Distance(leftSpot, headPosition).CompareTo(Vector3.Distance(rightSpot, headPosition)));
            });



            bool mustBePlacedOnTable = false;

            foreach (GameObject item in spaceObjects)
            {
                int      index    = -1;
                Collider collider = item.GetComponent <Collider>();
                if (item.tag == "PlaceOnTable")
                {
                    mustBePlacedOnTable = true;
                }
                if (surfaceType == PlacementSurfaces.Vertical)
                {
                    index = FindNearestPlane(surfaces, collider.bounds.size, UsedPlanes, true, mustBePlacedOnTable);
                }
                else
                {
                    index = FindNearestPlane(surfaces, collider.bounds.size, UsedPlanes, false, mustBePlacedOnTable);
                }
                mustBePlacedOnTable = false;
                // If we can't find a good plane we will put the object floating in space.
                Vector3    position = Camera.main.transform.position + Camera.main.transform.forward * 2.0f + Camera.main.transform.right * (Random.value - 1.0f) * 2.0f;
                Quaternion rotation = Quaternion.identity;

                // If we do find a good plane we can do something smarter.
                if (index >= 0)
                {
                    UsedPlanes.Add(index);
                    GameObject   surface = surfaces[index];
                    SurfacePlane plane   = surface.GetComponent <SurfacePlane>();
                    position = surface.transform.position + (plane.PlaneThickness * plane.SurfaceNormal);
                    position = AdjustPositionWithSpatialMap(position, plane.SurfaceNormal);
                    rotation = Camera.main.transform.localRotation;

                    if (surfaceType == PlacementSurfaces.Vertical)
                    {
                        // Vertical objects should face out from the wall.
                        rotation = Quaternion.LookRotation(surface.transform.forward, Vector3.up);
                    }
                    else
                    {
                        // Horizontal objects should face the user.
                        rotation   = Quaternion.LookRotation(Camera.main.transform.position);
                        rotation.x = 0f;
                        rotation.z = 0f;
                    }
                }

                //Vector3 finalPosition = AdjustPositionWithSpatialMap(position, surfaceType);
                GameObject spaceObject = Instantiate(item, position, rotation) as GameObject;
                spaceObject.transform.parent = gameObject.transform;
            }
            if (onlyOneGaz == 0)
            {
                GameObject ceiling         = GameObject.FindGameObjectWithTag("Ceiling");
                GameObject gazInstantiated = Instantiate(gaz, ceiling.transform.position, Quaternion.identity) as GameObject;

                onlyOneGaz = 1;
            }
        }
    private bool CreateMarginVolumeObject(out GameObject marginVolume, out Vector3 centerPointOnFrontPlane, out Vector3 centerPointOnBackPlane, GameObject embedded, HoloToolkit.Unity.SpatialMapping.SurfacePlane plane)
    {
        BoxCollider embeddedOBB = embedded.GetComponent <BoxCollider>();

        if (null == embeddedOBB)
        {
            Debug.Log("ERROR: Embedded object " + embedded.name + " lacks a box collider");
            marginVolume            = null;
            centerPointOnFrontPlane = Vector3.zero;
            centerPointOnBackPlane  = Vector3.zero;
            return(true);
        }
        HoloToolkit.Unity.SpatialMapping.OrientedBoundingBox surfaceBounds = plane.Plane.Bounds;

        /*
         * Compute margin volume front (i.e., the actual surface) and back (onto
         * which spatial mesh triangles will be projected) planes based on embedded
         * object thickness.
         *
         * Note that the embedded object position is not in the center of the
         * object but rather at a point flush with the surface it will be embedded
         * in.
         */
        Vector3 intoSurfaceNormal  = -Vector3.Normalize(embeddedOBB.transform.forward);
        float   embeddedThickness  = embeddedOBB.size.z * embeddedOBB.transform.lossyScale.z + extraDisplacement;
        Vector3 embeddedPosOnPlane = plane.transform.InverseTransformPoint(embedded.transform.position);

        embeddedPosOnPlane.x    = 0;
        embeddedPosOnPlane.y    = 0;
        centerPointOnFrontPlane = plane.transform.TransformPoint(embeddedPosOnPlane);
        centerPointOnBackPlane  = centerPointOnFrontPlane + intoSurfaceNormal * embeddedThickness;
        Vector3 centerPoint = 0.5f * (centerPointOnFrontPlane + centerPointOnBackPlane);

        //Debug.Log("*** PlanePos: " + plane.transform.position + ", PlaneFwd: " + plane.transform.forward + ", Embed Point: " + embedded.transform.position.ToString("F2") + ", IntoNorm: " + intoSurfaceNormal.ToString("F2") + ", thick: " + embeddedThickness + ", embeddedPosOnPlane: " + embeddedPosOnPlane.ToString("F2") + ", centerFront: " + centerPointOnFrontPlane.ToString("F2") + ", centerBack: " + centerPointOnBackPlane.ToString("F2"));

        /*
         * Create a game object to describe the size, position, and orientation of
         * the margin volume we want to create.
         *
         * The box collider is something of a formality. The surface mesh
         * deformation procedure and OBB/mesh intersection tests use box colliders
         * to describe OBBs. Here, the box collider is made the same size as the
         * game object to which it is parented. The downstream intersection testing
         * code knows to properly scale the box based on its parent.
         */
        marginVolume = new GameObject("deformation-" + embedded.name);
        marginVolume.transform.position   = centerPoint;
        marginVolume.transform.localScale = new Vector3(2 * surfaceBounds.Extents.x, 2 * surfaceBounds.Extents.y, embeddedThickness);
        marginVolume.transform.rotation   = surfaceBounds.Rotation; // need to use surface plane rotation because x, y differ from obj's
        BoxCollider obb = marginVolume.AddComponent <BoxCollider>();

        obb.center  = Vector3.zero;
        obb.size    = Vector3.one;
        obb.enabled = false; // we do not actually want collision detection

        return(false);
    }
Beispiel #14
0
    private void CreateSurfaceHitFX(GameObject hitObject, Vector3 hitPoint, Vector3 hitNormal)
    {
        if (hitObject.CompareTag(Layers.Instance.surfacePlaneTag))
        {
            ParticleEffectsManager.Instance.CreateBulletImpact(hitPoint, hitNormal);
            HoloToolkit.Unity.SpatialMapping.SurfacePlane plane = hitObject.GetComponent <HoloToolkit.Unity.SpatialMapping.SurfacePlane>();
            switch (plane.PlaneType)
            {
            case HoloToolkit.Unity.SpatialMapping.PlaneTypes.Wall:
                ParticleEffectsManager.Instance.CreateBulletImpactDebris(hitPoint, hitNormal, 0.1f, 3, 0);
                ParticleEffectsManager.Instance.CreateBulletHole(hitPoint, hitNormal, plane);
                break;

            case HoloToolkit.Unity.SpatialMapping.PlaneTypes.Floor:
                ParticleEffectsManager.Instance.CreateLingeringFireball(hitPoint, hitNormal, 0);
                //ParticleEffectsManager.Instance.CreateCrater(hitPoint, hitNormal);
                break;

            default:
                break;
            }
        }
        else
        {
            ParticleEffectsManager.Instance.CreateBulletImpact(hitPoint, hitNormal);
            SpatialUnderstandingDll.Imports.RaycastResult.SurfaceTypes surfaceType = PlayspaceManager.Instance.QuerySurfaceType(hitPoint, hitNormal);
            Debug.Log("hitNormal=" + hitNormal + ", hitPoint=" + hitPoint);

            float cos80 = 0.1736f;
            if (Mathf.Abs(Vector3.Dot(hitNormal, Vector3.right)) > cos80 &&
                Mathf.Abs(Vector3.Dot(hitNormal, Vector3.up)) > cos80 &&
                Mathf.Abs(Vector3.Dot(hitNormal, Vector3.forward)) > cos80)
            {
                PlayRicochetSound();
            }
            else if (surfaceType == SpatialUnderstandingDll.Imports.RaycastResult.SurfaceTypes.WallExternal)
            //else if (Mathf.Abs(hitNormal.y) < 0.05f)
            {
                // Must have hit a wall
                //TODO: for spatial understanding, we should raycast and determine whether we actually hit a real wall
                ParticleEffectsManager.Instance.CreateBulletImpactDebris(hitPoint, hitNormal, 0.1f, 3, 0);
                ParticleEffectsManager.Instance.CreateBulletHole(hitPoint, hitNormal);
            }
            else if (surfaceType == SpatialUnderstandingDll.Imports.RaycastResult.SurfaceTypes.Floor)
            //else if (hitNormal.y > 0.95f)
            {
                // Must have hit the floor
                //TODO: raycast spatial understanding
                ParticleEffectsManager.Instance.CreateLingeringFireball(hitPoint, hitNormal, 0);
            }
        }

        /*
         * if (Vector3.Angle(hitNormal, Vector3.up) < 10)
         * {
         * // Lingering fireball only when hitting the ground
         * ParticleEffectsManager.Instance.CreateLingeringFireball(hitPoint, hitNormal, 0);
         * }
         * else if (Mathf.Abs(90 - Vector3.Angle(hitNormal, Vector3.up)) < 10)
         * {
         * // Debris when hitting walls
         * //TODO: wall detection should actually involve testing against detected wall planes
         * ParticleEffectsManager.Instance.CreateBulletImpactDebris(hitPoint, hitNormal, 0.1f, 3, 0);
         * }
         */
    }