Jump to content

World space to Screen space conversion


photo

Recommended Posts

Is there a Unigine function that will translate world position vec3(x,y,z) to screen position (x,y)? This will be useful to place UI images on/around 3d objects within the world.

Link to comment

Is there a Unigine function that will translate world position vec3(x,y,z) to screen position (x,y)? This will be useful to place UI images on/around 3d objects within the world.

 

 

Sorry misread it.

 

Have a look at this function, there should :

 

       vec3 p0,p1;
       Unigine::getPlayerMouseDirection(p0,p1);
Link to comment

You could use Player::getModelview() and Player::getProjection() functions for manual calculation of combined modelview-projection-matrix for world to screen space transformation.

 

But maybe its much simpler to use ObjectGui instead as it can be attached as child nodes and already provides things like billboarding etc. Have a look at UNIGINE samples_object demo gui_06 (see screenshot). Relevant source code can be found in <UNIGINE-sdk-root>\data\samples\objects\gui_06.cpp.

 

post-82-0-97495500-1307372765_thumb.jpg

Link to comment

I would need the other direction... getting the screen position based on an objects location in 3d space (and without using the mouse).

Link to comment

Manual math seems like the only option as I need to draw pointers when objects leave the screen as well.

 

Then maybe engine.visualizer functions might be a usable approach for drawing 3D vectors/lines/text etc. See example with vectors drawn by engine.visualizer.renderVector()

 

post-82-0-14008100-1307373717_thumb.jpg

Link to comment

Doing the math works very well, except Player::getProjection() always returns a mat4 with an apsect ration of 1, so everything is a bit off unless your run your app the same width/height resolution. We got around this by using the perspective() function.

Link to comment
  • 2 weeks later...

it would be nice if engine provided some function to do these kind of jobs.

 

agreed

this is the class I am using.

class ScreenPoint{
vec3 world_position;
vec4 screen_position;
int floor,optimise;
// 	Object selection;
Gui gui;
ScreenPoint(vec3 pos,int floor_ = false ,int optimise_ = true) {
	world_position = pos;
	floor = floor_;
	optimise = optimise_;
	gui = engine.getGui();
}
vec4 update(mat4 mvp) {
	mat4 position = vec4(mat4(world_position).m03m13m23,1.0);
	screen_position = mvp * position;
	if(screen_position.w < EPSILON && optimise) return NULL;
	screen_position /= abs(screen_position.w);
	screen_position.x = (0.5 + screen_position.x * 0.5) * gui.getWidth();
	screen_position.y = (0.5 - screen_position.y * 0.5) * gui.getHeight();
	return screen_position;
}
vec3 getWorldPosition() {return world_position;}
void setWorldPosition(vec3 pos=NULL) {
	if(is_vec3(pos)) {world_position = pos;return;}
}
vec4 getScreenPosition() {return screen_position;}
void setScreenPosition(vec4 pos) {screen_position = pos;}
};

 

where mvp is calculated using

mat4 projection = player.getProjection();
	projection.m00 *= float(gui.getHeight()) / gui.getWidth();
	mat4 mvp = projection * player.getIWorldTransform();

This only needs to be calculated once everytime the camera changes.

Link to comment
  • 4 weeks later...

This function will be available in the next SDK.

 

int getScreenPosition(vec3 point,int &x,int &y) {
Player player = getPlayer();
if(player == NULL) return 0;
int width = engine.app.getWidth();
int height = engine.app.getHeight();
mat4 projection = player.getProjection();
mat4 modelview = player.getIWorldTransform();
projection.m00 *= float(height) / width;
vec4 p = projection * (modelview * vec4(point,1.0f));
if(p.w > 0.0f) {
	x = int(width * (0.5f + p.x * 0.5f / p.w));
	y = int(height * (0.5f - p.y * 0.5f / p.w));
	return 1;
}
return 0;
}

Link to comment
×
×
  • Create New...