//Sphere constructor public Cube(Vector3 frontFloor, float h, float w, float d) { planes = new List<GeometricObject>(); hitTri = new Triangle(); frontFloorPoint = frontFloor; height = h; width = w; depth = d; frontTopPoint = frontFloorPoint - new Vector3(0, height, 0); leftFloorPoint = new Vector3(frontFloorPoint.X - width, frontFloorPoint.Y, frontFloorPoint.Z + depth); backFloorPoint = new Vector3(frontFloorPoint.X, frontFloorPoint.Y, frontFloorPoint.Z + depth + depth); rightFloorPoint = new Vector3(frontFloorPoint.X + width, frontFloorPoint.Y, frontFloorPoint.Z + depth); leftTopPoint = leftFloorPoint - new Vector3(0, height, 0); backTopPoint = backFloorPoint - new Vector3(0, height, 0); rightTopPoint = rightFloorPoint - new Vector3(0, height, 0); }
public virtual Vector3 NormalAtCube(Vector3 i, Vector3 from, Triangle tri) { throw new Exception("INTERSECTION NOT IMPLEMENTED!!!"); }
private Vector3 GetPixelColorFromTexture(Vector3 hp, Triangle hitShape){ if (hitShape.Tag == "t3") { int i = 0; } KeyValuePair<Vector3,Vector2>[] posTex = new KeyValuePair<Vector3,Vector2>[3]; posTex[0] = new KeyValuePair<Vector3,Vector2>(hitShape.Vertices[0], hitShape.TextureCoords[0]); posTex[1] = new KeyValuePair<Vector3,Vector2>(hitShape.Vertices[1], hitShape.TextureCoords[1]); posTex[2] = new KeyValuePair<Vector3,Vector2>(hitShape.Vertices[2], hitShape.TextureCoords[2]); Vector3 B1, B2; Vector2 C1, C2; Vector2 Offset; if (posTex[0].Key.Length() < posTex[1].Key.Length() && posTex[0].Key.Length() < posTex[2].Key.Length()) { C1 = posTex[1].Value - posTex[0].Value; C2 = posTex[2].Value - posTex[0].Value; B1 = posTex[1].Key - posTex[0].Key; B2 = posTex[2].Key - posTex[0].Key; Offset = posTex[0].Value; } else if (posTex[1].Key.Length() < posTex[0].Key.Length() && posTex[1].Key.Length() < posTex[2].Key.Length()) { C1 = posTex[0].Value - posTex[1].Value; C2 = posTex[2].Value - posTex[1].Value; B1 = posTex[0].Key - posTex[1].Key; B2 = posTex[2].Key - posTex[1].Key; Offset = posTex[1].Value; } else { C1 = posTex[1].Value - posTex[2].Value; C2 = posTex[0].Value - posTex[2].Value; B1 = posTex[1].Key - posTex[2].Key; B2 = posTex[0].Key - posTex[2].Key; Offset = posTex[2].Value; } float p1, p2; float a, b, c, d; if (hitShape.TCC == TextureCoordConst.Z) { a = B1.X; b = B2.X; c = B1.Y; d = B2.Y; p1 = hp.X; p2 = hp.Y; } else if (hitShape.TCC == TextureCoordConst.X) { a = B1.Z; b = B2.Z; c = B1.Y; d = B2.Y; p1 = hp.Z; p2 = hp.Y; } else if (hitShape.TCC == TextureCoordConst.Y) { a = B1.X; b = B2.X; c = B1.Z; d = B2.Z; p1 = hp.X; p2 = hp.Z; } else { throw new Exception("No Texture Coord Const set"); } float det = 1 / (a * d - b * c); float alpha = d * p1 - b * p2; float beta = -c * p1 + a * p2; alpha *= det; beta *= det; Vector2 UV = alpha * C1 + beta * C2; UV += Offset; if (UV.X > 1) UV.X = 1; if (UV.Y > 1) UV.Y = 1; float xReal = UV.Y * hitShape.TextureToUse.TexSize.Y - 1; float yReal = UV.X * hitShape.TextureToUse.TexSize.X - 1; int x0 = (int)xReal, y0 = (int)yReal; float dx = xReal - x0, dy = yReal - y0, omdx = 1 - dx, omdy = 1 - dy; if (x0 < 1) x0 = 1; if (y0 < 1) y0 = 1; if (x0 == hitShape.TextureToUse.TexSize.Y - 1 || y0 == hitShape.TextureToUse.TexSize.X - 1 || x0 == 0 || y0 == 0) return hitShape.TextureToUse.TexturePixels[x0, y0]; Vector3 color = omdx * omdy * hitShape.TextureToUse.TexturePixels[x0, y0] + omdx * dy * hitShape.TextureToUse.TexturePixels[x0, y0 - 1] + dx * omdy * hitShape.TextureToUse.TexturePixels[x0 - 1, y0] + dx * dy * hitShape.TextureToUse.TexturePixels[x0 - 1, y0 - 1]; return color; }
/// <summary> /// Traces rays and calculates their color. Recursive method /// </summary> /// <param name="ray"></param> /// <param name="depth"></param> /// <param name="coef"></param> /// <param name="specOn">if at any point an object is not specular, all successive recursive calls will ignore specular</param> /// <returns></returns> private Vector3 AddRay(Ray ray, int depth, float coef, ref float prevDist, float lastRIndex = 1) { Vector3 curColor = new Vector3(0, 0, 0); GeometricObject hitShape = null; double hitShapeDist = float.MaxValue; Vector3 vNormal; Vector3 hp; float LightValue = 0.0f; Triangle hitTri = new Triangle(); foreach (GeometricObject shape in Shapes) { if (shape == null) continue; double t; if (shape is Cube) { Tuple<double, Triangle> temp = shape.intersectionCube(ray); t = temp.Item1; hitTri = temp.Item2; } else { t = shape.intersection(ray); } if (t > 0.0 && t < hitShapeDist) { hitShape = shape; hitShapeDist = t; prevDist = (float)t; } } if (hitShape == null) { if (depth == 0) return new Vector3(-1, -1, -1); else return new Vector3(0, 0, 0); } else { hp = FindPointOnRay(ray, hitShapeDist); if (hitShape is Cube) { vNormal = hitShape.NormalAtCube(hp, Eye, hitTri); } else { vNormal = hitShape.NormalAt(hp, Eye); } if (hitShape.surface.type == textureType.bump) { const double bumpLevel = 0.2; double noiseX = perlinTexture.noise(0.1 * (double)hp.X, 0.1 * (double)hp.Y, 0.1 * (double)hp.Z); double noiseY = perlinTexture.noise(0.1 * (double)hp.Y, 0.1 * (double)hp.Z, 0.1 * (double)hp.X); double noiseZ = perlinTexture.noise(0.1 * (double)hp.Z, 0.1 * (double)hp.X, 0.1 * (double)hp.Y); vNormal.X = (float)((1.0 - bumpLevel) * vNormal.X + bumpLevel * noiseX); vNormal.Y = (float)((1.0 - bumpLevel) * vNormal.Y + bumpLevel * noiseY); vNormal.Z = (float)((1.0 - bumpLevel) * vNormal.Z + bumpLevel * noiseZ); double temp = Vector3.Dot(vNormal, vNormal); if (temp != 0.0) { temp = 1.0 / Math.Sqrt(temp); vNormal = (float)temp * vNormal; } } vNormal.Normalize(); foreach (Light light in Lights) { Vector3 dir = light.position - hp; dir.Normalize(); Ray lightRay = new Ray(hp, dir); if ((LightValue = isVisible(light, hp, lightRay)) > 0) { Vector3 color = new Vector3(); if (hitShape is Triangle) { if (((Triangle)hitShape).HasTexture) { color = GetPixelColorFromTexture(hp, hitShape as Triangle); } else { color = hitShape.surface.color; } } else { color = hitShape.surface.color; } //TODO to add ambient just do Llight[ambient] * hitShape[ambiemt] float lambert = Vector3.Dot(lightRay.Direction, vNormal) ; curColor += light.intensity * lambert * ((light.color)) * (color) * coef; Vector3 blinn = lightRay.Direction - ray.Direction; blinn.Normalize(); float blinnValue = (float)Math.Pow(Math.Max(0, Vector3.Dot(vNormal, blinn)), hitShape.surface.SpecExponent); curColor += hitShape.surface.specular * light.intensity * light.color * blinnValue * coef; curColor *= LightValue; } } } if (depth >= NumBounces) return Clamp(curColor); else { //calculate reflections Vector3 dir = ray.Direction - (2.0f * Vector3.Dot(ray.Direction, vNormal)) * vNormal; dir.Normalize(); float UGH = 0; curColor += AddRay(new Ray(hp, dir), depth + 1, coef * ((float)hitShape.surface.reflectiveness / 100.0f), ref UGH); //calculate refraction (nigguh) float refr = hitShape.surface.RefractionIndex; if (refr > 0) { float n = lastRIndex/refr; float cos = Vector3.Dot(ray.Direction, vNormal); float sin = (float)Math.Pow(n, 2) * (1 - (float)Math.Pow(cos,2)); if (Math.Pow(sin,2) <= 1) { Vector3 transmissiveDir = n * ray.Direction - (n * cos + (float)Math.Sqrt(1 - (float)Math.Pow(sin, 2))) * vNormal; transmissiveDir.Normalize(); float dist = 0; Vector3 theColor = AddRay(new Ray(hp, transmissiveDir), depth + 1, coef, ref dist, refr); Vector3 absorbance = hitShape.surface.color * 0.0000015f * -dist; Vector3 trans = new Vector3((float)Math.Exp(absorbance.X), (float)Math.Exp(absorbance.Y), (float)Math.Exp(absorbance.Z)); curColor += theColor * trans; } } } return Clamp(curColor); }
public override Vector3 NormalAtCube(Vector3 i, Vector3 from, Triangle tri) { if (tri.Normal.X != float.MaxValue) return tri.Normal; else return Vector3.Cross(tri.Vertices[0] - tri.Vertices[1], tri.Vertices[2] - tri.Vertices[1]); }
public override Tuple<double, Triangle> intersectionCube(Ray ray) { float closest = float.PositiveInfinity; foreach (Triangle triangle in planes) { Vector3 p0 = triangle.Vertices[0]; Vector3 p1 = triangle.Vertices[2]; Vector3 p2 = triangle.Vertices[1]; Vector3 e1 = p1 - p0; Vector3 e2 = p2 - p0; Vector3 p = Vector3.Cross(ray.Direction, e2); float a = Vector3.Dot(e1, p); if (a < 0.000001) continue;// return 0.0; float f = 1.0f / a; Vector3 s = ray.Start - p0; float u = f * Vector3.Dot(s, p); if (u < 0.0 || u > 1.0) continue;// return 0.0; Vector3 q = Vector3.Cross(s, e1); float v = f * Vector3.Dot(ray.Direction, q); if (v < 0.0 || u + v > 1.0) continue;// return 0.0; float t = f * Vector3.Dot(e2, q); //return t; if (t < closest) { closest = t; hitTri = triangle; } } if (closest < float.PositiveInfinity) { return new Tuple<double,Triangle>(closest,hitTri); } else return new Tuple<double, Triangle>(0.0, null) ; }