public IntersectionInfo Intersection(Ray r) { Vector3D normal = VectorOperations.VectorProduct(new Vector3D(A, B), new Vector3D(A, C)); normal *= (1 / normal.Length); Vector3D V = new Vector3D(r.Origin.X - A.X, r.Origin.Y - A.Y, r.Origin.Z - A.Z); //определяем пересекает ли луч треугольник double t = -VectorOperations.ScalarProduct(V, normal) / VectorOperations.ScalarProduct(r.Direction, normal); if (t <= epsilon || Double.IsNaN(t) || Double.IsInfinity(t)) { return(null); } Point3D crossPoint = new Point3D(r.Origin.X + r.Direction.X * t, r.Origin.Y + r.Direction.Y * t, r.Origin.Z + r.Direction.Z * t); Vector3D OX = new Vector3D(A, B); Vector3D AC = new Vector3D(A, C); Vector3D AD = new Vector3D(A, crossPoint); Vector3D OY = VectorOperations.VectorProduct(normal, OX); Line3D axis = new Line3D(A, OX); Line3D ordinate = new Line3D(A, OY); double Bx = VectorOperations.Distance(ordinate, B); double By = 0; double Cx = VectorOperations.Distance(ordinate, C) * ((VectorOperations.Cos(OX, AC) < 0)? -1 : 1); double Cy = VectorOperations.Distance(axis, C) * ((VectorOperations.Cos(OY, AC) < 0)? -1 : 1); double Dx = VectorOperations.Distance(ordinate, crossPoint) * ((VectorOperations.Cos(OX, AD) < 0)? -1 : 1); double Dy = VectorOperations.Distance(axis, crossPoint) * ((VectorOperations.Cos(OY, AD) < 0) ? -1 : 1); int s1 = Math.Sign(Bx * Dy - By * Dx); int s2 = Math.Sign((Cx - Bx) * (Dy - By) - (Cy - By) * (Dx - Bx)); int s3 = Math.Sign(-Cx * (Dy - Cy) + Cy * (Dx - Cx)); if (s1 == s2 && s1 == s3 && s2 == s3) { Material m = ownerSurface.MaterialFront; if (VectorOperations.Cos(normal, r.Direction) >= -epsilon && (ownerSurface.MaterialBack != null)) { normal *= (-1); m = ownerSurface.MaterialBack; } return(new IntersectionInfo(crossPoint, normal, m)); } return(null); }
public IntersectionInfo Intersection(Ray r) { Vector3D N = VectorOperations.VectorProduct(new Vector3D(A, B), new Vector3D(A, C)); //нормаль определяет внешнюю и внутреннюю сторону треугольника N *= (1 / N.Length); Vector3D V = new Vector3D(r.Origin.X - A.X, r.Origin.Y - A.Y, r.Origin.Z - A.Z); double t = -VectorOperations.ScalarProduct(V, N) / VectorOperations.ScalarProduct(r.Direction, N); if (t <= epsilon || Double.IsNaN(t) || Double.IsInfinity(t)) { return(null); } Point3D crossPoint = new Point3D(r.Origin.X + r.Direction.X * t, r.Origin.Y + r.Direction.Y * t, r.Origin.Z + r.Direction.Z * t); Vector3D OX = new Vector3D(A, B); Vector3D AC = new Vector3D(A, C); Vector3D AD = new Vector3D(A, crossPoint); Vector3D OY = VectorOperations.VectorProduct(N, OX); Line3D axis = new Line3D(A, OX); Line3D ordinate = new Line3D(A, OY); double Bx = VectorOperations.Distance(ordinate, B); double By = 0; double Cx = VectorOperations.Distance(ordinate, C); if (VectorOperations.Cos(OX, AC) < 0) { Cx *= -1; } double Cy = VectorOperations.Distance(axis, C); if (VectorOperations.Cos(OY, AC) < 0) { Cy *= -1; } double Dx = VectorOperations.Distance(ordinate, crossPoint); if (VectorOperations.Cos(OX, AD) < 0) { Dx *= -1; } double Dy = VectorOperations.Distance(axis, crossPoint); if (VectorOperations.Cos(OY, AD) < 0) { Dy *= -1; } int s1 = Math.Sign(Bx * Dy - By * Dx); int s2 = Math.Sign((Cx - Bx) * (Dy - By) - (Cy - By) * (Dx - Bx)); int s3 = Math.Sign(-Cx * (Dy - Cy) + Cy * (Dx - Cx)); if (s1 == s2 && s1 == s3 && s2 == s3) { Material m = material_front; if (VectorOperations.Cos(N, r.Direction) >= -epsilon && (material_back != null)) { N *= (-1); m = material_back; } return(new IntersectionInfo(crossPoint, N, m)); } return(null); }
//public Material Material //{ // set // { // material = value; // } //} public IntersectionInfo Intersection(Ray r) { double epsilon = 0.01; Vector3D v = new Vector3D(r.Origin.X - center.X, r.Origin.Y - center.Y, r.Origin.Z - center.Z); double A = r.Direction.LengthSquare; double B = VectorOperations.ScalarProduct(r.Direction, v); double C = v.LengthSquare - radius * radius; double D = B * B - A * C; if (D <= 0.0) { return(null); } double t1 = (-B - Math.Sqrt(D)) / A; double t2 = (-B + Math.Sqrt(D)) / A; double t = t1; if (t2 <= epsilon) { return(null); } if (t1 <= epsilon) //луч идет из шара { t = t2; } Point3D P = new Point3D(r.Origin.X + r.Direction.X * t, r.Origin.Y + r.Direction.Y * t, r.Origin.Z + r.Direction.Z * t); //первая точка пересечения Vector3D N = new Vector3D(center, P); //вектор нормали единичной длины N *= (1 / N.Length); if (t1 <= epsilon) //луч идет из шара { N *= (-1.0); } if (texture != null) { Point3D E = new Point3D(P.X - center.X, P.Y - center.Y, P.Z - center.Z); double psi, fi; psi = Math.Asin(E.Z / radius); if (Math.Abs(psi) == Math.PI / 2) { fi = 0; } else { double cosfi = E.X / (radius * Math.Cos(psi)); if (cosfi > 1) { cosfi = 1; } if (cosfi < -1) { cosfi = -1; } fi = Math.Acos(cosfi); if (E.Y < 0) { fi = 2 * Math.PI - fi; } } Material m; lock (texture) { int x = (int)((fi / (Math.PI * 2)) * (texture.Width - 1)); int y = (int)((0.5 - psi / Math.PI) * (texture.Height - 1)); m = new Material(texture.GetPixel(x, y), material.Diffusion, material.Specularity, material.Reflection, material.Transparency, material.FongCoeff); } material = m; } return(new IntersectionInfo(P, N, material)); }