Example #1
0
        /// <summary>
        /// Converts the color to a .NET <see cref="Color"/>, using the specified alpha value.
        /// </summary>
        /// <param name="alpha">The alpha channel to use.</param>
        public Color ToColor(double alpha)
        {
            DoubleColor clamped = Clamp();

            alpha = Util.Clamp(alpha, 0, 1);
            return(Color.FromArgb((int)(alpha * 255), (int)(clamped.R * 255), (int)(clamped.G * 255), (int)(clamped.B * 255)));
        }
Example #2
0
        public static Scene FromFile(string filename)
        {
            StreamReader reader = null;

            try
            {
                reader = new StreamReader(filename);
                Scene outScene = new Scene();

                // Camera state
                Camera addCam      = null;
                double imagePlane  = 0;
                double dofAmount   = 0;
                double focalLength = 0;
                Vec4D  focalPoint  = Vec4D.Zero;

                // Primitive state
                IObject obj = null;

                List <Primitive> prims           = new List <Primitive>();
                bool             twoSided        = true;
                bool             invert          = false;
                DoubleColor      emission        = DoubleColor.Placeholder;
                DoubleColor      diffuse         = DoubleColor.Placeholder;
                DoubleColor      specular        = DoubleColor.Placeholder;
                double           shininess       = -1;
                DoubleColor      refraction      = DoubleColor.Placeholder;
                double           refractionIndex = -1;

                stack    = new MatrixStack();                   // Transform stack
                invStack = new MatrixStack();                   // Inverse transforms

                List <Vec4D>  vertices        = new List <Vec4D>();
                List <Vertex> verticesNormals = new List <Vertex>();

                int lineNum = 1;

                while (!reader.EndOfStream)
                {
                    string line        = reader.ReadLine();
                    var    lineMatched = lineRegex.Match(line);

                    if (!lineMatched.Success)
                    {
                        throw new Exception("Line did not match expected format.");
                    }

                    // Line is blank
                    if (lineMatched.Groups[1].Captures.Count > 0)
                    {
                        // Grab the command name from the first capture group.
                        string cmd = lineMatched.Groups[1].Value.ToLowerInvariant();

                        // Pull all the parameters from the matched groups after the command name.
                        paramEnum = lineMatched.Groups.Values.Skip(2).SelectMany((g) => g.Captures).Select((c) => c.Value).GetEnumerator();

#if !DEBUG
                        try
#endif
                        {
                            Vec4D pos;

                            switch (cmd)
                            {
                            case "size":
                                outScene.Width  = NextInt();
                                outScene.Height = NextInt();
                                break;

                            case "background":
                                outScene.BackgroundRGB   = NextRGB();
                                outScene.BackgroundAlpha = NextDbl();
                                break;

                            case "ambient":
                                outScene.AmbientRGB = Next() switch
                                {
                                    "miss" => DoubleColor.Placeholder,
                                    "color" => NextRGB(),
                                    _ => throw new Exception($"Unknown ambient type {paramEnum.Current}."),
                                };
                                break;

                            case "recursion":
                            case "bounce":
                                outScene.Recursion = NextInt();
                                break;

                            case "debug":
                                outScene.DebugGeom = Next() switch
                                {
                                    "geom" => true,
                                    "off" => false,
                                    _ => throw new Exception($"Unknown debug type {paramEnum.Current}."),
                                };
                                break;

                            // Cameras:
                            case "dof":
                                imagePlane = NextDbl();
                                dofAmount  = NextDbl();

                                switch (Next())
                                {
                                case "at":
                                    focalPoint  = NextVecTransf();
                                    focalLength = 0;
                                    break;

                                case "to":
                                    focalLength = NextDbl();
                                    focalPoint  = Vec4D.Zero;
                                    break;

                                case "camera":
                                    focalLength = 0;
                                    focalPoint  = Vec4D.Zero;
                                    break;

                                default:
                                    throw new Exception($"Unknown dof focal command {paramEnum.Current}.");
                                }

                                break;

                            case "camera":
                            case "frustum":
                            case "orthographic":
                                pos = NextVec(1);
                                Vec4D lookAt = NextVec(1);
                                Vec4D up     = Transf(NextVec(0) + pos);
                                pos = Transf(pos);
                                up -= pos;

                                if (cmd == "orthographic")
                                {
                                    addCam = new OrthoCamera(pos, lookAt, up, NextDbl());
                                }
                                else
                                {
                                    addCam = new FrustumCamera(pos, lookAt, up, NextDbl());
                                }
                                break;

                            // Materials:
                            case "twosided":
                                twoSided = NextBool();
                                break;

                            case "invert":
                                invert = NextBool();
                                break;

                            case "emission":
                                emission = NextRGB();
                                break;

                            case "diffuse":
                                diffuse = NextRGB();
                                break;

                            case "specular":
                                specular = NextRGB();
                                break;

                            case "shininess":
                                shininess = NextDbl();
                                if (paramEnum.MoveNext())
                                {
                                    shininess = Math.Pow(shininess, ParseDbl(paramEnum.Current));
                                }
                                break;

                            case "refraction":
                                if (Next() == "off")
                                {
                                    refraction      = DoubleColor.Placeholder;
                                    refractionIndex = -1;
                                }
                                else
                                {
                                    refraction      = new DoubleColor(ParseDbl(paramEnum.Current), NextDbl(), NextDbl());
                                    refractionIndex = NextDbl();
                                }
                                break;

                            // Transforms:
                            case "translate":
                                Vec4D tVec = NextVec(0);
                                stack.Transform(MatrixTransforms.Translate(tVec.X, tVec.Y, tVec.Z));
                                invStack.InvTransform(MatrixTransforms.Translate(-tVec.X, -tVec.Y, -tVec.Z));
                                break;

                            case "scale":
                                Vec4D sVec = NextVec(0);
                                stack.Transform(MatrixTransforms.Scale(sVec.X, sVec.Y, sVec.Z));
                                invStack.InvTransform(MatrixTransforms.Scale(1 / sVec.X, 1 / sVec.Y, 1 / sVec.Z));
                                break;

                            case "rotate":
                                Vec4D  axis  = NextVec(0);
                                double angle = NextDbl();
                                stack.Transform(MatrixTransforms.Rotate(Consts.toRadians(angle), axis));
                                invStack.InvTransform(MatrixTransforms.Rotate(-Consts.toRadians(angle), axis));
                                break;

                            case "pushtransform":
                                stack.Push();
                                invStack.Push();
                                break;

                            case "poptransform":
                                stack.Pop();
                                invStack.Pop();
                                break;

                            // Primitives:
                            case "sphere":
                                prims.Add(new Sphere(NextVec(1), NextDbl()));
                                break;

                            case "plane":
                                prims.Add(new Plane(NextDbl(), NextVec(0)));
                                break;

                            case "vertex":
                                vertices.Add(NextVec(1));
                                break;

                            case "tri":
                                Vec4D p0     = vertices[NextInt()];
                                Vec4D p1     = vertices[NextInt()];
                                Vec4D p2     = vertices[NextInt()];
                                bool  mirror = false;

                                if (paramEnum.MoveNext() && paramEnum.Current == "mirrored")
                                {
                                    mirror = true;
                                }

                                Triangle tri = new Triangle(p0, p1, p2, mirror);
                                prims.Add(tri);
                                break;

                            case "vertexnormal":
                                verticesNormals.Add(new Vertex(NextVec(1), NextVec(0)));
                                break;

                            case "trinormal":
                                Vertex   v0      = verticesNormals[NextInt()];
                                Vertex   v1      = verticesNormals[NextInt()];
                                Vertex   v2      = verticesNormals[NextInt()];
                                Triangle triNorm = new Triangle(v0, v1, v2);
                                prims.Add(triNorm);
                                break;

                            // Objects
                            case "cube":
                                pos = NextVec(1);
                                Vec4D size = NextVec(0);
                                Cube  cube = new Cube(pos, size);
                                obj = cube;

                                if (paramEnum.MoveNext())
                                {
                                    switch (paramEnum.Current)
                                    {
                                    case "all":
                                        prims.AddRange(cube.GetChildren(Cube.AllSides));
                                        break;

                                    case "only":
                                        prims.AddRange(cube.GetChildren(ReadAll().Aggregate(Cube.NoSides, (sides, name) => sides | Cube.GetSide(name))));
                                        break;

                                    case "not":
                                        prims.AddRange(cube.GetChildren(ReadAll().Aggregate(Cube.AllSides, (sides, name) => sides & ~Cube.GetSide(name))));
                                        break;

                                    default:
                                        throw new Exception("Unknown option provided for cube construction: " + paramEnum.Current);
                                    }
                                }

                                prims.AddRange(obj.GetChildren(ObjectConsts.ImplicitInstance));
                                break;

                            // Instancing:
                            case "instance":
                                // Add instances from the previously assigned object (primitive group).
                                prims.AddRange(ReadAll().SelectMany((s) => obj.GetChildren(s)));
                                break;

                            // Other:
                            case "maxverts":
                                break;

                            case "maxvertnorms":
                                break;

                            default:
                                Trace.WriteLine("Unknown command: " + cmd);
                                break;
                            }

                            if (addCam != null)
                            {
                                addCam.imagePlane = imagePlane;
                                addCam.dofAmount  = dofAmount;

                                if (focalPoint != Vec4D.Zero)
                                {
                                    addCam.focalLength = (focalPoint - addCam.position).Length;
                                }
                                else if (focalLength != 0)
                                {
                                    addCam.focalLength = focalLength;
                                }
                                else
                                {
                                    addCam.focalLength = (addCam.initLookAt - addCam.position).Length;
                                }

                                outScene.Cameras.Add(addCam);
                                addCam = null;
                            }

                            foreach (Primitive prim in prims)
                            {
                                prim.TwoSided = twoSided;
                                prim.Invert   = invert;

                                if (emission != DoubleColor.Placeholder)
                                {
                                    prim.Emission = emission;
                                }

                                if (diffuse != DoubleColor.Placeholder)
                                {
                                    prim.Diffuse = diffuse;
                                }

                                if (specular != DoubleColor.Placeholder)
                                {
                                    prim.Specular = specular;
                                }
                                if (shininess != -1)
                                {
                                    prim.Shininess = shininess;
                                }

                                if (refraction != DoubleColor.Placeholder)
                                {
                                    prim.Refraction      = refraction;
                                    prim.RefractiveIndex = refractionIndex;
                                }

                                prim.Transform(stack.Peek(), invStack.Peek());

                                outScene.AddPrimitive(prim);
                            }

                            prims.Clear();
                        }
#if !DEBUG
                        catch (Exception e) when(e is Exception || e is FormatException || e is OverflowException || e is IndexOutOfRangeException)
                        {
                            throw new LoaderException(cmd, lineNum, e);
                        }
#endif
                    }

                    lineNum++;
                }

                return(outScene);
            }
            catch (FileNotFoundException e)
            {
            }
            finally
            {
                reader?.Close();
            }

            return(null);
        }