public static void TestRIEqual(Ray ray, double ta, double tb, List<RenderItem> ris, RenderItem ria, RenderItem rib) { if(ria != rib) { Assert.AreEqual(ria, rib, string.Format("The hitpoint was {0}/{3} with ray {2} and scenario {1}", ray.PointAt(ta), string.Join(",", ris), ray, ray.PointAt(tb))); } else { Assert.AreEqual(ria, rib); } }
public RenderItem CalculateHit (Ray ray, out double t, double MaxT) { double tmin = 0.0d; t = MaxT; //first setting up the interval foreach(NormalInterval ni in intervals) { Utils.CloseInterval(ray, ni, ref tmin, ref t); } if(t > tmin) {//the ray passes through the bounding sheared box RenderItem ri = null; Point3 inter = new Point3(); ray.PointAt(tmin, inter); this.root.Hit(ray, inter, ref ri, ref tmin, t, ref t); return ri; } else { return null; } }
public void Hit (Ray ray, Point3 inter, ref RenderItem item, ref double tcur, double tmig, ref double tmax) { if(this.splitNormal != null) {//we're not at a leaf double x = inter[this.splitNormal]; double dxi = Maths.SoftInv(ray.Direction[this.splitNormal]); if((x < xm && dxi <= 0.0d) || x > xM && dxi >= 0.0d) { return; } double x0 = ray.Offset[this.splitNormal]; double tt = tcur; double tmig0; if(x < xa) { if(dxi > 0.0d) { tt = tcur+dxi*(xb-x); tmig0 = Math.Min(tmig, dxi*(xa-x0)); this.left.Hit(ray, inter, ref item, ref tcur, tmig0, ref tmax); tmig = Math.Min(tmig, tmax); if(tt <= tmig) { #if FAST_COLOR_MIGRATION SystemDiagnostics.Migrations++; #endif tcur = tt; ray.PointAt(tcur, inter); this.right.Hit(ray, inter, ref item, ref tcur, tmig, ref tmax); } } else { this.left.Hit(ray, inter, ref item, ref tcur, tmig, ref tmax); } } else if(x > xb) { if(dxi < 0.0d) { tt = tcur+dxi*(xa-x); tmig0 = Math.Min(tmig, dxi*(xb-x0)); this.right.Hit(ray, inter, ref item, ref tcur, tmig0, ref tmax); tmig = Math.Min(tmig, tmax); if(tt <= tmig) { #if FAST_COLOR_MIGRATION SystemDiagnostics.Migrations++; #endif tcur = tt; ray.PointAt(tcur, inter); this.left.Hit(ray, inter, ref item, ref tcur, tmig, ref tmax); } } else { this.right.Hit(ray, inter, ref item, ref tcur, tmig, ref tmax); } } else {//in the death zone if(dxi < 0.0d) { #if FAST_COLOR_MIGRATION SystemDiagnostics.Migrations++; #endif tcur = dxi*(xa-x); ray.PointAt(tcur, inter); this.left.Hit(ray, inter, ref item, ref tcur, tmig, ref tmax); } else if(dxi > 0.0d) { #if FAST_COLOR_MIGRATION SystemDiagnostics.Migrations++; #endif tcur = dxi*(xb-x0); ray.PointAt(tcur, inter); this.right.Hit(ray, inter, ref item, ref tcur, tmig, ref tmax); } //else we cannot move in the death zone, thus go back one level } } else { double tt; foreach(RenderItem ri in items) { tt = ri.HitAt(ray); if(tt < tmax) { tmax = tt; item = ri; } } } }
public Color CalculateColor(Ray ray, int depth, Color intensityHint) { RenderItem best = null; double t, tdummy; best = acc.CalculateHit(ray, out t); if(best != null) { best.Cast(ray, nw); Point3 norm = nw.Normal; ray.PointAt(t, hp); Material mat = best.Material; Color ambient, diffuse, specular, reflectance, refraction; mat.ADSAtAndBump(nw, ray.Direction, out ambient, out diffuse, out specular, out reflectance, out refraction); Color clr = this.ambientColor*ambient; Point3.ReflectRefract(ray.Direction, nw.Normal, mat.NFactor, rl, rf); rayCache[depth].SetWithEpsilon(hp, rf); foreach(Light li in this.lights) { double len = Point3.DiffLength(hp, li.Position); double thetafrac = Math.PI-Math.Asin(li.Radius/len); uint light = 0x00; double lightD; dis.SetValues(hp, li.Position); dis.Normalize(); if(Point3.CosAngleNorm(dis, norm) >= 0.0d) { if(!double.IsNaN(thetafrac) && lightTest > 0x00) { dis.SetValues(hp, li.Position); dis.Normalize(); sr.SetOffsetWithEpsilon(hp); if(this.acc.CalculateHit(sr, out tdummy, len-li.Radius) == null) { light++; } for(int i = 1; i < lightTest; i++) { lp.SetValues(li.Position, li.Radius); dis.SetValues(hp, lp); dis.Normalize(); sr.SetOffsetWithEpsilon(hp); if(this.acc.CalculateHit(sr, out tdummy, len-li.Radius) == null) { light++; } } lightD = (double)light/lightTest; } else { lightD = 1.0d; } if(lightD > 0.0d) { dis.SetValues(hp, li.Position); dis.Normalize(); Color clrl = (li.Color*diffuse)*Point3.CosAngleNorm(dis, norm); clrl += (li.Color*specular)*Math.Max(0.0d, Math.Pow(Point3.CosAngleNorm(rl, dis), mat.Shininess)); clr += Color.LoseIntensity((clrl*lightD), distanceUnit, len); } } } if(depth < maxDepth) { Color reflint = intensityHint*reflectance; if(reflint.IntensityTreshold) { ray.SetWithEpsilon(hp, rl); clr += this.CalculateColor(ray, depth+1, reflint)*reflectance; } Color refrint = intensityHint*refraction; if(refrint.IntensityTreshold) { if(double.IsNaN(rayCache[depth].Direction.X)) { ray.SetWithEpsilon(hp, rl); clr += this.CalculateColor(ray, depth+1, refrint)*refraction; } else { clr += this.CalculateColor(rayCache[depth], depth+1, refrint)*refraction; } } } return Color.LoseIntensity(clr, distanceUnit, t); } else { return this.EnvironmentMap(ray); } }
public void Hit(Ray ray, Point3 rayinv, Point3 inter, ref double t, ref double tHit, ref RenderItem ri) { double tt; if(this.tri == null) { if(t < tHit) { int cur = Math.Sign(inter[dim]-x); if(cur*Math.Sign(rayinv[dim]) < 0.0d) { tt = t+(x-inter[dim])*rayinv[dim]; double tt2 = Math.Min(tt, tHit); this.children[(cur+0x01)>>0x01].Hit(ray, rayinv, inter, ref t, ref tt2, ref ri); if(tt <= tt2) { t = tt; ray.PointAt(tt, inter); this.children[(0x01-cur)>>0x01].Hit(ray, rayinv, inter, ref t, ref tHit, ref ri); } else { tHit = tt2; } } else { this.children[(cur+0x01)>>0x01].Hit(ray, rayinv, inter, ref t, ref tHit, ref ri); } } } else { foreach(RenderItem rit in tri) { tt = rit.HitAt(ray); if(tt < tHit) { tHit = tt; ri = rit; } } } }
private void proceedSubTree (Ray ray, int dpos, double[] seqxyz, Point3 inter, ref RenderItem ri, ref double t, ref double tHit, FastOctTreeNode fotn) { double tt; if(fotn.IsLeaf) { long refs = fotn.data; if(refs != 0x00) { long end = refs>>0x20; for(refs &= 0xffffffff; refs < end; refs++) { tt = ris[refs].HitAt(ray); if(tt < tHit) { tHit = tt; ri = ris[refs]; } } } } else if(t < tHit) { int pos = Maths.BinarySign(inter.X-fotn.x)|(Maths.BinarySign(inter.Y-fotn.y)<<0x02)|(Maths.BinarySign(inter.Z-fotn.z)<<0x04); double xt, yt, zt; int nextdim = 0x00; do { #if FAST_COLOR_MIGRATION SystemDiagnostics.Migrations++; #endif seqxyz[0x04] = fotn.x; seqxyz[0x07] = fotn.y; seqxyz[0x0a] = fotn.z; tt = double.PositiveInfinity; int pos2 = pos+dpos; calcDim(ref tt, ref nextdim, ray.X0, seqxyz[(pos2&0x03)+0x03], seqxyz[0x00], 0x00); calcDim(ref tt, ref nextdim, ray.Y0, seqxyz[((pos2&0x0c)>>0x02)+0x06], seqxyz[0x01], 0x02); calcDim(ref tt, ref nextdim, ray.Z0, seqxyz[((pos2&0x30)>>0x04)+0x09], seqxyz[0x02], 0x04); xt = seqxyz[0x05-((pos&0x01)<<0x01)]; yt = seqxyz[0x08-((pos&0x04)>>0x01)]; zt = seqxyz[0x0b-((pos&0x10)>>0x03)]; seqxyz[0x05-((pos&0x01)<<0x01)] = fotn.x; seqxyz[0x08-((pos&0x04)>>0x01)] = fotn.y; seqxyz[0x0b-((pos&0x10)>>0x03)] = fotn.z; proceedSubTree(ray, dpos, seqxyz, inter, ref ri, ref t, ref tHit, fotn.node[((pos&0x01)<<0x02)|((pos&0x04)>>0x01)|((pos&0x10)>>0x04)]); seqxyz[0x05-((pos&0x01)<<0x01)] = xt; seqxyz[0x08-((pos&0x04)>>0x01)] = yt; seqxyz[0x0b-((pos&0x10)>>0x03)] = zt; t = tt; ray.PointAt(t, inter); pos += (0x02*((dpos>>nextdim)&0x03)-0x01)<<nextdim; } while(t < tHit && (pos&ValidPositionMask) == 0x00); } }