int Camera::getHorizIntersectionFromScreenSpace(const glm::vec2& ndcClick, glm::vec2& result) { // this first part finds the intersection of your ray with the horizontal z = 0 plane, whether in front of you // or behind you. glm::vec4 rayClip = getProjInv() * glm::vec4(ndcClick.x, ndcClick.y, -1.f, 1.f); glm::vec4 rayWorld = getViewInv() * glm::vec4(rayClip.x, rayClip.y, -1.f, 0.f); if (rayWorld.z) { glm::vec4 ray = glm::normalize(rayWorld); if (ray.x) { float slopeX = ray.z / ray.x; result.x = eye.x + (-eye.z / slopeX); } else { result.x = eye.x; } if (ray.y) { float slopeY = ray.z / ray.y; result.y = eye.y + (-eye.z / slopeY); } else { result.y = eye.y; } } // the rest is to make sure the ray actually hits the horizontal plane (not the horizon) and that // it hits somewhere in the camera's field of view (that it hits in front of you) int clickedSkyOrGround = (rayWorld.z > 0) - (rayWorld.z < 0); // results 1 for sky, -1 for ground, 0 for horizon int cameraAboveOrBelow = (eye.z > 0) - (eye.z < 0); // results 1 for above horizon, -1 for below, 0 for horizon if (cameraAboveOrBelow) { if (cameraAboveOrBelow == -clickedSkyOrGround) { return clickedSkyOrGround; } else { return 0; } } else { return 0; } // so finally, it returns 1 if you hit the horizontal plane from below (meaning the z = 0 plane was your sky) // or -1 if you hit the same z = 0 plane from above (you hit the ground) // or 0 if you never hit the z = 0 plane (like if you are above it and also shoot above it, // or you shoot the horizon line or something. }
std::vector<glm::vec3> kore::Camera::getWSfrustumCorners() { glm::mat4 matViewInv = getViewInv(); // calculate frustum corner coordinates float fFov2 = getFovRad() / 2.0f; float tanFov2 = glm::tan(fFov2); float h2Far = tanFov2 * _fFar; float h2Near = tanFov2 * _fNear; float hFar = 2.0f * h2Far; float hNear = 2.0f * h2Near; const glm::ivec2& res = kore::RenderManager::getInstance()->getRenderResolution(); float aspect = static_cast<float>(res.x) / static_cast<float>(res.y); float w2Far = (hFar * aspect) / 2.0f; float w2Near = (hNear * aspect) / 2.0f; glm::vec3 v3Corners[8]; v3Corners[0] = glm::vec3(-1.0f * w2Near, -1.0f * h2Near, -_fNear); // lbn v3Corners[1] = glm::vec3(1.0f * w2Near, -1.0f * h2Near, -_fNear); // rbn v3Corners[2] = glm::vec3(1.0f * w2Near, 1.0f * h2Near, -_fNear); // rtn v3Corners[3] = glm::vec3(-1.0f * w2Near, 1.0f * h2Near, -_fNear); // ltn v3Corners[4] = glm::vec3(-1.0f * w2Far, -1.0f * h2Far, -_fFar); // lbn v3Corners[5] = glm::vec3(1.0f * w2Far, -1.0f * h2Far, -_fFar); // rbn v3Corners[6] = glm::vec3(1.0f * w2Far, 1.0f * h2Far, -_fFar); // rtn v3Corners[7] = glm::vec3(-1.0f * w2Far, 1.0f * h2Far, -_fFar); // ltn std::vector<glm::vec3> vReturnCorners; // transform each corner into WS for (int i = 0; i < 8; ++i) { glm::vec4 v4Result = matViewInv * glm::vec4(v3Corners[ i ], 1.0f); vReturnCorners.push_back(glm::vec3(v4Result.x, v4Result.y, v4Result.z)); } return vReturnCorners; }