// commented, dpl 10 august 2005 Spectrum Lafortune::Sample_f(const Vector &wo, Vector *wi, float u1, float u2, float *pdf) const { u_int comp = RandomUInt() % (nLobes+1); if (comp == nLobes) { // Cosine-sample the hemisphere, flipping the direction if necessary *wi = CosineSampleHemisphere(u1, u2); if (wo.z < 0.) wi->z *= -1.f; } else { // Sample lobe _comp_ for Lafortune BRDF float xlum = x[comp].y(); float ylum = y[comp].y(); float zlum = z[comp].y(); float costheta = powf(u1, 1.f / (.8f * exponent[comp].y() + 1)); float sintheta = sqrtf(max(0.f, 1.f - costheta*costheta)); float phi = u2 * 2.f * M_PI; Vector lobeCenter = Normalize(Vector(xlum * wo.x, ylum * wo.y, zlum * wo.z)); Vector lobeX, lobeY; CoordinateSystem(lobeCenter, &lobeX, &lobeY); *wi = SphericalDirection(sintheta, costheta, phi, lobeX, lobeY, lobeCenter); } if (!SameHemisphere(wo, *wi)) return Spectrum(0.f); *pdf = Pdf(wo, *wi); return f(wo, *wi); }
Point Sphere::Sample(const Point &p, float u1, float u2, Normal *ns) const { // Compute coordinate system for sphere sampling Point Pcenter = (*ObjectToWorld)(Point(0,0,0)); Vector wc = Normalize(Pcenter - p); Vector wcX, wcY; CoordinateSystem(wc, &wcX, &wcY); // Sample uniformly on sphere if $\pt{}$ is inside it if (DistanceSquared(p, Pcenter) - radius*radius < 1e-4f) return Sample(u1, u2, ns); // Sample sphere uniformly inside subtended cone float cosThetaMax = sqrtf(max(0.f, 1.f - radius*radius / DistanceSquared(p, Pcenter))); DifferentialGeometry dgSphere; float thit, rayEpsilon; Point ps; Ray r(p, UniformSampleCone(u1, u2, cosThetaMax, wcX, wcY, wc), 1e-3f); if (!Intersect(r, &thit, &rayEpsilon, &dgSphere)) ps = Pcenter - radius * wc; else ps = r(thit); *ns = Normal(Normalize(ps - Pcenter)); if (ReverseOrientation) *ns *= -1.f; return ps; }
Spectrum DiffuseAreaLight::Sample_Le(const Point2f &u1, const Point2f &u2, Float time, Ray *ray, Normal3f *nLight, Float *pdfPos, Float *pdfDir) const { ProfilePhase _(Prof::LightSample); // Sample a point on the area light's _Shape_, _pShape_ Interaction pShape = shape->Sample(u1, pdfPos); pShape.mediumInterface = mediumInterface; *nLight = pShape.n; // Sample a cosine-weighted outgoing direction _w_ for area light Vector3f w; if (twoSided) { Point2f u = u2; // Choose a side to sample and then remap u[0] to [0,1] before // applying cosine-weighted hemisphere sampling for the chosen side. if (u[0] < .5) { u[0] = std::min(u[0] * 2, OneMinusEpsilon); w = CosineSampleHemisphere(u); } else { u[0] = std::min((u[0] - .5f) * 2, OneMinusEpsilon); w = CosineSampleHemisphere(u); w.z *= -1; } *pdfDir = 0.5f * CosineHemispherePdf(std::abs(w.z)); } else { w = CosineSampleHemisphere(u2); *pdfDir = CosineHemispherePdf(w.z); } Vector3f v1, v2, n(pShape.n); CoordinateSystem(n, &v1, &v2); w = w.x * v1 + w.y * v2 + w.z * n; *ray = pShape.SpawnRay(w); return L(pShape, w); }
bool Sphere::Sample(const Interaction &ref, const Point2f &sample, Interaction *it) const { // Compute coordinate system for sphere sampling Point3f pCenter = (*ObjectToWorld)(Point3f(0, 0, 0)); Point3f pOrigin = OffsetRayOrigin(ref.p, ref.pError, ref.n, pCenter - ref.p); Vector3f wc = Normalize(pCenter - ref.p); Vector3f wcX, wcY; CoordinateSystem(wc, &wcX, &wcY); // Sample uniformly on sphere if $\pt{}$ is inside it if (DistanceSquared(pOrigin, pCenter) <= 1.0001f * radius * radius) return Sample(sample, it); // Sample sphere uniformly inside subtended cone Float sinThetaMax2 = radius * radius / DistanceSquared(ref.p, pCenter); Float cosThetaMax = std::sqrt(std::max((Float)0., (Float)1. - sinThetaMax2)); SurfaceInteraction isectSphere; Float tHit; Ray r = ref.SpawnRay(UniformSampleCone(sample, cosThetaMax, wcX, wcY, wc)); if (!Intersect(r, &tHit, &isectSphere)) return false; *it = isectSphere; if (ReverseOrientation) it->n *= -1.f; return true; }
void TreeRepository::rebuild() { // CX_LOG_CHANNEL_DEBUG("CA") << " reuild tree..."; for (unsigned i=0; i<mNodes.size(); ++i) disconnect(mNodes[i].get(), &TreeNode::changed, this, &TreeRepository::onChanged); mNodes.clear(); this->insertTopNode(); QStringList groups = QStringList() << "tool" << "data" << "space" << "view"; for (unsigned i=0; i<groups.size(); ++i) this->insertGroupNode(groups[i]); this->insertSpaceNode(CoordinateSystem(csREF)); std::map<QString, DataPtr> source = this->getServices()->patient()->getDatas(); for (std::map<QString, DataPtr>::const_iterator iter = source.begin(); iter != source.end(); ++iter) { this->insertDataNode(iter->second); } for (std::map<QString, DataPtr>::const_iterator iter = source.begin(); iter != source.end(); ++iter) { QString space = iter->second->getParentSpace(); if (space.isEmpty()) continue; if (source.count(space)) continue; this->insertSpaceNode(CoordinateSystem(csDATA, space)); } this->insertSpaceNode(CoordinateSystem(csPATIENTREF)); std::map<QString, ToolPtr> tools = this->getServices()->tracking()->getTools(); for (std::map<QString, ToolPtr>::const_iterator iter = tools.begin(); iter != tools.end(); ++iter) { this->insertToolNode(iter->second); } for (unsigned i=0; i<this->getServices()->view()->groupCount(); ++i) { this->appendNode(new ViewGroupTreeNode(mSelf, i)); } // for (unsigned i=0; i<mNodes.size(); ++i) // CX_LOG_CHANNEL_DEBUG("CA") << " node: " << mNodes[i]->getUid(); }
TreeNodePtr ToolTreeNode::getParent() const { if (this->repo()->getMode()=="flat") return this->repo()->getNodeForGroup("tool"); if (mTool->getUid() == this->getServices()->tracking()->getManualTool()->getUid()) return this->repo()->getNode(CoordinateSystem(csPATIENTREF).toString()); if (mTool->hasType(Tool::TOOL_REFERENCE)) return this->repo()->getNode(CoordinateSystem(csPATIENTREF).toString()); ToolPtr ref = this->getServices()->tracking()->getReferenceTool(); if (ref) return this->repo()->getNode(ref->getUid()); return this->repo()->getNode(CoordinateSystem(csPATIENTREF).toString()); }
ON_BOOL32 ON_Light::GetLightXform( const ON_Viewport& vp, ON::coordinate_system dest_cs, ON_Xform& xform ) const { ON::coordinate_system src_cs = CoordinateSystem(); return vp.GetXform( src_cs, dest_cs, xform ); }
/** Utility function: return the coordinate the the reference space. * */ Vector3D PointMetric::getRefCoord() const { if (!mCachedRefCoord.isValid()) { Transform3D rM1 = mSpaceProvider->get_toMfrom(this->getSpace(), CoordinateSystem(csREF)); Vector3D val = rM1.coord(this->getCoordinate()); mCachedRefCoord.set(val); } return mCachedRefCoord.get(); }
CoordinateSystem Ship :: getCameraCoordinateSystem () const { const Vector3& forward = getForward(); const Vector3& up = getUp(); Vector3 camera_at = getPosition() + forward * CAMERA_FORWARD_DISTANCE + up * CAMERA_UP_DISTANCE; return CoordinateSystem(camera_at, forward, up); }
void AxisConnector::changedSlot() { Transform3D rMs = mSpaceProvider->get_toMfrom(mListener->getSpace(), CoordinateSystem(csREF)); mRep->setTransform(rMs); mRep->setVisible(true); // if connected to tool: check visibility if (mTool) mRep->setVisible(mTool->getVisible()); // Dont show if equal to base if (mBase) { Transform3D rMb = mSpaceProvider->get_toMfrom(mBase->getSpace(), CoordinateSystem(csREF)); if (similar(rMb, rMs)) mRep->setVisible(false); } }
Point3f Sphere::Sample( const Point3f& p , LightSample& lightSample , Vector3f& SampleNormal ) { Vector3f dirZ = Normalize( mWorldPos - p ); // 在球面上采样一个点 if( ( p - mWorldPos ).LengthSq() - m_Radius * m_Radius < 1e4f ) { // 使用默认的采样 Vector3f SampleDir = UniformSampleHemisphere( Point2f( lightSample.value[0] , lightSample.value[1] ) ); if( Dot( SampleDir , dirZ ) < 0.0 ) { SampleDir *= -1.0; } Point3f SamplePoint = mWorldPos + Normalize( dirZ ) * m_Radius; // Compute Normal Dir SampleNormal = Normalize( Vector3f( SamplePoint - mWorldPos ) ); return SamplePoint; } Vector3f dirX , dirY; CoordinateSystem( dirZ , &dirX , &dirY ); // 均匀采样cone float sinThetaMax2 = m_Radius * m_Radius / ( p - mWorldPos ).LengthSq(); float cosThetaMax = sqrt( MAX( 0.0f , 1.0f - sinThetaMax2 ) ); Rayf r( p , UniformSampleCone( lightSample.value[0] , lightSample.value[1] , cosThetaMax , dirX , dirY , dirZ ) ); // Test whether intersect float t; IntersectRecord record; Point3f SamplePoint; if( !Intersect( r , &record ) ) { // 必定是切线但被判定为无交点 t = Dot( mWorldPos - p , r.Direction ); SamplePoint = r( t ); } else { SamplePoint = record.HitPoint; } SampleNormal = Normalize( SamplePoint - mWorldPos ); return SamplePoint; }
/** Utility function: return the coordinate the the reference space. * */ Vector3D PointMetric::getRefCoord() const { // std::cout << " ** PointMetric::getRefCoord" << std::endl; // return Vector3D(1,2,3); if (!mCachedRefCoord.isValid()) { // std::cout << " ** PointMetric::getRefCoord FILL CACHE" << std::endl; Transform3D rM1 = mSpaceProvider->get_toMfrom(this->getSpace(), CoordinateSystem(csREF)); Vector3D val = rM1.coord(this->getCoordinate()); mCachedRefCoord.set(val); } return mCachedRefCoord.get(); }
Vector SampleHG(const Vector &w, float g, const float u1, const float u2) { float costheta; if (fabsf(g) < 1e-3f) costheta = 1.f - 2.f * u1; else { // NOTE - lordcrc - Bugfix, pbrt tracker id 0000082: bug in SampleHG const float sqrTerm = (1.f - g * g) / (1.f - g + 2.f * g * u1); costheta = (1.f + g * g - sqrTerm * sqrTerm) / (2.f * g); } const float sintheta = sqrtf(Max(0.f, 1.f - costheta * costheta)); const float phi = 2.f * M_PI * u2; Vector v1, v2; CoordinateSystem(w, &v1, &v2); return SphericalDirection(sintheta, costheta, phi, v1, v2, w); }
Vector SampleHG(const Vector &w, float g, float u1, float u2) { float costheta; if (fabsf(g) < 1e-3) costheta = 1.f - 2.f * u1; else { float sqrTerm = (1.f - g * g) / (1.f - g + 2.f * g * u1); costheta = (1.f + g * g - sqrTerm * sqrTerm) / (2.f * g); } float sintheta = sqrtf(max(0.f, 1.f-costheta*costheta)); float phi = 2.f * M_PI * u2; Vector v1, v2; CoordinateSystem(w, &v1, &v2); return SphericalDirection(sintheta, costheta, phi, v1, v2, w); }
Spectrum DistantLight::Sample_L(const Point2f &sample1, const Point2f &sample2, Float time, Ray *ray, Normal3f *Ns, Float *pdfPos, Float *pdfDir) const { // Choose point on disk oriented toward infinite light direction Vector3f v1, v2; CoordinateSystem(wLight, &v1, &v2); Point2f cd = ConcentricSampleDisk(sample1); Point3f Pdisk = worldCenter + worldRadius * (cd.x * v1 + cd.y * v2); // Set ray origin and direction for infinite light ray *ray = Ray(Pdisk + worldRadius * wLight, -wLight, Infinity, time); *Ns = (Normal3f)ray->d; *pdfPos = 1.f / (Pi * worldRadius * worldRadius); *pdfDir = 1.f; return L; }
Spectrum DiffuseAreaLight::Sample_Le(const Point2f &u1, const Point2f &u2, Float time, Ray *ray, Normal3f *nLight, Float *pdfPos, Float *pdfDir) const { Interaction pShape = shape->Sample(u1); pShape.mediumInterface = mediumInterface; Vector3f w = CosineSampleHemisphere(u2); *pdfDir = CosineHemispherePdf(w.z); // Transform cosine-weighted direction to normal's coordinate system Vector3f v1, v2, n(pShape.n); CoordinateSystem(n, &v1, &v2); w = w.x * v1 + w.y * v2 + w.z * n; *ray = pShape.SpawnRay(w); *nLight = pShape.n; *pdfPos = shape->Pdf(pShape); return L(pShape, w); }
bool DistanceEstimator::Intersect(const Ray &r, float *tHit, float *rayEpsilon, DifferentialGeometry *dg) const { bool succeed = DoesIntersect(r, tHit); if (!succeed) return false; Ray ray; (*WorldToObject)(r, &ray); Point p = ray(*tHit); *rayEpsilon = DE_params.hitEpsilon * DE_params.rayEpsilonMultiplier; Vector n = CalculateNormal(p, DE_params.normalEpsilon); Vector DPDU, DPDV; CoordinateSystem(n, &DPDU, &DPDV); const Transform &o2w = *ObjectToWorld; *dg = DifferentialGeometry(o2w(p), o2w(DPDU), o2w(DPDV), Normal(), Normal(), 0, 0, this); return true; }
Interaction Sphere::Sample(const Interaction &ref, const Point2f &u) const { // Compute coordinate system for sphere sampling Point3f pCenter = (*ObjectToWorld)(Point3f(0, 0, 0)); Vector3f wc = Normalize(pCenter - ref.p); Vector3f wcX, wcY; CoordinateSystem(wc, &wcX, &wcY); // Sample uniformly on sphere if $\pt{}$ is inside it Point3f pOrigin = OffsetRayOrigin(ref.p, ref.pError, ref.n, pCenter - ref.p); if (DistanceSquared(pOrigin, pCenter) <= radius * radius) return Sample(u); // Sample sphere uniformly inside subtended cone // Compute $\theta$ and $\phi$ values for sample in cone Float sinThetaMax2 = radius * radius / DistanceSquared(ref.p, pCenter); Float cosThetaMax = std::sqrt(std::max((Float)0, 1 - sinThetaMax2)); Float cosTheta = (1 - u[0]) + u[0] * cosThetaMax; Float sinTheta = std::sqrt(1 - cosTheta * cosTheta); Float phi = u[1] * 2 * Pi; // Compute angle $\alpha$ from center of sphere to sampled point on surface Float dc = Distance(ref.p, pCenter); Float ds = dc * cosTheta - std::sqrt(std::max( (Float)0, radius * radius - dc * dc * sinTheta * sinTheta)); Float cosAlpha = (dc * dc + radius * radius - ds * ds) / (2 * dc * radius); Float sinAlpha = std::sqrt(std::max((Float)0, 1 - cosAlpha * cosAlpha)); // Compute surface normal and sampled point on sphere Vector3f nObj = SphericalDirection(sinAlpha, cosAlpha, phi, -wcX, -wcY, -wc); Point3f pObj = radius * Point3f(nObj.x, nObj.y, nObj.z); // Return _Interaction_ for sampled point on sphere Interaction it; // Reproject _pObj_ to sphere surface and compute _pObjError_ pObj *= radius / Distance(pObj, Point3f(0, 0, 0)); Vector3f pObjError = gamma(5) * Abs((Vector3f)pObj); it.p = (*ObjectToWorld)(pObj, pObjError, &it.pError); it.n = (*ObjectToWorld)(Normal3f(nObj)); if (reverseOrientation) it.n *= -1.f; return it; }
Spectrum DiffuseAreaLight::Sample_Le(const Point2f &u1, const Point2f &u2, Float time, Ray *ray, Normal3f *nLight, Float *pdfPos, Float *pdfDir) const { // Sample a point on the area light's _Shape_, _pShape_ Interaction pShape = shape->Sample(u1); pShape.mediumInterface = mediumInterface; *pdfPos = shape->Pdf(pShape); *nLight = pShape.n; // Sample a cosine-weighted outgoing direction _w_ for area light Vector3f w = CosineSampleHemisphere(u2); *pdfDir = CosineHemispherePdf(w.z); Vector3f v1, v2, n(pShape.n); CoordinateSystem(n, &v1, &v2); w = w.x * v1 + w.y * v2 + w.z * n; *ray = pShape.SpawnRay(w); return L(pShape, w); }
Spectrum DistantLight::Sample_L(const Scene *scene, const LightSample &ls, float u1, float u2, float time, Ray *ray, Normal *Ns, float *pdf) const { // Choose point on disk oriented toward infinite light direction Point worldCenter; float worldRadius; scene->WorldBound().BoundingSphere(&worldCenter, &worldRadius); Vector v1, v2; CoordinateSystem(lightDir, &v1, &v2); float d1, d2; ConcentricSampleDisk(ls.uPos[0], ls.uPos[1], &d1, &d2); Point Pdisk = worldCenter + worldRadius * (d1 * v1 + d2 * v2); // Set ray origin and direction for infinite light ray *ray = Ray(Pdisk + worldRadius * lightDir, -lightDir, 0.f, INFINITY, time); *pdf = 1.f / (M_PI * worldRadius * worldRadius); return L; }
void CustomMetric::createOrDestroyToolListener() { if (this->needForToolListenerHasChanged()) { bool toolDefinesUp = mDefineVectorUpMethod == mDefineVectorUpMethods.tool; if (mTextureFollowTool || toolDefinesUp) { mToolListener = mSpaceProvider->createListener(); mToolListener->setSpace(CoordinateSystem(csTOOL_OFFSET, "active")); connect(mToolListener.get(), &SpaceListener::changed, this, &CustomMetric::transformChanged); } else { disconnect(mToolListener.get(), &SpaceListener::changed, this, &CustomMetric::transformChanged); mToolListener.reset(); } } }
// HenyeyGreenstein Method Definitions Float HenyeyGreenstein::Sample_p(const Vector3f &wo, Vector3f *wi, const Point2f &u) const { // Compute $\cos \theta$ for Henyey--Greenstein sample Float cosTheta; if (std::abs(g) < 1e-3) cosTheta = 1 - 2 * u[0]; else { Float sqrTerm = (1 - g * g) / (1 - g + 2 * g * u[0]); cosTheta = (1 + g * g - sqrTerm * sqrTerm) / (2 * g); } // Compute direction _wi_ for Henyey--Greenstein sample Float sinTheta = std::sqrt(std::max((Float)0, 1 - cosTheta * cosTheta)); Float phi = 2 * Pi * u[1]; Vector3f v1, v2; CoordinateSystem(wo, &v1, &v2); *wi = SphericalDirection(sinTheta, cosTheta, phi, v1, v2, -wo); return PhaseHG(-cosTheta, g); }
Spectrum DistantLight::Sample_L(const Scene *scene, float u1, float u2, float u3, float u4, Ray *ray, float *pdf) const { // Choose point on disk oriented toward infinite light direction Point worldCenter; float worldRadius; scene->WorldBound().BoundingSphere(&worldCenter, &worldRadius); Vector v1, v2; CoordinateSystem(lightDir, &v1, &v2); float d1, d2; ConcentricSampleDisk(u1, u2, &d1, &d2); Point Pdisk = worldCenter + worldRadius * (d1 * v1 + d2 * v2); // Set ray origin and direction for infinite light ray ray->o = Pdisk + worldRadius * lightDir; ray->d = -lightDir; *pdf = 1.f / (M_PI * worldRadius * worldRadius); return L; }
void MobileRootJoint::velocity(const Task& task, const Environment& environment, const ContinousStateValueVector& continousState, ChildLink& childLink) const { Vector3 position = continousState[*mPositionStateInfo]; Quaternion orientation = continousState[*mOrientationStateInfo]; Vector6 velocity = continousState[*mVelocityStateInfo]; childLink.setCoordinateSystem(CoordinateSystem(position, orientation)); velocity = childLink.getCoordinateSystem().rotToReference(velocity); Vector3 angularBaseVelocity = environment.getAngularVelocity(task.getTime()); Vector6 baseVelocity(angularMotionTo(position, angularBaseVelocity)); childLink.setVelocity(velocity); childLink.setInertialVelocity(baseVelocity + velocity); childLink.setForce(Vector6::zeros()); childLink.setInertia(SpatialInertia::zeros()); }
std::shared_ptr<SpotLight> CreateSpotLight(const Transform &l2w, const Medium *medium, const ParamSet ¶mSet) { Spectrum I = paramSet.FindOneSpectrum("I", Spectrum(1.0)); Spectrum sc = paramSet.FindOneSpectrum("scale", Spectrum(1.0)); Float coneangle = paramSet.FindOneFloat("coneangle", 30.); Float conedelta = paramSet.FindOneFloat("conedeltaangle", 5.); // Compute spotlight world to light transformation Point3f from = paramSet.FindOnePoint3f("from", Point3f(0, 0, 0)); Point3f to = paramSet.FindOnePoint3f("to", Point3f(0, 0, 1)); Vector3f dir = Normalize(to - from); Vector3f du, dv; CoordinateSystem(dir, &du, &dv); Transform dirToZ = Transform(Matrix4x4(du.x, du.y, du.z, 0., dv.x, dv.y, dv.z, 0., dir.x, dir.y, dir.z, 0., 0, 0, 0, 1.)); Transform light2world = l2w * Translate(Vector3f(from.x, from.y, from.z)) * Inverse(dirToZ); return std::make_shared<SpotLight>(light2world, medium, I * sc, coneangle, coneangle - conedelta); }
bool Curve::Intersect(const Ray &r, Float *tHit, SurfaceInteraction *isect, bool testAlphaTexture) const { ++nTests; // Transform _Ray_ to object space Vector3f oErr, dErr; Ray ray = (*WorldToObject)(r, &oErr, &dErr); // Compute object-space control points for curve segment, _cpObj_ Point3f cpObj[4]; cpObj[0] = BlossomBezier(common->cpObj, uMin, uMin, uMin); cpObj[1] = BlossomBezier(common->cpObj, uMin, uMin, uMax); cpObj[2] = BlossomBezier(common->cpObj, uMin, uMax, uMax); cpObj[3] = BlossomBezier(common->cpObj, uMax, uMax, uMax); // Project curve control points to plane perpendicular to ray Vector3f dx, dy; CoordinateSystem(ray.d, &dx, &dy); Transform objectToRay = LookAt(ray.o, ray.o + ray.d, dx); Point3f cp[4] = {objectToRay(cpObj[0]), objectToRay(cpObj[1]), objectToRay(cpObj[2]), objectToRay(cpObj[3])}; // Compute refinement depth for curve, _maxDepth_ Float L0 = 0; for (int i = 0; i < 2; ++i) L0 = std::max( L0, std::max( std::max(std::abs(cp[i].x - 2 * cp[i + 1].x + cp[i + 2].x), std::abs(cp[i].y - 2 * cp[i + 1].y + cp[i + 2].y)), std::abs(cp[i].z - 2 * cp[i + 1].z + cp[i + 2].z))); Float eps = std::max(common->width[0], common->width[1]) * .05f; // width / 20 #define LOG4(x) (std::log(x) * 0.7213475108f) Float fr0 = LOG4(1.41421356237f * 12.f * L0 / (8.f * eps)); #undef LOG4 int r0 = (int)std::round(fr0); int maxDepth = Clamp(r0, 0, 10); return recursiveIntersect(ray, tHit, isect, cp, Inverse(objectToRay), uMin, uMax, maxDepth); }
bool RGBVolume::Scatter(const Sample &sample, bool scatteredStart, const Ray &ray, float u, Intersection *isect, float *pdf, float *pdfBack, SWCSpectrum *L) const { // Determine scattering distance const float k = sigS.Filter(); const float d = logf(1 - u) / k; //the real distance is ray.mint-d bool scatter = d > ray.mint - ray.maxt; if (scatter) { // The ray is scattered ray.maxt = ray.mint - d; isect->dg.p = ray(ray.maxt); isect->dg.nn = Normal(-ray.d); isect->dg.scattered = true; CoordinateSystem(Vector(isect->dg.nn), &(isect->dg.dpdu), &(isect->dg.dpdv)); isect->ObjectToWorld = Transform(); isect->primitive = &primitive; isect->material = &material; isect->interior = this; isect->exterior = this; isect->arealight = NULL; // Update if volumetric emission if (L) *L *= SigmaT(sample.swl, isect->dg); } if (pdf) { *pdf = expf((ray.mint - ray.maxt) * k); if (isect->dg.scattered) *pdf *= k; } if (pdfBack) { *pdfBack = expf((ray.mint - ray.maxt) * k); if (scatteredStart) *pdfBack *= k; } if (L) *L *= Exp(-Tau(sample.swl, ray)); return scatter; }
void Triangle::GetShadingGeometry(const Transform &obj2world, const DifferentialGeometry &dg, DifferentialGeometry *dgShading) const { if (!mesh->n && !mesh->s) { *dgShading = dg; return; } // Initialize _Triangle_ shading geometry with _n_ and _s_ // Compute barycentric coordinates for point float b[3]; // Initialize _A_ and _C_ matrices for barycentrics float uv[3][2]; GetUVs(uv); float A[2][2] = { { uv[1][0] - uv[0][0], uv[2][0] - uv[0][0] }, { uv[1][1] - uv[0][1], uv[2][1] - uv[0][1] } }; float C[2] = { dg.u - uv[0][0], dg.v - uv[0][1] }; if (!SolveLinearSystem2x2(A, C, &b[1], &b[2])) { // Handle degenerate parametric mapping b[0] = b[1] = b[2] = 1.f/3.f; } else b[0] = 1.f - b[1] - b[2]; // Use _n_ and _s_ to compute shading tangents for triangle, _ss_ and _ts_ Normal ns; Vector ss, ts; if (mesh->n) ns = Normalize(obj2world(b[0] * mesh->n[v[0]] + b[1] * mesh->n[v[1]] + b[2] * mesh->n[v[2]])); else ns = dg.nn; if (mesh->s) ss = Normalize(obj2world(b[0] * mesh->s[v[0]] + b[1] * mesh->s[v[1]] + b[2] * mesh->s[v[2]])); else ss = Normalize(dg.dpdu); ts = Cross(ss, ns); if (ts.LengthSquared() > 0.f) { ts = Normalize(ts); ss = Cross(ts, ns); } else CoordinateSystem((Vector)ns, &ss, &ts); Normal dndu, dndv; // Compute $\dndu$ and $\dndv$ for triangle shading geometry if (mesh->n) { float uvs[3][2]; GetUVs(uvs); // Compute deltas for triangle partial derivatives of normal float du1 = uvs[0][0] - uvs[2][0]; float du2 = uvs[1][0] - uvs[2][0]; float dv1 = uvs[0][1] - uvs[2][1]; float dv2 = uvs[1][1] - uvs[2][1]; Normal dn1 = mesh->n[v[0]] - mesh->n[v[2]]; Normal dn2 = mesh->n[v[1]] - mesh->n[v[2]]; float determinant = du1 * dv2 - dv1 * du2; if (determinant == 0.f) dndu = dndv = Normal(0,0,0); else { float invdet = 1.f / determinant; dndu = ( dv2 * dn1 - dv1 * dn2) * invdet; dndv = (-du2 * dn1 + du1 * dn2) * invdet; } } else dndu = dndv = Normal(0,0,0); *dgShading = DifferentialGeometry(dg.p, ss, ts, (*ObjectToWorld)(dndu), (*ObjectToWorld)(dndv), dg.u, dg.v, dg.shape); dgShading->dudx = dg.dudx; dgShading->dvdx = dg.dvdx; dgShading->dudy = dg.dudy; dgShading->dvdy = dg.dvdy; dgShading->dpdx = dg.dpdx; dgShading->dpdy = dg.dpdy; }
bool Triangle::IntersectP(const Ray &ray) const { PBRT_RAY_TRIANGLE_INTERSECTIONP_TEST(const_cast<Ray *>(&ray), const_cast<Triangle *>(this)); // Compute $\VEC{s}_1$ // Get triangle vertices in _p1_, _p2_, and _p3_ const Point &p1 = mesh->p[v[0]]; const Point &p2 = mesh->p[v[1]]; const Point &p3 = mesh->p[v[2]]; Vector e1 = p2 - p1; Vector e2 = p3 - p1; Vector s1 = Cross(ray.d, e2); float divisor = Dot(s1, e1); if (divisor == 0.) return false; float invDivisor = 1.f / divisor; // Compute first barycentric coordinate Vector d = ray.o - p1; float b1 = Dot(d, s1) * invDivisor; if (b1 < 0. || b1 > 1.) return false; // Compute second barycentric coordinate Vector s2 = Cross(d, e1); float b2 = Dot(ray.d, s2) * invDivisor; if (b2 < 0. || b1 + b2 > 1.) return false; // Compute _t_ to intersection point float t = Dot(e2, s2) * invDivisor; if (t < ray.mint || t > ray.maxt) return false; // Test shadow ray intersection against alpha texture, if present if (ray.depth != -1 && mesh->alphaTexture) { // Compute triangle partial derivatives Vector dpdu, dpdv; float uvs[3][2]; GetUVs(uvs); // Compute deltas for triangle partial derivatives float du1 = uvs[0][0] - uvs[2][0]; float du2 = uvs[1][0] - uvs[2][0]; float dv1 = uvs[0][1] - uvs[2][1]; float dv2 = uvs[1][1] - uvs[2][1]; Vector dp1 = p1 - p3, dp2 = p2 - p3; float determinant = du1 * dv2 - dv1 * du2; if (determinant == 0.f) { // Handle zero determinant for triangle partial derivative matrix CoordinateSystem(Normalize(Cross(e2, e1)), &dpdu, &dpdv); } else { float invdet = 1.f / determinant; dpdu = ( dv2 * dp1 - dv1 * dp2) * invdet; dpdv = (-du2 * dp1 + du1 * dp2) * invdet; } // Interpolate $(u,v)$ triangle parametric coordinates float b0 = 1 - b1 - b2; float tu = b0*uvs[0][0] + b1*uvs[1][0] + b2*uvs[2][0]; float tv = b0*uvs[0][1] + b1*uvs[1][1] + b2*uvs[2][1]; DifferentialGeometry dgLocal(ray(t), dpdu, dpdv, Normal(0,0,0), Normal(0,0,0), tu, tv, this); if (mesh->alphaTexture->Evaluate(dgLocal) == 0.f) return false; } PBRT_RAY_TRIANGLE_INTERSECTIONP_HIT(const_cast<Ray *>(&ray), t); return true; }
TerrainManager::TerrainManager( const Time & runTime, const dictionary & dict, const searchableSurface * const stl_ ): BlockMeshManager(runTime), stl_(stl_), blockNrs_(dict.lookup("blocks")), cellNrs_(dict.lookup("cells")), domainBox_ ( CoordinateSystem ( point(dict.lookup("p_corner")), List< Foam::vector >(dict.subDict("coordinates").lookup("baseVectors")) ), scalarList(dict.lookup("dimensions")), dict.lookupOrDefault< scalar >("boxResolution",0.0001) ), stlBox_(domainBox_), splineNormalDist_(0), mode_upwardSplines_(0), zeroLevel_(0), gradingFactors_(dict.lookup("gradingFactors")), cylinderModule_(this), modificationModule_(this), gradingModule_(this), blendingFunction_ ( new ScalarBlendingFunction() ){ // Read dictionary: p_above_ = point(dict.lookup("p_above")); maxDistProj_ = readScalar(dict.lookup("maxDistProj")); // option for stl_ inside the domain box: if(dict.found("stlInsideBox")){ if(dict.subDict("stlInsideBox").found("zeroLevel")){ zeroLevel_ = readScalar(dict.subDict("stlInsideBox").lookup("zeroLevel")); } stlBox_ = Box ( CoordinateSystem ( point(dict.subDict("stlInsideBox").lookup("p_corner_inside_stl")), coordinateSystem().axes() ), scalarList(dict.subDict("stlInsideBox").lookup("dimensions_inside_stl")), dict.subDict("stlInsideBox").lookupOrDefault< scalar >("boxResolution",0.0001) ); blendingFunction_ = ScalarBlendingFunction::New ( dict.subDict("stlInsideBox").subDict("blendingFunction") ); if(dict.subDict("stlInsideBox").subDict("blendingFunction").found("writePDF")){ const dictionary & writeDict = dict.subDict("stlInsideBox").subDict("blendingFunction").subDict("writePDF"); blendingFunction_().writePDFs ( word(writeDict.lookup("baseName")), fileName(writeDict.lookup("resultsFolder")), point(writeDict.lookup("probePoint0")), point(writeDict.lookup("probePoint1")), 0,1, readLabel(writeDict.lookup("steps")), readLabel(writeDict.lookup("plotPoints")), readLabel(writeDict.lookup("interpolOrder")) ); } else { Info << "TerrainManager: keyword 'writePDF' not found in sub dictionary 'blendingFunction'." << endl; } } // module orography modifications: if(dict.found("terrainModification")){ Info << " loading orography modification module" << endl; if(!modificationModule_.load(dict.subDict("terrainModification"))){ Info << "\n TerrainManager: Error while loading orography modification module." << endl; throw; } } // module block grading: if(dict.found("blockGrading")){ Info << " loading block grading module" << endl; if(!gradingModule_.load(dict.subDict("blockGrading"))){ Info << "\n TerrainManager: Error while loading block grading module." << endl; throw; } } // module outer cylinder: if(dict.found("outerCylinder")){ Info << " loading cylinder module" << endl; if(!cylinderModule_.load(dict.subDict("outerCylinder"))){ Info << "\n TerrainManager: Error while loading cylinder module." << endl; throw; } } // option for othogonalization of upward splines: if(dict.found("orthogonalizeUpwardSplines")){ dictionary upsDict = dict.subDict("orthogonalizeUpwardSplines"); splineNormalDist_ = readScalar(upsDict.lookup("splineNormalDist")); if(upsDict.found("ignoreBoundary")) mode_upwardSplines_ = 2; else mode_upwardSplines_ = 1; } // add patches: patchesRef().resize(6); patchesRef().set ( Block::WEST, new BlockMeshPatch ( *this, word(dict.lookup("patch_name_west")), word(dict.lookup("patch_type_west")) ) ); patchesRef().set ( Block::EAST, new BlockMeshPatch ( *this, word(dict.lookup("patch_name_east")), word(dict.lookup("patch_type_east")) ) ); patchesRef().set ( Block::SOUTH, new BlockMeshPatch ( *this, word(dict.lookup("patch_name_south")), word(dict.lookup("patch_type_south")) ) ); patchesRef().set ( Block::NORTH, new BlockMeshPatch ( *this, word(dict.lookup("patch_name_north")), word(dict.lookup("patch_type_north")) ) ); patchesRef().set ( Block::GROUND, new BlockMeshPatch ( *this, word(dict.lookup("patch_name_ground")), word(dict.lookup("patch_type_ground")) ) ); patchesRef().set ( Block::SKY, new BlockMeshPatch ( *this, word(dict.lookup("patch_name_sky")), word(dict.lookup("patch_type_sky")) ) ); // only one block in up direction: blockNrs_[UP] = 1; // set spline point numbers: splinePointNrs_.resize(3); splinePointNrs_[0] = cellNrs_[0] - 1; splinePointNrs_[1] = cellNrs_[1] - 1; splinePointNrs_[2] = cellNrs_[2] - 1; // init landscape_: if(stl_){ landscape_.set ( new STLLandscape ( stl_, &(blendingFunction_()), &domainBox_, &stlBox_, zeroLevel_ ) ); } // output boxes: domainBox_.writeSTL("domainBox.stl"); stlBox_.writeSTL("stlBox.stl"); }