Get Screen-Size Bounds of 3d Mesh

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Ikes

Hi,

I’m new to Godot and learning this great tool on the way. I’m making a 3d world where I can click on objects to select them. I already can project a name tag to it that follows the position on screen.

Now I want to place 4 corners around the object to indicate it is selected. That depends on how close I am to the object, so it has to grow or shrink. Is there something like unproject_position, but then for 2d dimensions?

Thanks in advance!

:bust_in_silhouette: Reply From: TheFamousRat

Yes, there is indeed a way to unproject 3d coordinates.

You could get the active camera (in your viewport) and call unprojected_position on it.

It woud look like this :

var screenCoordinates : Vector2 = get_viewport().get_camera().unproject_position(oneMeshVertices)

If you’re looking to make a rectangle around your mesh, you could just find the smallest x, the biggest one, and same for y.
Hope it answers your question.

Disclaimer : I’m not 100% sure I understood the premise of your question though. If you want to color the boundaries of the mesh, there would be a way to do that with shaders that might be faster. If you want to do it for detection of clicks on the Mesh, I would advise you to use an Area and to check “Input Ray Pickable”. Sorry if I didn’t get your question in the right way

Hi TheFamousRat,

Thank you for the time to answer my question. Sorry I didn’t make it clear enough.
I already use unproject_position to get the 2d position of the mesh on screen, but I want something like on this image below with the 4 red corners that scale with it, depending on the distance you look at it.
I don’t quite understand what you mean with finding the smallest x and y, but I want to place 2d corners in top left-right and bottom left-right over the object.

I hope this makes my question more clear.

selected object with indication

Ikes | 2019-02-02 09:31

Hello Ikes,

Sorry what I said wasn’t clear. I was going from the idea that you can define a rectangle only by two 2d points : one containing the smallest x and y couple, and the other the biggest.

An algorithm to find such bounds in your case would look something like this :

#Supposing that you already have an Array containing all the unprojected positions of the vertices. Let's call him unprojectedVerticesArray (as such he contains only Vector2 variables)

#We initialize the points so that the bounds can't be made of something not in the Array. Initializing them with a Vector2(0,0) might be incorrect
var p1 : Vector2 = unprojectedVerticesArray[0]
var p2 : Vector2 = p1

for i in unprojectedVerticesArray:
	p1.x = min(p1.x, unprojectedVerticesArray.x)
	p1.y = min(p1.y, unprojectedVerticesArray.y)
	p2.x = max(p2.x, unprojectedVerticesArray.x)
	p2.y = max(p2.y, unprojectedVerticesArray.y)

Normally in the ends p1 and p2 should define your rectangle correctly. The four points of the rectangle would be (in screen coordinates) (p1.x,p1.y), (p2.x,p1.y), (p2.x,p2.y), (p1.x,p2.y)

Hope it helps a bit more !

TheFamousRat | 2019-02-02 15:57

Hi TheFamousRat,

Thanks again for your reply. Your assumption that I already have an array is not quite right… I believe it has to do with “$MeshInstance.mesh.get_faces()” Could you point me in that direction as well? Sorry, I’m new to 3D programming, but really want to learn it.

Also when I pasted your code in my code it gave me an error on: `

var p1 : Vector2 = unprojectedVerticesArray[0]

`

expected end of statement (var)
Is this because of the systax p1 : Vector2 =
and what does the i do in the for loop, because it’s not being used elsewhere?
Edit: Oh, I think I understand. It goes through all indexes to find the min and max values?

Sorry to bother you with my questions, I hope you’re willing to point me in the right direction.

Regards, Ikes

Ikes | 2019-02-02 21:58

Oh ! Sorry, I assumed you were working with Godot 3.1, which wasn’t especially sound at all. The error has to do (I think) with static typing not being a thing until Godot 3.1. if you’re using a previous version, just remove the types specifications (“: Vector2” and others)

TheFamousRat | 2019-02-03 00:49