Search Unity

Is it possible to get UV coordinates of an object without using mesh colliders ?

Discussion in 'Physics' started by antoined73, Oct 13, 2019.

  1. antoined73

    antoined73

    Joined:
    Feb 23, 2014
    Posts:
    24
    Hello,

    I'd like to create a painting mechanic where you can paint on any surface. I already have all the painting system working but I'd like the paint to paint on adjacent surfaces rather than just the one model at a time (the one I have my mouse on).

    Here is a preview of what I'm talking about :
    Capture.PNG
    The ground has been painted but the walls didn't because my mouse wasn't exactly on them

    Here is the code I use to make it happen :
    Code (CSharp):
    1.  
    2.         // Find mesh to paint with the mouse
    3.         if (Physics.Raycast(_camera.ScreenPointToRay(Input.mousePosition), out _hit, 10f))
    4.         {
    5.             //Paint hit object
    6.             PaintableSurface paintableSurface = _hit.collider.GetComponent<PaintableSurface>();
    7.             if (paintableSurface != null)
    8.             {
    9.                 paintableSurface.Paint(_hit.textureCoord);
    10.             }
    11.  
    12.             // Paint adjacent objects
    13.             Collider[] cols = Physics.OverlapSphere(_hit.point, 0.75f);
    14.             foreach (Collider col in cols)
    15.             {
    16.                 PaintableSurface adjacentPaintableSurface = col.GetComponent<PaintableSurface>();
    17.                 if (adjacentPaintableSurface != null)
    18.                 {
    19.                     // Get closest point and paint on
    20.                     Vector3 closestPointOnCollider = col.ClosestPoint(_hit.point);
    21.                     if (Physics.Raycast(new Ray(_hit.point, (closestPointOnCollider -_hit.point).normalized), out, _hit2, 5f))
    22.                     {
    23.                         Debug.Log(_hit.textureCoord + " " + _hit2.textureCoord);
    24.                         adjacentPaintableSurface.Paint(_hit2.textureCoord);
    25.                     }
    26.                 }
    27.             }
    28.         }
    29.  
    I use raycasts to get the texcoord of the surface I hit. This method requires to use only non convex mesh colliders if I want right UV coordinates.
    To make the adjacent objects painted at the same time, I get the closest point between the collider and the hit point.
    Unfortunately, the ClosestPoint method force me to use all colliders BUT non convex mesh colliders...

    Since it will be on mobile and I want to be able to paint on large surfaces and many objects, is there another way to achieve the same effect efficiently without shooting random rays in all direction from the first hit point ?

    Thank you for your lights !
     
    Last edited: Oct 13, 2019
  2. damonp

    damonp

    Joined:
    Dec 7, 2012
    Posts:
    8
    Instead of Raycast, you may want to try SphereCastAll https://docs.unity3d.com/ScriptReference/Physics.SphereCastAll.html

    Then, you may not need to do the OverlapSphere part.
     
    antoined73 likes this.
  3. Olmi

    Olmi

    Joined:
    Nov 29, 2012
    Posts:
    1,553
    antoined73 likes this.
  4. antoined73

    antoined73

    Joined:
    Feb 23, 2014
    Posts:
    24
    Thank you for the tip ! Tested it and it works ! But It does not reproduce exactly the effect intended.
    Note at the end of the gif that the paint still does not cover the asjacent walls and the paint start upper from expected.
    It cannot be solved by increasing the sphere value because it is a sphere and the paint will go even further away from the expected border we want the paint to be visible.
    But it's definitely better !



    Here is the modifed code using the method :
    Code (CSharp):
    1.  
    2.          _hits = Physics.SphereCastAll(_camera.ScreenPointToRay(Input.mousePosition), 1f, 10f, LayerMask.GetMask("Paintable"));
    3.         foreach (RaycastHit hit in _hits)
    4.         {
    5.             PaintableSurface paintableSurface = hit.collider.GetComponent<PaintableSurface>();
    6.             if (paintableSurface != null)
    7.             {
    8.                 paintableSurface .Paint(hit.textureCoord);
    9.             }
    10.         }
    Anyway, I guess I could counter that by creating big models with only one texture rather than 1 mesh per wall (in this example).

    I could also try to calculate the closest point along the mesh to the center hit, but I don't know where to start.

    @Olmi Thank you for the link, definitely will dive into, It seams exactly the kind of problematic they are tackling !
    They seams to use vertex painting, but I'm not sure if it's a good idea for mobile devices.
     
  5. holykiller

    holykiller

    Joined:
    Nov 1, 2013
    Posts:
    10
    @antoined73 how do you manage to paint into that single point? im talking about the
    Code (CSharp):
    1. adjacentPaintableSurface.Paint(_hit2.textureCoord);
     
  6. antoined73

    antoined73

    Joined:
    Feb 23, 2014
    Posts:
    24
    Last edited: Dec 15, 2020