public Vertex(RTPoint vertex, RTVector normal) { Location = vertex; if (normal != null) { Normal = new Normal(normal); } }
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 Sphere(RTPoint center, float radius, Transformation transformation) { Center = center; Radius = radius; Transformation = transformation; _boundingBox = new BoundingBox(Transformation.ApplyTo(new RTPoint(Center.X - Radius, Center.Y - Radius, Center.Z - Radius)), Transformation.ApplyTo(new RTPoint(Center.X + Radius, Center.Y + Radius, Center.Z + Radius))); }
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 Triangle(List <Vertex> vertices, Transformation transformation) { Vertices = new List <Vertex>(); float minX = float.MaxValue; float minY = float.MaxValue; float minZ = float.MaxValue; float maxX = float.MinValue; float maxY = float.MinValue; float maxZ = float.MinValue; foreach (Vertex v in vertices) { RTPoint point = transformation.ApplyTo(v.Location); //point /= point.W; Normal normal = null; if (v.Normal != null) { normal = new Normal(transformation.ApplyTo(v.Normal)); } Vertices.Add(new Vertex(point, normal)); if (point.X < minX) { minX = point.X; } if (point.Y < minY) { minY = point.Y; } if (point.Z < minZ) { minZ = point.Z; } if (point.X > maxX) { maxX = point.X; } if (point.Y > maxY) { maxY = point.Y; } if (point.Z > maxZ) { maxZ = point.Z; } } Normal = ComputeNormal(); _boundingBox = new BoundingBox(minX, maxX, minY, maxY, minZ, maxZ); }
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 }; }
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); }
public void Commit(RTPoint point, Color color) { lock (_lock) { // TODO : "accumuler" valeur si dans même pixel _film.SetPixel((int)(float)Math.Floor(point.X), (int)(float)Math.Floor(point.Y), color); } Interlocked.Increment(ref _commited); long time = _sw.ElapsedMilliseconds; if (time - _lastCommit > 500L) { long total = Width * Height; _lastCommit = time; float pps = (_commited / (float)time) * 1000f; TimeSpan elapsed = TimeSpan.FromMilliseconds(time); TimeSpan remaining = TimeSpan.FromSeconds((total - _commited) / pps); Console.Write($"\rElapsed : {elapsed.TotalHours:0}:{elapsed.Minutes:00}:{elapsed.Seconds:00} - {_commited}/{total} - {pps:0.00} pixel/s - Est. remaining : {remaining.TotalHours:0}:{remaining.Minutes:00}:{remaining.Seconds:00} <>"); } }
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 RTVector(RTPoint p) { Vector = new Vector4(p.X, p.Y, p.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 RTPoint ApplyTo(RTPoint p) { return(p.ApplyMatrix(Compute())); }
public BoundingBox() { Min = new RTPoint(0f, 0f, 0f); Max = new RTPoint(0f, 0f, 0f); }
public BoundingBox(float xMin, float xMax, float yMin, float yMax, float zMin, float zMax) { Min = new RTPoint(xMin, yMin, zMin); Max = new RTPoint(xMax, yMax, zMax); }
public PointLight(RTPoint source, RTColor color) { Source = source; Color = color; }
public Vertex(RTPoint vertex) { Location = vertex; Normal = null; }
public RTPoint ApplyInverseTo(RTPoint p) { return(p.ApplyMatrix(ComputeInverse())); }
public Vertex(float x, float y, float z) { Location = new RTPoint(x, y, z); Normal = null; }
public BoundingBox(RTPoint min, RTPoint max) { Min = min; Max = max; }
public Vertex(float x, float y, float z, float nx, float ny, float nz) { Location = new RTPoint(x, y, z); Normal = new Normal(nx, ny, nz); }
public RTPoint(RTPoint p) { Vector = new Vector4(p.X, p.Y, p.Z, p.W); }