Is there a way to get the scaling value of a unprojected point from a 3D camera?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By avencherus
:warning: Old Version Published before Godot 3 was released.

When using camera.unproject_point(Vector3), you get the 2D coordinates in a Vector2, but I was wondering if there is a method that can be used to get what it’s scaling value would be at that position.

What do you mean by scaling?

Zylann | 2016-10-30 20:04

The perspective scalar that is calculated in 3D transforms. In 4D vectors it’s that W component. It would determine how much something grows or shrinks based on how near or far they are from the camera.

avencherus | 2016-10-31 03:09

Is it for making an object appear the same size whatever distance it is from? Because doing that can actually be done easily from a shader, by computing the projection a bit differently (I’ve done that once but I don’t remember how :s)

Otherwise, I would do something like that as a workaround (untested, dunno if it’s right):

func get_scaling(camera, point_3d):
	var right = camera.get_camera_transform().basis.x
	var point_2d = camera.unproject_position(point_3d)
	var point_offset_2d = camera.unproject_position(point_3d + right * camera.get_znear())
	return point_2d.distance_to(point_offset_2d)

Which should return 1 if the object is on the near plane, or a smaller and smaller number the further it goes.
But I feel this is not quite the right code, mostly because I would have used W tbh ^^"

Edit: testing it right now, first thing is, the size of the screen also affects that number…
Doesn’t looks that bad once the screen size is taken into account https://www.youtube.com/watch?v=3hB3oUDh9pM&feature=youtu.be

Zylann | 2016-10-31 19:48

Thanks.

That’s a fun effect. X)

I’m just looking to get the scaling out a 3D world to use in a 2D interface. I haven’t yet approached 3D rendering yet, so I’m not too educated yet on camera and frustum transformations. So I can’t really verify those results. They do appear to be appropriately rising and falling, though the numbers are a bit high, so I don’t know if I can use them, because the 2D items will get too large when scaling to 6+ times.

I’m not sure how to calculate the ranges, so I wouldn’t know what numbers I could use to remap them with.

avencherus | 2016-11-01 10:11

Well, the thing is, a scale has to be relative to something. Scaling is not size. The example I wrote takes the near plane as reference, but you could take anything.

However, the way you describe your interface makes me think maybe you don’t need that method. So you have something in 3D, and you want to show it fitting into a 2D GUI rectangle, right?

Zylann | 2016-11-01 20:05

It’s a sort of a 2.5D kind of game. I was thinking maybe using a viewport sprite and perhaps billboarding the sprites.

But I have concerns about if the texture scaling will suffer, or if it is more expensive in general to render that way. If you just forward the position and scale to the sprite, the resizing I think would be better.

But it’s something worth testing, now that you mention it. X)

avencherus | 2016-11-01 20:41

2.5D, like… orthographic 3D?

Zylann | 2016-11-01 20:54

Yeah, though I would need objects to change scale. As the X and Y is not like a side scroller, but instead being laid out like a perspective plane. There seems to be several ways of doing this, and I’m just trying to figure out which is the best approach.

avencherus | 2016-11-01 21:15

Do you have an example of what you want to achieve?

Zylann | 2016-11-01 21:44

I suppose something like this: https://youtu.be/6sJFMyI3eZ0?t=54s

Though I haven’t had much luck with 2D with dynamically changing the collision shapes. It’s a bit fidgety. So I’d like to get the benefits of a 3D world cast into perspective against 2D background images. Only the objects in the main area will scale.

There are challenges though.

avencherus | 2016-11-01 22:41

For doing this without scripting, I would have a 2D fullscreen image rendered before anything else (like a background), then a 3D scene on top of it, with colliders cleverly positionned. The character would be a 3D billobard.
But I never tested this before so no idea if it’s the best way. You could ask the devs of LeftWay, eventually :slight_smile:

Zylann | 2016-11-02 01:24

Yeah it has interesting problems. I’d like to make a prototype of each idea and see which works the best. The one idea of taking 3D coordinates straight from the camera lacks a reasonable scalar. So I will put that aside for now and try some ideas using the viewport sprites.

The alignment shouldn’t be too much of a problem, but when the screen scrolls all the objects might move in parallax against a sprite background that moves at a rate to match the character.

Thanks for the replies Zylann. X)

I might have to see if those devs will respond.

avencherus | 2016-11-02 05:31