예제 #1
0
 public void RecalculateColors(LightSource lightSource, Observer observer, bool clipInvisible)
 {
     foreach (ModelNode modelNode in this.ModelGraph)
     {
         modelNode.RecalculateColors(lightSource, observer, clipInvisible);
     }
 }
예제 #2
0
파일: Spectro.cs 프로젝트: vsuley/Spectro
        private void UpdateObserverChart(Observer observer)
        {
            int channel = 0;
            foreach (SpectralData spectrum in observer.ResponseSpectra)
            {
                Series series = ObserverChart.Series[channel];

                series.Points.Clear();
                for (int wavelength = spectrum.LowestWavelength, i = 0; wavelength <= spectrum.HighestWavelength; wavelength += spectrum.StepSize, i++)
                {
                    series.Points.Add(new DataPoint((float)wavelength, spectrum.WaveData[i]));
                }

                channel++;
            }
        }
예제 #3
0
파일: ModelNode.cs 프로젝트: vsuley/Spectro
        public void RecalculateColors(LightSource lightSource, Observer observer, bool clipInvisible)
        {
            try
            {
                // Calculate RGB values
                this.MaterialRGB = Utilities.GetEquivalentRGB(this.Material);

                // Calculate the tristimulus values.
                this.FinalTristimulus = Utilities.CalculateTristimulusValues(lightSource, this.Material, observer, clipInvisible);
                this.FinalRGB = Utilities.CalculateRGBfromXYZ(FinalTristimulus);

                // Not sure why I'm having to do this, but for now sometimes the scene renders like a ghost, so make alpha 1.
                this.FinalRGB = new Vector4(FinalRGB.X, FinalRGB.Y, FinalRGB.Z, 1f);
                this.MaterialRGB = new Vector4(MaterialRGB.X, MaterialRGB.Y, MaterialRGB.Z, 1f);
            }
            catch (Exception e)
            {
                MessageBox.Show("Color calculations because " + e.Message);
                throw;
            }
        }
예제 #4
0
        /// <summary>
        /// Read in all the observers from the given file.
        /// </summary>
        /// <param name="fileName">Path to the data file.</param>
        protected void ReadInObservers(string fileName)
        {
            XmlDocument observersXML = new XmlDocument();
            observersXML.Load(fileName);

            foreach (XmlElement observerXML in observersXML.GetElementsByTagName(XMLDataConstants.Observer))
            {
                Observer observer = new Observer();
                observer.Initialize(observerXML);
                this.Observers.Add(observer);
            }
        }
예제 #5
0
파일: Utilities.cs 프로젝트: vsuley/Spectro
        /// <summary>
        /// Calculate the tristimulus values for the given combination of light source, material and observer.
        /// </summary>
        /// <returns>A float array of size 3 containing X, Y and Z in each cell respectively.</returns>
        public static Vector3 CalculateTristimulusValues(LightSource lightSource, Material material, Observer observer, bool clipInvisible = false)
        {
            // TODO: This may not be the most efficient of all approaches, make sure you change this to be more streamlined.

            // Normalize spectra.
            //
            List<SpectralData> spectraBank = new List<SpectralData>();
            spectraBank.Add(lightSource.SpectralPowerDistribution);
            spectraBank.Add(material.ReflectanceDistribution);
            spectraBank.Add(observer.ResponseSpectra[0]);
            spectraBank.Add(observer.ResponseSpectra[1]);
            spectraBank.Add(observer.ResponseSpectra[2]);

            Utilities.NormalizeSpectra(spectraBank);

            // Calculate the normalizing constant for tristimulus integration
            //
            float K = Utilities.TristimulusNormalizingConstant(lightSource, observer);

            float summation;
            int stepSize = lightSource.SpectralPowerDistribution.StepSize;

            // The wave data we need is nested deep inside objects. So grab it into local arrays
            // for convenience of coding.
            //
            float[] lightSourceData, materialData, observerXData, observerYData, observerZData;

            if (clipInvisible)
            {
                // Find out what indexes correspond to wavelengths between 380 and 780 nm.
                // Since the data is normalized, calculating based on 1 source should be enough.
                int startIndex = (380 - lightSource.SpectralPowerDistribution.LowestWavelength) / lightSource.SpectralPowerDistribution.StepSize;
                int count = (780 - 380) / lightSource.SpectralPowerDistribution.StepSize + 1;

                // Sanity check
                if (startIndex < 0)
                {
                    throw new ArgumentException("wavelength data provided started after 380 nm");
                }

                lightSourceData = lightSource.SpectralPowerDistribution.WaveData.GetRange(startIndex, count).ToArray();
                materialData = material.ReflectanceDistribution.WaveData.GetRange(startIndex, count).ToArray();
                observerXData = observer.ResponseSpectra[0].WaveData.GetRange(startIndex, count).ToArray();
                observerYData = observer.ResponseSpectra[1].WaveData.GetRange(startIndex, count).ToArray();
                observerZData = observer.ResponseSpectra[2].WaveData.GetRange(startIndex, count).ToArray();
            }
            else
            {
                lightSourceData = lightSource.SpectralPowerDistribution.WaveData.ToArray();
                materialData = material.ReflectanceDistribution.WaveData.ToArray();
                observerXData = observer.ResponseSpectra[0].WaveData.ToArray();
                observerYData = observer.ResponseSpectra[1].WaveData.ToArray();
                observerZData = observer.ResponseSpectra[2].WaveData.ToArray();
            }

            // Calculate the L*M product array. This reduces the repeated multiplication operations that would otherwise be
            // required.
            //
            float[] lmProductArray = Utilities.ComputeLMProductArray(lightSourceData, materialData);

            Vector3 tristimulusValues = new Vector3();

            // Calculate X
            //
            summation = Utilities.ComputeSummationTerm(lmProductArray, observerXData);
            tristimulusValues.X = K * summation * (float)stepSize;

            // Calculate Y
            //
            summation = Utilities.ComputeSummationTerm(lmProductArray, observerYData);
            tristimulusValues.Y = K * summation * (float)stepSize;

            // Calculate Z
            //
            summation = Utilities.ComputeSummationTerm(lmProductArray, observerZData);
            tristimulusValues.Z = K * summation * (float)stepSize;

            return tristimulusValues;
        }
예제 #6
0
파일: Utilities.cs 프로젝트: vsuley/Spectro
        /// <summary>
        /// Calculates the Tristimulus normalizing constant using the formula 
        /// K = 100.0 / (total * stepSize) 
        /// Where total is the sum of products of lightsource power and observers Y channel response
        /// </summary>
        /// <param name="lightSource">Light source</param>
        /// <param name="observer">The observer</param>
        /// <returns>The calculated tristimulus constant</returns>
        public static float TristimulusNormalizingConstant(LightSource lightSource, Observer observer)
        {
            int stepSize = lightSource.SpectralPowerDistribution.StepSize;
            int start = lightSource.SpectralPowerDistribution.LowestWavelength;
            int end = lightSource.SpectralPowerDistribution.HighestWavelength;

            int i, index;

            float[] observerYData = observer.ResponseSpectra[1].WaveData.ToArray();
            float[] lightSourceData = lightSource.SpectralPowerDistribution.WaveData.ToArray();

            float total = (float)0.0;
            for (i=start, index=0; i <= end; i += stepSize, index++)
            {
                total += lightSourceData[index] * observerYData[index];
            }

            return (float)100.0 / (total * (float)stepSize);
        }