Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question Get side of plane

Discussion in 'Scripting' started by DevDunk, Jun 13, 2023.

  1. DevDunk

    DevDunk

    Joined:
    Feb 13, 2020
    Posts:
    4,362
    I am working on a mesh slicer for VR.
    A user can grab a mesh and break it off (into 2 pieces) using a realtime slicing system.

    Now I want the user to keep holding onto the side that was already in hand. I do this by checking on which side of the plane (used for cutting the mesh) the hand is using the dot product of the hand position relative to the plane's position and normal.
    This works great, except when the mesh is flipped. In this case the mesh bends the other way, but the slicing plane is the same. This time the part that should be stationary is grabbed.

    Does anyone know how to work around this?
    I thought about using the bounds' center, but this will add complexity since I need to get the components again after the objects being generated. Might work, but I feel like there is a better solution

    Pseudocode:

    Code (CSharp):
    1. private void BreakMesh(float3 transformPos, float3 halfTangent)
    2.         {            CurveTools.GetPointOnQuadraticBezierCurve(StationairyAttatchmentPoint, bendPoint, transformPos, bendStrength, out float3 pos); //Get point of breaking
    3.  
    4.             currentGrabber.TryRelease(); //Release old mesh
    5.  
    6.             BreakAtPosition(pos, halfTangent);
    7.         }
    8.  
    9. public void BreakAtPosition(Vector3 position, Vector3 normal)
    10.         {
    11. //Loop over all triangles and filling lists using GetVertexSide
    12. bool grabbingRight = MeshTools.GetVertexSide(handVisual.position, position, normal) > 0;
    13.             GenerateMesh(leftNormals, leftVerts, leftUVs, leftIndices, leftTris, mat, grabbingRight);
    14.             GenerateMesh(rightNormals,rightVerts, rightUVs, rightIndices, rightTris, mat, !grabbingRight);
    15. }
    16.  
    17. public static float GetVertexSide(in float3 vert, in float3 pos, in float3 norm)
    18.         {
    19.             return math.dot(vert - pos, norm);
    20.         }
    21.  
    22. void GenerateMesh(NativeList<Vector3> normals, NativeList<Vector3> verts, NativeList<Vector2> uvs, NativeList<int> indices, NativeList<int> tris, Material mat, bool isKinematic)
    23.         {
    24.            Mesh mesh = //make mesh and fill data
    25.             GameObject go = //Set all data for gameobject
    26.          
    27. var grabbable = go.GetComponent<Grabbable>();
    28.          
    29. //Set rigidbody as kinematic when not grabbing
    30.             if (isKinematic && go.TryGetComponent<Rigidbody>(out Rigidbody rb))
    31.             {
    32.                 rb.isKinematic = true;
    33.             }
    34.             if (!isKinematic) Grab mesh
    35.             {
    36.                 currentGrabber.GrabGrabbable(grabbable);
    37.             }
    38.         }

    Edit:
    I have a hacky workaround where I check the distance from the hand to a random vertex position in each new mesh. The closest one will be grabbed. Works fine for most meshes, but not a permanent fix
     
    Last edited: Jun 13, 2023
  2. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,043
    Can Plane.GetSide help you?

    You can also compute a cross between two vectors. Use three fingers on your left hand to anticipate the direction of the result. Cross is non-commutative, so you can switch places.
     
  3. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,043
    Wai wait. What do you mean by "the mesh is flipped"?
     
  4. DevDunk

    DevDunk

    Joined:
    Feb 13, 2020
    Posts:
    4,362
    I meant rotated 180 degrees (or maybe my model itself has a different rotation, not too sure actually).
    Haven't used cross yet, so gotta look into it.
    Plane.GetSide is basically what I do now manually
     
  5. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,495
    where does that "halfTangent" come from? I guess that's your cutting plain normal, right? Also I don't know what kind of cutting tool you're using, but do you cut in local space of the object or do you convert all the vertices into worldspace. When you work in local space you should transform your cutting plane into local space (InverseTransformDirection for the plain normal and InverseTransformPoint for the plane origin).
     
  6. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,043
    It took me a while before I was able to understand you properly. Let's use proper terminology:

    You slice a mesh in two parts. You use a slicing plane to split the mesh. The hand is holding the mesh prior to slicing. Now you want to know whether to keep holding onto the part that was already in hand.

    The usage of the word 'side' threw me off completely.

    Yes, to detect this you need to get both bounding boxes, take their centroids. Whatever centroid is on the same side of the slicing plane as the hand, that part is what the hand is holding. I can't think of a scenario where this doesn't work. Even if the mesh was concave, slicing plane would introduce a clear separation between centroids. And no matter what you do with the rotation of the plane, the hand must end up on one side of it. The only weird case is slicing your own hand, but that's in the quality of life department, mathematically it's still the same check.

    Yes Plane.GetSide is the sign of the dot product between the delta vector and plane's normal.
    Just throw in the grab coordinate. Whichever centroid's GetSide gets you the same sign as the grab coordinate, that's the winner.
     
    DevDunk likes this.
  7. DevDunk

    DevDunk

    Joined:
    Feb 13, 2020
    Posts:
    4,362
    Thanks! I'll integrate it into the new version!

    Yep, that's the normal vector
    I work in local space to reduce the amount of conversion. Did not get the hand position into local space, so might give that a quick try as well
     
    orionsyndrome and Bunny83 like this.