Unprojecting screen coordinates to world coordinates

Hello,

I’m adding functionality to spawn an object on the world from a mouse click. I found that gEnv->pRenderer->UnProjectFromScreen(…) wouldn’t properly unproject the screencoords, because it retrieved the identity matrix for the projection matrix (see line 6770 of DriverD3D.cpp).

Instead, I used gEnv->pSystem->GetViewCamera().Unproject(…) which worked as expected:

    Vec3 PerformRayCast(const Vec2& position)
{
// invert the mouse y for the raycast
float invMouseY = static_cast<float>(gEnv->pRenderer->GetHeight()) - position.y;
Vec3 s0, s1;
gEnv->pSystem->GetViewCamera().Unproject(Vec3(position.x, invMouseY, 0.0f), s0);
gEnv->pSystem->GetViewCamera().Unproject(Vec3(position.x, invMouseY, 1.0f), s1);
// Vec3 direction = end - start;
Vec3 direction = s1 - s0;
direction.Normalize();
// set up our raycast options - you can choose what entities to ignore and much more, but this // example just returns the first object hit const unsigned int flags = rwi_stop_at_pierceable | rwi_colltype_any | rwi_ignore_back_faces;
int entityTypes = ent_all;
const int maxHits = 1;
ray_hit hit;
if (gEnv->pPhysicalWorld->RayWorldIntersection(s0, direction * gEnv->p3DEngine->GetMaxViewDistance(), entityTypes, flags, &hit, maxHits))
{
// this is the hit position and normal Vec3 hitPosition = hit.pt;
Vec3 hitNormal = hit.n;
// did we hit an entity?
IEntity *pEntity = nullptr;
if (hit.pCollider)
{
pEntity = gEnv->pEntitySystem->GetEntityFromPhysics(hit.pCollider);
}
return hitPosition;
}
return Vec3(0, 0, 0);
}

Note: I called this “PerformRayCast” after retrieving mouse input from the InputChannelEventListener.

Question: Is this the desired/expected way of unprojecting screen coords? Or am I doing something wrong with IRenderer::UnProjectFromScreen (e.g., calling it too early/late in the frame?)

1 Like