void RayTracer::tracePhotons(Photon p, int bouncesLeft){ //Only trace the photon if more than one bounce if (bouncesLeft > 0){ //Get the intersected surface shared_ptr<UniversalSurfel> surfel = dynamic_pointer_cast<UniversalSurfel>(castRay(G3D::Ray(p.origin,p.direction).bumpedRay(0.0001), finf(), 0)); if (surfel){ p.origin = surfel->position; //Don't store for mirror surfaces if (!(surfel->glossyReflectionCoefficient.nonZero() && (surfel->glossyReflectionExponent == inf()))){ Vector3 D = p.origin - m_camera->frame().translation; //if (D.length() < 10){ if(castRay(G3D::Ray(m_camera->frame().translation,D).bumpedRay(0.0001), D.length(), 1)) { photons.insert(p); } //} } shared_ptr<Random> rnd = m_rnd[0]; Vector3 wo; Color3 weight; //scatter the photon using the method provided by G3D. Used to be a lot of lines which got deleted surfel->scatter(PathDirection::SOURCE_TO_EYE, -p.direction, true, *rnd, weight, wo); //If it scatters, continue tracing if (wo.magnitude() > 0){ p.direction = wo; p.power *= weight; tracePhotons(p, bouncesLeft - 1); } rnd.reset(); } } }
bool SceneObject::castRayRendered(const Point3F &start, const Point3F &end, RayInfo *info) { // By default, all ray checking against the rendered mesh will be passed // on to the collision mesh. This saves having to define both methods // for simple objects. return castRay( start, end, info ); }
std::tuple<cv::Mat, cv::Mat> SimpleRayCaster::renderZMasks() { cv::Mat fgMask(_res_y, _res_x, CV_32F); cv::Mat bgMask(_res_y, _res_x, CV_32F); for (int y=0; y<_res_y; y++) { for (int x=0; x<_res_x; x++) { Eigen::Vector2f co((float)x/(float)_res_x,(float)y/(float)_res_y); auto zvalues = castRay(co); float fgPixel = 0.0f; float bgPixel = 0.0f; /* only valid masks if there were 2 intersections */ if (zvalues.size() == 2) { if (zvalues[0] < zvalues[1]) { fgPixel = zvalues[0]; bgPixel = zvalues[1]; } else { fgPixel = zvalues[1]; bgPixel = zvalues[0]; } } fgMask.at<float>(y,x) = fgPixel; bgMask.at<float>(y,x) = bgPixel; } } return std::make_tuple(fgMask, bgMask); }
SceneNode *SceneManager::castRay( SceneNode *node, const Vec3f &rayOrig, const Vec3f &rayDir, float &minDist ) { if( !node->_active ) return 0x0; static Vec3f intsPos; SceneNode *nearestNode = 0x0; if( rayAABBIntersection( rayOrig, rayDir, node->_bBox.getMinCoords(), node->_bBox.getMaxCoords() ) ) { if( node->checkIntersection( rayOrig, rayDir, intsPos ) ) { float dist = (intsPos - rayOrig).length(); if( dist < minDist ) { nearestNode = node; minDist = dist; } } for( uint32 i = 0; i < node->_children.size(); ++i ) { SceneNode *sn = castRay( node->_children[i], rayOrig, rayDir, minDist ); if( sn != 0x0 ) nearestNode = sn; } } return nearestNode; }
bool PhysShape::castRayLocal(const Point3F &startLocal, const Point3F &endLocal, RayInfo* info) { if (m_physInfo.owner) { const VectorF& scale = m_physInfo.owner->getScale(); const MatrixF& objToWorld = m_physInfo.owner->getTransform(); Point3F start(startLocal); Point3F end (endLocal); start.convolve(scale); end.convolve(scale); objToWorld.mulP(start); objToWorld.mulP(end); bool res = castRay(start,end,info); if (res && info) { info->normal = startLocal - endLocal; info->normal.normalize(); } return res; } return false; }
void SceneView::handleDrop(float x, float y) { const char* path = (const char*)m_app.getDragData().data; auto hit = castRay(x, y); if (hit.m_is_hit) { if (Lumix::PathUtils::hasExtension(path, "msh")) { auto* command = LUMIX_NEW(m_editor->getAllocator(), InsertMeshCommand)( *m_editor, hit.m_origin + hit.m_t * hit.m_dir, Lumix::Path(path)); m_editor->executeCommand(command); } else if (Lumix::PathUtils::hasExtension(path, "mat") && hit.m_mesh) { auto* desc = Lumix::PropertyRegister::getDescriptor(RENDERABLE_TYPE, Lumix::crc32("Material")); auto drag_data = m_app.getDragData(); m_editor->selectEntities(&hit.m_entity, 1); auto* model = m_pipeline->getScene()->getRenderableModel(hit.m_component); int mesh_index = 0; for (int i = 0; i < model->getMeshCount(); ++i) { if (&model->getMesh(i) == hit.m_mesh) { mesh_index = i; break; } } m_editor->setProperty(RENDERABLE_TYPE, mesh_index, *desc, drag_data.data, drag_data.size); } } }
Radiance3 RayTracer::L_i(const Point3 P, const Vector3& wi, int bouncesLeft, Random& rnd) const{ //Get the surfel hit and call L_o to compute radiance at the surfel shared_ptr<Surfel> surfel = castRay(G3D::Ray(P,wi).bumpedRay(0.0001), finf(), 0); if (surfel){ return L_o(surfel, -wi, bouncesLeft, rnd); } else{ //No surfel, return black return Radiance3(0,0,0); } }
void RayTracer::traceOnePhoton(int ignoreX, int ignoreY, int threadID) { ThreadData& threadData(m_threadData[threadID]); Photon photon; emitPhoton(*threadData.rnd, photon); const float MIN_POWER_THRESHOLD = 0.001f / m_settings.photon.numEmitted; float probabilityHint = 1.0; for (int numBounces = 0; (numBounces < m_settings.photon.numBounces) && (photon.power.sum() > MIN_POWER_THRESHOLD); ++numBounces) { // Find the first surface float distance = finf(); const shared_ptr<Surfel>& surfel = castRay(photon.position, -photon.wi, distance, false); if (isNull(surfel)) { return; } // Store the photon (if this is not the first bounce and it is // not a purely specular surface) if ((numBounces > 0) && surfel->nonZeroFiniteScattering()) { photon.effectRadius = photonEffectRadius(probabilityHint); // Update photon position. Store it slightly before it hit the surface // to improve filtering later. photon.position = surfel->position + photon.wi * min(photon.effectRadius, distance) / 4; // Store a copy of this photon m_photonList[threadID].append(photon); } // Scatter Color3 weight; Vector3 wo; float probabilityScale; surfel->scatter(PathDirection::SOURCE_TO_EYE, photon.wi, true, *threadData.rnd, weight, wo, probabilityScale); probabilityHint *= probabilityScale; // Update photon power and direction photon.power *= weight; photon.wi = -wo; photon.position = bump(surfel, wo); } }
void SimpleRayCaster::renderDebugImage(int width, int height) { for (int y=0; y<height; y++) { for (int x=0; x<width; x++) { Eigen::Vector2f co((float)x/(float)width,(float)y/(float)height); auto zvalues = castRay(co); if (zvalues.size() > 0) { std::cout << "0"; } else { std::cout << " "; } } std::cout << std::endl; } }
bool RayTracer::visible(const Point3& Y, const Point3& X, bool shadowRay) const { Vector3 w(X - Y); float distance = w.length(); w /= distance; distance -= BUMP_EPSILON * 2; shared_ptr<Surfel> surfel = castRay(Y + w * BUMP_EPSILON, w, distance, true); if (isNull(surfel)) { return true; } else if (shadowRay && notNull(surfel->surface) && ! surfel->surface->expressiveLightScatteringProperties.castsShadows) { // Re-cast the ray return visible(surfel->position, X, true); } else { // Hit a surface return false; } }
Radiance3 RayTracer::L_in(const Point3& X, const Vector3& wi, ThreadData& threadData, int bouncesLeft) const { if (bouncesLeft == 0) { // We aren't allowed to trace farther, so estimate from the // environment map return BACKGROUND_RADIANCE; } // Surface hit by the primary ray (at X) float maxDistance = finf(); shared_ptr<Surfel> surfel(castRay(X, wi, maxDistance)); if (notNull(surfel)) { // Hit something return L_out(surfel, -wi, threadData, bouncesLeft); } else { // Hit background return BACKGROUND_RADIANCE; } }
GameObject * GameController::FindObjectAtScreenPosition(const Point &point) { if (mInstance) { glm::vec3 nearPoint = mCamera->Unproject(point, 0); glm::vec3 farPoint = mCamera->Unproject(point, 1); glm::vec3 direction = glm::normalize(farPoint - nearPoint); Ray castRay(nearPoint, direction); //mDebugRay->ClearPoints(); //mDebugRay->AddPoint(nearPoint); //mDebugRay->AddPoint(castRay.ValueAt(1000)); return mInstance->FindNearestObject(castRay); } return NULL; }
/* returns true if a point is in shadow from a light */ Color3 RayTracer::visiblePercentage(Ray ray, const shared_ptr<Light>& light, float distance) const{ //Only computes if we are actually casting shadows if (m_settings.enableShadows && light->castsShadows()){ //Increment the amount of shadow rays ++m_stats->shadowRays; //If partial coverage is enabled, we need to compute the actual percentage, otherwise just need to test visible if (m_settings.enablePartialCoverage){ Color3 visibility(1,1,1); //the current position of shadow ray Point3 oldPosition = ray.origin(); //Iterate through the surfels in between and multiply visibility by their trasmissiveness //Until we reach the original surface (distance <=0) or the visibility becomes 0 while ((distance > 0) && !(visibility.clamp(0,1).isZero())){ shared_ptr<UniversalSurfel> surfel = dynamic_pointer_cast<UniversalSurfel>(castRay(ray.bumpedRay(0.0001), distance, 0)); //If no more surfel left, simply return if (!surfel){ return visibility; } else{ visibility *= surfel->transmissionCoefficient; } distance = distance - (surfel->position - oldPosition).magnitude(); oldPosition = surfel->position; ray = Ray(oldPosition, ray.direction()); } return visibility; } else{ //If not doing partial coverage, just need to test visibility. Set anysurfel to 1 for faster intersection if(castRay(ray.bumpedRay(0.0001), distance, 1)) { return Color3(0,0,0); } else{ return Color3(1,1,1); } } } else{ //Non shadow casting always gives total visibility return Color3(1,1,1); } }
void generateRays ( std::vector<xe::sg::Ray> &rays, const xe::Vector2i &size, const xe::Vector3f &cam_pos, const xe::Vector3f &cam_up, const xe::Vector3f &cam_dir, const xe::Vector3f &cam_right) { assert(size.x > 0); assert(size.y > 0); assert(rays.size() == size.x*size.y); const xe::Vector2f sizef = (xe::Vector2f)size; const int rayCount = size.x * size.y; for (int i=0; i<rayCount; i++) { xe::Vector2i coord = computePixel(i, size); xe::Vector2f coordf = static_cast<xe::Vector2f>(coord); xe::sg::Ray ray = castRay(coordf, sizef, cam_pos, cam_up, cam_dir, cam_right); rays[i] = ray; } }
btScalar RaycastCar::rayCast(WheelInfo& wheel) { btScalar depth = -1; btScalar raylen = wheel.getSuspensionRestLength() + wheel.m_wheelsRadius; btVector3 rayvector = wheel.m_raycastInfo.m_wheelDirectionWS * (raylen); const btVector3& source = wheel.m_raycastInfo.m_hardPointWS; wheel.m_raycastInfo.m_contactPointWS = source + rayvector; const btVector3& target = wheel.m_raycastInfo.m_contactPointWS; btScalar param = btScalar(0.0); RaycasterResult rayResults; void * object = castRay(source,target,rayResults); wheel.m_raycastInfo.m_groundObject = 0; if (object) { param = rayResults.m_distFraction; depth = raylen * rayResults.m_distFraction; wheel.m_raycastInfo.m_contactNormalWS = rayResults.m_hitNormalInWorld; wheel.m_raycastInfo.m_isInContact = true; #ifdef USE_TMP_FIXED_OBJECT wheel.m_raycastInfo.m_groundObject = tmp_fixed; #else wheel.m_raycastInfo.m_groundObject = object; #endif btScalar hitDistance = param*raylen; wheel.m_raycastInfo.m_suspensionLength = hitDistance - wheel.m_wheelsRadius; //clamp on max suspension travel btScalar minSuspensionLength = wheel.getSuspensionRestLength()-wheel.m_maxSuspensionTravelCm*btScalar(0.01f); btScalar maxSuspensionLength = wheel.getSuspensionRestLength()+wheel.m_maxSuspensionTravelCm*btScalar(0.01f); if (wheel.m_raycastInfo.m_suspensionLength < minSuspensionLength) { wheel.m_raycastInfo.m_suspensionLength = minSuspensionLength; } if (wheel.m_raycastInfo.m_suspensionLength > maxSuspensionLength) { wheel.m_raycastInfo.m_suspensionLength = maxSuspensionLength; } wheel.m_raycastInfo.m_contactPointWS = rayResults.m_hitPointInWorld; btScalar denominator= wheel.m_raycastInfo.m_contactNormalWS.dot( wheel.m_raycastInfo.m_wheelDirectionWS ); btVector3 chassis_velocity_at_contactPoint; btVector3 relpos = wheel.m_raycastInfo.m_contactPointWS-getRigidBody()->getCenterOfMassPosition(); chassis_velocity_at_contactPoint = getRigidBody()->getVelocityInLocalPoint(relpos); btScalar projVel = wheel.m_raycastInfo.m_contactNormalWS.dot( chassis_velocity_at_contactPoint ); if ( denominator >= btScalar(-0.1f)) { wheel.m_suspensionRelativeVelocity = btScalar(0.0f); wheel.m_clippedInvContactDotSuspension = btScalar(1.0f) / btScalar(0.1f); } else { btScalar inv = btScalar(-1.0f) / denominator; wheel.m_suspensionRelativeVelocity = projVel * inv; wheel.m_clippedInvContactDotSuspension = inv; } } else { //put wheel info as in rest position wheel.m_raycastInfo.m_suspensionLength = wheel.getSuspensionRestLength(); wheel.m_suspensionRelativeVelocity = btScalar(0.0f); wheel.m_raycastInfo.m_contactNormalWS = - wheel.m_raycastInfo.m_wheelDirectionWS; wheel.m_clippedInvContactDotSuspension = btScalar(1.0f); } return depth; }