public Vector ReflectAndRefract(Shape3D obj, Ray ray, Vector intersect, Vector normal, int depth) { // var cVec = obj.material.Intersect(ray, intersect, normal, obj).ToVector(); var cVec = Vector.Build.Dense(3); var lIntersect = intersect + (normal * 0.001f); bool outside = Extensions.Dot3(ray.direction, normal) > 0.0f; if (obj.material.kReflection > 0f) { var reflect = Extensions.Reflected(-ray.direction, normal).Normalize(); Ray r = new Ray(lIntersect, reflect); SpawnRay(r, out var reflectColor, depth + 1); cVec += (reflectColor.ToVector() * obj.material.kReflection); } if (obj.material.kTransmission > 0f) { var refract = Extensions.Refract(ray.direction, normal, airKt, obj.material.kTransmission).Normalize(); var rO = outside ? intersect + (normal * 0.001f) : intersect - (normal * 0.001f); Ray r = new Ray(rO, refract); SpawnRay(r, out var refractColor, depth + 1); cVec += (refractColor.ToVector() * obj.material.kTransmission); } return(cVec); }
public override bool Intersect(Ray ray, out Vector <float>[] intersection, out Vector <float>[] normal) { Shape3D closestT = null; intersection = new Vector[1]; normal = new Vector[1]; float closestD = float.MaxValue; int ti = 0; foreach (Shape3D t in shapes) { if (t.Intersect(ray, out var i, out var n)) { float dist = Math.Abs((ray.origin - i[0]).Length()); if (dist < closestD) { closestD = dist; closestT = t; intersection[0] = i[0]; normal[0] = n[0]; } } ti++; } return(closestT != null); }
public static bool IntersectObjects(List <Shape3D> L, Ray ray, ref Shape3D hitObject, ref Vector intersect, ref Vector normal) { // run intersection test Shape3D closestObj = null; float? closestD = null; if (hitObject != null) { closestObj = hitObject; closestD = Math.Abs((ray.origin - intersect).Length()); } foreach (Shape3D obj in L) { // if (obj.AABB.Intersect(ray, out var min, out var max)) // { if (obj.Intersect(ray, out var i, out var n)) { float dist = Math.Abs((ray.origin - i[0]).Length()); if (closestD == null || dist < closestD) { closestD = dist; closestObj = obj; intersect = i[0]; normal = n[0]; } } // } } if (closestObj != null) { hitObject = closestObj; } return(hitObject != null); }
public bool InBounds(Shape3D s) { if (s is Triangle) { return(InBounds(s as Triangle)); } if (s.AABB != null) { return(InBounds(s.AABB)); } else { System.Console.WriteLine("no AABB"); return(false); } // else if (s is Sphere) // { // return InBounds(s as Sphere); // } // else if (s is Plane) // { // return InBounds(s as Plane); // } // else return false; }
public static bool Traverse(Ray ray, Node node, ref Shape3D hitObject, ref Vector intersect, ref Vector normal, int depth = 0) { // System.Console.WriteLine("Traversing Depth: " + depth); if (node is LeafNode) { var ln = node as LeafNode; // if(ln.bounds.Intersect(ray, out var min, out var max)) IntersectObjects(ln.shapes, ray, ref hitObject, ref intersect, ref normal); } else { // traverse var ax = node.partition.axis; if (node.bounds.Intersect(ray, out var ad, out var bd)) { var s = float.MaxValue; if (node.partition.Intersect(ray, out var splitIntersect, out var n)) { s = splitIntersect[0][ax]; } float a, b; a = ray.origin[ax] + (ray.direction[ax] * ad); b = ray.origin[ax] + (ray.direction[ax] * bd); if (a <= s) { if (b < s) { Traverse(ray, node.right, ref hitObject, ref intersect, ref normal, depth + 1); } else { if (b == s) { Traverse(ray, node.left, ref hitObject, ref intersect, ref normal, depth + 1); Traverse(ray, node.right, ref hitObject, ref intersect, ref normal, depth + 1); } else { Traverse(ray, node.right, ref hitObject, ref intersect, ref normal, depth + 1); Traverse(ray, node.left, ref hitObject, ref intersect, ref normal, depth + 1); } } } else { if (b > s) { Traverse(ray, node.left, ref hitObject, ref intersect, ref normal, depth + 1); } else { Traverse(ray, node.left, ref hitObject, ref intersect, ref normal, depth + 1); Traverse(ray, node.right, ref hitObject, ref intersect, ref normal, depth + 1); } } } } return(hitObject != null); }
public Shape3D TraceRayKD(Ray ray, out Vector intersect, out Vector normal) { Shape3D hitObj = null; intersect = null; normal = null; KDTree.Traverse(ray, tree, ref hitObj, ref intersect, ref normal); return(hitObj); }
public static ComplexObject LoadObjFile(string filename) { var factory = new ObjLoader.Loader.Loaders.ObjLoaderFactory(); var loader = factory.Create(); var fs = File.OpenRead(filename); var result = loader.Load(fs); List <Shape3D> objShapes = new List <Shape3D>(); var m = new BasicMaterial(Rgba32.Gray); foreach (var g in result.Groups) { foreach (var f in g.Faces) { Vector[] verts = new Vector[f.Count]; for (var fv = 0; fv < f.Count; fv++) { var vx = result.Vertices[f[fv].VertexIndex - 1].X; var vy = result.Vertices[f[fv].VertexIndex - 1].Y; var vz = result.Vertices[f[fv].VertexIndex - 1].Z; Vector vert = Vector.Build.DenseOfArray(new float[] { vx, vy, vz }); verts[fv] = vert; } Shape3D shape = null; // Vector c = Vector.Build.Dense(3); // foreach (Vector v in verts) // { // c += v; // } // c /= verts.Length; // shape = new Sphere(c, 0.01f, m); switch (f.Count) { case 3: shape = new Triangle(verts, m); break; case 4: shape = new Plane(verts, m); break; default: shape = new Plane(verts, m); break; } if (shape != null) { objShapes.Add(shape); } } } ComplexObject obj = new ComplexObject(objShapes, m); return(obj); }
public Material GetMaterial(Shape3D obj, Vector <float> intersection) { var tex = obj.GetTextureCoords(intersection); float row = tex[1] / checksize; float col = tex[0] / checksize; if ((int)row % 2 == (int)col % 2) { return(material1); } else { return(material2); } }
public Vector ReflectAndRefractKD(Shape3D obj, Ray ray, Vector intersect, Vector normal, int depth) { var cVec = Vector.Build.Dense(3); if (obj.material is LenseMaterial) { var bh = obj as BlackHole; var sw_radius = bh.Sradius; var ray_to_center = obj.center - ray.origin; float tca = ray_to_center.DotProduct(ray.direction); var p = ray.origin + (ray.direction * tca); var d = (float)Math.Abs((p - obj.center).Length()); if (d < sw_radius) { return(cVec); } var a = (2 * sw_radius / d); var rO = intersect - (normal * (0.001f)); var rotationMatrix = obj.GetRotationMatrixAboutAxis(normal.CrossProduct(ray.direction).Normalize(), a); var refract = (rotationMatrix * ray.direction.GetVector4()).SubVector(0, 3).Normalize(); Ray r = new Ray(rO, refract); SpawnRayKD(r, out var reflectColor, depth + 1); cVec += (reflectColor.ToVector()); } if (obj.material.kReflection > 0f) { var lIntersect = intersect + (normal * 0.001f); var reflect = Extensions.Reflected(-ray.direction, normal).Normalize(); Ray r = new Ray(lIntersect, reflect); SpawnRayKD(r, out var reflectColor, depth + 1); cVec += (reflectColor.ToVector() * obj.material.kReflection); } if (obj.material.kTransmission > 0f) { bool outside = Extensions.Dot3(ray.direction, normal) > 0.0f; var n1 = airKt; var n2 = obj.material.kTransmission; var norm = normal.Clone(); var refract = Extensions.Refract(ray.direction, norm, n1, n2).Normalize(); var rO = outside ? intersect + (normal * 0.001f) : intersect - (normal * 0.001f); Ray r = new Ray(rO, refract); SpawnRayKD(r, out var refractColor, depth + 1); cVec += (refractColor.ToVector() * obj.material.kTransmission); } return(cVec); }
public Shape3D TraceRay(Ray ray, out Vector intersect, out Vector normal) { Shape3D closestObj = null; float? closestD = null; intersect = null; normal = null; foreach (Shape3D obj in objects) { if (obj.Intersect(ray, out var i, out var n)) { float dist = Math.Abs((ray.origin - i[0]).Length()); if (closestD == null || dist < closestD) { closestD = dist; closestObj = obj; intersect = i[0]; normal = n[0]; } } } return(closestObj); }
public bool SpawnRayKD(Ray ray, out Rgba32 color, int depth = 0) { if (depth > 4) { color = (ambientLight.ToVector() * ambientCoefficient).ToColor();//background; return(false); } var cVec = Vector.Build.Dense(3); Shape3D obj = TraceRayKD(ray, out var intersect, out var normal); if (obj != null) { cVec += obj.material.Intersect(ray, intersect, normal, obj, true).ToVector(); cVec += ReflectAndRefractKD(obj, ray, intersect, normal, depth); color = cVec.ToColor(); return(true); } else { color = (ambientLight.ToVector() * ambientCoefficient).ToColor();//background; return(false); } }
////// // Phong Illumination Model: // // L = ka * La <--- ambient // + kd * [Li * Od * (Si . N)] <--- diffuse // + ks * [Li * Os * (Ri . V) ^ ke)] <--- specular // // L - Final returned radiance (color value) // ka - ambient coefficient // La - world ambient radiance // kd - diffuse coefficient // ke - specular exponent // [] - summation of all the light sources (i) // Li - radiance of light i // Si - angle of incidence of light i // Ri - angle of reflectance of light i // V - viewing angle ////// public Rgba32 Illuminate(Ray ray, Vector isect, Vector normal, PhongMaterial material, Shape3D obj, bool KD = false) { // initialize Light (zeros) Vector L = Vector.Build.Dense(3); // add ambient lighting Vector La = world.ambientLight.ToVector(); float ka = world.ambientCoefficient; L += (La * ka); // add up diffuse/specular/reflection lighting for each light Vector Ld = Vector.Build.Dense(3); Vector Ls = Vector.Build.Dense(3); Vector Lr = Vector.Build.Dense(3); // object/material diffuse/specular colors Vector Od = material.diffuseColor.ToVector(); Vector Os = material.specularColor.ToVector(); // viewing direction Vector V = -ray.direction.Normalize(); // shift intersection to avoid self-collision Vector lIntersection = isect + (normal * 0.001f); foreach (LightSource Li in world.GetLightSources()) { // shadow ray Vector Sdir = (Li.center - lIntersection).Normalize(); float l_d = Math.Abs((Li.center - lIntersection).Length()); Ray S = new Ray(lIntersection, Sdir); // reflected ray Vector Rdir = Extensions.Reflected(Sdir, normal).Normalize(); // Ray R = new Ray(lIntersection, Rdir); // check for shadow ray -> other object intersection bool shaded = false; float shade = 0.0f; if (KD) { var s_shape = world.TraceRayKD(S, out var i, out var n); if (s_shape != null) { var s_d = Math.Abs((isect - i[0]).Length()); if (s_d < l_d) { shaded = true; shade = 1.0f - Extensions.Clamp(s_shape.material.kTransmission, 0.0f, 1.0f); } } } else { foreach (Shape3D o_obj in world.objects) { if (!o_obj.Equals(obj)) { if (o_obj.Intersect(S, out var I, out var N)) { shaded = true; shade = 1.0f - Extensions.Clamp(o_obj.material.kTransmission, 0.0f, 1.0f); } } } } if (!shaded || shade < 1.0f) { // diffuse Vector LiOd = Li.color.ToVector().Multiply(Od).Clamp(0.0f, 1.0f); float dist = (float)Distance.Euclidean(Li.center, lIntersection); float attenuation = Li.strength / (dist * dist); // System.Console.WriteLine(attenuation); LiOd *= attenuation; float SdotN = Sdir.DotProduct(normal).Clamp(0.0f, 1.0f); Ld += (SdotN * LiOd); Ld -= shade; Ld.Clamp(0.0f, 1.0f); // specular Vector LiOs = Li.color.ToVector().Multiply(Os).Clamp(0.0f, 1.0f); LiOs *= attenuation; float RdotV = ((float)Math.Pow(Rdir.DotProduct(V), material.specularExponent)).Clamp(0.0f, 1.0f); Ls += (RdotV * LiOs); Ls -= shade; Ls.Clamp(0.0f, 1.0f); } } Ld *= material.kDiffuse; Ls *= material.kSpecular; L += (Ld + Ls); return(L.Clamp(0.0f, 1.0f).ToColor()); }
public override Rgba32 Intersect(Ray ray, Vector intersection, Vector normal, Shape3D obj, bool KD = false) { return(this.color); }
public override Rgba32 Intersect(Ray ray, Vector <float> intersection, Vector <float> normal, Shape3D obj, bool KD = false) { return(GetMaterial(obj, intersection).Intersect(ray, intersection, normal, obj, KD)); }
public abstract Rgba32 Intersect(Ray ray, Vector intersection, Vector normal, Shape3D obj, bool KD = false);
public override Rgba32 Intersect(Ray ray, Vector intersection, Vector normal, Shape3D obj, bool KD = false) { return(lightingModel.Illuminate(ray, intersection, normal.Normalize(), this, obj, KD)); }
public void AddObject(Shape3D o) { o.objID = objects.Count; objects.Add(o); }