public Ray GenerateRay(LocalGeo geo, out RTColor color) { color = Color; RTVector ray = Source - geo.Point; return(new Ray(geo.Point, ray.Normalize(), 1e-3f, ray.Length, false)); }
public void MoveCamera(RTPoint lookFrom, RTPoint lookAt, RTVector up) { Eye = new RTPoint(lookFrom); W = (lookFrom - lookAt).Normalize(); U = RTVector.CrossProduct(up, W).Normalize(); V = RTVector.CrossProduct(W, U); }
public Vertex(RTPoint vertex, RTVector normal) { Location = vertex; if (normal != null) { Normal = new Normal(normal); } }
public Ray GenerateRay(RTPoint p) { float alpha = (float)Math.Tan(FovX / 2.0f) * ((p.X - (Width / 2.0f)) / (Width / 2.0f)); float beta = (float)Math.Tan(FovY / 2.0f) * (((Height / 2.0f) - p.Y) / (Height / 2.0f)); RTVector rayVec = new RTVector(alpha * U + beta * V - W).Normalize(); return(new Ray(Eye, rayVec, 0, float.MaxValue, false)); }
public Camera(RTPoint lookFrom, RTPoint lookAt, RTVector up, float fovy, int width, int height) { MoveCamera(lookFrom, lookAt, up); Width = width; Height = height; FovY = fovy.ToRadians(); FovX = 2.0f * (float)Math.Atan((float)Math.Tan(FovY / 2.0f) * (width / (float)height)); }
public SceneBuilder SetCameraPosition(RTPoint lookFrom, RTPoint lookAt, RTVector up) { if (_camera == null) { InitCameraDefault(); } _camera.MoveCamera(lookFrom, lookAt, up); return(this); }
public SceneBuilder SetCamera(RTPoint lookFrom, RTPoint lookAt, RTVector up, float fovy) { if (_sampler == null) { throw new InvalidOperationException("La taille doit être définie avant la caméra."); } _camera = new Camera(lookFrom, lookAt, up, fovy, _sampler.Width, _sampler.Height); return(this); }
public Ray(RTPoint point, RTVector vector, float tMin, float tMax, bool directional) { Point = point; Vector = vector; TMin = tMin; TMax = tMax; Directional = directional; InvDir = 1f / Vector; Signs = new int[] { InvDir.X < 0 ? 1 : 0, InvDir.Y < 0 ? 1 : 0, InvDir.Z < 0 ? 1 : 0 }; }
private RTColor Shading(LocalGeo geo, ShadingInfos si, Ray camRay, Ray lightRay, RTColor lightCol) { float nDotL = RTVector.DotProduct(geo.Normal, lightRay.Vector); RTColor lambert = lightCol * si.Diffuse * (nDotL > 0 ? nDotL : 0.0f); RTVector half = (lightRay.Vector - camRay.Vector.Normalize()).Normalize(); float nDotH = RTVector.DotProduct(geo.Normal, half); RTColor phong = lightCol * si.Specular * (float)Math.Pow((nDotH > 0 ? nDotH : 0.0f), si.Shininess); float r = lightRay.Directional ? 0 : lightRay.TMax; // Dans le cas d'un point, le t max est la distance entre le point et la source RTColor res = (lambert + phong) / (Attenuation.Constant + Attenuation.Linear * r + Attenuation.Quadratic * (float)Math.Pow(r, 2)); return(res); }
public bool Intersect(Ray ray, bool computeGeo, out LocalGeo geo, out float pos) { RTPoint A = Vertices[0].Location; RTPoint B = Vertices[1].Location; RTPoint C = Vertices[2].Location; RTVector p0 = new RTVector(ray.Point); pos = RTVector.DotProduct(A - ray.Point, Normal) / RTVector.DotProduct(ray.Vector, Normal); geo = new LocalGeo(); if (pos >= ray.TMin && pos <= ray.TMax) { geo.Point = ray.Point + pos * ray.Vector; geo.Normal = Normal; RTVector u = B - A; RTVector v = C - A; RTVector w = geo.Point - A; RTVector vCrossW = RTVector.CrossProduct(v, w); RTVector vCrossU = RTVector.CrossProduct(v, u); if (RTVector.DotProduct(vCrossW, vCrossU) < 0) { return(false); } RTVector uCrossW = RTVector.CrossProduct(u, w); RTVector uCrossV = RTVector.CrossProduct(u, v); if (RTVector.DotProduct(uCrossW, uCrossV) < 0) { return(false); } float denom = uCrossV.Length; float r = vCrossW.Length / denom; float t = uCrossW.Length / denom; return(r + t <= 1); } return(false); }
private Matrix4x4 ComputeMatrix(RTVector axisIn, float radians) { Matrix4x4 matrix; if (axisIn.X == 1 && axisIn.Y == 0 && axisIn.Z == 0) { matrix = Matrix4x4.CreateRotationX(radians); } else if (axisIn.X == 0 && axisIn.Y == 1 && axisIn.Z == 0) { matrix = Matrix4x4.CreateRotationY(radians); } else if (axisIn.X == 0 && axisIn.Y == 0 && axisIn.Z == 1) { matrix = Matrix4x4.CreateRotationZ(radians); } else { RTVector axis = axisIn.Normalize(); Matrix4x4 part1 = Matrix4x4.Multiply(Matrix4x4.Identity, (float)Math.Cos(radians)); Matrix4x4 part2 = Matrix4x4.Multiply(new Matrix4x4((float)Math.Pow(axis.X, 2), axis.X * axis.Y, axis.X * axis.Z, 0, axis.X * axis.Y, (float)Math.Pow(axis.Y, 2), axis.Y * axis.Z, 0, axis.X * axis.Z, axis.Y * axis.Z, (float)Math.Pow(axis.Z, 2), 0, 0, 0, 0, 0), 1.0f - (float)Math.Cos(radians)); Matrix4x4 part3 = Matrix4x4.Multiply(new Matrix4x4(0, -axis.Z, axis.Y, 0, axis.Z, 0, -axis.X, 0, -axis.Y, axis.X, 0, 0, 0, 0, 0, 0), (float)Math.Sin(radians)); matrix = part1 + Matrix4x4.Transpose(part2) + Matrix4x4.Transpose(part3); matrix.M44 = 1; } return(matrix); }
private Normal ComputeNormal() { Normal res; bool normVertex = Vertices[0].Normal != null; if (normVertex) { // TODO res = new Normal(0, 1, 0); } else { RTPoint A = Vertices[0].Location; RTPoint B = Vertices[1].Location; RTPoint C = Vertices[2].Location; RTVector U = B - A; RTVector V = C - A; res = new Normal(RTVector.CrossProduct(U, V)); } return(res); }
public Scene BuildScene() { SceneBuilder sb = new SceneBuilder(); string line; InitPrimitiveProperties(); _transStack = new Stack <Transformation>(); _currentTransformation = new Transformation(); using (FileStream fs = new FileStream(_path, FileMode.Open, FileAccess.Read, FileShare.Read)) using (StreamReader sr = new StreamReader(fs)) { while (!sr.EndOfStream) { line = sr.ReadLine().TrimStart(" \t".ToCharArray()).ToLowerInvariant(); if (string.IsNullOrWhiteSpace(line) || line[0] == '#') { continue; } string[] split = line.Split(" \t".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); switch (split[0]) { #region General/Camera case "size": int width = int.Parse(split[1]); int height = int.Parse(split[2]); sb.SetSize(width, height); break; case "maxdepth": int maxDepth = int.Parse(split[1]); sb.SetMaxDepth(maxDepth); break; case "output": sb.SetOutputPath(split[1]); break; case "camera": RTPoint lFrom = PointFromConfig(split); RTPoint lAt = PointFromConfig(split, 4); RTVector up = VectorFromConfig(split, 7); float fovy = float.Parse(split[10]); sb.SetCamera(lFrom, lAt, up, fovy); break; #endregion #region Geometry case "sphere": RTPoint center = PointFromConfig(split); float radius = float.Parse(split[4]); Sphere s = new Sphere(center, radius, _currentTransformation); sb.AddGeoPrimitive(s, _currentMaterial); InitPrimitiveProperties(); break; case "maxverts": int maxverts = int.Parse(split[1]); _currentVertex = new List <Vertex>(maxverts); break; case "maxvertsnorms": int maxvertsnorms = int.Parse(split[1]); _currentVertex = new List <Vertex>(maxvertsnorms); break; case "vertex": RTPoint vertex = PointFromConfig(split); _currentVertex.Add(new Vertex(vertex)); break; case "vertexnormal": RTPoint vertexnorm = PointFromConfig(split); RTVector normal = VectorFromConfig(split, 3); _currentVertex.Add(new Vertex(vertexnorm, normal)); break; case "tri": case "trinormal": int v1 = int.Parse(split[1]); int v2 = int.Parse(split[2]); int v3 = int.Parse(split[3]); List <Vertex> vList = new List <Vertex>(); vList.Add(_currentVertex[v1]); vList.Add(_currentVertex[v2]); vList.Add(_currentVertex[v3]); Triangle tri = new Triangle(vList, _currentTransformation); sb.AddGeoPrimitive(tri, _currentMaterial); InitPrimitiveProperties(); break; #endregion #region Transforms case "translate": RTVector transvec = VectorFromConfig(split); _currentTransformation.AddTransform(new Translation(transvec)); break; case "rotate": RTVector rotaxis = VectorFromConfig(split); float degrees = float.Parse(split[4]); _currentTransformation.AddTransform(new Rotation(rotaxis, degrees)); break; case "scale": _currentTransformation.AddTransform(new Scaling(float.Parse(split[1]), float.Parse(split[2]), float.Parse(split[3]))); break; case "pushtransform": _transStack.Push(new Transformation(_currentTransformation)); break; case "poptransform": _currentTransformation = _transStack.Pop(); break; #endregion #region Lights case "directional": RTVector dir = VectorFromConfig(split); RTColor dirCol = ColorFromConfig(split, 4); sb.AddLight(new DirLight(dir, dirCol)); break; case "point": RTPoint source = PointFromConfig(split); RTColor pointCol = ColorFromConfig(split, 4); sb.AddLight(new PointLight(source, pointCol)); break; case "attenuation": Attenuation att = new Attenuation { Constant = float.Parse(split[1]), Linear = float.Parse(split[2]), Quadratic = float.Parse(split[3]) }; sb.SetAttenuation(att); break; case "ambient": RTColor ambient = ColorFromConfig(split); _currentMaterial.Properties.Ambient = ambient; break; #endregion #region Materials case "diffuse": RTColor diffuse = ColorFromConfig(split); _currentMaterial.Properties.Diffuse = diffuse; break; case "specular": RTColor spec = ColorFromConfig(split); _currentMaterial.Properties.Specular = spec; break; case "shininess": float shine = float.Parse(split[1]); _currentMaterial.Properties.Shininess = shine; break; case "emission": RTColor emission = ColorFromConfig(split); _currentMaterial.Properties.Emission = emission; break; #endregion } } } return(sb.Build()); }
public static float DotProduct(RTVector v1, RTVector v2) { return(Vector4.Dot(v1.Vector, v2.Vector)); }
public static RTVector CrossProduct(RTVector l, RTVector r) { return(new RTVector(l.Y * r.Z - l.Z * r.Y, -l.X * r.Z + l.Z * r.X, l.X * r.Y - l.Y * r.X)); }
public RTVector(RTVector vector) { Vector = new Vector4(vector.X, vector.Y, vector.Z, 0); }
public bool Intersect(Ray ray, bool computeGeo, out LocalGeo geo, out float t) { RTPoint tPoint = Transformation.ApplyInverseTo(new RTPoint(ray.Point.X, ray.Point.Y, ray.Point.Z)); RTVector tVec = Transformation.ApplyInverseTo(new RTVector(ray.Vector.X, ray.Vector.Y, ray.Vector.Z)); RTVector ec = tPoint - Center; float a = RTVector.DotProduct(tVec, tVec); float b = 2.0f * RTVector.DotProduct(tVec, ec); float c = RTVector.DotProduct(ec, ec) - (float)Math.Pow(Radius, 2); float det = (float)Math.Pow(b, 2) - 4.0f * a * c; t = float.MaxValue; bool intersect = false; if (det == 0d) { intersect = true; t = -b / (2.0f * a); } else if (det > 0d) { float t1 = (-b + (float)Math.Sqrt(det)) / (2.0f * a); float t2 = (-b - (float)Math.Sqrt(det)) / (2.0f * a); if ((t1 > 0 && t2 < 0) || (t1 < 0 && t2 > 0)) { intersect = true; if (t1 > 0) { t = t1; } else { t = t2; } } else if (t1 > 0 && t2 > 0) { intersect = true; if (t1 < t2) { t = t1; } else { t = t2; } } } geo = new LocalGeo(); if (intersect && t >= ray.TMin && t <= ray.TMax) { if (computeGeo) { geo.Point = tPoint + t * tVec; geo.Normal = new Normal(geo.Point - Center); geo.Point = Transformation.ApplyTo(geo.Point); geo.Normal = new Normal(Transformation.ApplyInverseTransposeTo(geo.Normal)); } return(true); } return(false); }
public DirLight(RTVector dir, RTColor color) { Direction = dir; Color = color; }
public RTVector ApplyInverseTransposeTo(RTVector v) { return(v.ApplyMatrix(Matrix4x4.Transpose(ComputeInverse()))); }
public Normal(RTVector vec) : base(vec) { Vector4 norm = Vector4.Normalize(new Vector4(vec.X, vec.Y, vec.Z, 0)); Vector = norm; }
public RTColor Trace(Ray ray, int depth) { RTColor res = new RTColor(); float lastT = float.MaxValue; bool shadow; // TODO: initialiser l'arbre autrepart // TODO: corriger la bounding box des spheres if (_tree == null) { _tree = new BBTree(Primitives); } IEnumerable <HitResult> hits = _tree.Hit(ray); //IList<HitResult> hits = Primitives.Select(p => //{ // if (p.Intersect(ray, true, out LocalGeo geo, out float t)) // { // return new HitResult { Primitive = p, Geo = geo, T = t }; // } // return null; //}).Where(h => h != null).ToList(); foreach (HitResult h in hits) { if (h.T < lastT) { lastT = h.T; ShadingInfos si = h.Primitive.GetShading(h.Geo); // Ambient & emission res = si.Emission + si.Ambient; // Phong shading foreach (ILight light in Lights) { shadow = false; RTColor lightCol; Ray lightRay = light.GenerateRay(h.Geo, out lightCol); foreach (IPrimitive pShadow in Primitives) { if (pShadow.Intersect(lightRay, false, out _, out _)) { shadow = true; } } if (!shadow) { res += Shading(h.Geo, si, ray, lightRay, lightCol); } } // Reflection if ((si.Specular.Red > 0 || si.Specular.Green > 0 || si.Specular.Blue > 0) && depth < MaxDepth) { Ray reflected = new Ray(h.Geo.Point, ray.Vector - 2.0f * RTVector.DotProduct(ray.Vector, h.Geo.Normal) * h.Geo.Normal, 1e-3f, float.MaxValue, false); res += si.Specular * Trace(reflected, depth + 1); } } } return(res); }
public RTVector ApplyTo(RTVector v) { return(v.ApplyMatrix(Compute())); }
public RTVector ApplyInverseTo(RTVector v) { return(v.ApplyMatrix(ComputeInverse())); }
public Translation(RTVector vector) { Vector = vector; }
public Rotation(RTVector axis, float degrees) { Axis = axis; Degrees = degrees; }