Hello everyone.

We have decided to phase out the Mixed Reality Forums over the next few months in favor of other ways to connect with us.

The first way we want to connect with you is our mixed reality developer program, which you can sign up for at https://aka.ms/IWantMR.

The plan between now and the beginning of May is to clean up old, unanswered questions that are no longer relevant. The forums will remain open and usable.

On May 1st we will be locking the forums to new posts and replies. They will remain available for another three months for the purposes of searching them, and then they will be closed altogether on August 1st.

So, where does that leave our awesome community to ask questions? Well, there are a few places we want to engage with you. For technical questions, please use Stack Overflow, and tag your questions using either hololens or windows-mixed-reality. If you want to join in discussions, please do so in the HoloDevelopers Slack, which you can join by going to https://aka.ms/holodevelopers. And always feel free to hit us up on Twitter @MxdRealityDev.

Spatial Mapping Collider not always working

[c-sharp]

using UnityEngine;
using System.Collections;
using UnityEngine.VR.WSA.Persistence;
using UnityEngine.VR.WSA;

public class AnchorManager : MonoBehaviour {

public string ObjectAnchorStoreName;
WorldAnchorStore anchorStore;
private bool meshBugging = false; //debugging variable if the ray cast will not collide with the spatial mapping collider

bool Placing = false;

void Start()
{
    WorldAnchorStore.GetAsync(AnchorStoreReady);
}

void AnchorStoreReady(WorldAnchorStore store)
{
    anchorStore = store;
    Placing = true; //we want to default to placing mode if no anchor ends up found

    Debug.Log("looking for " + ObjectAnchorStoreName);
    string[] ids = anchorStore.GetAllIds();
    for (int index = 0; index < ids.Length; index++) //will look to see if any of the exisiting anchors are the one we want
    {
        Debug.Log(ids[index]);
        if (ids[index] == ObjectAnchorStoreName)
        {
            WorldAnchor wa = anchorStore.Load(ids[index], gameObject);
            Placing = false; //if anchor is found, then we do not want to be in placing mode
            break;
        }
    }
}

void Update()
{
    if (Placing)
    {
        var headPosition = Camera.main.transform.position;
        var gazeDirection = Camera.main.transform.forward;

        this.transform.position = headPosition + gazeDirection * 2;//Place 2 meters in front in case the physics raycast
                                                                   //fails/returns false

        RaycastHit hitInfo;
        if (Physics.Raycast(headPosition, gazeDirection, out hitInfo,
            30.0f, SpatialMappingManager.SpatialMappingLayerMask)) //if a ray cast from current postion out in the
                                                                   //gaze direction collides with an object in the
                                                                   //31st layer (where the spatial mapping collider is)
        {
            meshBugging = false;
            Debug.Log("gaze collision detected");

            this.transform.position = hitInfo.point;
            Quaternion toQuat = Camera.main.transform.localRotation;
            toQuat.x = 0;
            toQuat.z = 0;
            this.transform.rotation = toQuat;
        }
        else //if the raycast collision failed
        {
            meshBugging = true;
            Debug.Log("gaze collision NOT detected");
        }
    }
}

void OnPickUp() //puts the gameObject in placing mode
{
    Placing = true;
    if (anchorStore == null)
    {
        return;
    }
    WorldAnchor anchor = gameObject.GetComponent<WorldAnchor>(); //if an anchor exists, it must be destroyed to pick up
    if (anchor != null)
    {
        DestroyImmediate(anchor);
    }

    string[] ids = anchorStore.GetAllIds();
    for (int index = 0; index < ids.Length; index++)
    {
        Debug.Log(ids[index]);
        if (ids[index] == ObjectAnchorStoreName)
        {
            bool deleted = anchorStore.Delete(ids[index]);
            Debug.Log("deleted: " + deleted);
            break;
        }
    }
}

void OnDrop() //anchors gameObject where it ended in placing mode
{
    if (Placing)
    {
        Placing = false;
        if (!meshBugging) //there will be no newPoint if the raycast failed so must check this first
        {
            this.transform.position = newPoint; //performs the shift calclated in placing mode
        }
        Debug.Log("drop performing");
        //SpatialMapping.Instance.DrawVisualMeshes = false;
        if (anchorStore == null)
        {
            return;
        }
        WorldAnchor attachingAnchor = gameObject.AddComponent<WorldAnchor>(); //creates an anchor for the gameObject
        if (attachingAnchor.isLocated)
        {
            Debug.Log("Saving persisted position immediately");
            bool saved = anchorStore.Save(ObjectAnchorStoreName, attachingAnchor);
            Debug.Log("saved: " + saved);
        }
        else
        {
            attachingAnchor.OnTrackingChanged += AttachingAnchor_OnTrackingChanged;
        }
    }
}

private void AttachingAnchor_OnTrackingChanged(WorldAnchor self, bool located)
{
    if (located)
    {
        Debug.Log("Saving persisted position in callback");
        bool saved = anchorStore.Save(ObjectAnchorStoreName, self);
        Debug.Log("saved: " + saved);
        self.OnTrackingChanged -= AttachingAnchor_OnTrackingChanged;
    }
}

}

