public static Mesh[] SplitIntoMeshesOnOrthographicZ(Mesh meshToSplit, Vector3 buildVolume, ReportProgressRatio reportProgress)
		{
			// check if the part is bigger than the build plate (if it is we need to use that as our size)
			AxisAlignedBoundingBox partBounds = meshToSplit.GetAxisAlignedBoundingBox();

			buildVolume.x = Math.Max(buildVolume.x, partBounds.XSize + 2);
			buildVolume.y = Math.Max(buildVolume.y, partBounds.YSize + 2);
			buildVolume.z = Math.Max(buildVolume.z, partBounds.ZSize + 2);

			// Find all the separate objects that are on the plate
			// Create a 2D image the size of the printer bed at some scale with the parts draw on it top down

			double scaleFactor = 5;
			ImageBuffer partPlate = new ImageBuffer((int)(buildVolume.x * scaleFactor), (int)(buildVolume.y * scaleFactor), 32, new BlenderBGRA());
			Vector2 renderOffset = new Vector2(buildVolume.x / 2, buildVolume.y / 2) - new Vector2(partBounds.Center.x, partBounds.Center.y);

			PolygonMesh.Rendering.OrthographicZProjection.DrawTo(partPlate.NewGraphics2D(), meshToSplit, renderOffset, scaleFactor, RGBA_Bytes.White);

			bool continueProcessin = true;
			if (reportProgress != null)
			{
				reportProgress(.2, "", out continueProcessin);
			}

			//ImageIO.SaveImageData("test part plate 0.png", partPlate);
			// expand the bounds a bit so that we can collect all the vertices and polygons within each bound
			Dilate.DoDilate3x3Binary(partPlate, 1);
			//ImageIO.SaveImageData("test part plate 1.png", partPlate);

			// trace all the bounds of the objects on the plate
			PolyTree polyTreeForPlate = FindDistictObjectBounds(partPlate);
			if (polyTreeForPlate == null)
			{
				Mesh[] singleMesh = new Mesh[1];
				singleMesh[0] = meshToSplit;
				return singleMesh;
			}

			// get all the discrete areas that are polygons so we can search them
			Polygons discreteAreas = new Polygons();
			GetAreasRecursive(polyTreeForPlate, discreteAreas);
			if (discreteAreas.Count == 0)
			{
				return null;
			}
			else if (discreteAreas.Count == 1)
			{
				Mesh[] singleMesh = new Mesh[1];
				singleMesh[0] = meshToSplit;
				return singleMesh;
			}

			Graphics2D graphics2D = partPlate.NewGraphics2D();
			graphics2D.Clear(RGBA_Bytes.Black);
			Random rand = new Random();
			foreach (Polygon polygon in discreteAreas)
			{
				graphics2D.Render(PlatingHelper.PolygonToPathStorage(polygon), new RGBA_Bytes(rand.Next(128, 255), rand.Next(128, 255), rand.Next(128, 255)));
			}
			if (reportProgress != null)
			{
				reportProgress(.5, "", out continueProcessin);
			}
			//ImageIO.SaveImageData("test part plate 2.png", partPlate);

			// add each of the separate bounds polygons to new meshes
			Mesh[] discreteMeshes = new Mesh[discreteAreas.Count];
			for (int i = 0; i < discreteAreas.Count; i++)
			{
				discreteMeshes[i] = new Mesh();
			}

			foreach (Face face in meshToSplit.Faces)
			{
				bool faceDone = false;
				// figure out which area one or more of the vertices are in add the face to the right new mesh
				foreach (FaceEdge faceEdge in face.FaceEdges())
				{
					Vector2 position = new Vector2(faceEdge.firstVertex.Position.x, faceEdge.firstVertex.Position.y);
					position += renderOffset;
					position *= scaleFactor;

					for (int areaIndex = discreteAreas.Count - 1; areaIndex >= 0; areaIndex--)
					{
						if (PointInPolygon(discreteAreas[areaIndex], new IntPoint((int)position.x, (int)position.y)))
						{
							List<Vertex> faceVertices = new List<Vertex>();
							foreach (FaceEdge faceEdgeToAdd in face.FaceEdges())
							{
								Vertex newVertex = discreteMeshes[areaIndex].CreateVertex(faceEdgeToAdd.firstVertex.Position);
								faceVertices.Add(newVertex);
							}

							discreteMeshes[areaIndex].CreateFace(faceVertices.ToArray());
							faceDone = true;
							break;
						}
					}

					if (faceDone)
					{
						break;
					}
				}
			}

			if (reportProgress != null)
			{
				reportProgress(.8, "", out continueProcessin);
			}

			for (int i = 0; i < discreteMeshes.Count(); i++)
			{
				Mesh mesh = discreteMeshes[i];
			}

			return discreteMeshes;
		}