Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Need to update collision mesh when committing mesh data #542

Merged
merged 4 commits into from Mar 9, 2017

Conversation

trzy
Copy link

@trzy trzy commented Feb 28, 2017

There appears to be a bug with SpatialUnderstandingCustomMesh: when finalizing the mesh data (with Commit()), the rendering mesh picks up the changes but the collision mesh does not. Presumably this is a quirk of how Unity handles collision meshes.

The result of this is that using meshes produced by the Spatial Understanding system (as opposed to the underlying meshes provided by SpatialMappingManager) doesn't work in scenarios where rigid bodies are expected to collide with the world.

This patch appears to be the minimum required change to fix the problem however it's a bit ugly: I have to set a reference to the MeshCollider in MeshData, which otherwise consists exclusively of readonly members. A proper fix would require modifying CreateSurfaceObject() but that is a bit more of an extensive modification and I think something along the line of my approach is simpler.

@msftclas
Copy link

This seems like a small (but important) contribution, so no Contribution License Agreement is required at this point. We will now review your pull request.
Thanks,
Microsoft Pull Request Bot

@StephenHodgson
Copy link
Contributor

StephenHodgson commented Feb 28, 2017

So you're saying this may fix #228? (if so that would be awesome!)

@@ -98,6 +98,11 @@ private class MeshData
public readonly Mesh MeshObject = new Mesh();

/// <summary>
/// The MeshCollider with which this mesh is associated.
/// </summary>
public MeshCollider Collider = null;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest using a more specific name. Collider is a name for a Unity class. I suggest SpatialCollider or something along those lines.

@@ -118,6 +123,11 @@ public void Commit()
MeshObject.SetTriangles(tris, 0);
MeshObject.RecalculateNormals();
MeshObject.RecalculateBounds();
if (Collider)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: if (Collider != null)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll rename it to SpatialCollider as suggested above and also make this change. To be honest, I would actually prefer not even performing this test. Ideally, we want to ensure this member is always set and having it blow up with a null pointer exception would quickly draw attention to erroneous usage.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed.

));
SurfaceObject surfaceObject = CreateSurfaceObject(
mesh: nextSectorData.MeshObject,
objectName: string.Format("SurfaceUnderstanding Mesh-{0}", surfaceObjectIndex),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where do we use the object name?
Is it just for naming the object in the hierarchy of the scene?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I know, that is all the name is used for.

@@ -118,6 +123,8 @@ public void Commit()
MeshObject.SetTriangles(tris, 0);
MeshObject.RecalculateNormals();
MeshObject.RecalculateBounds();
SpatialCollider.sharedMesh = null;
SpatialCollider.sharedMesh = MeshObject;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just one last thing. Do we need to set the sharedMesh to null before we set it?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup. Take a look at CreateSurfaceObject().

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're correct. I had to look it up. Strange that you'd need to set it null before setting it, but it's the only way to reset the mesh collider apparently.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mesh colliders need serious pre-processing to function, and are not suitable for updating in real-time.

Would it be feasible to use primitive colliders?

Copy link
Author

@trzy trzy Mar 1, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Primitive colliders are not feasible -- mesh colliders are used for spatial mapping, too. Also, note that the code that generates these meshes runs "asynchronously" as a coroutine and periodically yields. Also, it appears to me that Spatial Understanding produces a lot of really tiny meshes, which should be easier to set up.

If you look at where Commit() is called, on line 319, you can see that the routine yields immediately afterwards. This should be fine, especially considering that this is performed only once when finalizing the mesh.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should definitely add a comment here to clarify this quirk so that someone doesn't accidentally remove the null assignment in the future.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done and pushed.

@trzy
Copy link
Author

trzy commented Mar 1, 2017

Ok. I've pushed the changes discussed. Regarding #228, I don't think this is the same issue. The symptom here is that when disabling the spatial meshes produced by SpatialMappingManager and only using the meshes generated by SpatialUnderstanding, there are no collisions at all (all rigid bodies will simply fall through).

I'm guessing this was not necessarily by design but I'm not sure. If Spatial Understanding meshes are intended to be used in place of the raw input spatial meshes (i.e., for occlusion and room collision), then collision should definitely be enabled.

The mesh collider exists because the underlying spatial mapping modules are used to produce the game objects but that doesn't mean it was intended to be used... If spatial understanding is intended only to produce "metadata" for object placement, then maybe this "fix" isn't needed.

@StephenHodgson
Copy link
Contributor

StephenHodgson commented Mar 1, 2017

I think having the choice of utilizing the generated colliders or not would be beneficial.

@trzy
Copy link
Author

trzy commented Mar 1, 2017

Agreed about the choice of using colliders. Shall I add that and push here for you to check? Can probably do it tonight or tomorrow.

@StephenHodgson
Copy link
Contributor

StephenHodgson commented Mar 1, 2017

That's up to you.

@thebanjomatic Good thinking adding that comment btw. I think it's a good one to have there in case someone removes and doesn't understand the necessity of it.

@trzy
Copy link
Author

trzy commented Mar 2, 2017

I've added an option, CreateMeshCollider, that is set true by default, which can be unchecked in order to avoid assigning a collision mesh. It'll also outright disable the collider in that case. Let me know if it looks okay to you.

@StephenHodgson
Copy link
Contributor

StephenHodgson commented Mar 2, 2017

I can't test on the HoloLens to confirm though, so we might need someone with a device to confirm.

@StephenHodgson
Copy link
Contributor

StephenHodgson commented Mar 2, 2017

I am a bit concerned that CreateMeshColliders and CreateMeshCollider is a bit confusing though.

[edit]
Oh I see, CreateMeshCollider is part of the MeshData class.

/// <summary>
/// Whether to create mesh colliders. If unchecked, mesh colliders will be empty and disabled.
/// </summary>
public bool CreateMeshColliders = true;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only comment I have at this point is that I like the idea of this being a property following the behavior of DrawProcessedMesh such that setting it to false would disable the Collider for all the existing surfaceObjects

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great idea.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At which point "UseProcessedMeshCollider" or something else might be more appropriate I guess.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's one problem with that: setting to true would have to enable the collision meshes (potentially generating them for the first time) and this is too slow to do inside of a setter. Kicking off an async task of some sort also violates the principle of least surprise, I think.

Let me know whether we should pursue this suggestion. I'm definitely open to making it work if there's a simple way of doing it that's consistent with the rest of the API.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good point, and it seems like more trouble than its worth. I'm fine with things as they are right now.

@StephenHodgson StephenHodgson merged commit 54d087d into microsoft:master Mar 9, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants