예제 #1
0
    public OBJFileParser Create(int recursionLevel)
    {
        this.geometry = new OBJFileParser();
        this.middlePointIndexCache = new Dictionary <long, int>();
        this.index = 0;

        // create 12 vertices of a icosahedron
        var t = (1.0 + Math.Sqrt(5.0)) / 2.0;

        addVertex(new Point(-1, t, 0));
        addVertex(new Point(1, t, 0));
        addVertex(new Point(-1, -t, 0));
        addVertex(new Point(1, -t, 0));

        addVertex(new Point(0, -1, t));
        addVertex(new Point(0, 1, t));
        addVertex(new Point(0, -1, -t));
        addVertex(new Point(0, 1, -t));

        addVertex(new Point(t, 0, -1));
        addVertex(new Point(t, 0, 1));
        addVertex(new Point(-t, 0, -1));
        addVertex(new Point(-t, 0, 1));


        // create 20 triangles of the icosahedron
        var faces = new List <Tri>();

        // 5 faces around point 0
        faces.Add(new Tri(0, 11, 5));
        faces.Add(new Tri(0, 5, 1));
        faces.Add(new Tri(0, 1, 7));
        faces.Add(new Tri(0, 7, 10));
        faces.Add(new Tri(0, 10, 11));

        // 5 adjacent faces
        faces.Add(new Tri(1, 5, 9));
        faces.Add(new Tri(5, 11, 4));
        faces.Add(new Tri(11, 10, 2));
        faces.Add(new Tri(10, 7, 6));
        faces.Add(new Tri(7, 1, 8));

        // 5 faces around point 3
        faces.Add(new Tri(3, 9, 4));
        faces.Add(new Tri(3, 4, 2));
        faces.Add(new Tri(3, 2, 6));
        faces.Add(new Tri(3, 6, 8));
        faces.Add(new Tri(3, 8, 9));

        // 5 adjacent faces
        faces.Add(new Tri(4, 9, 5));
        faces.Add(new Tri(2, 4, 11));
        faces.Add(new Tri(6, 2, 10));
        faces.Add(new Tri(8, 6, 7));
        faces.Add(new Tri(9, 8, 1));


        // refine triangles
        for (int i = 0; i < recursionLevel; i++)
        {
            var faces2 = new List <Tri>();
            foreach (var tri in faces)
            {
                // replace triangle by 4 triangles
                int a = getMiddlePoint(tri.v1, tri.v2);
                int b = getMiddlePoint(tri.v2, tri.v3);
                int c = getMiddlePoint(tri.v3, tri.v1);

                faces2.Add(new Tri(tri.v1, a, c));
                faces2.Add(new Tri(tri.v2, b, a));
                faces2.Add(new Tri(tri.v3, c, b));
                faces2.Add(new Tri(a, b, c));
            }
            faces = faces2;
        }

        // done, now add triangles to mesh
        Point origin = new Point(0, 0, 0);

        foreach (var tri in faces)
        {
            // Create the point normals for the smoothing
            Vector n0 = (geometry.Verticies[tri.v1] - origin).Normalize();
            Vector n1 = (geometry.Verticies[tri.v2] - origin).Normalize();
            Vector n2 = (geometry.Verticies[tri.v3] - origin).Normalize();
            // texture map coordinates
            Point t0 = new Point((geometry.Verticies[tri.v1].X + 1) / 2, (geometry.Verticies[tri.v1].Y + 1) / 2, 0);
            Point t1 = new Point((geometry.Verticies[tri.v2].X + 1) / 2, (geometry.Verticies[tri.v2].Y + 1) / 2, 0);
            Point t2 = new Point((geometry.Verticies[tri.v3].X + 1) / 2, (geometry.Verticies[tri.v3].Y + 1) / 2, 0);

            // Create the texture maps for each vertex
            SmoothTriangle st = new SmoothTriangle(geometry.Verticies[tri.v1], geometry.Verticies[tri.v2], geometry.Verticies[tri.v3]);
            st.AddNormals(n0, n1, n2);
            st.AddTexture(t0, t1, t2);
            this.geometry.AddToCurrentGroup(st);
        }

        return(this.geometry);
    }
예제 #2
0
파일: Program.cs 프로젝트: kemptm/RayTracer
        static void Main(string[] args)
        {
            IcoSphereCreator dome = new IcoSphereCreator();

            OBJFileParser g = dome.Create(1);
        }
