void C3DCamera::unproject(const C3DViewport* viewport, Vector3* src, Vector3* dst) { assert(dst); // Create our screen space position in NDC. assert(viewport->width != 0.0f && viewport->height != 0.0f); Vector4 screen((src->x - viewport->x) / viewport->width, ((viewport->height - src->y) - viewport->y) / viewport->height, src->z, 1.0f); // Map to range -1 to 1. screen.x = screen.x * 2.0f - 1.0f; screen.y = screen.y * 2.0f - 1.0f; screen.z = screen.z * 2.0f - 1.0f; // Transform the screen-space NDC by our inverse view projection matrix. getInverseViewProjectionMatrix().transformVector(screen, &screen); // Divide by our W coordinate. if (screen.w != 0.0f) { screen.x /= screen.w; screen.y /= screen.w; screen.z /= screen.w; } dst->set(screen.x, screen.y, screen.z); }
const glm::mat4& CTransformer::getInverseModelViewProjectionMatrix() const { if (m_modelViewProjection.m_inverseDirty) { m_modelViewProjection.m_inverse = getInverseModelMatrix() * getInverseViewProjectionMatrix(); m_modelViewProjection.m_inverseDirty = false; } return m_modelViewProjection.m_inverse; }
const glm::mat4& Node::getInverseViewProjectionMatrix() const { Scene* scene = getScene(); auto camera = scene ? scene->getActiveCamera() : nullptr; if( camera ) { return camera->getInverseViewProjectionMatrix(); } static const glm::mat4 identity{1.0f}; return identity; }
void Camera::unproject(const Viewport* viewport, float x, float y, float depth, Vector3* dst) { // Determine viewport coords to use. float vpx, vpy, vpw, vph; if (viewport) { vpx = viewport->getX(); vpy = viewport->getY(); vpw = viewport->getWidth(); vph = viewport->getHeight(); } else { vpx = 0; vpy = 0; vpw = Game::getInstance()->getWidth(); vph = Game::getInstance()->getHeight(); } // Create our screen space position in NDC. Vector4 screen( ((float)x - (float)vpx) / (float)vpw, ((float)(vph - y) - (float)vpy) / (float)vph, depth, 1.0f ); // Map to range -1 to 1. screen.x = screen.x * 2.0f - 1.0f; screen.y = screen.y * 2.0f - 1.0f; screen.z = screen.z * 2.0f - 1.0f; // Transform the screen-space NDC by our inverse view projection matrix. getInverseViewProjectionMatrix().transformVector(screen, &screen); // Divide by our W coordinate. if (screen.w != 0.0f) { screen.x /= screen.w; screen.y /= screen.w; screen.z /= screen.w; } dst->set(screen.x, screen.y, screen.z); }