[c-sharp]

When the application is launched in the emulator without an anchor on the object the raycast for placing the object usually works fine with the spatial mapping collider, but when it is launched with an anchor the raycast fails. It can't just be the layer mask because we do a raycast for the cursor which doesn't use a layer mask and also fails.

Best Answer

Answers

  • should the code be setting newpoint in update?

    ===
    This post provided as-is with no warranties and confers no rights. Using information provided is done at own risk.

    (Daddy, what does 'now formatting drive C:' mean?)

  • Ignore the if statement with new point, the plan is to manipulate the point into a new point, but for now the raycast isn't working.

  • okay, I figured it was orthogonal, just wanted to be sure. And then you have a taptoplace type script that sends the OnDrop and OnPickup messages when the OnSelect is fired?

    ===
    This post provided as-is with no warranties and confers no rights. Using information provided is done at own risk.

    (Daddy, what does 'now formatting drive C:' mean?)

  • I'm not experiencing the raycast failing. How do you have spatial mapping setup? Are you using the HoloToolkit prefabs or the components Unity recently added?

    ===
    This post provided as-is with no warranties and confers no rights. Using information provided is done at own risk.

    (Daddy, what does 'now formatting drive C:' mean?)

  • The components recently added by unity. I created an empty object and added the SpatialMappingRenderer and SpatialMappingCollider components. I named layer 31 in layers spatialMapping and chose this layer for this new spatialMapping object as well as the mesh layer for the SpatialMappingCollider. I also attached a script to the object similar to the one in hololens 101e for spatial mapping. You can see in the script I tried some settings in the Awake() method to try to make the collider work.
    The script is below:

    [c-sharp]
    using UnityEngine;
    using System.Collections;
    using UnityEngine.VR.WSA;

    public class SpatialMappingManager : MonoBehaviour {

    public static SpatialMappingManager Instance { private set; get; }
    public static int SpatialMappingLayerMask; //Unity layer for spatial mapping to help choose what things to collide with
    bool drawVisualMeshes = true;
    private SpatialMappingRenderer spatialMappingRenderer;
    private SpatialMappingCollider spatialMappingCollider;
    private int physicsLayer = 31;
    
    // Use this for initialization
    void Awake() {
        Instance = this;
    
        spatialMappingRenderer = gameObject.GetComponent<SpatialMappingRenderer>();
        spatialMappingRenderer.surfaceParent = this.gameObject;
        spatialMappingCollider = gameObject.GetComponent<SpatialMappingCollider>();
        spatialMappingCollider.surfaceParent = this.gameObject;
        SpatialMappingLayerMask = 1 << physicsLayer; //31 is the layer and bit shifting 1 to the left 31 times makes the 31st layer
                                           //the only layer looked for when this layermask is used.
        spatialMappingCollider.layer = physicsLayer;
    
    
        DrawVisualMeshes = drawVisualMeshes;
        spatialMappingCollider.freezeUpdates = false;
        spatialMappingRenderer.freezeUpdates = false;
        spatialMappingCollider.enableCollisions = true;
        spatialMappingCollider.enabled = true;
        gameObject.SetActive(true);
        spatialMappingCollider.enabled = true;
    
    }
    
    // Update is called once per frame
    void Update () {
    
    }
    
    public bool DrawVisualMeshes //mainly just to see the room on the emulator, this shows the spatial mapping mesh
    {
        get
        {
            return drawVisualMeshes;
        }
    
        set
        {
            drawVisualMeshes = value;
            if (drawVisualMeshes)
            {
                spatialMappingRenderer.currentRenderSetting = SpatialMappingRenderer.RenderSetting.CustomMaterial;
            }
            else
            {
                spatialMappingRenderer.currentRenderSetting = SpatialMappingRenderer.RenderSetting.None;
            }
        }
    }
    

    }
    [c-sharp]

  • Can you try the prefab in the holotoolkit? It might be that there's an issue with the Unity component.

    ===
    This post provided as is, without warranty and confers no rights. Use information provided at own risk.

    Personal account of @Patrick. Looks like he's not at work right now. :)

    Daddy what does now formatting drive C: mean?

  • @Patrick said:
    okay, I figured it was orthogonal, just wanted to be sure. And then you have a taptoplace type script that sends the OnDrop and OnPickup messages when the OnSelect is fired?

    missed this in my response, but for right now just a speech recognizer is firing the OnDrop and OnPickup messages.

  • @Darax said:
    Can you try the prefab in the holotoolkit? It might be that there's an issue with the Unity component.

    I tried putting the holotoolkit in my project, which caused many compile errors and things like plugins colliding. I took out everything from the toolkit out of my unity project except I left the spatial mapping folder in my assets folder, but the scripts attached to the prefab all have compile errors. On the SpatialMappingManager visual studio says the type or namespace 'Singleton<>' could not be found and below gameObject does not exist in the context. There are more errors on the other scripts too.

  • Ack, wasn't considering that Holotoolkit might be a pain for you to integrate. Singleton is defined in utilities/scripts . I'll be back at my desk in a little bit and I can try with the Unity component.

    ===
    This post provided as is, without warranty and confers no rights. Use information provided at own risk.

    Personal account of @Patrick. Looks like he's not at work right now. :)

    Daddy what does now formatting drive C: mean?

  • After reading your latest response, I did not change much. I created a new object to attach the GazeGestureManager and speech manager instead of having them attached to the anchor object. I already had a visible hologram which is a child to the anchor, and another SpatialMapping object, essentially the same as yours. I had the anchor script on the anchor object. Now it seems to work every time. It seems like moving the GazeGestureManager and SpeechManager off of the anchor and onto their own object is all that did it, but that still seems strange because I do not see why that would have affected the cursor script's raycasting (same cursor script form holograms101e), which failed whenever the anchor script's raycasting did. That suggested it was the spatial mapping collider not working. Either way thanks so much, it is currently working consistently. One last thing, do you have any idea why the spatial mapping would not be rendering now? The way the SpatialMappingManager script is, it seems to me that it should always be rendering.

  • I'm not sure why attaching the gaze script to the anchor should matter. I just tried and for a minute thought I was experiencing the same behavior, but the next time I started and thereafter everything worked. Maybe there's a timing issue lurking.

    I was able to get the spatial mapping to only draw when the placing flag was set (or all the time as your scripts are configured). What material do you have set for the spatial mapping renderer?

    ===
    This post provided as-is with no warranties and confers no rights. Using information provided is done at own risk.

    (Daddy, what does 'now formatting drive C:' mean?)

  • It is working just fine now, thank you.

Sign In or Register to comment.