コード例 #1
0
        public void Calculate(RenderPointsStructure renderPointsStructure)
        {
            // Непосредственно калькулятор, который будет просчитывать точки
            var calculator = new DoubleLocalEstimationCalculator(this.RayTracer.Scene, this.RayTracer, NRays, WMin, this.Log);

            // Формируем ускоряющую структуру на основе сетки
            var giRenderPointsStructure = this.GenerateCalculatedStructure(renderPointsStructure);

            foreach (var item in giRenderPointsStructure.RenderPointsFace)
            {
                RayDebugStaticCollection.Add(new Ray(item.Vertexes[0].Position, item.Vertexes[1].Position), Color.WhiteSmoke);
                RayDebugStaticCollection.Add(new Ray(item.Vertexes[1].Position, item.Vertexes[2].Position), Color.WhiteSmoke);
                RayDebugStaticCollection.Add(new Ray(item.Vertexes[2].Position, item.Vertexes[0].Position), Color.WhiteSmoke);
            }

            //const float nPackets = 3;
            //const float wMin = 0.01f;

            // главный цикл по пакетам
            var calculationPoints = giRenderPointsStructure.RenderPointsVertexes.Select(x => (CalculationPointDLE)x).ToList();

            for (var packet = 0; packet < NPackets; packet++)
            {
                giRenderPointsStructure.RenderPointsVertexes.ForEach(x => x.Illuminance = new Spectrum());
                calculator.Calculate(calculationPoints);

                //calculator.Calculate(giRenderPointsStructure.RenderPointsVertexes);

                giRenderPointsStructure.RenderPointsVertexes.ForEach(x => x.IlluminancePacket.Add(x.Illuminance));
            }

            this.IlluminanceBugsCorrection(giRenderPointsStructure);

            foreach (var giface in giRenderPointsStructure.RenderPointsFace)
            {
                var e = new Spectrum[3];
                e[0] = giface.Vertexes[0].Illuminance;
                e[1] = giface.Vertexes[1].Illuminance;
                e[2] = giface.Vertexes[2].Illuminance;

                foreach (var point in giface.RenderPoints)
                {
                    var bc = giface.GetBarycentricCoordinates(point);
                    //var bc = giface.GetBarycentricCoordinates_Old( point );

                    var x = e[0] * ((float)bc[1]) + e[1] * ((float)bc[2]) + e[2] * ((float)bc[0]);

                    if (float.IsNaN(x.R))
                    {
                        throw new Exception();
                        //x = new Spectrum();
                    }

                    //point.IlluminanceIndirect = x;
                    point.IlluminanceIndirect = x;
                    //point.IlluminanceDirect = x;
                }
            }
        }
コード例 #2
0
ファイル: FormMain.cs プロジェクト: Zheltov/Illuminarium
        private void btnTestTraceCameraRays_Click(object sender, EventArgs e)
        {
            // новый список отладочных лучей для контрола визуализации сцены
            RayDebugStaticCollection.Init();

            // создаем объект трассировщика, т.к. он IDisposable, то используем конструкцию using чтобы гарантированно высвободить ресурсы
            // см. public void Dispose() в RayTracerEmbree
            using (IRayTracer rayTracer = new RayTracerEmbree(this.Scene))
            {
                // циклы по экранным координатам по x и y
                for (int x = 0; x < this.sceneViewer.Width; x = x + 50)
                {
                    for (int y = 0; y < this.sceneViewer.Height; y = y + 50)
                    {
                        // получаем луч из камеры для соответствующих экранных координат
                        Ray ray = this.sceneViewer.Camera.GetTracingRay(x, y, this.sceneViewer.Width, this.sceneViewer.Height);

                        RayDebugStaticCollection.Add(new Ray(ray.From, ray.Direction), Color.Red);

                        // ищем пересечение со сценой
                        var intersection = rayTracer.Trace(ray.From, ray.Direction);

                        // если пересчение со сценой есть (объект intersection не пустой), то добавляем луч в список отладочных лучей
                        if (intersection != null)
                        {
                            RayDebugStaticCollection.Add(new Ray(ray.From, intersection.Point), Color.Green);

                            var fall   = ray.Direction;
                            var normal = intersection.Face.Normal;


                            var reflected = fall.Reflect(normal);

                            RayDebugStaticCollection.Add(new Ray(intersection.Point, normal), Color.Blue);
                            RayDebugStaticCollection.Add(new Ray(intersection.Point, reflected), Color.Red);
                        }
                    }
                }
            }
        }
