public void intersectPrimitive(Ray r, int primID, IntersectionState state) { // intersect in local space float qa = r.dx * r.dx + r.dy * r.dy + r.dz * r.dz; intersectFlake(r, state, level, qa, 1 / qa, 0, 0, 0, axis.x, axis.y, axis.z, baseRadius); }
public void intersectPrimitive(Ray r, int primID, IntersectionState state) { if (r.getMax() == float.PositiveInfinity) { state.setIntersection(0, 0, 0); } }
private void computeSubPixel(ImageSample sample, IntersectionState istate) { float x = sample.rx; float y = sample.ry; double q0 = QMC.halton(1, sample.i); double q1 = QMC.halton(2, sample.i); double q2 = QMC.halton(3, sample.i); if (superSampling > 1) { // multiple sampling sample.add(scene.getRadiance(istate, x, y, q1, q2, q0, sample.i)); for (int i = 1; i < superSampling; i++) { double time = QMC.mod1(q0 + i * invSuperSampling); double lensU = QMC.mod1(q1 + QMC.halton(0, i)); double lensV = QMC.mod1(q2 + QMC.halton(1, i)); sample.add(scene.getRadiance(istate, x, y, lensU, lensV, time, sample.i + i)); } sample.scale((float)invSuperSampling); } else { // single sample sample.set(scene.getRadiance(istate, x, y, q1, q2, q0, sample.i)); } }
public void intersectPrimitive(Ray r, int primID, IntersectionState state) { int i3 = primID * 3; float ocx = r.ox - particles[i3 + 0]; float ocy = r.oy - particles[i3 + 1]; float ocz = r.oz - particles[i3 + 2]; float qa = r.dx * r.dx + r.dy * r.dy + r.dz * r.dz; float qb = 2 * ((r.dx * ocx) + (r.dy * ocy) + (r.dz * ocz)); float qc = ((ocx * ocx) + (ocy * ocy) + (ocz * ocz)) - r2; double[] t = Solvers.solveQuadric(qa, qb, qc); if (t != null) { // early rejection if (t[0] >= r.getMax() || t[1] <= r.getMin()) { return; } if (t[0] > r.getMin()) { r.setMax((float)t[0]); } else { r.setMax((float)t[1]); } state.setIntersection(primID); } }
public void run() { IntersectionState istate = new IntersectionState(); while (true) { int bx, by; lock (renderer)//synchronized (renderer) { { if (renderer.bucketCounter >= renderer.bucketCoords.Length) { return; } UI.taskUpdate(renderer.bucketCounter); bx = renderer.bucketCoords[renderer.bucketCounter + 0]; by = renderer.bucketCoords[renderer.bucketCounter + 1]; renderer.bucketCounter += 2; } renderer.renderBucket(renderer.display, bx, by, threadID, istate); if (UI.taskCanceled()) { return; } } }
private int progressiveRenderNext(IntersectionState istate) { int TASK_SIZE = 16; SmallBucket first = smallBucketQueue.Count > 0 ? smallBucketQueue.Dequeue() : null; if (first == null) { return(0); } int ds = first.size / TASK_SIZE; bool useMask = smallBucketQueue.Count != 0; int mask = 2 * first.size / TASK_SIZE - 1; int pixels = 0; for (int i = 0, y = first.y; i < TASK_SIZE && y < imageHeight; i++, y += ds) { for (int j = 0, x = first.x; j < TASK_SIZE && x < imageWidth; j++, x += ds) { // check to see if this is a pixel from a higher level tile if (useMask && (x & mask) == 0 && (y & mask) == 0) { continue; } int instance = (x & (sigma.Length - 1)) * sigma.Length + sigma[y & (sigma.Length - 1)]; double time = QMC.halton(1, instance); double lensU = QMC.halton(2, instance); double lensV = QMC.halton(3, instance); ShadingState state = scene.getRadiance(istate, x, imageHeight - 1 - y, lensU, lensV, time, instance); Color c = state != null?state.getResult() : Color.BLACK; pixels++; // fill region display.imageFill(x, y, Math.Min(ds, imageWidth - x), Math.Min(ds, imageHeight - y), c); } } if (first.size >= 2 * TASK_SIZE) { // generate child buckets int size = (int)((uint)first.size >> 1);//>>> for (int i = 0; i < 2; i++) { if (first.y + i * size < imageHeight) { for (int j = 0; j < 2; j++) { if (first.x + j * size < imageWidth) { SmallBucket b = new SmallBucket(); b.x = first.x + j * size; b.y = first.y + i * size; b.size = size; b.constrast = 1.0f / size; smallBucketQueue.Enqueue(b); } } } } } return(pixels); }
public void intersectPrimitive(Ray r, int primID, IntersectionState state) { // intersect in local space float qa = r.dx * r.dx + r.dy * r.dy + r.dz * r.dz; float qb = 2 * ((r.dx * r.ox) + (r.dy * r.oy) + (r.dz * r.oz)); float qc = ((r.ox * r.ox) + (r.oy * r.oy) + (r.oz * r.oz)) - 1; double[] t = Solvers.solveQuadric(qa, qb, qc); if (t != null) { // early rejection if (t[0] >= r.getMax() || t[1] <= r.getMin()) { return; } if (t[0] > r.getMin()) { r.setMax((float)t[0]); } else { r.setMax((float)t[1]); } state.setIntersection(0, 0, 0); } }
public void intersect(Ray r, IntersectionState state) { for (int i = 0; i < n; i++) { primitives.intersectPrimitive(r, i, state); } }
public void RefractedColorWithRay() { var w = World.Default; var s = w.Objects[0]; s.Material.Ambient = 1f; s.Material.Pattern = new TestPattern(); var b = w.Objects[1]; b.Material.Transparency = 1; b.Material.IOR = 1.5f; var r = new Ray(0, 0, .1f, 0, 1, 0); var xs = new List <Intersection> { new(-.9899f, s), new(-.4899f, b), new(.4899f, b), new(.9899f, s) }; var hit = xs[2]; var comps = IntersectionState.Prepare(ref hit, ref r, xs); var c = w.RefractedColor(ref comps, 5); Assert.That.VectorsAreEqual(c, new Color(0, .99888f, .04725f), 1e-3f); }
public void ShadeHitSchlick() { var w = World.Default; var floor = new Plane(Translation(0, -1, 0)) { Material = { Transparency = .5f, IOR = 1.5f, Reflectivity = .5f } }; w.Objects.Add(floor); var s = new Sphere(Translation(0, -3.5f, -.5f)) { Material = { BaseColor = new Color(1, 0, 0), Ambient = .5f } }; w.Objects.Add(s); var r = new Ray(0, 0, -3, 0, -MathF.Sqrt(2f) / 2f, MathF.Sqrt(2f) / 2f); var xs = new Intersection(MathF.Sqrt(2f), floor); var comps = IntersectionState.Prepare(ref xs, ref r); var color = w.ShadeHit(ref comps, 5); Assert.That.VectorsAreEqual(color, new Color(.93391f, .69643f, .69243f), 1e-4f); }
private void OnPlayersChanged(SnowmanControl[] players) { // Regenerate the intersections state data // to reflect the new collection of players. IntersectionState[] newStates = new IntersectionState[players.Length]; int i = 0; foreach (SnowmanControl controller in players) { newStates[i] = new IntersectionState { player = controller }; // Check to see if this player had any previous state. // This ensures adds/drops cannot interrupt a collision state. try { foreach (IntersectionState priorState in intersectionStates) { if (priorState.player == controller) { // Ensure the new array contains the same collision state. newStates[i].isIntersecting = priorState.isIntersecting; break; } } i++; } catch { float e = 2; } } intersectionStates = newStates; }
public void ChapterVI() { const float wallZ = 10f; const float wallSize = 7f; const int px = 100; const float pxSize = wallSize / px; const float half = wallSize / 2f; var canvas = new Canvas(px, px); var rayOrigin = Point(0f, 0f, -5f); var shape = new Sphere { Material = new PhongMaterial(new Color(1f, .2f, 1f)) }; var l = new PointLight(Point(-10f, 10f, -10f), Color.White); Parallel.For(0, px, y => { var wY = half - pxSize * y; for (var x = 0; x < px; x++) { var wx = -half + pxSize * x; var pos = Point(wx, wY, wallZ); var ray = new Ray(rayOrigin, Vector4.Normalize(pos - rayOrigin)); var hit = shape.Hit(ref ray); if (hit == null) { continue; } var comps = IntersectionState.Prepare(ref hit, ref ray); canvas[x, y] = shape.Material.Shade(l, ref comps, 0); } }); }
public BucketThread(int threadID, BucketRenderer renderer) { this.threadID = threadID; istate = new IntersectionState(); this.renderer = renderer; thread = new Thread(new ThreadStart(run)); thread.IsBackground = true; }
public void SchlickN2GreaterN1() { var s = Sphere.GlassSphere; var r = new Ray(0, .99f, -2, 0, 0, 1); var xs = new Intersection(1.8589f, s); var comps = IntersectionState.Prepare(ref xs, ref r); Assert.That.FloatsAreEqual(comps.Schlick(), .48873f); }
public void PrecomputingReflectionVector() { var s = new Plane(); var r = new Ray(0f, 1f, -1f, 0f, -MathF.Sqrt(2f) / 2f, MathF.Sqrt(2f) / 2f); var i = new Intersection(MathF.Sqrt(2f), s); var comps = IntersectionState.Prepare(ref i, ref r); Assert.AreEqual(comps.Reflect, Direction(0f, MathF.Sqrt(2f) / 2f, MathF.Sqrt(2f) / 2f)); }
public void HitOccursOutside() { var r = new Ray(0f, 0f, -5f, 0f, 0f, 1f); var s = new Sphere(); var i = new Intersection(4f, s); var comps = IntersectionState.Prepare(ref i, ref r); Assert.IsFalse(comps.IsInside); }
public void The_hit_should_be_preserved_when_calculating_the_intersection_state() { var hit = new Intersection(1, _triangle, 0.45, 0.25); var ray = new Ray(new Point(-0.2, 0.3, -2), Vector.UnitZ); var intersections = new IntersectionList(hit); var state = IntersectionState.Create(hit, ray, intersections); state.Normal.Should().Be(new Vector(-0.5547, 0.83205, 0)); }
public void Precomputing_the_hit_when_an_intersection_occurs_on_the_outside() { var ray = new Ray(new Point(0, 0, -5), new Vector(0, 0, 1)); var shape = new Sphere(); var hit = new Intersection(4, shape); var state = IntersectionState.Create(hit, ray, new IntersectionList(hit)); state.IsInside.Should().BeFalse(); }
public void Precomputing_the_reflection_vector() { var shape = new Plane(); var ray = new Ray(new Point(0, 1, -1), new Vector(0, -Math.Sqrt(2) / 2, Math.Sqrt(2) / 2)); var hit = new Intersection(Math.Sqrt(2), shape); var state = IntersectionState.Create(hit, ray, new IntersectionList(hit)); state.Reflection.Should().Be(new Vector(0, Math.Sqrt(2) / 2, Math.Sqrt(2) / 2)); }
public void LightingWithSurfinShadow() { var eye = Direction(0f, 0f, -1f); var normal = Direction(0f, 0f, -1f); var l = new PointLight(Point(0f, 0f, -10f), Color.White); var comps = new IntersectionState(_position, eye, normal); var res = _m.Shade(l, ref comps, 0); Assert.That.VectorsAreEqual(res, new Color(.1f, .1f, .1f)); }
public void EyeBeweenLightAndSurf() { var eye = Direction(0f, 0f, -1f); var normal = Direction(0f, 0f, -1f); var l = new PointLight(Point(0f, 0f, -10f), Color.White); var comps = new IntersectionState(_position, eye, normal); var res = _m.Shade(l, ref comps, 1); Assert.That.VectorsAreEqual(res, new Color(1.9f, 1.9f, 1.9f)); }
public void LightOffset45() { var eye = Direction(0f, 0, -1f); var normal = Direction(0f, 0f, -1f); var l = new PointLight(Point(0f, 10f, -10f), Color.White); var comps = new IntersectionState(_position, eye, normal); var res = _m.Shade(l, ref comps, 1); Assert.That.VectorsAreEqual(res, new Color(.7364f, .7364f, .7364f)); }
public void Precomputing_the_hit_should_offset_the_point() { var ray = new Ray(new Point(0, 0, -5), Vector.UnitZ); var shape = new Sphere(transform: Matrix4x4.CreateTranslation(0, 0, 1)); var hit = new Intersection(5, shape); var state = IntersectionState.Create(hit, ray, new IntersectionList(hit)); state.OverPoint.Z.Should().BeLessThan(-NumberExtensions.Epsilon / 2); state.Point.Z.Should().BeGreaterThan(state.OverPoint.Z); }
public BucketThread(int threadID, MultipassRenderer renderer) { this.threadID = threadID; istate = new IntersectionState(); cache = renderer.shadingCache ? new ShadingCache() : null; this.renderer = renderer; thread = new Thread(new ThreadStart(run)); thread.IsBackground = true; this.renderer = renderer; }
public void HitOffsetsPoint() { var r = new Ray(0f, 0f, -5f, 0f, 0f, 1f); var s = new Sphere(Translation(0f, 0f, 1f)); var i = new Intersection(5f, s); var c = IntersectionState.Prepare(ref i, ref r); Assert.IsTrue(c.OverPoint.Z < -Constants.Epsilon / 2f); Assert.IsTrue(c.Point.Z > c.OverPoint.Z); }
public void RefractedColor_should_return_the_refracted_color_at_the_maximum_recursive_depth() { var world = World.CreateDefaultWorld(); var shape = world.Shapes[0].ChangeMaterial(m => m.WithTransparency(1.0).WithRefractiveIndex(1.5)); var ray = new Ray(new Point(0, 0, -5), Vector.UnitZ); var intersections = new IntersectionList((4, shape), (6, shape)); var state = IntersectionState.Create(intersections[0], ray, intersections); Color color = world.RefractedColor(state, 0); color.Should().Be(Colors.Black); }
public void EyeInPath() { var val = -MathF.Sqrt(2f) / 2f; var eye = Direction(0f, val, val); var normal = Direction(0f, 0f, -1f); var l = new PointLight(Point(0f, 10f, -10f), Color.White); var comps = new IntersectionState(_position, eye, normal); var res = _m.Shade(l, ref comps, 1); Assert.That.VectorsAreEqual(res, new Color(1.6364f, 1.6364f, 1.6364f), 1e-4f); }
public void ShadingIntersection() { var w = World.Default; var r = new Ray(0f, 0f, -5f, 0f, 0f, 1f); var s = w.Objects[0]; var i = new Intersection(4f, s); var comps = IntersectionState.Prepare(ref i, ref r); var c = w.ShadeHit(ref comps); Assert.That.VectorsAreEqual(c, new Color(.38066f, .47583f, .2855f)); }
public void ShadeHit_should_shade_an_intersection_from_the_inside() { var world = World.CreateDefaultWorld().ChangeLights(new PointLight(new Point(0, 0.25, 0), Colors.White)); var ray = new Ray(new Point(0, 0, 0), Vector.UnitZ); Shape shape = world.Shapes[1]; var intersection = new Intersection(0.5, shape); var state = IntersectionState.Create(intersection, ray, new IntersectionList(intersection)); Color color = world.ShadeHit(state); color.Should().Be(new Color(0.90498, 0.90498, 0.90498)); }
public void ShadeHit_should_shade_an_intersection() { var world = World.CreateDefaultWorld(); var ray = new Ray(new Point(0, 0, -5), Vector.UnitZ); Shape shape = world.Shapes[0]; var intersection = new Intersection(4, shape); var state = IntersectionState.Create(intersection, ray, new IntersectionList(intersection)); Color color = world.ShadeHit(state); color.Should().Be(new Color(0.38066, 0.47583, 0.2855)); }
void Update() { if (State == IntersectionState.ReleaseNextCar) { if (cars.Count == 0) { State = IntersectionState.Empty; } else { WaitingCar waitingCar = cars.Dequeue(); m_waitingOnCar = waitingCar; CarController car = waitingCar.car; car.StartTurn (); State = IntersectionState.WaitingForCar; } } }
private void intersectFlake(Ray r, IntersectionState state, int level, float qa, float qaInv, float cx, float cy, float cz, float dx, float dy, float dz, float radius) { if (level <= 0) { // we reached the bottom - intersect sphere and bail out float vcx = cx - r.ox; float vcy = cy - r.oy; float vcz = cz - r.oz; float b = r.dx * vcx + r.dy * vcy + r.dz * vcz; float disc = b * b - qa * ((vcx * vcx + vcy * vcy + vcz * vcz) - radius * radius); if (disc > 0) { // intersects - check t values float d = (float) Math.Sqrt(disc); float t1 = (b - d) * qaInv; float t2 = (b + d) * qaInv; if (t1 >= r.getMax() || t2 <= r.getMin()) return; if (t1 > r.getMin()) r.setMax(t1); else r.setMax(t2); state.setIntersection(0, cx, cy, cz); } } else { float boundRadius = radius * (1 + boundingRadiusOffset[level]); float vcx = cx - r.ox; float vcy = cy - r.oy; float vcz = cz - r.oz; float b = r.dx * vcx + r.dy * vcy + r.dz * vcz; float vcd = (vcx * vcx + vcy * vcy + vcz * vcz); float disc = b * b - qa * (vcd - boundRadius * boundRadius); if (disc > 0) { // intersects - check t values float d = (float) Math.Sqrt(disc); float t1 = (b - d) * qaInv; float t2 = (b + d) * qaInv; if (t1 >= r.getMax() || t2 <= r.getMin()) return; // we hit the bounds, now compute intersection with the actual // leaf sphere disc = b * b - qa * (vcd - radius * radius); if (disc > 0) { d = (float) Math.Sqrt(disc); t1 = (b - d) * qaInv; t2 = (b + d) * qaInv; if (t1 >= r.getMax() || t2 <= r.getMin()) { // no hit } else { if (t1 > r.getMin()) r.setMax(t1); else r.setMax(t2); state.setIntersection(0, cx, cy, cz); } } // recursively intersect 9 other spheres // step1: compute basis around displacement vector float b1x, b1y, b1z; if (dx * dx < dy * dy && dx * dx < dz * dz) { b1x = 0; b1y = dz; b1z = -dy; } else if (dy * dy < dz * dz) { b1x = dz; b1y = 0; b1z = -dx; } else { b1x = dy; b1y = -dx; b1z = 0; } float n = 1 / (float) Math.Sqrt(b1x * b1x + b1y * b1y + b1z * b1z); b1x *= n; b1y *= n; b1z *= n; float b2x = dy * b1z - dz * b1y; float b2y = dz * b1x - dx * b1z; float b2z = dx * b1y - dy * b1x; b1x = dy * b2z - dz * b2y; b1y = dz * b2x - dx * b2z; b1z = dx * b2y - dy * b2x; // step2: generate 9 children recursively float nr = radius * (1 / 3.0f), scale = radius + nr; for (int i = 0; i < 9 * 3; i += 3) { // transform by basis float ndx = recursivePattern[i] * dx + recursivePattern[i + 1] * b1x + recursivePattern[i + 2] * b2x; float ndy = recursivePattern[i] * dy + recursivePattern[i + 1] * b1y + recursivePattern[i + 2] * b2y; float ndz = recursivePattern[i] * dz + recursivePattern[i + 1] * b1z + recursivePattern[i + 2] * b2z; // recurse ! intersectFlake(r, state, level - 1, qa, qaInv, cx + scale * ndx, cy + scale * ndy, cz + scale * ndz, ndx, ndy, ndz, nr); } } } }
public void SignalCarFinished() { if (State == IntersectionState.WaitingForCar) { State = IntersectionState.ReleaseNextCar; } }
public void Enqueue(CarController car, StopLine stopLine) { cars.Enqueue(new WaitingCar(car, stopLine)); if (State == IntersectionState.Empty) { State = IntersectionState.ReleaseNextCar; } }
public void ResetIntersection() { cars.Clear(); State = IntersectionState.Empty; }
private void renderBucket(IDisplay display, int bx, int by, int threadID, IntersectionState istate, ShadingCache cache) { // pixel sized extents int x0 = bx * bucketSize; int y0 = by * bucketSize; int bw = Math.Min(bucketSize, imageWidth - x0); int bh = Math.Min(bucketSize, imageHeight - y0); // prepare bucket display.imagePrepare(x0, y0, bw, bh, threadID); Color[] bucketRGB = new Color[bw * bh]; float[] bucketAlpha = new float[bw * bh]; for (int y = 0, i = 0, cy = imageHeight - 1 - y0; y < bh; y++, cy--) { for (int x = 0, cx = x0; x < bw; x++, i++, cx++) { // sample pixel Color c = Color.black(); float a = 0; int instance = ((cx & ((1 << QMC.MAX_SIGMA_ORDER) - 1)) << QMC.MAX_SIGMA_ORDER) + QMC.sigma(cy & ((1 << QMC.MAX_SIGMA_ORDER) - 1), QMC.MAX_SIGMA_ORDER); double jitterX = QMC.halton(0, instance); double jitterY = QMC.halton(1, instance); double jitterT = QMC.halton(2, instance); double jitterU = QMC.halton(3, instance); double jitterV = QMC.halton(4, instance); for (int s = 0; s < numSamples; s++) { float rx = cx + 0.5f + (float) warpCubic(QMC.mod1(jitterX + s * invNumSamples)); float ry = cy + 0.5f + (float) warpCubic(QMC.mod1(jitterY + QMC.halton(0, s))); double time = QMC.mod1(jitterT + QMC.halton(1, s)); double lensU = QMC.mod1(jitterU + QMC.halton(2, s)); double lensV = QMC.mod1(jitterV + QMC.halton(3, s)); ShadingState state = scene.getRadiance(istate, rx, ry, lensU, lensV, time, instance + s, 5, cache); if (state != null) { c.add(state.getResult()); a++; } } bucketRGB[i] = c.mul(invNumSamples); bucketAlpha[i] = a * invNumSamples; if (cache != null) cache.reset(); } } // update pixels display.imageUpdate(x0, y0, bw, bh, bucketRGB, bucketAlpha); }