private ColorPacket256 Shade(Intersections isect, RayPacket256 rays, Scene scene, int depth) { var ds = rays.Dirs; var pos = isect.Distances * ds + rays.Starts; var normals = scene.Normals(isect.ThingIndices, pos); var reflectDirs = ds - (Multiply(VectorPacket256.DotProduct(normals, ds), Vector256.Create(2.0f)) * normals); var colors = GetNaturalColor(isect.ThingIndices, pos, normals, reflectDirs, scene); if (depth >= MaxDepth) { return(colors + new ColorPacket256(.5f, .5f, .5f)); } return(colors + GetReflectionColor(isect.ThingIndices, pos + (Vector256.Create(0.001f) * reflectDirs), normals, reflectDirs, scene, depth)); }
public MeshCutter(int initialArraySize) { PositiveMesh = new TempMesh(initialArraySize); NegativeMesh = new TempMesh(initialArraySize); addedPairs = new List <Vector3>(initialArraySize); ogVertices = new List <Vector3>(initialArraySize); ogTriangles = new List <int>(initialArraySize * 3); ogNormals = new List <Vector3>(initialArraySize); intersectPair = new Vector3[2]; tempTriangle = new Vector3[3]; intersect = new Intersections(); }
public void TestHitAllNegativeDistance() { var sphere = new Sphere(); var i1 = new Intersection(-1, sphere); var i2 = new Intersection(-2, sphere); var intersections = new Intersections { i2, i1 }; Assert.IsNull(intersections.Hit()?.Shape); }
public void RefractedColorWithAnOpaqueSurfaceTest() { var w = GetDefaultWorld(); var shape = w.Shapes[0]; var r = Helper.Ray(Helper.CreatePoint(0, 0, -5), Helper.CreateVector(0, 0, 1)); var xs = new Intersections { new Intersection(4, shape), new Intersection(6, shape) }; var comps = xs[0].Compute(r, xs); var c = w.RefractedColor(comps, 5); Check.That(c).IsEqualTo(Color.Black); }
public void TestHitNegativeDistance() { var sphere = new Sphere(); var i1 = new Intersection(-1, sphere); var i2 = new Intersection(1, sphere); var intersections = new Intersections { i2, i1 }; Assert.AreEqual(i2, intersections.Hit()); }
/// <summary> /// Slice a mesh by the slice plane. /// We assume the plane is already in the mesh's local coordinate frame /// Returns posMesh and negMesh, which are the resuling meshes on both sides of the plane /// (posMesh on the same side as the plane's normal, negMesh on the opposite side) /// </summary> public bool SliceMesh(Mesh mesh, ref Plane slice) { // Let's always fill the vertices array so that we can access it even if the mesh didn't intersect mesh.GetVertices(ogVertices); // 1. Verify if the bounds intersect first if (!Intersections.BoundPlaneIntersect(mesh, ref slice)) return false; mesh.GetTriangles(ogTriangles, 0); mesh.GetNormals(ogNormals); mesh.GetUVs(0, ogUvs); PositiveMesh.Clear(); NegativeMesh.Clear(); addedPairs.Clear(); // 2. Separate old vertices in new meshes for(int i = 0; i < ogVertices.Count; ++i) { if (slice.GetDistanceToPoint(ogVertices[i]) >= 0) PositiveMesh.AddVertex(ogVertices, ogNormals, ogUvs, i); else NegativeMesh.AddVertex(ogVertices, ogNormals, ogUvs, i); } // 2.5 : If one of the mesh has no vertices, then it doesn't intersect if (NegativeMesh.vertices.Count == 0 || PositiveMesh.vertices.Count == 0) return false; // 3. Separate triangles and cut those that intersect the plane for (int i = 0; i < ogTriangles.Count; i += 3) { if (intersect.TrianglePlaneIntersect(ogVertices, ogUvs, ogTriangles, i, ref slice, PositiveMesh, NegativeMesh, intersectPair)) addedPairs.AddRange(intersectPair); } if (addedPairs.Count > 0) { //FillBoundaryGeneral(addedPairs); FillBoundaryFace(addedPairs); return true; } else { throw new UnityException("Error: if added pairs is empty, we should have returned false earlier"); } }
public void RefractedColorIsBlackForTotalInternalRefraction() { var w = World.Default(); var s = w.Objects[0]; s.Material.Transparency = 1.0f; s.Material.RefractiveIndex = 1.5f; var r = new Ray(new Point(0, 0, MathF.Sqrt(2f) / 2f), new Vector(0, 1, 0)); var xs = Intersections.Create( new Intersection(-MathF.Sqrt(2f) / 2f, s), new Intersection(MathF.Sqrt(2f) / 2f, s)); // Inside sphere so look at second intersection. var comps = new IntersectionInfo(xs[1], r, xs); PhongShading.RefractedColor(w, comps, 5).Should().Be(Colors.Black); }
public void TestRefractColor() { var world = WorldBuilder.DefaultWorld(); var ray = new Ray(Tuple.Point(0, 0, -5), Tuple.Vector(0, 0, 1)); var xs = new Intersections { new Intersection(4, world.Shapes[0]), new Intersection(6, world.Shapes[0]) }; var comps = Computation.Prepare(xs[0], ray, xs); var col = world.RefractColor(comps, 5); Assert.AreEqual(new Color(0, 0, 0), col); }
public void RefractedColorTotalInternalReflection() { var world = new DefaultWorld(); var sphere = world.Shapes[0]; sphere.Material.Transparency = 1; sphere.Material.RefractiveIndex = 1.5f; var ray = new Ray(new Point(0, 0, MathF.Sqrt(2) / 2), Vector.UnitY); var intersections = new Intersections(new Intersection(-MathF.Sqrt(2) / 2, sphere), new Intersection(MathF.Sqrt(2) / 2, sphere)); var info = new IntersectionInfo(intersections, intersections[1], ray); var actual = world.RefractedColor(info, 5); Assert.Equal(Color.Black, actual); }
public void RefractedColorMaxRecursiveDepth() { var world = new DefaultWorld(); var sphere = world.Shapes[0]; sphere.Material.Transparency = 1; sphere.Material.RefractiveIndex = 1.5f; var ray = new Ray(new Point(0, 0, -5), Vector.UnitZ); var intersections = new Intersections(new Intersection(4, sphere), new Intersection(6, sphere)); var info = new IntersectionInfo(intersections, intersections[0], ray); var actual = world.RefractedColor(info, 0); Assert.Equal(Color.Black, actual); }
public void TestWorldRefractedColorTotalInternalReflection() { var w = World.Default; var shape = w.Objects[0]; shape.Material.Transparency = 1.0; shape.Material.RefractiveIndex = 1.5; var r = new Ray(new Point(0, 0, MathHelper.SQRT2 / 2.0), Vector.VectorY); var i1 = new Intersection(-MathHelper.SQRT2 / 2.0, shape); var i2 = new Intersection(MathHelper.SQRT2 / 2.0, shape); var xs = new Intersections(i1, i2); var comps = xs[1].PrepareComputations(r, xs); var c = w.RefractedColor(comps, 5); Assert.AreEqual(c, Color.Black); }
public void TestWorldRefractedColorMaxRecursion() { var w = World.Default; var shape = w.Objects[0]; shape.Material.Transparency = 1.0; shape.Material.RefractiveIndex = 1.5; var r = new Ray(new Point(0, 0, -5), Vector.VectorZ); var i1 = new Intersection(4, shape); var i2 = new Intersection(6, shape); var xs = new Intersections(i1, i2); var comps = xs[0].PrepareComputations(r, xs); var c = w.RefractedColor(comps, 0); Assert.AreEqual(c, Color.Black); }
public void GivenIntersectionHit_WhenIntersectionsHaveMixedTimeValue_ThenReturnLowestPositiveIntersection() { // Arrange var sphere = new Sphere(); var i1 = new Intersection(5, sphere); var i2 = new Intersection(7, sphere); var i3 = new Intersection(-3, sphere); var i4 = new Intersection(2, sphere); var intersections = new Intersections(i1, i2, i3, i4); // Act var hit = intersections.Hit(); // Assert Assert.Equal(i4, hit); }
public void DeterminesN1AndN2() { var a = Spheres.GlassSphere(); a.SetTransform(Transform.Scale(2f)); a.Material.RefractiveIndex = 1.5f; var b = Spheres.GlassSphere(); b.SetTransform(Transform.TranslateZ(-0.25f)); b.Material.RefractiveIndex = 2.0f; var c = Spheres.GlassSphere(); c.SetTransform(Transform.TranslateZ(0.25f)); c.Material.RefractiveIndex = 2.5f; var r = new Ray(new Point(0, 0, -4), new Vector(0, 0, 1)); var xs = Intersections.Create( new Intersection(2.00f, a), new Intersection(2.75f, b), new Intersection(3.25f, c), new Intersection(4.75f, b), new Intersection(5.25f, c), new Intersection(6.00f, a) ); var comps = new List <IntersectionInfo>(); for (var i = 0; i < xs.Count; i++) { comps.Add(new IntersectionInfo(xs[i], r, xs)); } comps[0].N1.Should().Be(1.0f); comps[0].N2.Should().Be(1.5f); comps[1].N1.Should().Be(1.5f); comps[1].N2.Should().Be(2.0f); comps[2].N1.Should().Be(2.0f); comps[2].N2.Should().Be(2.5f); comps[3].N1.Should().Be(2.5f); comps[3].N2.Should().Be(2.5f); comps[4].N1.Should().Be(2.5f); comps[4].N2.Should().Be(1.5f); comps[5].N1.Should().Be(1.5f); comps[5].N2.Should().Be(1.0f); }
public static List <Triangle> TriangulatePoints(List <Vertex> points) { //Generate the convex hull - will also remove the points from points list which are not on the hull List <Vertex> pointsOnConvexHull = HullAlgorithms.JarvisMarch(points); //Triangulate the convex hull List <Triangle> triangles = TriangulateHullAlgorithms.TriangulateConvexPolygon(pointsOnConvexHull); //Add the remaining points and split the triangles for (int i = 0; i < points.Count; i++) { Vertex currentPoint = points[i]; //2d space Vector2 p = new Vector2(currentPoint.position.x, currentPoint.position.z); //Which triangle is this point in? for (int j = 0; j < triangles.Count; j++) { Triangle t = triangles[j]; Vector2 p1 = new Vector2(t.v1.position.x, t.v1.position.z); Vector2 p2 = new Vector2(t.v2.position.x, t.v2.position.z); Vector2 p3 = new Vector2(t.v3.position.x, t.v3.position.z); if (Intersections.IsPointInTriangle(p1, p2, p3, p)) { //Create 3 new triangles Triangle t1 = new Triangle(t.v1, t.v2, currentPoint); Triangle t2 = new Triangle(t.v2, t.v3, currentPoint); Triangle t3 = new Triangle(t.v3, t.v1, currentPoint); //Remove the old triangle triangles.Remove(t); //Add the new triangles triangles.Add(t1); triangles.Add(t2); triangles.Add(t3); break; } } } return(triangles); }
/// <summary> /// General Hittesting on the infinite plane defined by the element transforms /// </summary> /// <param name="touch">The touch to be tested</param> /// <param name="prevpos">Calculate Intersection point for previous position</param> /// <returns>If the touch hits then an Intersection point otherwise null</returns> public IntersectionPoint PreparePlanarShapeHitTest(Touch touch, bool prevpos) { // when first hit consider the display transformation then // for the rest of the interaction consider the interaction transform touch.GetPreviousWorldPosition(Context, out var popos, out var pdir); var hit = Intersections.PlaneRay( prevpos ? popos : touch.WorldPosition, prevpos ? pdir : touch.ViewDir, DisplayMatrix, out var ispoint, out var planarpoint); return(hit ? new IntersectionPoint(ispoint, planarpoint, this, touch) { SurfaceSpace = planarpoint * 2 } : null); }
public void TestIntersectionList() { var sphere = new Sphere(); var i1 = new Intersection(1, sphere); var i2 = new Intersection(2, sphere); var intersections = new Intersections { i1, i2 }; Assert.AreEqual(intersections.Count, 2); Assert.AreEqual(intersections[0].Distance, 1, Epsilon); Assert.AreEqual(intersections[1].Distance, 2, Epsilon); }
public Vector3?Raycast(Ray ray) { var corners = GetCorners(); for (int i = 0; i < corners.Count; i++) { var v1 = corners[i]; var v2 = corners[(i + 1) % corners.Count]; if (Intersections.LineTriangleIntersection(ray, v1, v2, CenterPoint, out var intersectionPoint) == 1) { return(intersectionPoint); } } return(null); }
public override void IntersectLocal(ref Tuple origin, ref Tuple direction, Intersections intersections) { Intersections leftXs = new Intersections(); Left.Intersect(ref origin, ref direction, leftXs); var rightXs = new Intersections(); Right.Intersect(ref origin, ref direction, rightXs); Intersections result; if (leftXs.Any() || rightXs.Any()) { var xs = new Intersections(leftXs.Concat(rightXs)); result = Filter(xs); intersections.AddRange(result); } }
public override Intersections IntersectLocal(Ray ray) { var xs = new Intersections(); var a = ray.Direction.X * ray.Direction.X - ray.Direction.Y * ray.Direction.Y + ray.Direction.Z * ray.Direction.Z; var b = 2 * ray.Origin.X * ray.Direction.X - 2 * ray.Origin.Y * ray.Direction.Y + 2 * ray.Origin.Z * ray.Direction.Z; var c = ray.Origin.X * ray.Origin.X - ray.Origin.Y * ray.Origin.Y + ray.Origin.Z * ray.Origin.Z; if (Math.Abs(a) <= double.Epsilon && Math.Abs(b) > double.Epsilon) { var t = -c / (2 * b); xs.Add(new Intersection(t, this)); } if (Math.Abs(a) > double.Epsilon) { var disc = b * b - 4 * a * c; if (disc >= 0) { var t0 = (-b - Math.Sqrt(disc)) / (2 * a); var t1 = (-b + Math.Sqrt(disc)) / (2 * a); if (t0 > t1) { var tmp = t0; t0 = t1; t1 = tmp; } var y0 = ray.Origin.Y + t0 * ray.Direction.Y; if (Minimum < y0 && y0 < Maximum) { xs.Add(new Intersection(t0, this)); } var y1 = ray.Origin.Y + t1 * ray.Direction.Y; if (Minimum < y1 && y1 < Maximum) { xs.Add(new Intersection(t1, this)); } } } IntersectCaps(ray, xs); xs.Sort(); return(xs); }
public void FilteringAListOfIntersections(string operation, int x0, int x1) { var s1 = new Sphere(); var s2 = new Cube(); var c = new CSG(Operation.OfKind(operation), s1, s1); var xs = new Intersections( new Intersection(1, s1), new Intersection(2, s2), new Intersection(3, s1), new Intersection(4, s2)); var result = c.FilterIntersections(xs); Assert.AreEqual(2, result.Count); Assert.AreEqual(xs[x0], result[0]); Assert.AreEqual(xs[x1], result[1]); }
public List <Road> PathToRoadList() { var listRoads = new List <Road>(); foreach (var road in City.Instance.Roads) { if (Intersections.FindAll(i => i.Location == road.Start) .FindAll(i => i.Location == road.End).Count > 0) { listRoads.Add(road); } } listRoads.Add(GPSSystem.NearestRoad(Start)); listRoads.Add(GPSSystem.NearestRoad(End)); return(listRoads); }
public void TestN1N2AtIntersections(int index, double expectedN1, double expectedN2) { var sphereA = new Sphere { Transform = Matrix4.Scaling(2, 2, 2), Material = new Material { RefractiveIndex = 1.5 } }; var sphereB = new Sphere { Transform = Matrix4.Translation(0, 0, -0.25), Material = new Material { RefractiveIndex = 2.0 } }; var sphereC = new Sphere { Transform = Matrix4.Translation(0, 0, 0.25), Material = new Material { RefractiveIndex = 2.5 } }; var ray = new Ray(Tuple.Point(0, 0, -4), Tuple.Vector(0, 0, 1)); var xs = new Intersections { new Intersection(2, sphereA), new Intersection(2.75, sphereB), new Intersection(3.25, sphereC), new Intersection(4.75, sphereB), new Intersection(5.25, sphereC), new Intersection(6, sphereA), }; var comp = Computation.Prepare(xs[index], ray, xs); Assert.AreEqual(expectedN1, comp.N1, Epsilon); Assert.AreEqual(expectedN2, comp.N2, Epsilon); }
public override Intersections IntersectLocal(Ray ray) { var xs = new Intersections(); var a = ray.Direction.X * ray.Direction.X + ray.Direction.Z * ray.Direction.Z; // ray is not parallel to the y axis if (a > double.Epsilon) { var b = 2 * ray.Origin.X * ray.Direction.X + 2 * ray.Origin.Z * ray.Direction.Z; var c = ray.Origin.X * ray.Origin.X + ray.Origin.Z * ray.Origin.Z - 1; var disc = b * b - 4 * a * c; // ray does not intersect the cylinder if (disc < 0) { return(xs); } var t0 = (-b - Math.Sqrt(disc)) / (2 * a); var t1 = (-b + Math.Sqrt(disc)) / (2 * a); if (t0 > t1) { var t = t0; t0 = t1; t1 = t; } var y0 = ray.Origin.Y + t0 * ray.Direction.Y; if (Minimum < y0 && y0 < Maximum) { xs.Add(new Intersection(t0, this)); } var y1 = ray.Origin.Y + t1 * ray.Direction.Y; if (Minimum < y1 && y1 < Maximum) { xs.Add(new Intersection(t1, this)); } } IntersectCaps(ray, xs); xs.Sort(); return(xs); }
//Are two AABB intersecting? private void AABB_AABB() { MyVector2 t1_p1 = t1_p1_trans.position.ToMyVector2(); MyVector2 t1_p2 = t1_p2_trans.position.ToMyVector2(); MyVector2 t1_p3 = t1_p3_trans.position.ToMyVector2(); MyVector2 t2_p1 = t2_p1_trans.position.ToMyVector2(); MyVector2 t2_p2 = t2_p2_trans.position.ToMyVector2(); MyVector2 t2_p3 = t2_p3_trans.position.ToMyVector2(); Triangle2 t1 = new Triangle2(t1_p1, t1_p2, t1_p3); Triangle2 t2 = new Triangle2(t2_p1, t2_p2, t2_p3); bool isIntersecting = Intersections.AABB_AABB_2D( t1.MinX(), t1.MaxX(), t1.MinY(), t1.MaxY(), t2.MinX(), t2.MaxX(), t2.MinY(), t2.MaxY()); Debug.Log("AABB intersecting: " + isIntersecting); //Display the rectangles and the vertices we use to make the rectangles Vector3 r1_size = new Vector3(t1.MaxX() - t1.MinX(), 0.01f, t1.MaxY() - t1.MinY()); Vector3 r2_size = new Vector3(t2.MaxX() - t2.MinX(), 0.01f, t2.MaxY() - t2.MinY()); Vector3 r1_center = new Vector3(t1.MinX() + (r1_size.x * 0.5f), 0f, t1.MinY() + (r1_size.z * 0.5f)); Vector3 r2_center = new Vector3(t2.MinX() + (r2_size.x * 0.5f), 0f, t2.MinY() + (r2_size.z * 0.5f)); Gizmos.color = Color.white; Gizmos.DrawCube(r1_center, r1_size); float r = 0.1f; //Gizmos.DrawWireSphere(t1_p1.ToVector3(), r); //Gizmos.DrawWireSphere(t1_p2.ToVector3(), r); //Gizmos.DrawWireSphere(t1_p3.ToVector3(), r); Gizmos.color = isIntersecting ? Color.red : Color.white; Gizmos.DrawCube(r2_center, r2_size); //Gizmos.DrawWireSphere(t2_p1.ToVector3(), r); //Gizmos.DrawWireSphere(t2_p2.ToVector3(), r); //Gizmos.DrawWireSphere(t2_p3.ToVector3(), r); }
public void RefractedColorAtTheMaximumRecursiveDepthTest() { var w = GetDefaultWorld(); var shape = w.Shapes[0]; shape.Material.Transparency = 1.0; shape.Material.RefractiveIndex = 1.5; var r = Helper.Ray(Helper.CreatePoint(0, 0, -5), Helper.CreateVector(0, 0, 1)); var xs = new Intersections { new Intersection(4, shape), new Intersection(6, shape) }; var comps = xs[0].Compute(r, xs); var c = w.RefractedColor(comps, 0); Check.That(c).IsEqualTo(Color.Black); }
public void RayHitsCsgObjectTest() { var sphere1 = new Sphere(); var sphere2 = new Sphere(); sphere2.Translate(0, 0, 0.5); var csg = new CsgUnion(sphere1, sphere2); var r = Helper.Ray(0, 0, -5, 0, 0, 1); var xs = new Intersections(); csg.IntersectLocal(ref r.Origin, ref r.Direction, xs); Check.That(xs).CountIs(2); Check.That(xs[0].T).IsEqualTo(4); Check.That(xs[0].Object).IsEqualTo(sphere1); Check.That(xs[1].T).IsEqualTo(6.5); Check.That(xs[1].Object).IsEqualTo(sphere2); }
public override Intersections IntersectLocal(Ray ray) { Intersections leftXs = Left.Intersect(ray); var rightXs = Right.Intersect(ray); Intersections result; if (leftXs.Any() || rightXs.Any()) { var xs = new Intersections(leftXs.Concat(rightXs)); result = Filter(xs); } else { result = new Intersections(); } return(result); }
private void CleanInternal(IToolContext context) { Intersections?.ForEach(i => i.Clear(context)); Filters?.ForEach(f => f.Clear(context)); CurrentState = State.StartPoint; if (_line != null) { context.WorkingContainer.Shapes.Remove(_line); context.Renderer.SelectedShapes.Remove(_line.StartPoint); context.Renderer.SelectedShapes.Remove(_line.Point); _line = null; } context.Release?.Invoke(); context.Invalidate?.Invoke(); }
/// <summary> /// Поиск пересечений с лучом /// </summary> /// <param name="rayPos">Начало луча</param> /// <param name="rayDir">Направление луча</param> /// <param name="rayLength">Длина луча</param> /// <param name="pos">Место пересечения</param> /// <param name="normal">Нормаль пересечения</param> /// <returns>True если есть пересечение</returns> internal override bool RayHit(Vec3 rayPos, Vec3 rayDir, float rayLength, out Vec3 pos, out Vec3 normal) { // Если есть с чем пересекаться if (Indices != null && Vertices != null) { if (Indices.Length > 0) { float range = float.MaxValue; bool hit = false; Vec3 hpos = Vec3.Zero, hnorm = Vec3.Zero; for (int i = 0; i < Indices.Length; i += 3) { Vec3 v0 = Vertices[Indices[i + 0]]; Vec3 v1 = Vertices[Indices[i + 1]]; Vec3 v2 = Vertices[Indices[i + 2]]; Vec3 hp, hn; if (Intersections.RayTriangle(rayPos, rayDir, v0, v1, v2, false, out hp, out hn)) { float d = (hp - rayPos).LengthSquared; if (d < range) { range = d; hpos = hp; hnorm = hn; hit = true; } } } range = (float)Math.Sqrt(range); if (hit && range <= rayLength) { pos = hpos; normal = hnorm; return(true); } } } // Пересечения нет pos = Vec3.Zero; normal = Vec3.UnitZ; return(false); }