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.

Why would this crash? Thread safety?

edited May 2016 in Questions And Answers

I'm trying to access the spatial mesh(es) to extract part of the mesh in front of me. Not sure what's going on. I'm not allocating memory, but I get memory exceptions. Sometimes it (the debugger) says NULL reference. Here's a code snippet. It's dying on the last line. Hard.

        List<GameObject> meshGos = esmo.SurfaceObjects;
        List<Vector3> vertsInBounds = new List<Vector3> ();
        Mesh meshOut = new Mesh ();
        Vector3[] testTri =  new Vector3[3];
        Vector3[] worldTri =  new Vector3[3];
        int newTriIndex = 0;
        List<int> newTriList = new List<int> ();
        Bounds worldAAbounds;

        // construct a default mesh, in case nothing comes of this
        Vector3[] defVerts = new Vector3[3] { new Vector3(0f, 0f, 0f), new Vector3(-.5f, 0f, 1f), new Vector3(.5f, 0f, 1f) };
        int[] defTris = new int[3] { 0, 1, 2 };
        meshOut.vertices = defVerts;
        meshOut.triangles = defTris;
    // get rough estimate of target bounds in world space, use largest bound extents
    worldAAbounds = new Bounds ();
    worldAAbounds.center = boundsXform.position;
    float maxDim = Mathf.Max (bounds.extents.x, bounds.extents.y);
    maxDim = Mathf.Max (maxDim, bounds.extents.z);
    worldAAbounds.extents = Vector3.one * maxDim;
           bool foundAny = false;

    foreach (GameObject go in meshGos)
    {
        Renderer r = go.GetComponent<MeshRenderer> ();
        // if the world bounds of this mesh is not in the target bounds, move along
        if (r == null)
            continue;
        if (!r.bounds.Intersects (worldAAbounds))
            continue;
        MeshFilter[] meshFilters = go.GetComponents<MeshFilter> ();
        foreach (MeshFilter mf in meshFilters)
        {
            Mesh m = mf.sharedMesh;
            try
            {
                if (m == null)
                    continue;
                if (m.triangles != null)
                {
                   ** for (int i = 0; i < m.triangles.Length; i += 3) // for each triangle...`**

Note, I have commented out the contents of that 'for' loop, it does nothing. Nothing but increment i. If I comment this loop out, it runs fine.

I gotta guess that the mesh 'm', or its triangles, are not thread safe? I'm using a SpatialMappingObserver from the toolkit, only difference is I've exposed the SurfaceObjects so I can dig through them here. Before I call this function, I call 'StopObserving()' on that observer, hoping that it will prevent any change to this GameObject list, or the meshes it contains.

Any insights welcome

Best Answers

Answers

  • edited May 2016

    @ahillier said:
    Hi @WearableAR,
    You need to check that the meshFilter has a valid mesh before using it. In the SpatialMappingSource class, we provide the following function for getting meshes from the SurfaceObserver:

    virtual public List<MeshFilter> GetMeshFilters()
    {
         List<MeshFilter> meshFilters = new List<MeshFilter>();
            
         foreach(MeshFilter filter in surfaceObjectMeshFilters)
         {
               if (filter != null && 
                   filter.sharedMesh != null && 
                   filter.sharedMesh.vertexCount > 2)
               {
                    meshFilters.Add(filter);
               }
           }
    
           return meshFilters;
    }
    

    This is a good clue. I need to get more than just MF's though, I need the world coords of each vertex so I need the transforms, which means getting at the GameObjects they're on (to get their Transforms). So I'll massage the above into my code, see how that goes. Fingers crossed, this is really blocking me and soon the team.

    Unfortunately this did not fix it for me. I added this to my code:

                foreach (MeshFilter mf in meshFilters)
                {
                    if (mf == null || mf.sharedMesh == null || mf.sharedMesh.vertexCount <= 2)
                        continue;
    

    It still dies on:

    for (int i = 0; i < m.triangles.Length; i += 3) // for each triangle...

  • Yeah, you should be able to replace this line of your code:
    MeshFilter[] meshFilters = go.GetComponents ();
    with the function call above (or at least do all of the checks before using the filter object).

  • @ahillier said:
    Yeah, you should be able to replace this line of your code:
    MeshFilter[] meshFilters = go.GetComponents ();
    with the function call above (or at least do all of the checks before using the filter object).

    I didn't use that because it does not give me back world-space meshes. I suppose I could get the gameObject or transform off those mesh filters though, eh? Giving it a try...

  • No luck so far. Same problem. Code now like this, did I miss something obvious?

            List<MeshFilter> meshFilters = esmo.GetMeshFilters ();
            foreach (MeshFilter mf in meshFilters)
            {
                GameObject go = mf.gameObject;
                Renderer r = go.GetComponent<MeshRenderer>();
                // if the world bounds of this mesh is not in the target bounds, move along
                if (r == null)
                    continue;
                if (!r.bounds.Intersects(worldAAbounds))
                    continue;
                Mesh m = mf.sharedMesh;
                try
                {
                    if (m == null)
                        continue;
                    if (m.triangles != null)
                    {
                        for (int i = 0; i < m.triangles.Length; i += 3) // for each triangle...
                        {
    
  • FWIW It does get through some of these meshes. It reports 33 total, and about the 4th one that is 'in bounds' has 40968 triangles, 8254 vertices, then the 'for' statement crashes, Out of Memory.

    Seems like quite a lot of triangles for just that many verts, is this normal?

  • I can't say for sure what the compiler is going to do, but
    m.triangles will make a copy of the index array. Try calling m.triangles outside of the for loop, and do your work on the copy.

    ===
    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?)

Sign In or Register to comment.