MCPcopy Create free account
hub / github.com/defold/defold / CameraScreenToWorld

Function CameraScreenToWorld

engine/render/src/render/camera.cpp:229–290  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

227 }
228
229 Result CameraScreenToWorld(HRenderContext render_context, HRenderCamera camera_handle, float screen_x, float screen_y, float z, dmVMath::Vector3* out_world)
230 {
231 RenderCamera* camera = render_context->m_RenderCameras.Get(camera_handle);
232
233 // Window size
234 dmGraphics::HContext gc = GetGraphicsContext(render_context);
235 float win_w = (float) dmGraphics::GetWindowWidth(gc);
236 float win_h = (float) dmGraphics::GetWindowHeight(gc);
237 if (win_w <= 0.0f)
238 {
239 win_w = 1.0f;
240 }
241 if (win_h <= 0.0f)
242 {
243 win_h = 1.0f;
244 }
245
246 // Viewport-aware screen -> Normalized Device Coordinates
247 const dmVMath::Vector4& vp = camera->m_Data.m_Viewport;
248 float vx = vp.getX() * win_w;
249 float vy = vp.getY() * win_h;
250 float vw = vp.getZ() * win_w;
251 float vh = vp.getW() * win_h;
252 if (vw <= 0.0f || vh <= 0.0f)
253 {
254 vx = 0.0f; vy = 0.0f; vw = win_w; vh = win_h;
255 }
256 float x_ndc = 2.0f * ((screen_x - vx) / vw) - 1.0f;
257 float y_ndc = 2.0f * ((screen_y - vy) / vh) - 1.0f;
258
259 dmVMath::Matrix4 inv_vp = dmVMath::Inverse(camera->m_ViewProjection);
260
261 // Unproject near/far points and build pixel ray (world)
262 dmVMath::Vector4 v_near_clip(x_ndc, y_ndc, -1.0f, 1.0f);
263 dmVMath::Vector4 v_far_clip (x_ndc, y_ndc, 1.0f, 1.0f);
264 dmVMath::Vector4 v0 = inv_vp * v_near_clip;
265 dmVMath::Vector4 v1 = inv_vp * v_far_clip;
266 float iw0 = 1.0f / v0.getW();
267 float iw1 = 1.0f / v1.getW();
268 dmVMath::Point3 p_near(v0.getX() * iw0, v0.getY() * iw0, v0.getZ() * iw0);
269 dmVMath::Point3 p_far (v1.getX() * iw1, v1.getY() * iw1, v1.getZ() * iw1);
270 dmVMath::Vector3 dir = dmVMath::Normalize(p_far - p_near);
271
272 // Camera forward (world)
273 dmVMath::Vector3 forward = dmVMath::Rotate(camera->m_LastRotation, dmVMath::Vector3(0.0f, 0.0f, -1.0f));
274 forward = dmVMath::Normalize(forward);
275
276 // z is view-depth along forward (world units from camera plane)
277 float denom = dmVMath::Dot(dir, forward);
278 if (denom > -EPS && denom < EPS)
279 {
280 return RESULT_INVALID_PARAMETER;
281 }
282
283 dmVMath::Point3 cam_pos = camera->m_LastPosition;
284 // Intersect the ray r(s) = p_near + s * dir with the view-depth plane at distance z along 'forward'
285 float dot0 = dmVMath::Dot(p_near - cam_pos, forward);
286 float s = (z - dot0) / denom;

Calls 13

GetGraphicsContextFunction · 0.85
GetWindowWidthFunction · 0.50
GetWindowHeightFunction · 0.50
InverseFunction · 0.50
NormalizeFunction · 0.50
RotateFunction · 0.50
Vector3Class · 0.50
DotFunction · 0.50
GetMethod · 0.45
getXMethod · 0.45
getYMethod · 0.45
getZMethod · 0.45

Tested by

no test coverage detected