Real raySphereIntersectionTime(Ray3 const & ray, Vector3 const & center, Real radius) { Vector3 pmc = ray.getOrigin() - center; double s[3]; s[2] = ray.getDirection().squaredLength(); s[1] = 2 * pmc.dot(ray.getDirection()); s[0] = pmc.squaredLength() - radius * radius; double roots[2]; int num_roots = Math::solveQuadratic(s[0], s[1], s[2], roots); double min_root = -1; for (int i = 0; i < num_roots; ++i) if (roots[i] >= 0 && (min_root < 0 || roots[i] < min_root)) min_root = roots[i]; #if 0 if (min_root >= 0) qDebug() << "min_root =" << min_root; #endif return (Real)min_root; }
IResult Intersects(const Ray3& ray, const Transformation& objT) const{ if (!mBV) return IResult(false, FLT_MAX); Ray3 localRay = objT.ApplyInverse(ray); Ray3::IResult ret = localRay.Intersects(mBV.get()); return ret; }
//---------------------------------------------------------------------------- bool Mgc::FindIntersection (const Ray3& rkRay, const Triangle3& rkTriangle, Vector3& rkPoint) { Real fRayP; if ( SqrDistance(rkRay,rkTriangle,&fRayP) <= gs_fEpsilon ) { rkPoint = rkRay.Origin() + fRayP*rkRay.Direction(); return true; } return false; }
void GatherPointLightData(const BoundingVolume* aabb, const Transformation& transform, POINT_LIGHT_CONSTANTS* plConst) { struct GatheredData { GatheredData(Real distSQ, unsigned idx) :mDistanceSQ(distSQ), mIndex(idx) { } Real mDistanceSQ; unsigned mIndex; }; static std::vector<GatheredData> gathered; gathered.reserve(50); unsigned i = 0; for (auto it = mPointLights.begin(); it != mPointLights.end(); /**/) { IteratingWeakContainer(mPointLights, it, p); if (!p->GetEnabled()) continue; Ray3 ray(p->GetPosition(), transform.GetTranslation() - p->GetPosition()); Ray3 localRay = transform.ApplyInverse(ray); auto iresult = localRay.Intersects(aabb); Real distSQ = Squared(iresult.second); Real range = p->GetRange(); if (distSQ < (range*range)) { gathered.push_back(GatheredData(distSQ, i)); } ++i; } std::sort(gathered.begin(), gathered.end(), [](const GatheredData& a, const GatheredData& b){ return a.mDistanceSQ < b.mDistanceSQ; } ); plConst->gPointLightColor[0].w = 0; int count = std::min(3, (int)gathered.size()); unsigned validNumber = 0; for (int i = 0; i < count; i++) { PointLightPtr p = mPointLights[gathered[i].mIndex].lock(); if (p){ plConst->gPointLightPos[validNumber] = Vec4(p->GetPosition(), p->GetRange()); plConst->gPointLightColor[validNumber] = Vec4(p->GetColorPowered(), (Real)count); ++validNumber; } } gathered.clear(); }
void SpikeGuideRenderer::addSpike(const Ray3& ray, const FloatType length, const FloatType maxLength) { const float mix = static_cast<float>(maxLength / length / 2.0); m_spikeVertices.push_back(SpikeVertex(ray.origin, m_color)); m_spikeVertices.push_back(SpikeVertex(ray.pointAtDistance(length), Color(m_color, m_color.a() * mix))); }
Color rayTraceRecursive(Object &scene, Ray3& ray, int maxReflect, DirectionalLight light) { IntersectResult result = scene.intersect(ray); //cout<<result.getGeometry()->material->getReflectiveness()<<endl; if(result.getGeometry()) { Color color = Color::black; Vec3 lightSample = light.sample(scene, result.getPosition()); //cout<<lightSample.getx()<< " " << lightSample.gety() << " "<<lightSample.getz()<<endl; float reflectiveness = result.getGeometry()->material->getReflectiveness(); // just the float to int. it is rediculous color = result.getGeometry()->material->sample(ray,result.getPosition(),result.getNormal()); color = color.multiply(1-reflectiveness); // cout << reflectiveness <<endl; if(reflectiveness>0 && maxReflect > 0) { // cout << reflectiveness <<endl; Vec3 r = result.getNormal().multiply(-2*result.getNormal().dot(ray.getDirection())).add(ray.getDirection()); ray = Ray3(result.getPosition(),r); Color reflectedColor = rayTraceRecursive(scene, ray, maxReflect-1, light); color = color.add(reflectedColor.multiply(reflectiveness)); if(fabs(lightSample.getx())> 1e-4 || fabs(lightSample.gety())> 1e-4 || fabs(lightSample.getz()>1e-4)) { }else{ color = color.modulate(Color(0.3,0.3,0.3)); } } //cout<<"abc"<<endl; return color; }else{ return Color::black; } }
//---------------------------------------------------------------------------- bool Mgc::TestIntersection (const Ray3& rkRay, const Box3& rkBox) { Real fWdU[3], fAWdU[3], fDdU[3], fADdU[3], fAWxDdU[3], fRhs; Vector3 kDiff = rkRay.Origin() - rkBox.Center(); fWdU[0] = rkRay.Direction().Dot(rkBox.Axis(0)); fAWdU[0] = Math::FAbs(fWdU[0]); fDdU[0] = kDiff.Dot(rkBox.Axis(0)); fADdU[0] = Math::FAbs(fDdU[0]); if ( fADdU[0] > rkBox.Extent(0) && fDdU[0]*fWdU[0] >= 0.0f ) return false; fWdU[1] = rkRay.Direction().Dot(rkBox.Axis(1)); fAWdU[1] = Math::FAbs(fWdU[1]); fDdU[1] = kDiff.Dot(rkBox.Axis(1)); fADdU[1] = Math::FAbs(fDdU[1]); if ( fADdU[1] > rkBox.Extent(1) && fDdU[1]*fWdU[1] >= 0.0f ) return false; fWdU[2] = rkRay.Direction().Dot(rkBox.Axis(2)); fAWdU[2] = Math::FAbs(fWdU[2]); fDdU[2] = kDiff.Dot(rkBox.Axis(2)); fADdU[2] = Math::FAbs(fDdU[2]); if ( fADdU[2] > rkBox.Extent(2) && fDdU[2]*fWdU[2] >= 0.0f ) return false; Vector3 kWxD = rkRay.Direction().Cross(kDiff); fAWxDdU[0] = Math::FAbs(kWxD.Dot(rkBox.Axis(0))); fRhs = rkBox.Extent(1)*fAWdU[2] + rkBox.Extent(2)*fAWdU[1]; if ( fAWxDdU[0] > fRhs ) return false; fAWxDdU[1] = Math::FAbs(kWxD.Dot(rkBox.Axis(1))); fRhs = rkBox.Extent(0)*fAWdU[2] + rkBox.Extent(2)*fAWdU[0]; if ( fAWxDdU[1] > fRhs ) return false; fAWxDdU[2] = Math::FAbs(kWxD.Dot(rkBox.Axis(2))); fRhs = rkBox.Extent(0)*fAWdU[1] + rkBox.Extent(1)*fAWdU[0]; if ( fAWxDdU[2] > fRhs ) return false; return true; }
Real closestPtRayTriangle(Ray3 const & ray, Vector3 const & v0, Vector3 const & edge01, Vector3 const & edge02, Real & s, Vector3 & c1, Vector3 & c2) { Real sqdist = closestPtLineTriangle(Line3::fromPointAndDirection(ray.getOrigin(), ray.getDirection()), v0, edge01, edge02, s, c1, c2); if (s >= 0) return sqdist; // Not the most efficient way but the most convenient LocalTriangle3 tri(v0, v0 + edge01, v0 + edge02); s = 0; c1 = ray.getOrigin(); c2 = tri.closestPoint(c1); return (c1 - c2).squaredLength(); }
//---------------------------------------------------------------------------- // @ BoundingSphere::Intersect() // --------------------------------------------------------------------------- // Determine intersection between sphere and ray //----------------------------------------------------------------------------- bool BoundingSphere::Intersect( const Ray3& ray ) const { // compute intermediate values Vector3 w = mCenter - ray.GetOrigin(); float wsq = w.Dot(w); float proj = w.Dot(ray.GetDirection()); float rsq = mRadius*mRadius; // if sphere behind ray, no intersection if ( proj < 0.0f && wsq > rsq ) return false; float vsq = ray.GetDirection().Dot(ray.GetDirection()); // test length of difference vs. radius return ( vsq*wsq - proj*proj <= vsq*rsq ); }
Model::Hit VertexHandleManager::pickHandle(const Ray3& ray, const Renderer::Camera& camera, const Vec3& position, Model::Hit::HitType type) const { const FloatType distance = camera.pickPointHandle(ray, position, pref(Preferences::HandleRadius)); if (!Math::isnan(distance)) { const Vec3 hitPoint = ray.pointAtDistance(distance); return Model::Hit::hit<Vec3>(type, distance, hitPoint, position); } return Model::Hit::NoHit; }
//---------------------------------------------------------------------------- Real Mgc::SqrDistance (const Ray3& rkRay, const Box3& rkBox, Real* pfLParam, Real* pfBParam0, Real* pfBParam1, Real* pfBParam2) { #ifdef _DEBUG // The four parameters pointers are either all non-null or all null. if ( pfLParam ) { assert( pfBParam0 && pfBParam1 && pfBParam2 ); } else { assert( !pfBParam0 && !pfBParam1 && !pfBParam2 ); } #endif Line3 kLine; kLine.Origin() = rkRay.Origin(); kLine.Direction() = rkRay.Direction(); Real fLP, fBP0, fBP1, fBP2; Real fSqrDistance = SqrDistance(kLine,rkBox,&fLP,&fBP0,&fBP1,&fBP2); if ( fLP >= 0.0f ) { if ( pfLParam ) { *pfLParam = fLP; *pfBParam0 = fBP0; *pfBParam1 = fBP1; *pfBParam2 = fBP2; } return fSqrDistance; } else { fSqrDistance = SqrDistance(rkRay.Origin(),rkBox,pfBParam0, pfBParam1,pfBParam2); if ( pfLParam ) *pfLParam = 0.0f; return fSqrDistance; } }
Real Mgc::SqrDistance (const Vector3& rkPoint, const Ray3& rkRay, Real* pfParam) { Vector3 kDiff = rkPoint - rkRay.Origin(); Real fT = kDiff.Dot(rkRay.Direction()); if ( fT <= 0.0f ) { fT = 0.0f; } else { fT /= rkRay.Direction().SquaredLength(); kDiff -= fT*rkRay.Direction(); } if ( pfParam ) *pfParam = fT; return kDiff.SquaredLength(); }
Real Wml::SqrDistance (const Vector3<Real>& rkPoint, const Ray3<Real>& rkRay, Real* pfParam) { Vector3<Real> kDiff = rkPoint - rkRay.Origin(); Real fT = kDiff.Dot(rkRay.Direction()); if ( fT <= (Real)0.0 ) { fT = (Real)0.0; } else { fT /= rkRay.Direction().SquaredLength(); kDiff -= fT*rkRay.Direction(); } if ( pfParam ) *pfParam = fT; return kDiff.SquaredLength(); }
bool Wml::FindIntersection (const Ray3<Real>& rkRay, const Cylinder3<Real>& rkCylinder, int& riQuantity, Vector3<Real> akPoint[2]) { Real afT[2]; if ( rkCylinder.Capped() ) { riQuantity = Find(rkRay.Origin(),rkRay.Direction(),rkCylinder,afT); } else { riQuantity = FindHollow(rkRay.Origin(),rkRay.Direction(), rkCylinder,afT); } int iClipQuantity = 0; for (int i = 0; i < riQuantity; i++) { if ( afT[i] >= (Real)0.0 ) { akPoint[iClipQuantity++] = rkRay.Origin() + afT[i]*rkRay.Direction(); } } riQuantity = iClipQuantity; return riQuantity > 0; }
void SpikeGuideRenderer::add(const Ray3& ray, const FloatType length, View::MapDocumentSPtr document) { Model::PickResult pickResult = Model::PickResult::byDistance(document->editorContext()); document->pick(ray, pickResult); const Model::Hit& hit = pickResult.query().pickable().type(Model::Brush::BrushHit).occluded().minDistance(1.0).first(); if (hit.isMatch()) { if (hit.distance() <= length) addPoint(ray.pointAtDistance(hit.distance() - 0.01)); addSpike(ray, Math::min(length, hit.distance()), length); } else { addSpike(ray, length, length); } m_valid = false; }
Real rayTorusIntersectionTime(Ray3 const & ray, Real torus_radius, Real torus_width) { double r2pw2 = torus_radius * torus_radius + torus_width * torus_width; double r2mw2 = r2pw2 - 2 * torus_width * torus_width; Vector3 p2 = ray.getOrigin() * ray.getOrigin(); Vector3 pu = ray.getOrigin() * ray.getDirection(); Vector3 u2 = ray.getDirection() * ray.getDirection(); double s[5]; s[4] = u2[0] * (u2[0] + 2 * u2[1]) + u2[1] * (u2[1] + 2 * u2[2]) + u2[2] * (u2[2] + 2 * u2[0]); s[3] = 4 * (pu[0] + pu[1] + pu[2]) * (u2[0] + u2[1] + u2[2]); s[2] = 2 * (r2mw2 * u2[2] - r2pw2 * (u2[0] + u2[1])) + 8 * (pu[0] * pu[1] + pu[1] * pu[2] + pu[2] * pu[0]) + 6 * (pu[0] * pu[0] + pu[1] * pu[1] + pu[2] * pu[2]) + 2 * (p2[0] * (u2[1] + u2[2]) + p2[1] * (u2[2] + u2[0]) + p2[2] * (u2[0] + u2[1])); s[1] = 4 * (r2mw2 * pu[2] - r2pw2 * (pu[0] + pu[1]) + (p2[0] + p2[1] + p2[2]) * (pu[0] + pu[1] + pu[2])); s[0] = 2 * (r2mw2 * p2[2] - r2pw2 * (p2[0] + p2[1]) + p2[0] * p2[1] + p2[1] * p2[2] + p2[2] * p2[0]) + p2[0] * p2[0] + p2[1] * p2[1] + p2[2] * p2[2] + r2mw2 * r2mw2; double roots[4]; int num_roots = Math::solveQuartic(s[0], s[1], s[2], s[3], s[4], roots); double min_root = -1; for (int i = 0; i < num_roots; ++i) if (roots[i] >= 0 && (min_root < 0 || roots[i] < min_root)) min_root = roots[i]; #if 0 if (min_root >= 0) qDebug() << "min_root =" << min_root; #endif return (Real)min_root; }
Color PhongMaterial::sample(const Ray3& ray, const Vec3& position, const Vec3& normal) { // i don't know why global will lead to ld error //Vec3 lightDir = Vec3(1,1,1).normalize(); //Color lightColor = Color::white; // Vec3 lightDir = Vec3(1,1,1).normalize(); DirectionalLight lightDir(Vec3(-1,-1,-1)); Color lightColor = Color::white; float NdotL = normal.dot(lightDir.L); //cout << "NdotL: " << NdotL << endl; Vec3 H = lightDir.L.substract(ray.getDirection()).normalize(); float NdotH = normal.dot(H); //cout << "NdotH: " << NdotH << endl; Color diffuseTerm = diffuse.multiply(fmax(NdotL,0)); Color specularTerm = specular.multiply( pow( fmax(NdotH,0), shininess)); // cout << "diffTerm: " << diffuseTerm.getR() << " "<<diffuseTerm.getG() << " " << diffuseTerm.getB() << endl; // cout << "specTerm: " << specularTerm.getR() << " " << specularTerm.getG() << " " << specularTerm.getB() << endl; Color ret = lightColor.modulate(diffuseTerm.add(specularTerm)); if(ret.getR()>1) // it is possible that the color is overflow { ret.setR(1); } if(ret.getB()>1) { ret.setB(1); } if(ret.getG()>1) { ret.setG(1); } Color add = diffuseTerm.add(specularTerm); Color modulate = lightColor.modulate((add)); //cout << "add: " << add.getR() << " " << add.getG() << " " << add.getB() << endl; //cout << "modulate: " << modulate.getR() << " " << modulate.getG() << " " << modulate.getB() << endl; //cout << "lightColor: " << lightColor.getR() << " " << lightColor.getG() << " " << lightColor.getB() << endl; //cout << "ret: " << ret.getR() << " " << ret.getG() << " " << ret.getB() << endl; return ret; }
//---------------------------------------------------------------------------- bool Mgc::FindIntersection (const Ray3& rkRay, const Box3& rkBox, int& riQuantity, Vector3 akPoint[2]) { // convert ray to box coordinates Vector3 kDiff = rkRay.Origin() - rkBox.Center(); Vector3 kOrigin( kDiff.Dot(rkBox.Axis(0)), kDiff.Dot(rkBox.Axis(1)), kDiff.Dot(rkBox.Axis(2)) ); Vector3 kDirection( rkRay.Direction().Dot(rkBox.Axis(0)), rkRay.Direction().Dot(rkBox.Axis(1)), rkRay.Direction().Dot(rkBox.Axis(2)) ); Real fT0 = 0.0f, fT1 = Math::MAX_REAL; bool bIntersects = FindIntersection(kOrigin,kDirection,rkBox.Extents(), fT0,fT1); if ( bIntersects ) { if ( fT0 > 0.0f ) { riQuantity = 2; akPoint[0] = rkRay.Origin() + fT0*rkRay.Direction(); akPoint[1] = rkRay.Origin() + fT1*rkRay.Direction(); } else // fT0 == 0 { riQuantity = 1; akPoint[0] = rkRay.Origin() + fT1*rkRay.Direction(); } } else { riQuantity = 0; } return bIntersects; }
void CreateEntityTool::updateEntityPosition3D(const Ray3& pickRay, const Model::PickResult& pickResult) { assert(m_entity != NULL); MapDocumentSPtr document = lock(m_document); Vec3 delta; const Grid& grid = document->grid(); const Model::Hit& hit = pickResult.query().pickable().type(Model::Brush::BrushHit).occluded().first(); if (hit.isMatch()) { const Model::BrushFace* face = Model::hitToFace(hit); const Plane3 dragPlane = alignedOrthogonalDragPlane(hit.hitPoint(), face->boundary().normal); delta = grid.moveDeltaForBounds(dragPlane, m_entity->bounds(), document->worldBounds(), pickRay, hit.hitPoint()); } else { const Vec3 newPosition = pickRay.pointAtDistance(Renderer::Camera::DefaultPointDistance); const Vec3 center = m_entity->bounds().center(); delta = grid.moveDeltaForPoint(center, document->worldBounds(), newPosition - center); } if (delta.null()) return; document->translateObjects(delta); }
void CreateEntityTool::updateEntityPosition2D(const Ray3& pickRay) { assert(m_entity != NULL); MapDocumentSPtr document = lock(m_document); const Vec3 toMin = m_referenceBounds.min - pickRay.origin; const Vec3 toMax = m_referenceBounds.max - pickRay.origin; const Vec3 anchor = toMin.dot(pickRay.direction) > toMax.dot(pickRay.direction) ? m_referenceBounds.min : m_referenceBounds.max; const Plane3 dragPlane(anchor, -pickRay.direction); const FloatType distance = dragPlane.intersectWithRay(pickRay); if (Math::isnan(distance)) return; const Vec3 hitPoint = pickRay.pointAtDistance(distance); const Grid& grid = document->grid(); const Vec3 delta = grid.moveDeltaForBounds(dragPlane, m_entity->bounds(), document->worldBounds(), pickRay, hitPoint); if (delta.null()) return; document->translateObjects(delta); }
bool ResizeBrushesTool::resize(const Ray3& pickRay, const Renderer::Camera& camera) { assert(!m_dragFaces.empty()); Model::BrushFace* dragFace = m_dragFaces.front(); const Vec3& faceNormal = dragFace->boundary().normal; const Ray3::LineDistance distance = pickRay.distanceToLine(m_dragOrigin, faceNormal); if (distance.parallel) return true; const FloatType dragDist = distance.lineDistance; MapDocumentSPtr document = lock(m_document); const View::Grid& grid = document->grid(); const Vec3 relativeFaceDelta = grid.snap(dragDist) * faceNormal; const Vec3 absoluteFaceDelta = grid.moveDelta(dragFace, faceNormal * dragDist); const Vec3 faceDelta = selectDelta(relativeFaceDelta, absoluteFaceDelta, dragDist); if (faceDelta.null()) return true; if (m_splitBrushes) { if (splitBrushes(faceDelta)) { m_totalDelta += faceDelta; m_dragOrigin += faceDelta; m_splitBrushes = false; } } else { if (document->resizeBrushes(m_dragFaces, faceDelta)) { m_totalDelta += faceDelta; m_dragOrigin += faceDelta; } } return true; }
bool BVaabb::TestIntersection(const Ray3& ray) const { Vec3 normal; Ray3::IResult ret = ray.Intersects(mAABB, normal); return ret.first; }
// Intersect (Ray3) //------------------------------------------------------------------------------ bool AABB3::Intersect( const Ray3 & ray, float & dist ) const { const float ox = ray.GetOrigin().x; const float oy = ray.GetOrigin().y; const float oz = ray.GetOrigin().z; const float dx = ray.GetDir().x; const float dy = ray.GetDir().y; const float dz = ray.GetDir().z; float tx_min, ty_min, tz_min; float tx_max, ty_max, tz_max; // x float a = 1.f/dx; if ( a >= 0 ) { tx_min = ( m_Min.x-ox ) * a; tx_max = ( m_Max.x-ox ) * a; } else { tx_min = ( m_Max.x-ox ) * a; tx_max = ( m_Min.x-ox ) * a; } // y float b = 1.f/dy; if ( b >= 0 ) { ty_min = ( m_Min.y-oy ) * b; ty_max = ( m_Max.y-oy ) * b; } else { ty_min = ( m_Max.y-oy ) * b; ty_max = ( m_Min.y-oy ) * b; } // z float c = 1.f/dz; if ( c >= 0 ) { tz_min = ( m_Min.z-oz ) * c; tz_max = ( m_Max.z-oz ) * c; } else { tz_min = ( m_Max.z-oz ) * c; tz_max = ( m_Min.z-oz ) * c; } float t0, t1; // find largest entering t-value t0 = tx_min > ty_min ? tx_min : ty_min; t0 = tz_min > t0 ? tz_min : t0; // find smallest exiting t-value t1 = tx_max < ty_max ? tx_max : ty_max; t1 = tz_max < t1 ? tz_max : t1; if ( t0 < t1 && t1 > 0.001f ) // EPSILON { dist = t0; return true; } return false; }
bool Mgc::FindIntersection (const Ray3& rkRay, const Sphere& rkSphere, int& riQuantity, Vector3 akPoint[2]) { // set up quadratic Q(t) = a*t^2 + 2*b*t + c Vector3 kDiff = rkRay.Origin() - rkSphere.Center(); Real fA = rkRay.Direction().SquaredLength(); Real fB = kDiff.Dot(rkRay.Direction()); Real fC = kDiff.SquaredLength() - rkSphere.Radius()*rkSphere.Radius(); Real afT[2]; Real fDiscr = fB*fB - fA*fC; if ( fDiscr < 0.0f ) { riQuantity = 0; return false; } else if ( fDiscr > 0.0f ) { Real fRoot = Math::Sqrt(fDiscr); Real fInvA = 1.0f/fA; afT[0] = (-fB - fRoot)*fInvA; afT[1] = (-fB + fRoot)*fInvA; if ( afT[0] >= 0.0f ) { riQuantity = 2; akPoint[0] = rkRay.Origin() + afT[0]*rkRay.Direction(); akPoint[1] = rkRay.Origin() + afT[1]*rkRay.Direction(); return true; } else if ( afT[1] >= 0.0f ) { riQuantity = 1; akPoint[0] = rkRay.Origin() + afT[1]*rkRay.Direction(); return true; } else { riQuantity = 0; return false; } } else { afT[0] = -fB/fA; if ( afT[0] >= 0.0f ) { riQuantity = 1; akPoint[0] = rkRay.Origin() + afT[0]*rkRay.Direction(); return true; } else { riQuantity = 0; return false; } } }