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; } } }
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); } } } } }
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); }