4
\$\begingroup\$

The Elder Scrolls: Morrowind has a rather interesting way to display each focused objects' name. It's all a bit fuzzy in my memory right now, but the most important part I remember perfectly: the object's name is always displayed in the proximity of the object (most of the time on top of it).

My question is: given a 3D mesh, how should I proceed to calculate the name's position on the screen? I'd like to always position it on top of the given mesh for now. Like in this screenshot of Morrowind:

enter image description here

I'm working under Unity, if it helps. The first thing that comes to my mind is to somehow use the distance between the player and each object, then take the object's actual height in consideration, and determine a line in 2D space (the screen) that just "touches" (intersects) the top of the 2D representation of the mesh (what we're actually able to view on the screen). Something like this: enter image description here

But this feels a bit complicated and clunky, and might not work for characters that are not standing tall for example.

The 2nd thing that comes to my mind: would there be a way to achieve this using matrix multiplication, in the same way 2D representations of 3D objects are obtained?

Thanks!

\$\endgroup\$
3
  • \$\begingroup\$ If you already have bounding boxes for collision checks you could use easily make use of them. \$\endgroup\$
    – danijar
    Commented Mar 26, 2013 at 15:52
  • \$\begingroup\$ Billboard positioned at the top of (or slightly above) the character model. \$\endgroup\$
    – House
    Commented Mar 26, 2013 at 17:21
  • \$\begingroup\$ Never heard of billboarding before :) I've taken a look at it; this also makes Xerosigma's answer make more sense to me. I wonder if I can combine this with decals to make a different text show up for different objects (or is there a better way?) \$\endgroup\$
    – user15805
    Commented Mar 26, 2013 at 17:44

2 Answers 2

2
\$\begingroup\$

If you are using GameObjects you could easily:

float SomeYOffset = 1.1f;

// Set position of GUI element
nameBar.position = new Vector3(player.position.x, player.position.y * SomeYOffset, player.position.z);

If you're not using GameObjects, you can take the vertex with the highest Y value and offset the nameBar mesh from there.

for(int i = 0; i < nameBar.verts.Length; i++)
{
    nameBar.verts[i] += new Vector3(vert.x, vert.y += SomeYOffset, player.z);
}
\$\endgroup\$
9
  • \$\begingroup\$ Using the vertext with the highest Y-value might lead to weird placement on the horizontal axis. Maybe it would be better to use the Y-value of the highest vertext and the average of the outmost vectors for the X- and Z-coordinate. \$\endgroup\$
    – Philipp
    Commented Mar 26, 2013 at 15:50
  • \$\begingroup\$ Averaging could work with that approach. I use averaging to determine the center of my dynamic meshes all the time. \$\endgroup\$ Commented Mar 26, 2013 at 15:52
  • 2
    \$\begingroup\$ Is player.position.y *= SomeYOffset meant to be player.position.y * SomeYOffset? \$\endgroup\$
    – danijar
    Commented Mar 26, 2013 at 15:52
  • \$\begingroup\$ Lol yes, yes it is. \$\endgroup\$ Commented Mar 26, 2013 at 15:53
  • \$\begingroup\$ So basically you're telling me to treat the namebar itself as a 3D mesh? \$\endgroup\$
    – user15805
    Commented Mar 26, 2013 at 15:57
2
\$\begingroup\$

Some things to consider here are that the object might not be rotated towards the camera, and that the position in 3d world space of the object is not always linear. So, objects farther away from the camera would need the font size reduced in relation to their depth in the view.

Here is some sample code that transforms relative to the camera:

   objectname = GameObject.Instantiate(Resources.Load("HoverText")) as GameObject;
   GUIText name = objectname.GetComponent<GUIText>();

   name.text = "Test Name"; // Change Me

   objectname.transform.position = Camera.mainCamera.WorldToViewportPoint(transform.position) + new Vector3(0f, 0.05f, 0f); // Change the 0.05f value to some other value for desired height

"HoverText" should be in the Resources directory in the project. The gameobject itself should have a GUIText component added to it.

\$\endgroup\$

You must log in to answer this question.