コード例 #3
0
        public float GetFormFactorSmirnov(Point3D point, Vector normal)
        {
            // вектора на углы источника
            // порядок соединения берем с учетом формирования вершин при создании геометрии источника
            Vector[] vectors = new Vector[4]
            {
                new Vector(point, this.Vertices[0], true),
                new Vector(point, this.Vertices[1], true),
                new Vector(point, this.Vertices[3], true),
                new Vector(point, this.Vertices[2], true)
            };

            // спроецированне вектора
            Vector[] vectorsProjected = new Vector[4]
            {
                normal.Projected(vectors[0]),
                normal.Projected(vectors[1]),
                normal.Projected(vectors[2]),
                normal.Projected(vectors[3])
            };

            Vector[] vectorsProjectedNormalized = new Vector[4]
            {
                Vector.Normalize(vectorsProjected[0]),
                Vector.Normalize(vectorsProjected[1]),
                Vector.Normalize(vectorsProjected[2]),
                Vector.Normalize(vectorsProjected[3])
            };

            // углы между нормалью и векторами на источник
            double[] cosx = new double[4]
            {
                Vector.Dot(normal, vectors[0]),
                Vector.Dot(normal, vectors[1]),
                Vector.Dot(normal, vectors[2]),
                Vector.Dot(normal, vectors[3])
            };

            double[] sinx = new double[4]
            {
                Math.Sqrt(1 - cosx[0] * cosx[0]),
                Math.Sqrt(1 - cosx[1] * cosx[1]),
                Math.Sqrt(1 - cosx[2] * cosx[2]),
                Math.Sqrt(1 - cosx[3] * cosx[3])
            };

            // cos(a - b) = cosa * cosb + sina * sinb;
            // получаем "плоскостные по нормали" углы между векторами на источник
            double[] cos = new double[4]
            {
                cosx[0] * cosx[1] + sinx[0] * sinx[1],
                cosx[1] * cosx[2] + sinx[1] * sinx[2],
                cosx[2] * cosx[3] + sinx[2] * sinx[3],
                cosx[3] * cosx[0] + sinx[3] * sinx[0]
            };


            // нормали к 4 секторам
            Vector[] normals = new Vector[4]
            {
                Vector.Cross(vectors[0], vectors[1], true),
                Vector.Cross(vectors[1], vectors[2], true),
                Vector.Cross(vectors[2], vectors[3], true),
                Vector.Cross(vectors[3], vectors[0], true),
            };


            // определяем знаки для площадей секторов
            float[] signs = new float[4]
            {
                Vector.Dot(normal, normals[0]) > 0 ? 1 : -1,
                Vector.Dot(normal, normals[1]) > 0 ? 1 : -1,
                Vector.Dot(normal, normals[2]) > 0 ? 1 : -1,
                Vector.Dot(normal, normals[3]) > 0 ? 1 : -1
            };

            double[] dot = new double[4]
            {
                Math.Abs(Vector.Dot(vectorsProjectedNormalized[0], vectorsProjectedNormalized[1])),
                Math.Abs(Vector.Dot(vectorsProjectedNormalized[1], vectorsProjectedNormalized[2])),
                Math.Abs(Vector.Dot(vectorsProjectedNormalized[2], vectorsProjectedNormalized[3])),
                Math.Abs(Vector.Dot(vectorsProjectedNormalized[3], vectorsProjectedNormalized[0]))
            };


            // аркосинусы углов между направляющими секторов
            double[] acos = new double[4]
            {
                Math.Acos(Math.Abs(dot[0] > 1 ? 1 : dot[0])),
                Math.Acos(Math.Abs(dot[1] > 1 ? 1 : dot[1])),
                Math.Acos(Math.Abs(dot[2] > 1 ? 1 : dot[2])),
                Math.Acos(Math.Abs(dot[3] > 1 ? 1 : dot[3]))
            };

            //var f = acos[0] + acos[1] + acos[2] + acos[3];

            double[] lenght2 = new double[4]
            {
                vectorsProjected[0].Length2 > vectorsProjected[1].Length2 ? vectorsProjected[0].Length2 : vectorsProjected[1].Length2,
                vectorsProjected[1].Length2 > vectorsProjected[2].Length2 ? vectorsProjected[1].Length2 : vectorsProjected[2].Length2,
                vectorsProjected[2].Length2 > vectorsProjected[3].Length2 ? vectorsProjected[2].Length2 : vectorsProjected[3].Length2,
                vectorsProjected[3].Length2 > vectorsProjected[0].Length2 ? vectorsProjected[3].Length2 : vectorsProjected[0].Length2,
            };

            //double[] lenght2 = new double[4]
            //{
            //    ( vectorsProjected[0].Length2 + vectorsProjected[1].Length2 ) / 2,
            //    ( vectorsProjected[1].Length2 + vectorsProjected[2].Length2 ) / 2,
            //    ( vectorsProjected[2].Length2 + vectorsProjected[3].Length2 ) / 2,
            //    ( vectorsProjected[3].Length2 + vectorsProjected[0].Length2 ) / 2,
            //};


            // площади секторов
            double[] areas = new double[4]
            {
                signs[0] * (acos[0] / 2) * lenght2[0] * cos[0],
                signs[1] * (acos[1] / 2) * lenght2[1] * cos[1],
                signs[2] * (acos[2] / 2) * lenght2[2] * cos[2],
                signs[3] * (acos[3] / 2) * lenght2[3] * cos[3]
            };



            // через площади треугольников
            double[] edges = new double[4]
            {
                (vectorsProjected[0] - vectorsProjected[1]).Length,
                (vectorsProjected[1] - vectorsProjected[2]).Length,
                (vectorsProjected[2] - vectorsProjected[3]).Length,
                (vectorsProjected[3] - vectorsProjected[0]).Length
            };

            double[] halfp = new double[4]
            {
                (vectorsProjected[0].Length + vectorsProjected[1].Length + edges[0]) / 2,
                (vectorsProjected[1].Length + vectorsProjected[2].Length + edges[1]) / 2,
                (vectorsProjected[2].Length + vectorsProjected[3].Length + edges[2]) / 2,
                (vectorsProjected[3].Length + vectorsProjected[0].Length + edges[3]) / 2
            };

            double[] areas2 = new double[4]
            {
                signs[0] * Math.Sqrt(halfp[0] * (halfp[0] - vectorsProjected[0].Length) * (halfp[0] - vectorsProjected[1].Length) * (halfp[0] - edges[0])),
                signs[1] * Math.Sqrt(halfp[1] * (halfp[1] - vectorsProjected[1].Length) * (halfp[1] - vectorsProjected[2].Length) * (halfp[1] - edges[1])),
                signs[2] * Math.Sqrt(halfp[2] * (halfp[2] - vectorsProjected[2].Length) * (halfp[2] - vectorsProjected[3].Length) * (halfp[2] - edges[2])),
                signs[3] * Math.Sqrt(halfp[3] * (halfp[3] - vectorsProjected[3].Length) * (halfp[3] - vectorsProjected[0].Length) * (halfp[3] - edges[3])),
            };

            for (int i = 0; i < 4; i++)
            {
                if (double.IsNaN(areas2[i]))
                {
                    areas2[i] = 0;
                }
            }
            var result = Math.Abs(areas[0] + areas[1] + areas[2] + areas[3]);

            RayDebugStaticCollection.Add(new Ray(point, vectors[0]), Color.Red);
            RayDebugStaticCollection.Add(new Ray(point, vectors[1]), Color.Green);
            RayDebugStaticCollection.Add(new Ray(point, vectors[2]), Color.Blue);
            RayDebugStaticCollection.Add(new Ray(point, vectors[3]), Color.Yellow);

            //RayDebugStaticCollection.Add( new Ray( point, normalsN[2] ), Color.Blue );
            //RayDebugStaticCollection.Add( new Ray( point, normalsN[3] ), Color.Yellow );

            //RayDebugStaticCollection.Add( new Ray( point, normalsNProjected[0] ), Color.Cyan );
            //RayDebugStaticCollection.Add( new Ray( point, normalsNProjected[1] ), Color.Cyan );
            //RayDebugStaticCollection.Add( new Ray( point, normalsNProjected[2] ), Color.Cyan );
            //RayDebugStaticCollection.Add( new Ray( point, normalsNProjected[3] ), Color.Cyan );

            //RayDebugStaticCollection.Add( new Ray( point, vectorsProjected[0] ), Color.Red );
            //RayDebugStaticCollection.Add( new Ray( point, vectorsProjected[1] ), Color.Green );
            //RayDebugStaticCollection.Add( new Ray( point, vectorsProjected[2] ), Color.Blue );
            //RayDebugStaticCollection.Add( new Ray( point, vectorsProjected[3] ), Color.Yellow );

            //RayDebugStaticCollection.Add( new Ray( point, normals[0] ), signs[0] > 0 ? Color.Red : Color.Black );
            //RayDebugStaticCollection.Add( new Ray( point, normals[1] ), signs[1] > 0 ? Color.Green : Color.Black );
            //RayDebugStaticCollection.Add( new Ray( point, normals[2] ), signs[2] > 0 ? Color.Blue : Color.Black );
            //RayDebugStaticCollection.Add( new Ray( point, normals[3] ), signs[3] > 0 ? Color.Yellow : Color.Black );

            //return 0;


            // соотносим площадь к площади всего круга
            result = result / Math.PI;

            if (double.IsNaN(result))
            {
                result = 1;
            }

            //if ( result == float.NaN )
            //    result = 0;

            return((float)result);
        }