World To Screen Point

Whether there is a method to calculate the world coordinate XYZ to the screen point XY coordinate in Babylon. For example, U3D’s camera.WorldToScreenPoint (obj.transform.position);

1 Like

may be this will help
var coordinates = BABYLON.Vector3.Project(vector3,
BABYLON.Matrix.Identity(),
scene.getTransformMatrix(),
camera.viewport.toGlobal(
engine.getRenderWidth(),
engine.getRenderHeight(),
));

8 Likes

So this is supposed WorldToScreenPoint

Yo @Atul_Sharma … What about ScreenToWorldPoint … How we we do that ?

2 Likes

I think i found the answer: If world to screen to point is Vector3.Project … then Screen To World point must be Vecter2.Unproject

From @Deltakosh

var vector= BABYLON.Vector3.Unproject(
                        mousePosition,
            	        engine.getRenderWidth(),
                        engine.getRenderHeight(),
                        BABYLON.Matrix.Identity(), scene.getViewMatrix(),
                        scene.getProjectionMatrix());

where mousePosition is the Vector2 with the screen X/Y coord you want to convert to world space

Right ???

2 Likes

Yes that is the right function but the first parameter is a vec3: you also need to provide a z value in screen space (value between 0 and 1).

Hi,
Is there any way to convert world points(in latitude and longitude) to screen point which is the path array for tube structure in react-babylonjs?

You need to convert longitude/latitude into cartesian coordinates.

Here’s the first link that appeared in Google:

1 Like

@Evgeni_Popov could you please help me with another example?

You see a red pin, it is an indicator of object’s position in the world.

If you press UpArrow and move forward a little bit, red pin will be on top of screen, but must be on the bottom all the time(because object is behind us).

I think I should adjust matrices somehow, but I can’t figure out what I should change.

PS I have a game with objects on the XZ plane so I want to help players to rich objects in world.

You can try not to call ProjectToRef but do the clipping in clip space yourself:

You will see you get some Infinity when the object is too far behind, but it seems the display is still ok.

3 Likes

Tried to use this code but I get NaN. Could someone take a look please?
Playground: https://playground.babylonjs.com/#DTO22V#4

Something was not ready: https://playground.babylonjs.com/#DTO22V#5

1 Like

Oh, looks like there is some more complex problem. Thanks for pointing me! It looks like it should pass some scene.render() before it’s ready to use. That has a common sense, yeah.
It’s all in case you use your own update loop.

So if you use your own render-loop you SHOULD call world_to_screen() strictly after scene.render() was calling. Not before that. That’s why I got NaN. But it’s definitely may happen if you initialize your systems before render was actually start. For example, you may need to place some GUI elements sticked to some world point. You may think to do it before render will start but not, you can’t use it :smiley:

So I came up with this solution:

// initial creating Scene object goes here...
// right after it:
await wait_until_scene_is_ready( scene )
scene.render()
scene.render()
await wait_until_scene_is_ready( scene ) // don't know why, but to be on the safe side
console.log( `Scene IS FULLY READY!` )

// bjs_utils.ts:
export async wait_until_scene_is_ready( scene )
{
	return new Promise( resolve =>
	{
		scene.executeWhenReady( () => resolve( true ) )
	} );
}

BUT. It’s not dedicated to this problem but I found some bug when you do just one scene. render() in a row. Unfortunately I forgot to document that behaviour here but I remember if you call render() just one that BabylonJS set wrong positions to your objects or something like that. Calling render() twice in a row solved the problem. That’s why I call it twice now :smiley:

UPD
Oh, ok, about that “bug” I found in my code that comment:

this._scene.render()
this._scene.render() 
/* 
Looks like some BJS bug, but if I apply `moveWithCollisions()` right 
at the start without making that first `render()` call then my object 
will have some position offset which was not set by me, which is weird 
and not what I expect when making `moveWithCollisions()` call with my own
coordinates/deltas. It just goes in a wrong way at the first step and 
never will correct it.
*/

The scene render loop calls camera.update() and scene.setTransformMatrix() for you, but if you do some calculations that need an-up-to date camera, you must call these methods yourself:

1 Like