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); } }