private List <(Triangle, Vector3, Vector3)> GetIntersectedTriangles(ISceneCreator sceneCreator, List <INode> octrees, Vector3 rayDirection, ref int num) { var priorityQueue = new SimplePriorityQueue <INode, float>(); var triangles = new List <(Triangle, Vector3, Vector3)>(); float t = 0; foreach (var octree in octrees) { if (IsRayIntersectBox(octree.MinBoundary, octree.MaxBoundary, sceneCreator.ParamsProvider.Camera, rayDirection, ref t)) { priorityQueue.Enqueue(octree, t); } Triangle nearestTriangle = null; var nearestTriangleIntersectionPoint = new Vector3(); var minDistance = float.MaxValue; var barycentricIntersectionPoint = new Vector3(); var intersectionPoint = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue); var barycentricIntersectionPointOfNearestTriangle = new Vector3(); var flag = false; while (priorityQueue.Count != 0) { var node = priorityQueue.Dequeue(); var intersectedTriangle = FindIntersectionInBox(node.Faces, rayDirection, sceneCreator.ParamsProvider.Camera, ref num, ref intersectionPoint, ref barycentricIntersectionPoint); var distanceBetweenCameraAndTriangle = Distance(intersectionPoint, sceneCreator.ParamsProvider.Camera); if (distanceBetweenCameraAndTriangle < minDistance) { minDistance = distanceBetweenCameraAndTriangle; nearestTriangle = intersectedTriangle; nearestTriangleIntersectionPoint = intersectionPoint; barycentricIntersectionPointOfNearestTriangle = barycentricIntersectionPoint; flag = true; } if (node.IsLeaf()) { if (flag) { triangles.Add((nearestTriangle, nearestTriangleIntersectionPoint, barycentricIntersectionPointOfNearestTriangle)); break; } } else { foreach (var child in node.ChildNodes .Where(child => IsRayIntersectBox(child.MinBoundary, child.MaxBoundary, sceneCreator.ParamsProvider.Camera, rayDirection, ref t))) { priorityQueue.Enqueue(child, t); } } } } return(triangles); }
public List <List <Pixel> > Trace(ISceneCreator sceneCreator, List <INode> octrees) { var camera = sceneCreator.ParamsProvider.Camera; var screenZ = sceneCreator.ParamsProvider.ScreenZ; var watch = System.Diagnostics.Stopwatch.StartNew(); var num = 0; var image = new List <List <Pixel> >(); for (var i = 0; i < sceneCreator.ParamsProvider.ImageHeight; i++) { image.Add(new List <Pixel>()); var y = sceneCreator.SetXScreenCoordinate(i); for (var j = 0; j < sceneCreator.ParamsProvider.ImageWidth; j++) { var x = sceneCreator.SetYScreenCoordinate(j); var pixelCenterPoint = new Vector3(x, y, screenZ); var rayDirection = Normalize(pixelCenterPoint - camera); // float t = 0; // var priorityQueue = new SimplePriorityQueue<INode, float>(); var triangles = GetIntersectedTriangles(sceneCreator, octrees, rayDirection, ref num); var normal = new Vector3(); var sphereIntersectionPoint = new Vector3(); if (IsSphereIntersect(camera, rayDirection, ref normal, ref sphereIntersectionPoint)) { var lightRay = Normalize(sceneCreator.ParamsProvider.LightPosition - sphereIntersectionPoint); var dotProduct = Dot(lightRay, normal); var facingRatio = Math.Max(0, dotProduct); image[i].Add(new Pixel((byte)(239 * facingRatio), (byte)(154 * facingRatio), (byte)(154 * facingRatio))); } else if (!triangles.Any()) { image[i].Add(new Pixel(232, 234, 246)); } else { //var facingRatio = 0.18f / Math.PI * 30 * 0.5 * Math.Max(0f, dotProduct); var(nearestTriangle, intersectionPoint, barycentricIntersectionPoint) = GetNearestTriangle(triangles, sceneCreator.ParamsProvider.Camera); // trying to draw shadows var shadowRay = Normalize(intersectionPoint - sceneCreator.ParamsProvider.LightPosition); var barrier = GetIntersectedTriangles(sceneCreator, octrees, shadowRay, ref num); if (!barrier.Any()) { var temp = new Vector3(0, 0, 0); if (IsSphereIntersect(intersectionPoint, shadowRay, ref temp, ref temp)) { image[i].Add(new Pixel(0, 0, 0)); } else { normal = nearestTriangle.GetNormal(); // normal = nearestTriangle.GetBarycentricNormal(barycentricIntersectionPoint); var lightRay = Normalize(sceneCreator.ParamsProvider.LightPosition - intersectionPoint); var dotProduct = Dot(lightRay, normal); var facingRatio = Math.Max(0, dotProduct); var albedo = 0.18; image[i].Add(new Pixel((byte)(159 * facingRatio), (byte)(168 * facingRatio), (byte)(218 * facingRatio))); } } else { image[i].Add(new Pixel(0, 0, 0)); } // normal = nearestTriangle.GetNormal(); // // normal = nearestTriangle.GetBarycentricNormal(barycentricIntersectionPoint); // var lightRay = Normalize(sceneCreator.ParamsProvider.LightPosition - intersectionPoint); // var dotProduct = Dot(lightRay, normal); // var facingRatio = Math.Max(0, dotProduct); // var albedo = 0.18; // // image[i].Add(new Pixel((byte) (159 * facingRatio), (byte) (168 * facingRatio), // (byte) (218 * facingRatio))); } } } watch.Stop(); var time = watch.ElapsedMilliseconds / 1000; Console.WriteLine($"Exec time: {time} s"); Console.WriteLine($"Num of intersection tests: {num}"); return(image); }
public Startup(ICommandProcessor commandProcessor, ISceneCreator sceneCreator, IObjectFromFileProvider objectFromFileProvider, ITreeProvider treeProvider, ITracer tracer) => (_commandProcessor, _sceneCreator, _object, _treeProvider, _tracer) = (commandProcessor, sceneCreator,