double SphereLight::GetIntensity(const SceneContainer* Scene, const Point3D& TestLoc, const double& Time) { Vector3D Normal = TestLoc - position; Normal.normalize(); Matrix4x4 Rot; Rot.rotate('x', 45); // Potential error if Normal = x axis Vector3D u = cross((Rot * Normal), Normal); u.normalize(); u = radius * u; Vector3D v = cross(Normal, u); v.normalize(); v = radius * v; int NumVisiblePoints = 0; double theta = 0.f, RingInc = 1.f / (double)NumRings, AngleInc = (2 * M_PI) / (double)RingPoints; // Sum up the intensity of the visible points on the light for (double i = RingInc; i < 1.f; i += RingInc) { for (int j = 0; j < 4; j++) { if (IsVisibleFrom(Scene, position + i * sin(theta)*u + i * cos(theta)*v, TestLoc, Time)) { NumVisiblePoints++; } theta += AngleInc; } theta -= 3.f * (AngleInc); } return (double)NumVisiblePoints / ((double)RingPoints * NumRings); }
double Light::GetIntensity(const SceneContainer* Scene, const Point3D& TestLoc, const double& Time) { if (IsVisibleFrom(Scene, position, TestLoc, Time)) { return 1.f; } return 0.f; }
void CToyUtil::AddSceneAreaVisible(size_t iSceneArea, size_t iVisible) { TAssert(iSceneArea < m_asSceneAreas.size()); if (iSceneArea >= m_asSceneAreas.size()) return; TAssert(iVisible < m_asSceneAreas.size()); if (iVisible >= m_asSceneAreas.size()) return; if (IsVisibleFrom(iSceneArea, iVisible)) return; m_asSceneAreas[iSceneArea].m_aiVisibleAreas.push_back(iVisible); }
// Add any neighbors of iVisible which are visible to iArea's visible set. void CToyUtil::AddVisibleNeighbors(size_t iArea, size_t iVisible) { if (iArea == iVisible) return; tvector<Vector> avecPoints; for (size_t i = 0; i < m_asSceneAreas[iVisible].m_aiNeighboringAreas.size(); i++) { size_t iOther = m_asSceneAreas[iVisible].m_aiNeighboringAreas[i]; // If this area is already visible, we can skip it to prevent extra work and recursion. if (IsVisibleFrom(iArea, iOther)) continue; // Form a convex hull from the bounding boxes of iArea and i avecPoints.clear(); Vector vecMins = m_asSceneAreas[iArea].m_aabbArea.m_vecMins; Vector vecMaxs = m_asSceneAreas[iArea].m_aabbArea.m_vecMaxs; avecPoints.push_back(vecMins); avecPoints.push_back(Vector(vecMins.x, vecMins.y, vecMaxs.z)); avecPoints.push_back(Vector(vecMaxs.x, vecMins.y, vecMaxs.z)); avecPoints.push_back(Vector(vecMaxs.x, vecMins.y, vecMins.z)); avecPoints.push_back(Vector(vecMins.x, vecMaxs.y, vecMins.z)); avecPoints.push_back(Vector(vecMins.x, vecMaxs.y, vecMaxs.z)); avecPoints.push_back(Vector(vecMaxs.x, vecMaxs.y, vecMins.z)); avecPoints.push_back(vecMaxs); vecMins = m_asSceneAreas[iOther].m_aabbArea.m_vecMins; vecMaxs = m_asSceneAreas[iOther].m_aabbArea.m_vecMaxs; avecPoints.push_back(vecMins); avecPoints.push_back(Vector(vecMins.x, vecMins.y, vecMaxs.z)); avecPoints.push_back(Vector(vecMaxs.x, vecMins.y, vecMaxs.z)); avecPoints.push_back(Vector(vecMaxs.x, vecMins.y, vecMins.z)); avecPoints.push_back(Vector(vecMins.x, vecMaxs.y, vecMins.z)); avecPoints.push_back(Vector(vecMins.x, vecMaxs.y, vecMaxs.z)); avecPoints.push_back(Vector(vecMaxs.x, vecMaxs.y, vecMins.z)); avecPoints.push_back(vecMaxs); #ifdef __linux__ // Odd linker errors, linker can't find CConvexHullGenerator for some reason TUnimplemented(); #else CConvexHullGenerator c(avecPoints); const tvector<size_t>& avecConvexTriangles = c.GetConvexTriangles(); // Test to see if iVisible intersects that hull AABB aabbShrunkBounds = m_asSceneAreas[iVisible].m_aabbArea + AABB(Vector(0.1f, 0.1f, 0.1f), Vector(-0.1f, -0.1f, -0.1f)); // Shrink the bounds a tad so touching bounds on the far side don't count. bool bIntersect = ConvexHullIntersectsAABB(aabbShrunkBounds, avecPoints, avecConvexTriangles); if (bIntersect) { AddSceneAreaVisible(iArea, iOther); AddSceneAreaVisible(iOther, iArea); // Calling it recursively this way may allow visibility that doesn't exist, eg, in a chain a -> b -> c -> d, a can see d through c but not through b. // I'm willing to accept that for now if it doesn't become a problem. AddVisibleNeighbors(iArea, iOther); } #endif } }