所以基本上我想在三角形上反射一条光线。这是我的射线课
public sealed class Ray
{
public readonly Point3D Source;
public readonly Point3D Direction;
public readonly Color Light;
public Ray(Point3D source, Point3D direction, Color light)
{
if (source == direction)
{
throw new ArgumentException("Source and Direction cannot be equal");
}
this.Source = source;
this.Direction = direction;
this.Light = light;
}
}
这是我的 Point3D 课程
public struct Point3D : IEquatable<Point3D>
{
public static readonly Point3D Zero = new Point3D();
public float X;
public float Y;
public float Z;
public Point3D(float x, float y, float z)
{
this.X = x;
this.Y = y;
this.Z = z;
}
public override bool Equals(object obj)
{
if (!(obj is Point3D))
{
return false;
}
return this.Equals((Point3D)obj);
}
public static bool operator ==(Point3D one, Point3D two)
{
return one.Equals(two);
}
public static bool operator !=(Point3D one, Point3D two)
{
return !one.Equals(two);
}
public static Point3D operator *(float n, Point3D v)
{
return new Point3D(v.X * n, v.Y * n, v.Z * n);
}
public static Point3D operator +(Point3D v1, Point3D v2)
{
return new Point3D(v1.X + v2.X, v1.Y + v2.Y, v1.Z + v2.Z);
}
public static Point3D operator -(Point3D v1, Point3D v2)
{
return new Point3D(v1.X - v2.X, v1.Y - v2.Y, v1.Z - v2.Z);
}
public static float operator *(Point3D v1, Point3D v2)
{
return (v1.X * v2.X) + (v1.Y * v2.Y) + (v1.Z * v2.Z);
}
public static float Magnitude(Point3D v)
{
return (float)Math.Sqrt(v * v);
}
public static Point3D Normalize(Point3D v)
{
float mag = Magnitude(v);
float div = (mag == 0) ? float.PositiveInfinity : (1 / mag);
return div * v;
}
public static Point3D Cross(Point3D v1, Point3D v2)
{
return new Point3D(((v1.Y * v2.Z) - (v1.Z * v2.Y)),
((v1.Z * v2.X) - (v1.X * v2.Z)),
((v1.X * v2.Y) - (v1.Y * v2.X)));
}
/// <summary>
/// doesnt take square root
/// </summary>
public static float FastDistance(Point3D v1, Point3D v2)
{
float x = v1.X - v2.X;
x *= x;
float y = v1.Y - v2.Y;
y *= y;
float z = v1.Z - v2.Z;
z *= z;
return x + y + z;
}
/// <summary>
/// Takes square root:
/// </summary>
public static float Distance(Point3D v1, Point3D v2)
{
return (float)Math.Sqrt(Point3D.FastDistance(v1, v2));
}
public override int GetHashCode()
{
return this.X.GetHashCode()
^ this.Y.GetHashCode()
^ this.Y.GetHashCode();
}
public override string ToString()
{
return this.X + ", " + this.Y + ", " + this.Z;
}
public bool Equals(Point3D other)
{
return this.X == other.X
&& this.Y == other.Y
&& this.Z == other.Z;
}
}
最后,这是我需要实现我的方法的地方。
public interface ITriangleAccess
{
Triangle3D Find(Ray ray, out Point3D crossPoint);
}
public sealed class TriangleAccess : ITriangleAccess
{
private readonly List<KeyValuePair<float, Triangle3D>> trianglesByX;
private readonly List<Triangle3D> allTriangles;
public TriangleAccess(Body[] bodies)
{
if (null == bodies)
{
throw new ArgumentNullException("bodies");
}
this.allTriangles = bodies.SelectMany((x) => x.Parts).ToList();
this.trianglesByX = bodies.SelectMany((x) => x.Parts).SelectMany((y) => new KeyValuePair<float, Triangle3D>[]
{
new KeyValuePair<float,Triangle3D>(y.Point1.X,y),
new KeyValuePair<float,Triangle3D>(y.Point2.X,y),
new KeyValuePair<float,Triangle3D>(y.Point3.X,y)
}).ToList();
}
public Triangle3D Find(Ray ray, out Point3D crossPoint)
{
crossPoint = Point3D.Zero;
List<Triangle3D> relevant = this.GetRelevantTriangles(ray);
Triangle3D absoluteTriangle = null;
float min = float.MaxValue;
foreach (Triangle3D item in relevant)
{
Point3D currentCrossPoint;
if (this.RayIntersectTriangle(ray, item, out currentCrossPoint))
{
float distance = Point3D.Distance(ray.Source, currentCrossPoint);
if (distance < min)
{
absoluteTriangle = item;
crossPoint = currentCrossPoint;
min = distance;
}
}
}
return absoluteTriangle;
}
public Ray Reflect(Ray ray, Point3D crossPoint, Triangle3D intersect)
{
//need this to be realized
//please help
}
/// <summary>
/// TODO: Finish this Up:
/// </summary>
/// <param name="ray"></param>
/// <returns></returns>
private List<Triangle3D> GetRelevantTriangles(Ray ray)
{
return this.allTriangles;
}
private bool RayIntersectTriangle(Ray ray, Triangle3D triangle, out Point3D crossPoint)
{
// Find vectors for two edges sharing vert0
Point3D edge1 = triangle.Point2 - triangle.Point1;
Point3D edge2 = triangle.Point3 - triangle.Point1;
// Begin calculating determinant - also used to calculate barycentricU parameter
Point3D pvec = Point3D.Cross(ray.Direction, edge2);
// If determinant is near zero, ray lies in plane of triangle
float det = edge1 * pvec;
if (det < 0.0001f)
{
crossPoint = Point3D.Zero;
return false;
}
// Calculate distance from vert0 to ray origin
Point3D tvec = ray.Source - triangle.Point1;
// Calculate barycentricU parameter and test bounds
float barycentricU = tvec * pvec;
if (barycentricU < 0.0f || barycentricU > det)
{
crossPoint = Point3D.Zero;
return false;
}
// Prepare to test barycentricV parameter
Point3D qvec = Point3D.Cross(tvec, edge1);
// Calculate barycentricV parameter and test bounds
float barycentricV = ray.Direction * qvec;
if (barycentricV < 0.0f || barycentricU + barycentricV > det)
{
crossPoint = Point3D.Zero;
return false;
}
// Calculate pickDistance, scale parameters, ray intersects triangle
float pickDistance = edge2 * qvec;
float fInvDet = 1.0f / det;
pickDistance *= fInvDet;
barycentricU *= fInvDet;
barycentricV *= fInvDet;
crossPoint = MathHelper.BaryCentric(triangle, barycentricU, barycentricV);
return true;
}
}
谢谢你。PS对我有耐心......我才15岁:)