The Mixed Reality Forums here are no longer being used or maintained.
There are a few other places we would like to direct you to for support, both from Microsoft and from the community.
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.
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, or in our Microsoft Tech Communities forums at https://techcommunity.microsoft.com/t5/mixed-reality/ct-p/MicrosoftMixedReality.
And always feel free to hit us up on Twitter @MxdRealityDev.
Why would this crash? Thread safety?
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
-
ahillier mod
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; }
6 -
@Patrick said:
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.Yes, this seems to help! Do I have to copy the entire mesh (verts and tris) too? Yes, actually this solves it:
int[] tris = m.triangles;
int numTris = tris.Length;
Vector3[] verts = m.vertices;and then use those variables instead inside the loop. Thanks!
5 -
Patrick mod
Okay, so the output code must have been making a copy each iteration through the loop and the app was running out of memory. To answer your other question, that is a large number of triangles, but not unusual. What are you setting TrianglesPerCubicMeter to?
Whenever you access vertices, triangles, or normal (or any other array I'm forgetting) you'll make a copy. The first time you access someMeshFilter.mesh you will make a copy. If you access someMeshFilter.sharedMesh you will not make a 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?)
5
Answers
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:
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:
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).
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?
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?)
Yes, this seems to help! Do I have to copy the entire mesh (verts and tris) too? Yes, actually this solves it:
int[] tris = m.triangles;
int numTris = tris.Length;
Vector3[] verts = m.vertices;
and then use those variables instead inside the loop. Thanks!
Okay, so the output code must have been making a copy each iteration through the loop and the app was running out of memory. To answer your other question, that is a large number of triangles, but not unusual. What are you setting TrianglesPerCubicMeter to?
Whenever you access vertices, triangles, or normal (or any other array I'm forgetting) you'll make a copy. The first time you access someMeshFilter.mesh you will make a copy. If you access someMeshFilter.sharedMesh you will not make a 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?)