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.
 }
Beispiel #2
0
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;
}