void PointLightInteractionHandler::setLightPosFromScreenCoords(const vec2& normalizedScreenCoord) { vec2 deviceCoord(2.f * (normalizedScreenCoord - 0.5f)); // Flip vertical axis since mouse event y position starts at top of screen deviceCoord.y *= -1.f; // Use half distance between look from and look to positions as scene radius. float sceneRadius = 0.5f * glm::length(camera_->getLookTo() - camera_->getLookFrom()); vec3 rayOrigin = camera_->getWorldPosFromNormalizedDeviceCoords(vec3(deviceCoord, 0.f)); vec3 rayDir = glm::normalize( camera_->getWorldPosFromNormalizedDeviceCoords(vec3(deviceCoord, 1.f)) - rayOrigin); float t0 = 0, t1 = std::numeric_limits<float>::max(); float lightRadius = glm::length(lightPosition_->get()); if (raySphereIntersection(vec3(0.f), sceneRadius, rayOrigin, rayDir, &t0, &t1)) { lightPosition_->set(glm::normalize(rayOrigin + t1 * rayDir) * lightRadius); } else { // Project it to the rim of the sphere t0 = 0; t1 = std::numeric_limits<float>::max(); if (rayPlaneIntersection(camera_->getLookTo(), glm::normalize(camera_->getLookTo() - camera_->getLookFrom()), rayOrigin, rayDir, &t0, &t1)) { // Project it to the edge of the sphere lightPosition_->set(glm::normalize(rayOrigin + t1 * rayDir) * lightRadius); } } // Ensure that up vector is same as camera afterwards setLookUp(camera_->getLookUp()); }
/* @param t distance */ static intersection ray_hit_object(const point3 e, const point3 d, double t0, double t1, const rectangular_node rectangulars, rectangular_node *hit_rectangular, const sphere_node spheres, sphere_node *hit_sphere) { /* set these to not hit */ *hit_rectangular = NULL; *hit_sphere = NULL; point3 biased_e; multiply_vector(d, t0, biased_e); add_vector(biased_e, e, biased_e); double nearest = t1; intersection result, tmpresult; for (rectangular_node rec = rectangulars; rec; rec = rec->next) { if (rayRectangularIntersection(biased_e, d, &(rec->element), &tmpresult, &t1) && (t1 < nearest)) { /* hit is closest so far */ *hit_rectangular = rec; nearest = t1; result = tmpresult; } } /* check the spheres */ for (sphere_node sphere = spheres; sphere; sphere = sphere->next) { if (raySphereIntersection(biased_e, d, &(sphere->element), &tmpresult, &t1) && (t1 < nearest)) { *hit_sphere = sphere; *hit_rectangular = NULL; nearest = t1; result = tmpresult; } } return result; }
//Ray-Object intersection-------------------------------------------------------------------------- float rayObjectIntersection(Ray ray, SPHERE sphere, POLY4 poly, Point3dPtr n, Point3dPtr interp, float * kd) { float t1, t2; // The two distances; float *kd1, *kd2; Point3dPtr n1, n2, interp1, interp2; n1 = (Point3dPtr)malloc(sizeof(Point3d)); n2 = (Point3dPtr)malloc(sizeof(Point3d)); interp1 = (Point3dPtr)malloc(sizeof(Point3d)); interp2 = (Point3dPtr)malloc(sizeof(Point3d)); kd1 = (float*)malloc(sizeof(*kd1)); kd2 = (float*)malloc(sizeof(*kd2)); t1 = raySphereIntersection(ray, sphere, n1, interp1, kd1); t2 = rayPolygonIntersection(ray, poly, n2, interp2, kd2); if (t1 == 0.0 && t2 == 0.0) return 0.0; else if (t2 == 0) { //the normal = n1; n->x = n1->x; n->y = n1->y; n->z = n1->z; //the intersection point = interp1; interp->x = interp1->x; interp->y = interp1->y; interp->z = interp1->z; *kd = *kd1; return t1; } else if (t1 == 0.0) { //the normal = n2; n->x = n2->x; n->y = n2->y; n->z = n2->z; //the intersection point = interp2; interp->x = interp2->x; interp->y = interp2->y; interp->z = interp2->z; *kd = *kd2; return t2; } else if (t1 < t2) { //the normal = n1; n->x = n1->x; n->y = n1->y; n->z = n1->z; //the intersection point = interp1; interp->x = interp1->x; interp->y = interp1->y; interp->z = interp1->z; *kd = *kd1; return t1; } else { //the normal = n2; n->x = n2->x; n->y = n2->y; n->z = n2->z; //the intersection point = interp2; interp->x = interp2->x; interp->y = interp2->y; interp->z = interp2->z; *kd = *kd2; return t2; } free(n1); free(n2); free(interp1); free(interp2); free(kd1); free(kd2); }