Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Need help with vector math

Discussion in 'Scripting' started by TheCheese, Jul 27, 2012.

  1. TheCheese

    TheCheese

    Joined:
    Nov 25, 2009
    Posts:
    82
    Hi,

    I'm trying to position a label in screen space in the bottom-left corner of a 3D object.

    My current solution is to convert all the object's vertices to screen points (they are very low-poly objects), then find the largest x value and smallest y value and position the label there.

    However, some of the objects are pretty irregular, and I'd like the label to "hug" the objects a little more. Can anyone help me with the math / algorithm to find the closest "bottom right" point of the object?

    Thanks.
     
  2. karljj1

    karljj1

    Joined:
    Feb 17, 2011
    Posts:
    440
  3. wccrawford

    wccrawford

    Joined:
    Sep 30, 2011
    Posts:
    2,039
    I think his point is that the bounds aren't very accurate and he's like to scooch his objects closer together than that. He's looking for a way to efficiently do that.

    Other than pre-computing that kind of information for each corner the object's bounding cube, I can't think of a way to make that faster. (That way, you'd be checking at most 8 values instead of all of them, each time.) Or maybe checking each side of the cube would be better? How you partition it will depend on your needs, I guess.
     
  4. TheCheese

    TheCheese

    Joined:
    Nov 25, 2009
    Posts:
    82
    Thanks for the suggestions, but maybe I need to explain a little better.

    Using my current code, the label will always appear at the bottom left corner of the object.
    Here's the code I'm currently using each frame:

    Code (csharp):
    1.  
    2. float x = 0;
    3. float y = Screen.height;
    4.  
    5.         foreach(Vector3 v in mesh){
    6.             screenPoint = mainCam.WorldToScreenPoint(targetTransform.TransformPoint(v));
    7.             if (screenPoint.x > x) x = screenPoint.x;
    8.             if (screenPoint.y < y) y = screenPoint.y;
    9.         }
    10.         return new Vector2(x, y);
    11.    
    This works fine when the edge of the object is at the bottom right of the screen, but if the object is concave then the label can end up being positioned quite far away from the object. This picture might clear things up -

    This is the current functionality:
    You can see the label is positioned at the corner of the highlighted object


    This is the desired:
    I would like the label to "hug" the object more closely, but keep to the bottom right


    Thanks!
     
  5. karljj1

    karljj1

    Joined:
    Feb 17, 2011
    Posts:
    440
    You could apply a CONVEX Mesh collider to the object. Then use the bounding box corners as a guide to fire rays into the mesh to get the actual corners.
    I.E pre-compute the corners.

    K
     
  6. Brian-Stone

    Brian-Stone

    Joined:
    Jun 9, 2012
    Posts:
    222
    The easy way to do this would be to define some fixed points in space around the area, transform just those points to screen space (no need to transform the entire model), and that will make deciding which point is best to use as an anchor point for the label much easier. That way the label is exactly where you want it to be. Those points can morphological approximate the boundary of the area.

    If you want more a smooth and flowing transition rather than jumping from point-to-point, then you can take this a step further and define a spline around the area that the label anchors to.

    A good way to choose the label anchor point on the spline (or even just a set of points) is to choose some arbitrary angle around the area's local coordinate system. Calculate the point on the spline that intersects that angle, or choose the point that is closest.
     

    Attached Files:

  7. TheCheese

    TheCheese

    Joined:
    Nov 25, 2009
    Posts:
    82
    Thanks Brian -

    That's great in theory, but I'm a little lost as to how to "Calculate the point on the spline that intersects that angle, or choose the point that is closest."

    What would really be ideal would be an algorithm that chooses the closest point out of the array of screen-space vertices that intersects that angle (or chooses the closest) and simply skip the spline. I simply dont' know how that would be done though. Any help would be much appreciated.
     
  8. ChaseRLewis73003

    ChaseRLewis73003

    Joined:
    Apr 23, 2012
    Posts:
    85
    Well if a closed curve is parameterized from [0,1] then a spline collection could give you the spline point by submitting (angledesired)/2*Pi if you setup your own curve class to base the parameterization based on angle around the curve and not arc length. Where you get angle desired by taking the dotproduct of a reference angle pointing to where the curve has t = 0 and towards the direction you want the label to appear. That's some heavy math though if your not used to parameterized functions.

    Easiest way to do this depends on a few factors. Are you moving in a 3D scene? Is the game kinda isometric like the picture above? Do you have a zoom function?

    Honestly if you have zoom the offset will have to move based on your zoom or it will look weird. If you don't I'd just set an offset from the mesh that isn't set procedurally and child the object to the mesh you want to display it next too. With some event setup to enable/disable it when it needs to be displayed.