예제 #3
0
        ///-------------------------------------------------------------------------------------------------
        /// <summary>   Main entry-point for this application. </summary>
        ///
        /// <remarks>   Kemp, 11/19/2018. </remarks>
        ///
        /// <param name="args"> An array of command-line argument strings. Not used.</param>
        ///-------------------------------------------------------------------------------------------------

        static void Main(string[] args)
        {
            bool   show_help  = false;
            bool   mirror     = false;
            bool   center     = false;
            bool   bbox       = false;
            bool   nm         = false;
            bool   np         = false;
            string outputFile = "";
            uint   canvasX    = 200;
            uint   canvasY    = 200;
            uint   rotx       = 0;
            uint   roty       = 0;
            uint   rotz       = 0;
            double cameraZ    = 0;
            double cameraY    = 0;
            double myFOV      = 0;
            bool   serial     = false;
            var    pa         = new OptionSet()
            {
                { "o|output=", "the {NAME} of the output PMM file.",
                  v => outputFile = v },
                { "W|width=",
                  "The width in pixels of the output image.",
                  (uint v) => canvasX = v },
                { "H|height=",
                  "The height in pixels of the output image.",
                  (uint v) => canvasY = v },
                { "h|help", "show this message and exit",
                  v => show_help = v != null },
                { "x|xrotation=",
                  "The rotation around the x axis in units of PI/2.",
                  (uint v) => rotx = v },
                { "y|yrotation=",
                  "The rotation around the y axis in units of PI/2.",
                  (uint v) => roty = v },
                { "z|zrotation=",
                  "The rotation around the z axis in units of PI/2.",
                  (uint v) => rotz = v },
                { "cz|cameraz=",
                  "The angle of rotation of the camera in the upward direction in radians.",
                  (double v) => cameraZ = v },
                { "cy|cameray=",
                  "The angle of rotation of the camera in the right-ward direction in radians.",
                  (double v) => cameraY = v },
                { "fov|fieldofview=",
                  "The field of view of the camera (zoom).",
                  (double v) => myFOV = v },
                { "s|serial", "Use only one processor to render.",
                  v => serial = v != null },
                { "M|mirror", "Mirror image on X",
                  v => mirror = v != null },
                { "C|center", "Center group at the origin",
                  v => center = v != null },
                { "B|boundingbox", "Display bounding box of object",
                  v => bbox = v != null },
                { "n|nomove", "Don't move object to first quadrant",
                  v => nm = v != null },
                { "p|noplane", "Don't show the plane",
                  v => np = v != null }
            };

            List <string> extra;

            try {
                extra = pa.Parse(args);
            }
            catch (OptionException e) {
                Console.Write("RenderTriangleMesh: ");
                Console.WriteLine(e.Message);
                Console.WriteLine("Try `RenderTriangleMesh --help' for more information.");
                return;
            }

            if (show_help)
            {
                Console.WriteLine("RenderTriangleMesh [Options] inputFileName");
                Console.WriteLine("Options: ");
                pa.WriteOptionDescriptions(Console.Out);
                return;
            }

            /// The only positional parameter is the file name to process

            if (extra.Count != 1)
            {
                Console.Write("RenderTriangleMesh: exactly one input file name permitted.");
                return;
            }

            string ifn = extra[0];
            string ifp = Path.GetDirectoryName(ifn);

            if (outputFile == "")
            {
                outputFile = Path.Combine(ifp, Path.GetFileNameWithoutExtension(ifn));
            }

            Console.WriteLine("Started: " + DateTime.Now.ToString());
            World w = new World();

            /// Read the triangular mesh and color all the triangles red.
            OBJFileParser p    = new OBJFileParser(ifn, OBJFileParser.TriangleType.Smooth, mirror);
            Color         red  = new Color(1, 0, 0);
            Color         blue = new Color(0, 0, 1);
            Color         gray = new Color(0.5, 0.5, 0.5);
            /// collect what was parsed into a single group
            Group g = new Group();

            //Group a = Axes.Generate(25,5,new Color(1,0,0));
            //w.AddObject(a);
            //w.AddObject(BoundingBox.Generate(a,new Color(1,1,0)));

            foreach (Group gp in p.Groups)
            {
                g.AddObject(gp);
            }
            Console.WriteLine("Objects in default: " + g.Children.Count().ToString());
            //ColorShapes(g, gray);

            /// Transform the group containing the triangular mesh to correspond to our world and camera view point.
            /// Move it back to origin, rotate it, and return it to where it was.
            if (center)
            {
                g.Transform = (Matrix)(MatrixOps.CreateTranslationTransform(0 - (g.Bounds.MinCorner.X + (g.Bounds.MaxCorner.X - g.Bounds.MinCorner.X) / 2),
                                                                            0 - (g.Bounds.MinCorner.Y + (g.Bounds.MaxCorner.Y - g.Bounds.MinCorner.Y) / 2), 0 - (g.Bounds.MinCorner.Z + (g.Bounds.MaxCorner.Z - g.Bounds.MinCorner.Z) / 2)) * g.Transform);
            }
            if (rotx != 0)
            {
                g.Transform = (Matrix)(MatrixOps.CreateRotationXTransform(rotx * (Math.PI / 2)) * g.Transform);
            }
            if (roty != 0)
            {
                g.Transform = (Matrix)(MatrixOps.CreateRotationYTransform(roty * (Math.PI / 2)) * g.Transform);
            }
            if (rotz != 0)
            {
                g.Transform = (Matrix)(MatrixOps.CreateRotationZTransform(rotz * (Math.PI / 2)) * g.Transform);
            }
            /// Move the whole group into the first quadrant
            if (!nm)
            {
                g.Transform = (Matrix)(MatrixOps.CreateTranslationTransform(0 - g.Bounds.MinCorner.X, 0 - g.Bounds.MinCorner.Y, 0 - g.Bounds.MinCorner.Z) * g.Transform);
                w.AddObject(g);
            }

            /// add bounding box
            if (bbox)
            {
                Group bb = BoundingBox.Generate(g, blue);
                w.AddObject(bb);
            }

            /// three planes make up the background.
            if (!np)
            {
                Plane floor = new Plane();
                floor.Material.Pattern           = new Checked3DPattern(new Color(1, 1, 1), new Color(0.75, 0.75, 0.75));
                floor.Material.Pattern.Transform = MatrixOps.CreateScalingTransform(2, 2, 2);

                w.AddObject(floor);

                Plane wallz = (Plane)floor.Copy();
                wallz.Transform = (Matrix)(MatrixOps.CreateRotationXTransform(Math.PI / 2) * MatrixOps.CreateTranslationTransform(0, 0, 0));
                //w.AddObject(wallz);

                Plane wallx = (Plane)floor.Copy();
                wallx.Transform = (Matrix)(MatrixOps.CreateRotationZTransform(Math.PI / 2) * MatrixOps.CreateTranslationTransform(0, 0, 0));
                //w.AddObject(wallx);
            }
            Console.WriteLine("Bounds of object: " + g.Bounds.ToString());

            w.AddLight(new LightPoint(new Point(50000, 70000, -50000), new Color(0.5, 0.5, 0.5)));
            // w.AddLight(new LightPoint(new Point(-50000, 70000, -50000), new Color(0.2, 0.2, 0.2)));
            // w.AddLight(new RTLightPoint(new RTPoint(0, 10, -10), new Color(0.5, 0.5, 0.5)));

            /// Render the image
            Console.WriteLine("Now rendering ...");
            Point cameraPoint    = CalcCameraPoint(g, cameraY, cameraZ);
            Point cameraPointsAt = new Point(g.Bounds.MinCorner.X + (g.Bounds.MaxCorner.X - g.Bounds.MinCorner.X) / 2,
                                             g.Bounds.MinCorner.Y + (g.Bounds.MaxCorner.Y - g.Bounds.MinCorner.Y) / 2,
                                             g.Bounds.MinCorner.Z + (g.Bounds.MaxCorner.Z - g.Bounds.MinCorner.Z) / 2);
            double cameraFOV = myFOV == 0 ? CalcCameraFOV(cameraPoint, cameraPointsAt, g) : myFOV;
            Camera camera    = new Camera(canvasX, canvasY, cameraFOV);

            camera.Transform = MatrixOps.CreateViewTransform(cameraPoint, cameraPointsAt, new RayTracerLib.Vector(0, 1, 0));
            Console.WriteLine("CameraPoint = " + cameraPoint.ToString() + "CameraPointsAt = " + cameraPointsAt.ToString());
            Console.WriteLine("CameraFOV = " + cameraFOV.ToString());
            Canvas image;

            if (serial)
            {
                image = w.Render(camera);
            }
            else
            {
                image = w.ParallelRender(camera);
            }
            Console.WriteLine("Now writing output ...");

            /*
             * String ppm = image.ToPPM();
             * String ppmname = ("ToPPM.ppm");
             * System.IO.File.WriteAllText(outputFile, ppm);
             */
            image.WritePNG(outputFile + ".png");

            Console.WriteLine("Finished: " + DateTime.Now.ToString());
            Console.Write("Press Enter to finish ... ");
            Console.Read();
        }