public Interfaces.Rendering.Radiosity.RadiosityIntersection Intersection(Vector3 direction, Vector3 origin) { if (bounds.RayAABBIntersect(origin, direction)) { EnhancedMesh[] mesh; if (meshes.Length > (int)LevelOfDetail.SuperHigh) { mesh = meshes[(int)LevelOfDetail.SuperHigh]; } else { mesh = null; } if (mesh == null) { for (int x = (int)LevelOfDetail.SuperHigh; x >= 0; x--) { if ((meshes.Length > x) && (meshes[x] != null)) { mesh = meshes[x]; break; } } } Intersection closest = Wrappers.Intersection.None; float distSq = float.MaxValue; int meshIndex = -1; for (int x = 0; x < mesh.Length; x++) { Intersection regularIntersect = mesh[x].IntersectRay(origin, direction); if (!regularIntersect.NoIntersection) { float dist2 = (regularIntersect.Position - origin).LengthSq(); if (dist2 < distSq) { closest = regularIntersect; distSq = dist2; meshIndex = x; } } } if (!closest.NoIntersection) { int f = closest.FaceIndex * 3; Vertex a = mesh[meshIndex].Vertices[mesh[meshIndex].Indices[f]]; Vertex b = mesh[meshIndex].Vertices[mesh[meshIndex].Indices[f + 1]]; Vertex c = mesh[meshIndex].Vertices[mesh[meshIndex].Indices[f + 2]]; RadiosityIntersection radIntersect = RadiosityHelper.ProcessIntersection(direction, a, b, c, closest, null, false); return(radIntersect); } } return(RadiosityIntersection.None); }
private Interfaces.Rendering.Radiosity.RadiosityIntersection RadiosityIntersect(Vector3 origin, Vector3 direction) { if (direction.Length() != 1) { direction.Normalize(); } // TODO: Check bounding box for model, then for each node, then for each bsp. Interfaces.Rendering.Radiosity.RadiosityIntersection closest = RadiosityIntersection.None; // if (ax + by + cz == -D) then COLLISION foreach (NodeBlock node in modelCollisionGeometryValues._nodesList) { foreach (BspBlock bsp in node.Bsps) { //cosAlpha = DotProduct( // vnRayVector , vnPlaneNormal ); // if (cosAlpha==0) return -1.0f; // deltaD = planeD - // DotProduct(vRayOrigin,vnPlaneNormal); // return (deltaD/cosAlpha); int surfaceIndex = 0; foreach (SurfaceBlock surface in bsp.Surfaces) { RadiosityIntersection tempIntersect = Ray.IntersectRayOnPlane(new Ray(origin, direction), new Plane(bsp.Planes[surface.Plane.Value].Plane.I, bsp.Planes[surface.Plane.Value].Plane.J, bsp.Planes[surface.Plane.Value].Plane.K, bsp.Planes[surface.Plane.Value].Plane.D)); if ((bool)tempIntersect) { if (closest != RadiosityIntersection.None) { if (closest.Distance < tempIntersect.Distance) { continue; } } closest = tempIntersect; } } } } return(closest); }
public bool[,] CreateImportanceMap(Vector3 lightDirection, int photonCount, WorldBounds bounds, out int importanceMapIntersectCount) { bool[,] hiresMap; importanceMapIntersectCount = 0; float width = bounds.X.Difference; float height = bounds.Y.Difference; float countRoot = (float)Math.Sqrt(photonCount); int countX = (int)Math.Ceiling((countRoot * height) / width); int countY = (int)Math.Ceiling((countRoot * width) / height); float distanceX = width / (float)countX; float distanceY = height / (float)countY; hiresMap = new bool[countX, countY]; //lightDirection *= -1; // back to original; float xPos, yPos; yPos = bounds.Y.Lower; for (int y = 0; y < countY; y++) { xPos = bounds.X.Lower; for (int x = 0; x < countX; x++) { RadiosityIntersection intersect = m_bsp[0].RadiosityIntersect(new Vector3(xPos, yPos, bounds.Z.Upper), lightDirection); // DeMorgan's Theorem FTW! hiresMap[x, y] = !(intersect.NoIntersection || intersect.WrongSide); if (hiresMap[x, y]) { importanceMapIntersectCount++; } xPos += distanceX; IncrementProgress(); } yPos += distanceY; } //importanceMap = hiresMap; return(hiresMap); }
/// <summary> /// Main photon processing algorithm. /// </summary> private void ProcessCollisions() { ChangeStage(RadiosityStage.PhotonBouncing, m_maxPhotons); photonsComplete = 0; // Loop through all the lights. for (int _currentLightIndex = 0; _currentLightIndex < this.m_lights.Count; _currentLightIndex++) { lightIndex = _currentLightIndex; if (m_lights[_currentLightIndex] is DiffuseLight) { DiffuseLight light = m_lights[_currentLightIndex] as DiffuseLight; //AddDebugRay(light.Center, light.Normal); AddDebugRay(light.Center, light.Normal, RadiosityDebugLineListID.LightDirections); } if (m_lights[_currentLightIndex] is RadiosityLight) { (m_lights[_currentLightIndex] as RadiosityLight).pointCount = m_maxPhotons; } int retryCount = 20; photonMap.BeginLight(); // Loop through the number of photons per light. Parallel.For(0, m_lights[lightIndex].PhotonCount, delegate(int _currentPhotonIndex) { if (stopRequested) { return; } if (!updateInProgress) { SetOperation("Bouncing photons..."); } photonIndex = _currentPhotonIndex; int _collisionCount = 0; IPhoton _photon; lock (this.m_lights[_currentLightIndex]) { // Generate a photon from the current light. _photon = this.m_lights[_currentLightIndex].GeneratePhoton(); AddDebugPoint(_photon.Position, RadiosityDebugPointListID.PhotonSpawn); AddDebugRay(_photon.Position, _photon.Direction, RadiosityDebugLineListID.DirectOnly); } //_photon.Color.Multiply(m_lights[_currentLightIndex].Power * m_lights.Count); // Bounce the photon around for the maximum permitted bounces. while (true)//_collisionCount < this.m_maxBounces) { RadiosityIntersection closest = RadiosityIntersection.None; float distSq = float.MaxValue; if (collideModels) { for (int x = 0; x < m_models.Count; x++) { RadiosityIntersection intersect = m_models[x].Intersection(_photon.Direction, _photon.Position); if (intersect != RadiosityIntersection.None) { //AddDebugPoint(intersect.Position); float dist = (intersect.Position - _photon.Position).LengthSq(); if (dist < distSq) { distSq = dist; closest = intersect; } } } } for (int x = 0; x < m_bsp.Count; x++) { // TODO: Test radiosity model to see if changes fixed the issues. RadiosityIntersection intersect = m_bsp[x].RadiosityIntersect(_photon.Position, _photon.Direction); if ((intersect.NoIntersection) || (intersect.WrongSide)) { continue; } float dist = float.MaxValue; if ((dist = (intersect.Position - _photon.Position).LengthSq()) < distSq) { closest = intersect; distSq = dist; } } // If the diffuse light never collided, it will randomly generate another. if ((closest == RadiosityIntersection.None)) { if (m_lights[_currentLightIndex] is DiffuseLight) { if (_collisionCount < 1) { if (retryCount > 0) { retryCount--; _currentPhotonIndex--; break; } } } retryCount = 5; break; } retryCount = 5; if (_collisionCount == 0) { AddDebugPoint(closest.Position, RadiosityDebugPointListID.DirectOnly); } else { AddDebugPoint(closest.Position, RadiosityDebugPointListID.IndirectOnly); } Photon phot = new Photon { LightmapIndex = (short)closest.LightmapIndex, MaterialIndex = (short)closest.MaterialIndex, Direction = (PhotonVector3)_photon.Direction, position = (PhotonVector3)closest.Position, Power = _photon.Color.Copy() }; AddDebugRay(closest.Position, closest.NewDirection, RadiosityDebugLineListID.IndirectOnly); _photon.Position = closest.Position; _photon.Direction = closest.NewDirection; lock (photonMap) { photonMap.Store(phot); } _photon.Color.Tint(closest.Material.ReflectionTint); _collisionCount++; if ((closest.Absorbed) || (_collisionCount >= m_maxBounces)) { break; } } photonsComplete++; IncrementProgress(); }); //photonMap.EndLight(); } Interfaces.Output.Write(Interfaces.OutputTypes.Information, "Finished processing photons..."); ChangeStage(RadiosityStage.TreeBalancing, 100); SetOperation("Balancing the photon map..."); photonMap.Balance(); RadiosityRenderer.SavePhotonMap(); Interfaces.Output.Write(Interfaces.OutputTypes.Information, "Saved the photon map!"); SetOperation("Updating viewport..."); try { //UpdateBspLightmaps(); CreateLightmaps(); } catch (Exception a) { SetOperation("Error!.. " + a.Message); Interfaces.Output.Write(Interfaces.OutputTypes.Error, "Error!.. " + a.Message, a.StackTrace); } try { UpdateViewportLightmaps(); } catch (System.Threading.AggregateException a) { Interfaces.Output.Write(Interfaces.OutputTypes.Error, "Error of type AggregateException thrown."); foreach (Exception exc in a.InnerExceptions) { Interfaces.Output.Write(Interfaces.OutputTypes.Error, "Error: " + exc.Message, exc.StackTrace); } } #region Debug #if DEBUG Console.WriteLine("Done!"); #endif #endregion stopRequested = false; }
private void CreateRender() { int screenWidth = MdxRender.Device.Viewport.Width; int screenHeight = MdxRender.Device.Viewport.Height; float dist2 = RadiosityHelper.GatherDistance * RadiosityHelper.GatherDistance; Bitmap renderBitm;// = new Bitmap(screenWidth, screenHeight); float[,,] hdr = new float[screenWidth, screenHeight, 3]; ChangeStage(RadiosityStage.TextureGeneration, screenWidth * screenHeight); SetOperation("Rendering..."); int tenPercent = screenWidth / 10; int left = screenWidth / 2 - tenPercent; int right = screenWidth / 2 + tenPercent; for (int y = 0; y < screenHeight; y++) { for (int x = 0; x < screenWidth; x++) { Vector3 direction, origin; MdxRender.CalculatePickRayWorld(x, y, out direction, out origin); //AddDebugRay(origin, direction); RadiosityIntersection intersect = m_bsp[0].RadiosityIntersect(origin, direction); //AddDebugPoint(intersect.Position); if (!intersect.NoIntersection) { Vector3 normal = m_bsp[0].GetFaceNormal(intersect.LightmapIndex, intersect.MaterialIndex, intersect.FaceIndex); List <CompressedPhoton> photons = photonMap.RetrieveNearestNeighbors((PhotonVector3)intersect.Position, dist2, 10000); RealColor sum = RealColor.Black.Copy();//new RealColor(photons.Count, photons.Count, photons.Count); if (photons.Count == 0) { System.Diagnostics.Debugger.Break(); } foreach (CompressedPhoton phot in photons) { float dotP = Vector3.Dot(-phot.Direction, normal); if (dotP < 0) { dotP = 0; } sum.Add(phot.Power.Copy().Multiply(dotP)); } if ((sum.G > sum.B) && (sum.G > sum.R)) { if (x >= left) { if (x <= right) { if (photons.Count > 100) { AddDebugRay(origin, direction); AddDebugPoint(origin); foreach (var photon in photons) { AddDebugPoint(photon.position.ToVector3()); } } } } //System.Diagnostics.Debugger.Break(); } //sum.Multiply(1 / (dist2 * (float)Math.PI)); //sum.Multiply(intersect.Material.AmbientLight); for (int c = 0; c < 3; c++) { hdr[x, y, c] = sum[c]; } } else { hdr[x, y, 0] = 0; hdr[x, y, 1] = 0; hdr[x, y, 2] = 0; } IncrementProgress(); } } //renderBitm = LinearTonemap(hdr); Bitmap tempBitmap = new Bitmap(screenWidth, screenHeight); //Graphics g = Graphics.FromImage(tempBitmap); //g.DrawImage(renderBitm, 0, 0); //g.Dispose(); //renderBitm.Dispose(); tempBitmap.Save(@"C:\Users\David\render.bmp"); return; }