示例#1
0
 static RadiosityRenderer()
 {
     _renderer = new RadiosityRenderer(null);
 }
示例#2
0
        /// <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;
        }