bool Primitive::Intersect( Ray& ray, Intersection& isect ) { Ray localRay(ray); localRay.o = Vec3d(worldToLocal * Vec4d(ray.o, 1.0)); localRay.d = Vec3d(worldToLocal * Vec4d(ray.d, 0.0)); if (!shape->Intersect(localRay, isect)) { return false; } ray.minT = localRay.minT; ray.maxT = localRay.maxT; if (localToWorld != Mat4d(1.0)) { isect.p = Vec3d(localToWorld * Vec4d(isect.p, 1.0)); isect.sn = Math::Normalize(normalLocalToWorld * isect.sn); isect.gn = Math::Normalize(normalLocalToWorld * isect.gn); isect.ss = Math::Normalize(Vec3d(localToWorld * Vec4d(isect.ss, 0.0))); isect.st = Math::Normalize(Vec3d(localToWorld * Vec4d(isect.st, 0.0))); } return true; }
void CustomGeometry::ProcessRayQuery(const RayOctreeQuery& query, PODVector<RayQueryResult>& results) { RayQueryLevel level = query.level_; switch (level) { case RAY_AABB_NOSUBOBJECTS: case RAY_AABB: Drawable::ProcessRayQuery(query, results); break; case RAY_OBB: case RAY_TRIANGLE: Matrix3x4 inverse(node_->GetWorldTransform().Inverse()); Ray localRay(inverse * query.ray_.origin_, inverse * Vector4(query.ray_.direction_, 0.0f)); float distance = localRay.HitDistance(boundingBox_); if (distance <= query.maxDistance_) { if (level == RAY_TRIANGLE) { for (unsigned i = 0; i < batches_.Size(); ++i) { Geometry* geometry = batches_[i].geometry_; if (geometry) { distance = geometry->GetHitDistance(localRay); if (distance <= query.maxDistance_) { RayQueryResult result; result.drawable_ = this; result.node_ = node_; result.distance_ = distance; result.subObject_ = M_MAX_UNSIGNED; results.Push(result); break; } } } } else { RayQueryResult result; result.drawable_ = this; result.node_ = node_; result.distance_ = distance; result.subObject_ = M_MAX_UNSIGNED; results.Push(result); } } break; } }
void Light::ProcessRayQuery(const RayOctreeQuery& query, PODVector<RayQueryResult>& results) { // Do not record a raycast result for a directional light, as it would block all other results if (lightType_ == LIGHT_DIRECTIONAL) return; float distance; switch (query.level_) { case RAY_AABB_NOSUBOBJECTS: case RAY_AABB: Drawable::ProcessRayQuery(query, results); return; case RAY_OBB: { Matrix3x4 inverse(node_->GetWorldTransform().Inverse()); Ray localRay(inverse * query.ray_.origin_, inverse * Vector4(query.ray_.direction_, 0.0f)); distance = localRay.HitDistance(GetWorldBoundingBox().Transformed(inverse)); if (distance >= query.maxDistance_) return; } break; case RAY_TRIANGLE: if (lightType_ == LIGHT_SPOT) { distance = query.ray_.HitDistance(GetFrustum()); if (distance >= query.maxDistance_) return; } else // if (lightType_ == LIGHT_POINT) { distance = query.ray_.HitDistance(Sphere(node_->GetWorldPosition(), range_)); if (distance >= query.maxDistance_) return; } break; } // If the code reaches here then we have a hit RayQueryResult result; result.drawable_ = this; result.node_ = node_; result.distance_ = distance; result.subObject_ = M_MAX_UNSIGNED; results.Push(result); }
bool Geometry::intersect(const ray&r, isect&i) const { // Transform the ray into the object's local coordinate space vec3f pos = transform->globalToLocalCoords(r.getPosition()); vec3f dir = transform->globalToLocalCoords(r.getPosition() + r.getDirection()) - pos; double length = dir.length(); dir /= length; ray localRay( pos, dir ); if (intersectLocal(localRay, i)) { // Transform the intersection point & normal returned back into global space. i.N = transform->localToGlobalCoordsNormal(i.N); i.t /= length; return true; } else { return false; } }
bool StaticModel::IsInsideLocal(const Vector3& point) const { // Early-out if point is not inside bounding box if (boundingBox_.IsInside(point) == OUTSIDE) return false; Ray localRay(point, Vector3(1.0f, -1.0f, 1.0f)); for (unsigned i = 0; i < batches_.Size(); ++i) { Geometry* geometry = batches_[i].geometry_; if (geometry) { if (geometry->IsInside(localRay)) return true; } } return false; }
void generateRay(const Point2 &dirSample, const Point2 &lensSample, Float timeSample, Ray &ray) const { ++cameraRays; Float u = dirSample.x * m_invResolution.x, v = dirSample.y * m_invResolution.y; Vector direction = squareToSphereY(u, v); Point2 uvPrime = sphereToSquareY(direction); if ((std::abs(uvPrime.x-u) > Epsilon || std::abs(uvPrime.y-v)>Epsilon) && u < 1 && v < 1 && u > 0 && v > 0) cout << uvPrime.toString() << " vs " << u << ", " << v << endl; /* Construct ray in camera space */ Ray localRay(Point(0.0f), direction, m_shutterOpen + m_shutterOpenTime * timeSample); /* Transform into world space */ m_cameraToWorld(localRay, ray); }
bool TriangleMesh::intersects(const Ray& ray, double& t) const { if (!box.intersects(ray)) return false; Ray localRay(ray); bool any = false; double nearestT = ray.tmax; for (unsigned int i=0; i<m_nFaces; i++) { bool intersects = faces[i]->intersects(localRay,nearestT); if (intersects) { t = nearestT; localRay.tmax = nearestT; any = true; } } return any; }
bool Object::intersects(Ray const & ray, Intersection * intersection) { // We first move the ray to object space before computing the intersection Ray localRay(ray.from - this->position, ray.direction); if(this->hasRotation) { localRay.from = this->rotationMatrix * localRay.from; // No need to normalize because the rotation matrix already is localRay.direction = this->rotationMatrix * localRay.direction; } bool hasIntersection = computeIntersection(localRay, intersection); // Move back to world coordinates if(intersection != NULL) { if(this->hasRotation) { intersection->position = (this->rotationMatrixT * intersection->position); intersection->normal = (this->rotationMatrixT * intersection->normal); } intersection->position += this->position; } return hasIntersection; }
bool TriangleMesh::checkIntersection(const Ray& ray, Vector& N, double& t) const { if (!box.intersects(ray)) return false; Ray localRay(ray); bool any = false; double nearestT = ray.tmax; Vector normal; for (unsigned int i=0; i<m_nFaces; i++) { bool intersects = faces[i]->checkIntersection(localRay, normal, nearestT); if (intersects) { t = nearestT; localRay.tmax = nearestT; N = normal; any = true; } } return any; }