public void RayTriangleTest() { Vector3 origin = new Vector3(0, 0, 0); Vector3 direction = new Vector3(1, 0, 0); Ray r = new Ray(origin, direction); Triangle t = new Triangle( new Vertex() { Position = new Vector3(2, 1, 0) }, new Vertex() { Position = new Vector3(2, 0, -1) }, new Vertex() { Position = new Vector3(2, 0, 1) }); float time = -1f; bool collides = r.CollidesWith(t, ref time); Assert.True(collides); Assert.Equal(2f, time); Ray r2 = new Ray(origin, -direction); collides = r2.CollidesWith(t, ref time); Assert.False(collides); Assert.Equal(-2f, time); }
/// <summary> /// Determines if a point has direct line of sight to a light, or if it is shadowed by another object /// </summary> /// <param name="pos">The position being checked</param> /// <param name="light">The light source</param> /// <returns>Whether or not the point is lit by the light or in a shadow</returns> private bool InShadow(Vector3 pos, Light light) { // Get a vector from pos to light with some variation Vector3 lightVec = light.Location + new Vector3( (float)rand.NextDouble() * 2.0f * light.Radius - light.Radius, (float)rand.NextDouble() * 2.0f * light.Radius - light.Radius, (float)rand.NextDouble() * 2.0f * light.Radius - light.Radius) - pos; float lightDist = lightVec.Magnitude; Ray shadowRay = new Ray(pos, lightVec); float time = -1; // Iterate over all the triangles in the scene to see if they block the light foreach(var t in scene.Triangles) { if(shadowRay.CollidesWith(t, ref time)) { if(time < lightDist && time > ProximityTolerance) { return true; } } } return false; }
/// <summary> /// Casts a ray and gets the resultant color /// </summary> /// <param name="r">The ray to cast</param> /// <param name="depth">The current depth of the ray into the scene</param> /// <param name="sourceTriangle">The source of the ray if it was reflected/refracted</param> /// <returns>The resultant color of the ray</returns> public Vector4 CastRay(Ray r, int depth = 0, Triangle sourceTriangle = null) { float closestTime = float.MaxValue; Triangle closestTriangle = null; Vector3 closestPosition = Vector3.Zero; Vector4 returnColor = Vector4.Zero; foreach (var t in scene.Triangles) { float time = float.MaxValue; if (r.CollidesWith(t, ref time)) { if (time < closestTime && time > ProximityTolerance) { closestTime = time; closestTriangle = t; closestPosition = r.PointAtDistance(time); } } } // If we can still cast rays deeper and we collided with an object, then cast more rays if (depth < config.MaxRayDepth && closestTriangle != null) { // TODO: Cast reflection rays // TODO: Cast refraction rays // TODO: Add the color combinations from reflection and refraction returnColor = GetColor(closestTriangle, closestPosition); } else if (closestTriangle != null) { returnColor = GetColor(closestTriangle, closestPosition); } return returnColor; }