public static ObjData LoadFromFile(string filePath) { using (var streamReader = new StreamReader(filePath)) { var obj = new ObjData(); string line = null; while ((line = streamReader.ReadLine()) != null) { if (String.IsNullOrWhiteSpace(line)) { continue; } if (line[0] == '#') { continue; } var tokens = line.Split(' '); switch (tokens[0]) { case "v": { double x = Double.Parse(tokens[1], CultureInfo.InvariantCulture); double y = Double.Parse(tokens[2], CultureInfo.InvariantCulture); double z = Double.Parse(tokens[3], CultureInfo.InvariantCulture); obj.Vertices.Add(VectorHelpers.Create(x, y, z)); break; } case "vt": { double u = Double.Parse(tokens[1], CultureInfo.InvariantCulture); double v = Double.Parse(tokens[2], CultureInfo.InvariantCulture); obj.TexCoords.Add(VectorHelpers.Create(u, v)); break; } case "vn": { double x = Double.Parse(tokens[1], CultureInfo.InvariantCulture); double y = Double.Parse(tokens[2], CultureInfo.InvariantCulture); double z = Double.Parse(tokens[3], CultureInfo.InvariantCulture); obj.Normals.Add(VectorHelpers.Create(x, y, z)); break; } case "f": { var triangle = new IndexedTriangle(); for (int i = 0; i < 3; ++i) { var vertexTokens = tokens[i + 1].Split('/'); triangle.Vertices[i] = Int32.Parse(vertexTokens[0]) - 1; triangle.TexCoords[i] = Int32.Parse(vertexTokens[1]) - 1; triangle.Normals[i] = Int32.Parse(vertexTokens[2]) - 1; } obj.Triangles.Add(triangle); break; } } } return(obj); } }
public void RenderObjMesh(ObjData meshToRender, Matrix <double> transformation, Matrix <double> normalTransformation) { if (Material == null) { Material = new Material(); } if (TexturingEnabled) { if (Material.DiffuseTexture != null) { Material.DiffuseTexture.Lock(); } } var hw = _renderWindow.Framebuffer.PixelWidth * 0.5; var hh = _renderWindow.Framebuffer.PixelHeight * 0.5; foreach (var triangle in meshToRender.Triangles) { var tri = new PreparedTriangle(); for (int i = 0; i < 3; ++i) { Vector <double> modelSpacePosition = meshToRender.Vertices[triangle.Vertices[i]]; Vector <double> modelSpaceNormal = meshToRender.Normals[triangle.Normals[i]]; Vector <double> screenSpacePosition = (transformation * modelSpacePosition.ExtendVector()) .ToCartesian() .Add(VectorHelpers.Create(1.0, 1.0, 0.0)) .PointwiseMultiply(VectorHelpers.Create(hw, hh, 1.0)); Vector <double> worldSpacePosition = (normalTransformation * modelSpacePosition.ExtendVector()) .ToCartesian(); Vector <double> worldSpaceNormal = (normalTransformation * modelSpaceNormal.ExtendVector(0.0)) .DiscardLastCoordinate().Normalize(2); // Vertex shader tri.Vertices[i].SetCoordinates(screenSpacePosition); tri.Vertices[i].SetTextureCoordinates(meshToRender.TexCoords[triangle.TexCoords[i]]); var vR = 0; var vG = 0; var vB = 0; if (AmbientLightingEnabled) { vR += Material.AmbientColor.R; vG += Material.AmbientColor.G; vB += Material.AmbientColor.B; } if (DiffuseLightingEnabled || SpecularLightingEnabled) { foreach (var light in Lights) { var lightDirection = (light.Position - worldSpacePosition).Normalize(2); if (DiffuseLightingEnabled) { var diffuseLightFactor = Math.Max(lightDirection.DotProduct(worldSpaceNormal), 0); var fullSaturationDiffuseColor = MultiplyColors(light.Color, Material.DiffuseColor); vR += (byte)(fullSaturationDiffuseColor.R * diffuseLightFactor); vG += (byte)(fullSaturationDiffuseColor.G * diffuseLightFactor); vB += (byte)(fullSaturationDiffuseColor.B * diffuseLightFactor); } if (SpecularLightingEnabled) { var eyeDirection = (WorldPositionEye - worldSpacePosition).Normalize(2); var reflected = (2 * worldSpaceNormal.DotProduct(lightDirection) * worldSpaceNormal - lightDirection).Normalize(2); var specularLightFactor = Math.Pow(Math.Max(eyeDirection.DotProduct(reflected), 0), Material.ShineFactor); var fullSaturationSpecularColor = MultiplyColors(light.Color, Material.SpecularColor); vR += (byte)(fullSaturationSpecularColor.R * specularLightFactor); vG += (byte)(fullSaturationSpecularColor.G * specularLightFactor); vB += (byte)(fullSaturationSpecularColor.B * specularLightFactor); } } } tri.Vertices[i].VertexColor = Color.FromRgb( (byte)Math.Min(vR, 255), (byte)Math.Min(vG, 255), (byte)Math.Min(vB, 255)); // End of vertex shader } DrawScreenSpaceTriangleInterpolated(tri); } if (TexturingEnabled && Material.DiffuseTexture != null) { Material.DiffuseTexture.Unlock(); } }