public override bool IsHit(Ray ray, HitRecord record, float near, float far) { throw new NotImplementedException(); }
public override bool IsHit(Ray ray, HitRecord record, float near, float far) { Vector newCenter; if (Velocity.IsBlack()) newCenter = Center; else { newCenter = this.Center + ray.Time * this.Velocity; } //e - c Vector eMinusC = ray.Start - newCenter; //d.(e-c) float dDotEMinusC = Vector.Dot3(ray.Direction, eMinusC); float dDotD = Vector.Dot3(ray.Direction, ray.Direction); //d.(e-c)^2 - (d.d)((e-c).(e-c) - R^2)) float discriminant = dDotEMinusC * dDotEMinusC - dDotD * (Vector.Dot3(eMinusC, eMinusC) - this.Radius * this.Radius); //Intersection occurs float t1 = 0, t2 = 0, first_t = 0; if (discriminant >= 0) { t1 = (-dDotEMinusC + (float)Math.Sqrt(discriminant)) / dDotD; t2 = (-dDotEMinusC - (float)Math.Sqrt(discriminant)) / dDotD; Vector diff; Vector worldCoords; if (t2 >= 0) first_t = t2; else if (t1 >= 0) first_t = t1; else return false; // t*d diff = ray.Direction * first_t; // e + t*d worldCoords = diff + ray.Start; float distance = diff.Magnitude3(); if (distance <= record.Distance && distance <= ray.MaximumTravelDistance) { if (ray.UseBounds) { float cameraOrthogonalDistance = Math.Abs(Vector.Dot3(diff, ray.CameraLookDirection)); if (cameraOrthogonalDistance > far && cameraOrthogonalDistance < near) { return false; } } record.T = first_t; record.HitPoint = ray.Start + diff; record.Distance = distance; record.Material = this.Material; record.SurfaceNormal = SurfaceNormal(record.HitPoint, ray.Direction); if (Material.TextureImage != null) { double cos = (record.HitPoint.z - newCenter.z) / Radius; if (cos < -1) cos = -1; else if (cos > 1) cos = 1; double theta = Math.Acos(cos); double phi = Math.Atan2(record.HitPoint.y - newCenter.y, record.HitPoint.x - newCenter.x); if (phi < 0) phi += 2 * Math.PI; float u = (float)(phi / (2 * Math.PI)); float v = (float)((Math.PI - theta) / Math.PI); //Console.WriteLine(this.textureWidth); //Console.WriteLine(this.Material.TextureImage.Height); //int i = (int)(u * (this.textureWidth - 1) + 0.5); //int j = (int)(v * (this.textureHeight - 1) + 0.5); record.TextureColor = this.Material.GetTexturePixelColor(u, v); } return true; } } return false; }
public override bool IsHit(Ray ray, HitRecord record, float near, float far) { //(d.h)h Vector dDotHTimesH = Vector.Dot3(ray.Direction, HeightDirection) * HeightDirection; Vector deltaP = ray.Start - this.BasePoint; Vector deltaPDotHTimesH = Vector.Dot3(deltaP, HeightDirection) * HeightDirection; Vector deltaPMinusdeltaPDotHTimesH = deltaP - deltaPDotHTimesH; Vector dMinusdDotHTimesH = ray.Direction - dDotHTimesH; float B = 2 * Vector.Dot3(dMinusdDotHTimesH, deltaPMinusdeltaPDotHTimesH); float A = Vector.Dot3(dMinusdDotHTimesH, dMinusdDotHTimesH); float C = Vector.Dot3(deltaPMinusdeltaPDotHTimesH, deltaPMinusdeltaPDotHTimesH) - this.Radius * this.Radius; Vector diff, worldCoords; float discriminant = B * B - 4 * A * C; float t1 = 0, t2 = 0, first_t = float.MaxValue; List<float> candidates = new List<float>(); IntersectionType intersectionType = IntersectionType.Cylinder; if (discriminant >= 0) { t1 = (-B - (float)Math.Sqrt(discriminant)) / (2 * A); t2 = (-B + (float)Math.Sqrt(discriminant)) / (2 * A); if (t1 >= 0 && IsInside(ray.Start + ray.Direction*t1)) { first_t = t1; } if (t2 >= 0 && IsInside(ray.Start + ray.Direction*t2) && t2 < first_t) { first_t = t2; } } float hDotd = Vector.Dot3(this.HeightDirection, ray.Direction); if (hDotd != 0) { float basePlaneT = Vector.Dot3(this.HeightDirection, this.BasePoint) - Vector.Dot3(this.HeightDirection, ray.Start); basePlaneT = basePlaneT / hDotd; if (basePlaneT > 0 && IsCap(this.BasePoint, basePlaneT * ray.Direction + ray.Start) && basePlaneT < first_t) { intersectionType = IntersectionType.Base; first_t = basePlaneT; } float endPlaneT = Vector.Dot3(this.HeightDirection, this.EndPoint) - Vector.Dot3(this.HeightDirection, ray.Start); endPlaneT = endPlaneT / hDotd; if (endPlaneT > 0 && IsCap(this.EndPoint, endPlaneT * ray.Direction + ray.Start) && endPlaneT < first_t) { intersectionType = IntersectionType.End; first_t = endPlaneT; } } if (first_t == float.MaxValue) return false; // t*d diff = ray.Direction * first_t; // e + t*d worldCoords = diff + ray.Start; float distance = diff.Magnitude3(); if (distance <= record.Distance && distance <= ray.MaximumTravelDistance) { if (ray.UseBounds) { float cameraOrthogonalDistance = Math.Abs(Vector.Dot3(diff, ray.CameraLookDirection)); if (cameraOrthogonalDistance > far && cameraOrthogonalDistance < near) { return false; } } record.T = first_t; record.HitPoint = ray.Start + diff; record.Distance = distance; record.Material = this.Material; if (intersectionType == IntersectionType.Cylinder) { record.SurfaceNormal = SurfaceNormal(record.HitPoint, ray.Direction); if (Material.TextureImage != null) { float heightReached = Vector.Dot3(HeightDirection, record.HitPoint - this.BasePoint); float u = heightReached / Height; Vector circCenter = BasePoint + HeightDirection * heightReached; Vector projection = record.HitPoint - circCenter; projection.Normalize3(); float similarity = Vector.Dot3(projection, Tangent); float theta = (float)Math.Acos(similarity); float v = (float)((Math.PI - theta) / Math.PI); v = v < 0 ? -v : v; record.TextureColor = this.Material.GetTexturePixelColor(u, v); // float v = } } else { record.SurfaceNormal = PlaneNormal(record.HitPoint, ray.Direction); if (Material.TextureImage != null) { Vector circCenter = intersectionType == IntersectionType.Base ? BasePoint : EndPoint; Vector projection = record.HitPoint - circCenter; float length = projection.Magnitude3(); projection.Normalize3(); float similarity = Vector.Dot3(projection, Tangent); float theta = (float)Math.Acos(similarity); float u = length / Radius; float v = (float)((Math.PI - theta) / Math.PI); v = v < 0 ? -v : v; record.TextureColor = this.Material.GetTexturePixelColor(u, v); // float v = } } // record.SurfaceNormal = SurfaceNormal(record.HitPoint, ray.Direction); return true; } return false; }
public override bool IsHit(Ray ray, HitRecord record, float near, float far) { bool isHit = false; foreach (SceneTriangle triangle in triangles) { isHit = triangle.IsHit(ray, record, near, far) || isHit; } if (isHit) { record.ObjectName = this.Name; if (Material.TextureImage != null) { Vector l1 = Vertex[1] - Vertex[0]; Vector l2 = Vertex[3] - Vertex[0]; float f = l1.x; float g = l2.x; float h = record.HitPoint.x; float i = Vertex[0].x; float j = l1.y; float k = l2.y; float l = record.HitPoint.y; float m = Vertex[0].y; float n = l1.z; float o = l2.z; float p = record.HitPoint.z; float q = Vertex[0].z; float det = g * j - f * k; if (det == 0) { det = o * j - n * k; if (det == 0) { det = g * n - f * o; j = n; k = o; l = p; m = q; } else { f = n; h = o; h = p; i = q; } } if (det != 0) { float alpha = (g * l - g * m - h * k + i * k) / det; float beta = (-f * l + f * m + h * j - i * j) / det; //if (RenderingParameters.showMouse) //{ //Console.WriteLine("alpha: " + alpha + "\tbeta: " + beta); record.TextureColor = this.Material.GetTexturePixelColor(alpha, beta); } // } } } return isHit; }
public abstract bool IsHit(Ray ray, HitRecord record, float near, float far);
public override bool IsHit(Ray ray, HitRecord record, float near, float far) { //Vamos precalculando variables auxiliares para facilitar el calculo y aumentar eficiencia //Convencion de nombres usada es la misma del libro "Fundamentals of Computer Graphics": /* * | a d g | | beta | | j | * | b e h | | gamma | = | k | * | c f i | | t | = | l | */ float a = Vertex[0].x - Vertex[1].x; float b = Vertex[0].y - Vertex[1].y; float c = Vertex[0].z - Vertex[1].z; float d = Vertex[0].x - Vertex[2].x; float e = Vertex[0].y - Vertex[2].y; float f = Vertex[0].z - Vertex[2].z; float g = ray.Direction.x; float h = ray.Direction.y; float i = ray.Direction.z; float j = Vertex[0].x - ray.Start.x; float k = Vertex[0].y - ray.Start.y; float l = Vertex[0].z - ray.Start.z; float eiMinushf = e * i - h * f; float gfMinusdi = g * f - d * i; float dhMinuseg = d * h - e * g; float akMinusjb = a * k - j * b; float jcMinusal = j * c - a * l; float blMinuskc = b * l - k * c; float M = a * eiMinushf + b * gfMinusdi + c * dhMinuseg; //e + td = punto triangulo float t = -(f * akMinusjb + e * jcMinusal + d * blMinuskc) / M; if (t >= 0) { float gamma = (i * akMinusjb + h * jcMinusal + g * blMinuskc) / M; if (gamma >= 0) { float beta = (j * eiMinushf + k * gfMinusdi + l * dhMinuseg) / M; //alpha = 1 - beta - gamma if (beta >= 0 && 1 - beta - gamma >= 0) { Vector diff = t * ray.Direction; float distance = diff.Magnitude3(); if (distance <= record.Distance && distance <= ray.MaximumTravelDistance) { if (ray.UseBounds) { float cameraOrthogonalDistance = Math.Abs(Vector.Dot3(diff, ray.CameraLookDirection)); if (cameraOrthogonalDistance > far && cameraOrthogonalDistance < near) { return false; } } record.T = t; record.HitPoint = ray.Start + diff; record.Distance = distance; record.Material = Materials[0]; record.SurfaceNormal = SurfaceNormal(record.HitPoint, ray.Direction); if (record.Material.TextureImage != null) { float alpha = 1 - beta - gamma; float u = alpha * U[0] + beta * U[1] + gamma * U[2]; float v = alpha * V[0] + beta * V[1] + gamma * V[2]; record.TextureColor = record.Material.GetTexturePixelColor(u, v); } return true; } } } } return false; }