Exemple #1
0
        public WorldData(string filePath)
        {
            using (StreamReader sr = new StreamReader(filePath))
            {
                int    id = 0;
                string line;
                var    vertices = new List <Vector4>();
                while ((line = sr.ReadLine()) != null)
                {
                    if (line.Length > 0)
                    {
                        string[] points = line.Split(' ');
                        switch (line[0])
                        {
                        case 'v':
                            vertices.Add(new Vector4(float.Parse(points[1]), float.Parse(points[2]), float.Parse(points[3]), 1.0F));
                            break;

                        case 'f':
                            var poly = new Polygon {
                                ID = id++, vertices = new Vector4[points.Length - 1]
                            };
                            for (int i = 0; i < points.Length - 1; i++)
                            {
                                poly.vertices[i] = vertices[int.Parse(points[i + 1]) - 1];
                            }
                            poly.normal = Transformations.CalculateSurfaceNormal(poly);

                            Polygons.Add(poly);
                            break;
                        }
                    }
                }
            }

            BSPTree  = new BSPTree(Polygons);
            Polygons = BSPTree.Polygons;
        }
        private void Canvas_Paint(object sender, PaintEventArgs e)
        {
            graphics = Canvas.CreateGraphics();
            graphics.Clear(Color.Black);

            var fovRad      = 1.0F / (float)Math.Tan(fov * 0.5F / 180.0F * Math.PI);
            var aspectRatio = Canvas.Height / (float)Canvas.Width;
            var near        = 0.1F;
            var far         = 1000.0F;
            var projMat     = new Matrix4x4
            {
                M11 = fovRad * aspectRatio,
                M22 = fovRad,
                M33 = far / (far - near),
                M34 = 1.0F,
                M43 = -near * far / (far - near)
            };

            var up       = new Vector3(0.0F, 1.0F, 0.0F);
            var at       = new Vector3(0.0F, 0.0F, -1.0F);
            var rotXMat  = Transformations.RotateX(pitch / 180.0F * (float)Math.PI);
            var rotYMat  = Transformations.RotateY(yaw / 180.0F * (float)Math.PI);
            var rotZMat  = Transformations.RotateZ(roll / 180.0F * (float)Math.PI);
            var rotXYMat = rotXMat * rotYMat;

            lookDir  = Transformations.V4ToV3(Vector4.Transform(new Vector4(at, 1.0F), rotXYMat));
            rightDir = Vector3.Normalize(Vector3.Cross(up, lookDir));
            at       = camera + lookDir;
            var viewMat = Transformations.LookAt(camera, at, up) * rotZMat;

            projPolygons = new List <Polygon>();
            foreach (var poly in worldData.Polygons)
            {
                bool isClipped  = false;
                var  viewedPoly = new Vector4();
                var  projPoly   = new Polygon {
                    ID = poly.ID, vertices = new Vector4[poly.vertices.Length]
                };
                for (int i = 0; i < poly.vertices.Length; i++)
                {
                    viewedPoly           = Vector4.Transform(poly.vertices[i], viewMat);
                    projPoly.vertices[i] = Vector4.Transform(viewedPoly, projMat);

                    if (projPoly.vertices[i].X <-projPoly.vertices[i].W || projPoly.vertices[i].X> projPoly.vertices[i].W ||
                        projPoly.vertices[i].Y <-projPoly.vertices[i].W || projPoly.vertices[i].Y> projPoly.vertices[i].W ||
                        projPoly.vertices[i].Z <0 || projPoly.vertices[i].Z> projPoly.vertices[i].W)
                    {
                        isClipped = true;
                    }

                    projPoly.vertices[i]   /= projPoly.vertices[i].W;
                    projPoly.vertices[i].X *= -1.0F; projPoly.vertices[i].Y *= -1.0F;
                    projPoly.vertices[i]   += new Vector4(1.0F, 1.0F, 0, 0);
                    projPoly.vertices[i].X *= 0.5f * Canvas.Width; projPoly.vertices[i].Y *= 0.5f * Canvas.Height;
                }

                if (!isClipped)
                {
                    projPolygons.Add(projPoly);
                }
            }

            if (projPolygons.Count > 0)
            {
                TraverseProjection(worldData.BSPTree.Root);
            }
        }
        private Node GenerateTree(List <Polygon> polygons)
        {
            if (polygons.Count == 0)
            {
                return(null);
            }
            else
            {
                var polyRoot = new Node(polygons[0].ID);

                var frontPolygons = new List <Polygon>();
                var backPolygons  = new List <Polygon>();
                var d             = -Vector3.Dot(polygons[0].normal, Transformations.V4ToV3(polygons[0].vertices[0]));
                var plane         = new Vector4(polygons[0].normal, d);
                for (int i = 1; i < polygons.Count; i++)
                {
                    var polyPos = CheckPosition(polygons[i], plane);
                    if (polyPos == Position.InFront)
                    {
                        frontPolygons.Add(polygons[i]);
                    }
                    else if (polyPos == Position.Behind)
                    {
                        backPolygons.Add(polygons[i]);
                    }
                    else
                    {
                        var d2 = -Vector3.Dot(polygons[i].normal, Transformations.V4ToV3(polygons[i].vertices[0]));

                        var v   = Vector3.Cross(polygons[0].normal, polygons[i].normal);
                        var dot = Vector3.Dot(v, v);

                        var u1 = d2 * polygons[0].normal;
                        var u2 = -d * polygons[i].normal;
                        var p  = Vector3.Cross(u1 + u2, v / dot);

                        int     p1pos = -1, p2pos = -1;
                        Vector3 point1 = new Vector3(), point2 = new Vector3();
                        for (int j = 0; j < polygons[i].vertices.Length; j++)
                        {
                            var current = polygons[i].vertices[j];
                            var next    = polygons[i].vertices[(j + 1) % polygons[i].vertices.Length];

                            if (Vector4.Dot(current, plane) * Vector4.Dot(next, plane) <= 0)
                            {
                                var u = Transformations.V4ToV3(next - current);
                                var a = Vector3.Cross(v, u);
                                var b = Vector3.Cross(Transformations.V4ToV3(next) - p, u);

                                var t = 0.0F;
                                if (a.X != 0)
                                {
                                    t = b.X / a.X;
                                }
                                else if (a.Y != 0)
                                {
                                    t = b.Y / a.Y;
                                }
                                else if (a.Z != 0)
                                {
                                    t = b.Z / a.Z;
                                }

                                if (p1pos == -1)
                                {
                                    point1 = p + (t * v);
                                    p1pos  = j + 1;
                                }
                                else
                                {
                                    point2 = p + (t * v);
                                    p2pos  = j + 1;
                                }
                            }
                        }

                        var poly1 = new Polygon {
                            ID = Polygons.Count, vertices = new Vector4[p1pos + (polygons[i].vertices.Length - p2pos) + 2], normal = polygons[i].normal
                        };
                        for (int j = 0, k = 0; k < p1pos; j++, k++)
                        {
                            poly1.vertices[j] = polygons[i].vertices[k];
                        }
                        poly1.vertices[p1pos]     = new Vector4(point1, 1.0F);
                        poly1.vertices[p1pos + 1] = new Vector4(point2, 1.0F);
                        for (int j = p1pos + 2, k = p2pos; k < polygons[i].vertices.Length; j++, k++)
                        {
                            poly1.vertices[j] = polygons[i].vertices[k];
                        }
                        poly1.normal = Transformations.CalculateSurfaceNormal(poly1);
                        Polygons.Add(poly1);

                        var poly2 = new Polygon {
                            ID = Polygons.Count, vertices = new Vector4[p2pos - p1pos + 2], normal = polygons[i].normal
                        };
                        poly2.vertices[0] = new Vector4(point1, 1.0F);
                        for (int j = 1, k = p1pos; k < p2pos; j++, k++)
                        {
                            poly2.vertices[j] = polygons[i].vertices[k];
                        }
                        poly2.vertices[p2pos - p1pos + 1] = new Vector4(point2, 1.0F);
                        Polygons.Add(poly2);

                        if (CheckPosition(poly1, plane) == Position.InFront)
                        {
                            frontPolygons.Add(poly1);
                            backPolygons.Add(poly2);
                        }
                        else
                        {
                            frontPolygons.Add(poly2);
                            backPolygons.Add(poly1);
                        }
                    }
                }

                polyRoot.Front = GenerateTree(frontPolygons);
                polyRoot.Back  = GenerateTree(backPolygons);
                return(polyRoot);
            }
        }