public void TriangleInitialize() { Vertex a = new Vertex(); a.Position = new Vector3(0, 1, 0); Vertex b = new Vertex(); b.Position = new Vector3(-1, 0, 0); Vertex c = new Vertex(); c.Position = new Vector3(1, 0, 0); Triangle t = new Triangle(a,b,c); Assert.Equal(a, t.P0); Assert.Equal(b, t.P1); Assert.Equal(c, t.P2); Assert.Equal(new Vector3(0, 0, 1), t.Normal); }
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); }
public Vector4 GetColor(Triangle t, Vector3 pos) { Vector4 c = t.GetColor(pos); Vector4 retColor = new Vector4(0, 0, 0, 1); Vector3 viewVec = (cameraPosition - pos).Normalized; foreach (var light in config.Lights) { Vector3 lightVec = (light.Location - pos).Normalized; Vector4 avg = new Vector4(); // Calcualte diffuse lighting // If this is >0 then the triangle light is somewhere in front of the triangle float dot = Vector3.Dot(lightVec, t.Normal); if (dot < 0) { dot = 0; } Vector4 diffuse = new Vector4( c.X * light.DiffuseColor.X * dot, c.Y * light.DiffuseColor.Y * dot, c.Z * light.DiffuseColor.Z * dot, c.W * light.DiffuseColor.W * dot); // Calculate specular lighting Vector3 reflected = Vector3.Reflection(lightVec, t.Normal).Normalized; dot = Vector3.Dot(reflected, viewVec); Vector4 specular = new Vector4( (float)Math.Pow(light.SpecularColor.X * dot, t.GetSpecularCoefficient(pos)), (float)Math.Pow(light.SpecularColor.Y * dot, t.GetSpecularCoefficient(pos)), (float)Math.Pow(light.SpecularColor.Z * dot, t.GetSpecularCoefficient(pos)), (float)Math.Pow(light.SpecularColor.W * dot, t.GetSpecularCoefficient(pos))); // Cast a bunch of shadow rays to determine how well lit this point is from the given light source for(int i = 0;i < config.ShadowRays; i++) { if(!InShadow(pos, light)) { // If we are lit then add the diffuse and specular colors avg += diffuse; avg += specular; } } // Average the color by the number of shadow rays cast. avg /= config.ShadowRays; retColor.X += light.AmbientColor.X * c.X + avg.X; retColor.Y += light.AmbientColor.Y * c.Y + avg.Y; retColor.Z += light.AmbientColor.Z * c.Z + avg.Z; ScaleColor(ref retColor); } return retColor; }
/// <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; }
/// <summary> /// Does the conversion /// </summary> /// <param name="data">The obj data to convert</param> /// <returns>The constructed Scene</returns> public static Scene Convert(ObjData data) { Scene s = new Scene(); Dictionary<string, Material> materials = new Dictionary<string, Material>(); Dictionary<string, Bitmap> bitmaps = new Dictionary<string, Bitmap>(); foreach (var mat in data.materials) { LoadBitmap(mat.AlphaTextureMap, bitmaps); LoadBitmap(mat.AmbientTextureMap, bitmaps); LoadBitmap(mat.BumpMap, bitmaps); LoadBitmap(mat.DiffuseTextureMap, bitmaps); LoadBitmap(mat.DisplacementMap, bitmaps); LoadBitmap(mat.SpecularCoefficientMap, bitmaps); LoadBitmap(mat.SpecularTextureMap, bitmaps); Material m = new Material(); m.AlphaMap = bitmaps[mat.AlphaTextureMap]; m.AmbientMap = bitmaps[mat.AmbientTextureMap]; m.BumpMap = bitmaps[mat.AmbientTextureMap]; m.DiffuseMap = bitmaps[mat.AmbientTextureMap]; m.DisplacementMap = bitmaps[mat.AmbientTextureMap]; m.SpecularCoefficientMap = bitmaps[mat.AmbientTextureMap]; m.SpecularMap = bitmaps[mat.AmbientTextureMap]; m.Texture = bitmaps[mat.DiffuseTextureMap]; m.AmbientColor = mat.Ambient; m.DiffuseColor = mat.Diffuse; m.SpecularCoefficient = mat.SpecularCoefficient; m.SpecularColor = mat.Specular; m.Transparency = mat.Transparency; m.Name = mat.Name; materials[m.Name] = m; } foreach (var f in data.faces) { Vertex v1 = new Vertex(); Vertex v2 = new Vertex(); Vertex v3 = new Vertex(); v1.Position = data.vertices[f.Vert1.vertex - 1]; v2.Position = data.vertices[f.Vert2.vertex - 1]; v3.Position = data.vertices[f.Vert3.vertex - 1]; v1.Normal = data.normals[f.Vert1.normal - 1]; v2.Normal = data.normals[f.Vert2.normal - 1]; v3.Normal = data.normals[f.Vert3.normal - 1]; // Only set the texture coordinates if they were set if (f.Vert1.texCoord > 0 && f.Vert2.texCoord > 0 && f.Vert3.texCoord > 0) { v1.TexCoord = data.texCoords[f.Vert1.texCoord - 1]; v2.TexCoord = data.texCoords[f.Vert2.texCoord - 1]; v3.TexCoord = data.texCoords[f.Vert3.texCoord - 1]; } Triangle t = new Triangle(v1, v2, v3); if (!string.IsNullOrEmpty(f.Material)) { t.Material = materials[f.Material]; } s.Triangles.Add(t); } return s; }