//---------------------------------------------------------------------------- void SEIntrTriangle3Triangle3f::ProjectOntoAxis(const SETriangle3f& rTri, const SEVector3f& rAxis, float& rfMin, float& rfMax) { float fDot0 = rAxis.Dot(rTri.V[0]); float fDot1 = rAxis.Dot(rTri.V[1]); float fDot2 = rAxis.Dot(rTri.V[2]); rfMin = fDot0; rfMax = rfMin; if( fDot1 < rfMin ) { rfMin = fDot1; } else if( fDot1 > rfMax ) { rfMax = fDot1; } if( fDot2 < rfMin ) { rfMin = fDot2; } else if( fDot2 > rfMax ) { rfMax = fDot2; } }
void UFO::onUpdate() { SE_TRANSFORM[ty] = 16.0f; SEVector3f dir = (playerPos - SE_TRANSFORM.translation()) / 10.0f; float power = dir.lengthSqaure() - 150.0f; if (power > 300.0f) power = 300.0f; SE_RIGIDBODY.resetVelocity(se_data::AXIS_Y); SE_RIGIDBODY.applyForce(dir.unify() * power * UFO_SPEED); }
void Bot::onUpdate() { SEVector3f dir = (playerPos - SE_TRANSFORM.translation()) / 10.0f; float power = (dir.lengthSqaure() - 150.0f) / 2.0f; if (power > 90) power = 90.0f; dir[1] = 0.0f; dir = SE_MATRIX_ROTATE4(se_data::AXIS_Y, 90.0f - power)* SEVector4f(dir); SE_RIGIDBODY.applyForce(dir.unify() * BOT_SPEED); }
//---------------------------------------------------------------------------- bool SEIntrLine3Box3f::DoClipping(float fT0, float fT1, const SEVector3f& rOrigin, const SEVector3f& rDirection, const SEBox3f& rBox, bool bSolid, int& riCount, SEVector3f aPoint[2], int& riIntrType) { SE_ASSERT( fT0 < fT1 ); // 把linear component变换到box坐标体系下. SEVector3f vec3fDiff = rOrigin - rBox.Center; SEVector3f vec3fBOrigin( vec3fDiff.Dot(rBox.Axis[0]), vec3fDiff.Dot(rBox.Axis[1]), vec3fDiff.Dot(rBox.Axis[2]) ); SEVector3f vec3fBDirection( rDirection.Dot(rBox.Axis[0]), rDirection.Dot(rBox.Axis[1]), rDirection.Dot(rBox.Axis[2]) ); float fSaveT0 = fT0, fSaveT1 = fT1; bool bNotAllClipped = Clip(+vec3fBDirection.X, -vec3fBOrigin.X-rBox.Extent[0], fT0, fT1) && Clip(-vec3fBDirection.X, +vec3fBOrigin.X-rBox.Extent[0], fT0, fT1) && Clip(+vec3fBDirection.Y, -vec3fBOrigin.Y-rBox.Extent[1], fT0, fT1) && Clip(-vec3fBDirection.Y, +vec3fBOrigin.Y-rBox.Extent[1], fT0, fT1) && Clip(+vec3fBDirection.Z, -vec3fBOrigin.Z-rBox.Extent[2], fT0, fT1) && Clip(-vec3fBDirection.Z, +vec3fBOrigin.Z-rBox.Extent[2], fT0, fT1); if( bNotAllClipped && (bSolid || fT0 != fSaveT0 || fT1 != fSaveT1) ) { if( fT1 > fT0 ) { riIntrType = IT_SEGMENT; riCount = 2; aPoint[0] = rOrigin + fT0*rDirection; aPoint[1] = rOrigin + fT1*rDirection; } else { riIntrType = IT_POINT; riCount = 1; aPoint[0] = rOrigin + fT0*rDirection; } } else { riCount = 0; riIntrType = IT_EMPTY; } return riIntrType != IT_EMPTY; }
//---------------------------------------------------------------------------- static SESpectrum EstimateIrradianceWithPhotonMap(SEKdTree<SEBNPhoton>* map, int count, int lookupCount, SEBNClosePhoton* lookupBuf, float maxDistSquared, const SEVector3f& p, const SEVector3f& n) { if( !map ) { return 0.0f; } // Lookup nearby photons at irradiance computation point. SEBNPhotonProcess proc(lookupCount, lookupBuf); float md2 = maxDistSquared; map->Lookup(p, proc, md2); SE_ASSERT( md2 > 0.0f ); if( proc.FoundCount == 0 ) { return SESpectrum(0.0f); } // Accumulate irradiance value from nearby photons. SEBNClosePhoton* photons = proc.Photons; SESpectrum E(0.0f); for( SE_UInt32 i = 0; i < proc.FoundCount; ++i ) { float d = n.Dot(photons[i].Photon->Wi); if( d > 0.0f ) { E += photons[i].Photon->Alpha; } } return E / (count * md2 * SEMathf::PI); }
//---------------------------------------------------------------------------- bool SEIntrTriangle3Triangle3f::TestOverlap(const SEVector3f& rAxis, float fTMax, const SEVector3f& rVelocity, float& rfTFirst, float& rfTLast) { float fMin0, fMax0, fMin1, fMax1; ProjectOntoAxis(*m_pTriangle0, rAxis, fMin0, fMax0); ProjectOntoAxis(*m_pTriangle1, rAxis, fMin1, fMax1); float fSpeed = rVelocity.Dot(rAxis); return TestOverlap(fTMax, fSpeed, fMin0, fMax0, fMin1, fMax1, rfTFirst, rfTLast); }
//---------------------------------------------------------------------------- bool SEIntrTriangle3Triangle3f::FindOverlap(const SEVector3f& rAxis, float fTMax, const SEVector3f& rVelocity, ContactSide& reSide, SEConfiguration& rTCfg0, SEConfiguration& rTCfg1, float& rfTFirst, float& rfTLast) { SEConfiguration tempCfg0, tempCfg1; ProjectOntoAxis(*m_pTriangle0, rAxis, tempCfg0); ProjectOntoAxis(*m_pTriangle1, rAxis, tempCfg1); float fSpeed = rVelocity.Dot(rAxis); return FindOverlap(fTMax, fSpeed, tempCfg0, tempCfg1, reSide, rTCfg0, rTCfg1, rfTFirst, rfTLast); }
//---------------------------------------------------------------------------- bool Lighting::OnInitialize() { if( !SEWindowApplication3::OnInitialize() ) { return false; } m_spCamera->SetFrustum(-0.55f, 0.55f, -0.4125f, 0.4125f, 1.0f, 100.0f); SEVector3f tempCLoc(0.0f, 9.0f, -20.0f); SEVector3f tempCDir(0.0f, -0.2f, 1.0f); tempCDir.Normalize(); SEVector3f tempCUp(0.0f, 1.0f, 0.0f); SEVector3f tempCRight = tempCUp.Cross(tempCDir); tempCRight.Normalize(); tempCUp = tempCDir.Cross(tempCRight); tempCUp.Normalize(); m_spCamera->SetFrame(tempCLoc, tempCRight, tempCUp, tempCDir); CreateScene(); // initial update of objects m_spScene->UpdateGS(); m_spScene->UpdateRS(); // initial culling of scene m_Culler.SetCamera(m_spCamera); m_Culler.ComputeUnculledSet(m_spScene); #if defined(SE_USING_OES2) InitializeCameraMotion(0.1f, 0.01f); #else InitializeCameraMotion(0.01f, 0.001f); #endif InitializeObjectMotion(m_spScene); return true; }
//---------------------------------------------------------------------------- void SEExtremalQuery3PRJf::GetExtremeVertices(const SEVector3f& rDirection, int& riPositiveDirection, int& riNegativeDirection) { SEVector3f vec3fDiff = m_pPolytope->GetVertex(0) - m_Centroid; float fMin = rDirection.Dot(vec3fDiff), fMax = fMin; riNegativeDirection = 0; riPositiveDirection = 0; for( int i = 1; i < m_pPolytope->GetVCount(); i++ ) { vec3fDiff = m_pPolytope->GetVertex(i) - m_Centroid; float fDot = rDirection.Dot(vec3fDiff); if( fDot < fMin ) { riNegativeDirection = i; fMin = fDot; } else if( fDot > fMax ) { riPositiveDirection = i; fMax = fDot; } } }
//---------------------------------------------------------------------------- static SESpectrum EstimateRadianceWithPhotonMap(SEKdTree<SEBNPhoton>* map, int pathCount, int lookupCount, SEBNClosePhoton* lookupBuf, SEBSDF* bsdf, SERandomNumberGenerator& rng, const SEBNIntersection& isect, const SEVector3f& wo, float maxDistSquared) { SESpectrum L(0.0f); SEBxDF::BxDFType nonSpecular = SEBxDF::BxDFType(SEBxDF::BSDF_REFLECTION | SEBxDF::BSDF_TRANSMISSION | SEBxDF::BSDF_DIFFUSE | SEBxDF::BSDF_GLOSSY); if( map && bsdf->GetComponentCount(nonSpecular) > 0 ) { // Do photon map lookup at intersection point. SEBNPhotonProcess proc(lookupCount, lookupBuf); map->Lookup(isect.DG.p, proc, maxDistSquared); // Estimate reflected radiance due to incident photons. SEBNClosePhoton* photons = proc.Photons; int nFound = proc.FoundCount; SEVector3f Nf; SEVector3f::Faceforward(bsdf->DGShading.nn, wo, Nf); if( bsdf->GetComponentCount(SEBxDF::BxDFType(SEBxDF::BSDF_REFLECTION | SEBxDF::BSDF_TRANSMISSION | SEBxDF::BSDF_GLOSSY)) > 0 ) { // Compute exitant radiance from photons for glossy surface. for( int i = 0; i < nFound; ++i ) { const SEBNPhoton* p = photons[i].Photon; float k = Kernel(p, isect.DG.p, maxDistSquared); L += (k / (pathCount * maxDistSquared)) * bsdf->f(wo, p->Wi) * p->Alpha; } } else { // Compute exitant radiance from photons for diffuse surface. SESpectrum Lr(0.0f), Lt(0.0f); for( int i = 0; i < nFound; ++i ) { float d = Nf.Dot(photons[i].Photon->Wi); if( d > 0.0f ) { float k = Kernel(photons[i].Photon, isect.DG.p, maxDistSquared); Lr += (k / (pathCount * maxDistSquared)) * photons[i].Photon->Alpha; } else { float k = Kernel(photons[i].Photon, isect.DG.p, maxDistSquared); Lt += (k / (pathCount * maxDistSquared)) * photons[i].Photon->Alpha; } } L += Lr * bsdf->rho(wo, rng, SEBxDF::BSDF_ALL_REFLECTION) * SEMathf::INV_PI + Lt * bsdf->rho(wo, rng, SEBxDF::BSDF_ALL_TRANSMISSION) * SEMathf::INV_PI; } } return L; }
//---------------------------------------------------------------------------- void SEPhotonShootingTask::DoWork() { // Declare local variables for the task. SEMemoryArena arena; SERandomNumberGenerator rng(31 * TaskNum); std::vector<SEBNPhoton> localDirectPhotons; std::vector<SEBNPhoton> localIndirectPhotons; std::vector<SEBNPhoton> localCausticPhotons; std::vector<SEBNRadiancePhoton> localRadiancePhotons; SE_UInt32 totalPaths = 0; bool causticDone = (PhotonMapShader->CausticPhotonsWantedCount == 0); bool indirectDone = (PhotonMapShader->IndirectPhotonsWantedCount == 0); SEPermutedHalton halton(6, rng); std::vector<SESpectrum> localRpReflectances; std::vector<SESpectrum> localRpTransmittances; while( true ) { // Follow photon paths for a block of samples. const SE_UInt32 blockSize = 4096; for( SE_UInt32 i = 0; i < blockSize; ++i ) { float u[6]; halton.Sample(++totalPaths, u); // Choose light to shoot photon from. float lightPdf; int lightNum = LightDistribution->SampleDiscrete(u[0], &lightPdf); const SEBNLight* light = Scene->Lights[lightNum]; // Generate photonRay from light source. SERayDifferential photonRay; float pdf; SEBNLightSample lightSample(u[1], u[2], u[3]); SEVector3f lightSurfaceNormal; SESpectrum Le = light->Sample_L(Scene, lightSample, u[4], u[5], Time, &photonRay, &lightSurfaceNormal, &pdf); if( pdf == 0.0f || Le.IsBlack() ) { continue; } // Initialize alpha value. float absCostheta = fabsf(lightSurfaceNormal.Dot(photonRay.Direction)); SESpectrum alpha = Le * (absCostheta / (pdf * lightPdf)); if( !alpha.IsBlack() ) { // Follow photon path through scene and record intersections. bool specularPath = true; SEBNIntersection photonIsect; int nIntersections = 0; while( Scene->Intersect(photonRay, &photonIsect) ) { ++nIntersections; // Handle photon/surface intersection. alpha *= Renderer->Transmittance(Scene, photonRay, 0, rng, arena); // Determine if none specular component exists. SEBSDF* photonBSDF = photonIsect.GetBSDF(photonRay, arena); SEBxDF::BxDFType specularType = SEBxDF::BxDFType( SEBxDF::BSDF_REFLECTION | SEBxDF::BSDF_TRANSMISSION | SEBxDF::BSDF_SPECULAR); bool hasNonSpecular = (photonBSDF->GetComponentCount() > photonBSDF->GetComponentCount(specularType)); SEVector3f wo = -photonRay.Direction; if( hasNonSpecular ) { // Deposit photon at surface that has non-specular BSDF // component. SEBNPhoton photon(photonIsect.DG.p, alpha, wo); bool depositedPhoton = false; if( specularPath && nIntersections > 1 ) { if( !causticDone ) { // Deposit caustic photon at surface. depositedPhoton = true; localCausticPhotons.push_back(photon); } } else { // Deposit either direct or indirect photon. // Stop depositing direct photons once indirectDone // is true; don't want to waste memory storing too // many if we're going a long time trying to get // enough caustic photons desposited. if( nIntersections == 1 && !indirectDone && PhotonMapShader->FinalGather ) { // Deposit direct photon at surface. depositedPhoton = true; localDirectPhotons.push_back(photon); } else if( nIntersections > 1 && !indirectDone ) { // Deposit indirect photon at surface. depositedPhoton = true; localIndirectPhotons.push_back(photon); } } // Possibly create radiance photon at photon // intersection point. if( depositedPhoton && PhotonMapShader->FinalGather && rng.RandomFloat() < 0.125f ) { SEVector3f n = photonIsect.DG.nn; SEVector3f::Faceforward(n, -photonRay.Direction, n); SEBNRadiancePhoton radiancePhoton(photonIsect.DG.p, n); localRadiancePhotons.push_back(radiancePhoton); SESpectrum rho_r = photonBSDF->rho(rng, SEBxDF::BSDF_ALL_REFLECTION); localRpReflectances.push_back(rho_r); SESpectrum rho_t = photonBSDF->rho(rng, SEBxDF::BSDF_ALL_TRANSMISSION); localRpTransmittances.push_back(rho_t); } } // Stop bouncing if max photon depth has been reached. if( nIntersections >= PhotonMapShader->MaxPhotonDepth ) { break; } // Sample new photon ray direction. SEVector3f wi; float _pdf; SEBxDF::BxDFType flags; SESpectrum fr = photonBSDF->Sample_f(wo, &wi, SEBSDFSample(rng), &_pdf, SEBxDF::BSDF_ALL, &flags); if( fr.IsBlack() || _pdf == 0.0f ) { break; } float absCosi = fabsf(wi.Dot(photonBSDF->DGShading.nn)); SESpectrum anew = alpha * fr * (absCosi / _pdf); // Possibly terminate photon path with Russian roulette. float luminanceRatio = anew.y() / alpha.y(); float continueProb = SE_MIN(1.0f, luminanceRatio); if( rng.RandomFloat() > continueProb ) { break; } alpha = anew / continueProb; specularPath &= ((flags & SEBxDF::BSDF_SPECULAR) != 0); if( indirectDone && !specularPath ) { break; } photonRay = SERayDifferential(photonIsect.DG.p, wi, photonRay, photonIsect.RayEpsilon); } } arena.FreeAll(); } // Merge local photon data with data in photon map shader. { // Begin mutex scope. SEMutexLock lock(Mutex); // Give up if we're not storing enough photons. if( AbortTasks ) { return; } bool causticUnsuccessful = Unsuccessful( PhotonMapShader->CausticPhotonsWantedCount, CausticPhotons.size(), blockSize); bool indirectUnsuccessful = Unsuccessful( PhotonMapShader->IndirectPhotonsWantedCount, IndirectPhotons.size(), blockSize); if( ShotCount > SEBNPhotonMapShader::MAX_PHOTON_PATH_SHOT_COUNT && (causticUnsuccessful || indirectUnsuccessful) ) { // Unable to store enough photons. Giving up. CausticPhotons.erase(CausticPhotons.begin(), CausticPhotons.end()); IndirectPhotons.erase(IndirectPhotons.begin(), IndirectPhotons.end()); RadiancePhotons.erase(RadiancePhotons.begin(), RadiancePhotons.end()); // Notify all the other tasks to stop. AbortTasks = true; return; } ProgressReporter.Update(localIndirectPhotons.size() + localCausticPhotons.size()); ShotCount += blockSize; // Merge direct and indirect photons into shared array. if( !indirectDone ) { PhotonMapShader->IndirectPathsCount += blockSize; for( SE_UInt32 i = 0; i < localIndirectPhotons.size(); ++i ) { IndirectPhotons.push_back(localIndirectPhotons[i]); } localIndirectPhotons.erase(localIndirectPhotons.begin(), localIndirectPhotons.end()); if( IndirectPhotons.size() >= PhotonMapShader->IndirectPhotonsWantedCount ) { indirectDone = true; } DirectPathsCount += blockSize; for( SE_UInt32 i = 0; i < localDirectPhotons.size(); ++i ) { DirectPhotons.push_back(localDirectPhotons[i]); } localDirectPhotons.erase(localDirectPhotons.begin(), localDirectPhotons.end()); } // Merge caustic, and radiance photons into shared array. if( !causticDone ) { PhotonMapShader->CausticPathsCount += blockSize; for( SE_UInt32 i = 0; i < localCausticPhotons.size(); ++i ) { CausticPhotons.push_back(localCausticPhotons[i]); } localCausticPhotons.erase(localCausticPhotons.begin(), localCausticPhotons.end()); if( CausticPhotons.size() >= PhotonMapShader->CausticPhotonsWantedCount ) { causticDone = true; } } for( SE_UInt32 i = 0; i < localRadiancePhotons.size(); ++i ) { RadiancePhotons.push_back(localRadiancePhotons[i]); } localRadiancePhotons.erase(localRadiancePhotons.begin(), localRadiancePhotons.end()); for( SE_UInt32 i = 0; i < localRpReflectances.size(); ++i ) { RadiancePhotonReflectances.push_back(localRpReflectances[i]); } localRpReflectances.erase(localRpReflectances.begin(), localRpReflectances.end()); for( SE_UInt32 i = 0; i < localRpTransmittances.size(); ++i ) { RadiancePhotonTransmittances.push_back( localRpTransmittances[i]); } localRpTransmittances.erase(localRpTransmittances.begin(), localRpTransmittances.end()); // End mutex scope. } // Exit task if enough photons have been found. if( indirectDone && causticDone ) { break; } } }
//---------------------------------------------------------------------------- SEPlane3f::SEPlane3f(const SEVector3f& rNormal, const SEVector3f& rP0) : Normal(rNormal) { Constant = rNormal.Dot(rP0); }
//---------------------------------------------------------------------------- void SEIntrTriangle3Triangle3f::ProjectOntoAxis(const SETriangle3f& rTri, const SEVector3f& rAxis, SEConfiguration& rCfg) { // find projections of vertices onto potential separating axis float fD0 = rAxis.Dot(rTri.V[0]); float fD1 = rAxis.Dot(rTri.V[1]); float fD2 = rAxis.Dot(rTri.V[2]); // explicit sort of vertices to construct a SEConfiguration object if( fD0 <= fD1 ) { if( fD1 <= fD2 ) // D0 <= D1 <= D2 { if( fD0 != fD1 ) { if( fD1 != fD2 ) { rCfg.Map = M111; } else { rCfg.Map = M12; } } else // ( D0 == D1 ) { if( fD1 != fD2 ) { rCfg.Map = M21; } else { rCfg.Map = M3; } } rCfg.Index[0] = 0; rCfg.Index[1] = 1; rCfg.Index[2] = 2; rCfg.Min = fD0; rCfg.Max = fD2; } else if( fD0 <= fD2 ) // D0 <= D2 < D1 { if( fD0 != fD2 ) { rCfg.Map = M111; rCfg.Index[0] = 0; rCfg.Index[1] = 2; rCfg.Index[2] = 1; } else { rCfg.Map = M21; rCfg.Index[0] = 2; rCfg.Index[1] = 0; rCfg.Index[2] = 1; } rCfg.Min = fD0; rCfg.Max = fD1; } else // D2 < D0 <= D1 { if( fD0 != fD1 ) { rCfg.Map = M111; } else { rCfg.Map = M12; } rCfg.Index[0] = 2; rCfg.Index[1] = 0; rCfg.Index[2] = 1; rCfg.Min = fD2; rCfg.Max = fD1; } } else if( fD2 <= fD1 ) // D2 <= D1 < D0 { if( fD2 != fD1 ) { rCfg.Map = M111; rCfg.Index[0] = 2; rCfg.Index[1] = 1; rCfg.Index[2] = 0; } else { rCfg.Map = M21; rCfg.Index[0] = 1; rCfg.Index[1] = 2; rCfg.Index[2] = 0; } rCfg.Min = fD2; rCfg.Max = fD0; } else if( fD2 <= fD0 ) // D1 < D2 <= D0 { if( fD2 != fD0 ) { rCfg.Map = M111; } else { rCfg.Map = M12; } rCfg.Index[0] = 1; rCfg.Index[1] = 2; rCfg.Index[2] = 0; rCfg.Min = fD1; rCfg.Max = fD0; } else // D1 < D0 < D2 { rCfg.Map = M111; rCfg.Index[0] = 1; rCfg.Index[1] = 0; rCfg.Index[2] = 2; rCfg.Min = fD1; rCfg.Max = fD2; } }