// There can be a singleton of this because GL must always render on the UI thread and can't overlap this array private static void DrawToGLUsingBsp(Mesh meshToRender, Matrix4X4 meshToViewTransform, Matrix4X4 invMeshToViewTransform) { ImageBuffer lastFaceTexture = null; var bspFaceList = FaceBspTree.GetFacesInVisibiltyOrder(meshToRender.Faces, meshToRender.FaceBspTree, meshToViewTransform, invMeshToViewTransform); foreach (var face in bspFaceList) { if (face == null) { continue; } ImageBuffer faceTexture; meshToRender.FaceTexture.TryGetValue((face, 0), out faceTexture); if (faceTexture != lastFaceTexture) { // Make sure the GLMeshPlugin has a reference to hold onto the image so it does not go away before this. if (faceTexture != null) { ImageGlPlugin glPlugin = ImageGlPlugin.GetImageGlPlugin(faceTexture, true); GL.Enable(EnableCap.Texture2D); GL.BindTexture(TextureTarget.Texture2D, glPlugin.GLTextureHandle); } else { GL.Disable(EnableCap.Texture2D); } lastFaceTexture = faceTexture; } GL.Begin(BeginMode.Triangles); GL.Normal3(face.Normal.X, face.Normal.Y, face.Normal.Z); // load up the uvs if (faceTexture != null) { foreach (var vertex in face.AsUvTriangles()) { GL.TexCoord2(vertex.v0.uv); GL.Vertex3(vertex.v0.p); GL.TexCoord2(vertex.v1.uv); GL.Vertex3(vertex.v1.p); GL.TexCoord2(vertex.v2.uv); GL.Vertex3(vertex.v2.p); } } else { foreach (var vertex in face.AsTriangles()) { GL.Vertex3(vertex.p0); GL.Vertex3(vertex.p1); GL.Vertex3(vertex.p2); } } GL.End(); } }
// There can be a singleton of this because GL must always render on the UI thread and can't overlap this array private static void DrawToGLZSorted(Mesh mesh, Matrix4X4 meshToViewTransform, Matrix4X4 invMeshToViewTransform) { ImageBuffer lastFaceTexture = null; // var zSortedFaceList2 = mesh.GetFacesInVisibiltyOrder(meshToViewTransform); var zSortedFaceList = FaceBspTree.GetFacesInVisibiltyOrder(mesh, mesh.FaceBspTree, meshToViewTransform, invMeshToViewTransform); foreach (var face in zSortedFaceList) { if (face == -1) { continue; } FaceTextureData faceTexture; mesh.FaceTextures.TryGetValue(face, out faceTexture); if (faceTexture != null && faceTexture.image != lastFaceTexture) { // Make sure the GLMeshPlugin has a reference to hold onto the image so it does not go away before this. if (faceTexture != null) { var glPlugin = ImageGlPlugin.GetImageGlPlugin(faceTexture.image, true); GL.Enable(EnableCap.Texture2D); GL.BindTexture(TextureTarget.Texture2D, glPlugin.GLTextureHandle); } else { GL.Disable(EnableCap.Texture2D); } lastFaceTexture = faceTexture.image; } GL.Begin(BeginMode.Triangles); var normal = mesh.Faces[face].normal; GL.Normal3(normal.X, normal.Y, normal.Z); // load up the uvs if (faceTexture != null) { GL.TexCoord2(faceTexture.uv0); GL.Vertex3(mesh.Vertices[mesh.Faces[face].v0]); GL.TexCoord2(faceTexture.uv1); GL.Vertex3(mesh.Vertices[mesh.Faces[face].v1]); GL.TexCoord2(faceTexture.uv2); GL.Vertex3(mesh.Vertices[mesh.Faces[face].v2]); } else { GL.Vertex3(mesh.Vertices[mesh.Faces[face].v0]); GL.Vertex3(mesh.Vertices[mesh.Faces[face].v1]); GL.Vertex3(mesh.Vertices[mesh.Faces[face].v2]); } GL.End(); } }
public void CreateBspFaceTrees() { // a simple list of 3 faces // // Index 1 ^------------------- z = 3 // // Index 0 ^------------------- z = 2 // // Index 2 ^------------------- z = 1 var testMesh = new Mesh(); testMesh.CreateFace(new Vector3[] { new Vector3(0, 0, 2), new Vector3(10, 0, 2), new Vector3(5, 5, 2) }); testMesh.CreateFace(new Vector3[] { new Vector3(0, 0, 3), new Vector3(10, 0, 3), new Vector3(5, 5, 3) }); testMesh.CreateFace(new Vector3[] { new Vector3(0, 0, 1), new Vector3(10, 0, 1), new Vector3(5, 5, 1) }); // test they are in the right order { var root = FaceBspTree.Create(testMesh); Assert.IsTrue(root.Index == 1); Assert.IsTrue(root.BackNode.Index == 0); Assert.IsTrue(root.BackNode.BackNode.Index == 2); var renderOredrList = FaceBspTree.GetFacesInVisibiltyOrder(testMesh, root, Matrix4X4.Identity, Matrix4X4.Identity).ToList(); Assert.IsTrue(renderOredrList[0] == 1); Assert.IsTrue(renderOredrList[1] == 0); Assert.IsTrue(renderOredrList[2] == 2); } }
public void EnsureTransparentSorting() { var localMesh = Mesh; if (localMesh != null && localMesh.FaceBspTree == null && localMesh.Faces.Count < 2000 && !buildingFaceBsp) { this.buildingFaceBsp = true; Task.Run(() => { // TODO: make a SHA1 based cache for the sorting on this mesh and use them from memory or disk var bspTree = FaceBspTree.Create(localMesh); UiThread.RunOnIdle(() => localMesh.FaceBspTree = bspTree); this.buildingFaceBsp = false; }); } }
public void CreatePrintBed(Vector3 displayVolume, Vector2 bedCenter, BedShape bedShape) { if (MeshViewerWidget.BedCenter == bedCenter && MeshViewerWidget.bedShape == bedShape && MeshViewerWidget.displayVolume == displayVolume) { return; } MeshViewerWidget.BedCenter = bedCenter; MeshViewerWidget.bedShape = bedShape; MeshViewerWidget.displayVolume = displayVolume; Vector3 displayVolumeToBuild = Vector3.ComponentMax(displayVolume, new Vector3(1, 1, 1)); double sizeForMarking = Math.Max(displayVolumeToBuild.X, displayVolumeToBuild.Y); double divisor = 10; int skip = 1; if (sizeForMarking > 1000) { divisor = 100; skip = 10; } else if (sizeForMarking > 300) { divisor = 50; skip = 5; } switch (bedShape) { case BedShape.Rectangular: if (displayVolumeToBuild.Z > 0) { buildVolume = PlatonicSolids.CreateCube(displayVolumeToBuild); for (int i = 0; i < buildVolume.Vertices.Count; i++) { buildVolume.Vertices[i] = buildVolume.Vertices[i] + new Vector3Float(0, 0, displayVolumeToBuild.Z / 2); } var bspTree = FaceBspTree.Create(buildVolume); buildVolume.FaceBspTree = bspTree; } printerBed = PlatonicSolids.CreateCube(displayVolumeToBuild.X, displayVolumeToBuild.Y, 1.8); { printerBed.PlaceTextureOnFace(0, BedImage); } break; case BedShape.Circular: { throw new NotImplementedException(); //if (displayVolumeToBuild.Z > 0) //{ // buildVolume = VertexSourceToMesh.Extrude(new Ellipse(new Vector2(), displayVolumeToBuild.X / 2, displayVolumeToBuild.Y / 2), displayVolumeToBuild.Z); // foreach (Vertex vertex in buildVolume.Vertices) // { // vertex.Position = vertex.Position + new Vector3(0, 0, .2); // } //} //CreateCircularBedGridImage((int)(displayVolumeToBuild.X / divisor), (int)(displayVolumeToBuild.Y / divisor), skip); //printerBed = VertexSourceToMesh.Extrude(new Ellipse(new Vector2(), displayVolumeToBuild.X / 2, displayVolumeToBuild.Y / 2), 2); //{ // foreach (Face face in printerBed.Faces) // { // if (face.Normal.Z > 0) // { // face.SetTexture(0, BedImage); // foreach (FaceEdge faceEdge in face.FaceEdges()) // { // faceEdge.SetUv(0, new Vector2((displayVolumeToBuild.X / 2 + faceEdge.FirstVertex.Position.X) / displayVolumeToBuild.X, // (displayVolumeToBuild.Y / 2 + faceEdge.FirstVertex.Position.Y) / displayVolumeToBuild.Y)); // } // } // } //} } break; default: throw new NotImplementedException(); } var zTop = printerBed.GetAxisAlignedBoundingBox().MaxXYZ.Z; for (int i = 0; i < printerBed.Vertices.Count; i++) { printerBed.Vertices[i] = printerBed.Vertices[i] - new Vector3Float(-bedCenter, zTop + .02); } if (buildVolume != null) { for (int i = 0; i < buildVolume.Vertices.Count; i++) { buildVolume.Vertices[i] = buildVolume.Vertices[i] - new Vector3Float(-bedCenter, zTop + .02); } } Invalidate(); }
public static (Mesh bed, Mesh volume) CreatePrintBedAndVolume(PrinterConfig printer) { Mesh printerBed = null; Mesh buildVolume = null; Vector3 displayVolumeToBuild = Vector3.ComponentMax(printer.Bed.ViewerVolume, new Vector3(1, 1, 1)); ImageBuffer bedplateImage = CreatePrintBedImage(printer); switch (printer.Bed.BedShape) { case BedShape.Rectangular: if (displayVolumeToBuild.Z > 0) { buildVolume = PlatonicSolids.CreateCube(displayVolumeToBuild); foreach (Vertex vertex in buildVolume.Vertices) { vertex.Position = vertex.Position + new Vector3(0, 0, displayVolumeToBuild.Z / 2); } var bspTree = FaceBspTree.Create(buildVolume); buildVolume.FaceBspTree = bspTree; } printerBed = PlatonicSolids.CreateCube(displayVolumeToBuild.X, displayVolumeToBuild.Y, 1.8); { Face face = printerBed.Faces[0]; MeshHelper.PlaceTextureOnFace(face, bedplateImage); } break; case BedShape.Circular: { if (displayVolumeToBuild.Z > 0) { buildVolume = VertexSourceToMesh.Extrude(new Ellipse(new Vector2(), displayVolumeToBuild.X / 2, displayVolumeToBuild.Y / 2), displayVolumeToBuild.Z); foreach (Vertex vertex in buildVolume.Vertices) { vertex.Position = vertex.Position + new Vector3(0, 0, .2); } } printerBed = VertexSourceToMesh.Extrude(new Ellipse(new Vector2(), displayVolumeToBuild.X / 2, displayVolumeToBuild.Y / 2), 1.8); { foreach (Face face in printerBed.Faces) { if (face.Normal.Z > 0) { face.SetTexture(0, bedplateImage); foreach (FaceEdge faceEdge in face.FaceEdges()) { faceEdge.SetUv(0, new Vector2((displayVolumeToBuild.X / 2 + faceEdge.FirstVertex.Position.X) / displayVolumeToBuild.X, (displayVolumeToBuild.Y / 2 + faceEdge.FirstVertex.Position.Y) / displayVolumeToBuild.Y)); } } } } } break; default: throw new NotImplementedException(); } var zTop = printerBed.GetAxisAlignedBoundingBox().maxXYZ.Z; foreach (Vertex vertex in printerBed.Vertices) { vertex.Position = vertex.Position - new Vector3(-printer.Bed.BedCenter, zTop + .02); } if (buildVolume != null) { foreach (Vertex vertex in buildVolume.Vertices) { vertex.Position = vertex.Position - new Vector3(-printer.Bed.BedCenter, 2.2); } } return(printerBed, buildVolume); }
public static (Mesh bed, Mesh volume) CreatePrintBedAndVolume(PrinterConfig printer) { Mesh printerBed = null; Mesh buildVolume = null; Vector3 displayVolumeToBuild = Vector3.ComponentMax(printer.Bed.ViewerVolume, new Vector3(1, 1, 1)); ImageBuffer bedplateImage = CreatePrintBedImage(printer); switch (printer.Bed.BedShape) { case BedShape.Rectangular: if (displayVolumeToBuild.Z > 0) { buildVolume = PlatonicSolids.CreateCube(displayVolumeToBuild); for (int i = 0; i < buildVolume.Vertices.Count; i++) { buildVolume.Vertices[i] = buildVolume.Vertices[i] + new Vector3Float(0, 0, displayVolumeToBuild.Z / 2); } var bspTree = FaceBspTree.Create(buildVolume); buildVolume.FaceBspTree = bspTree; } printerBed = PlatonicSolids.CreateCube(displayVolumeToBuild.X, displayVolumeToBuild.Y, 1.8); { printerBed.PlaceTextureOnFaces(0, bedplateImage); } break; case BedShape.Circular: { if (displayVolumeToBuild.Z > 0) { buildVolume = VertexSourceToMesh.Extrude(new Ellipse(new Vector2(), displayVolumeToBuild.X / 2, displayVolumeToBuild.Y / 2), displayVolumeToBuild.Z); } printerBed = VertexSourceToMesh.Extrude(new Ellipse(new Vector2(), displayVolumeToBuild.X / 2, displayVolumeToBuild.Y / 2), 1.8); printerBed.PlaceTextureOnFaces(0, bedplateImage); } break; default: throw new NotImplementedException(); } var zTop = printerBed.GetAxisAlignedBoundingBox().MaxXYZ.Z; for (int i = 0; i < printerBed.Vertices.Count; i++) { printerBed.Vertices[i] = printerBed.Vertices[i] - new Vector3Float(-printer.Bed.BedCenter, zTop + .02); } if (buildVolume != null) { for (int i = 0; i < buildVolume.Vertices.Count; i++) { buildVolume.Vertices[i] = buildVolume.Vertices[i] - new Vector3Float(-printer.Bed.BedCenter, zTop + .02); } } return(printerBed, buildVolume); }
public static (Mesh bed, Mesh volume) CreatePrintBedAndVolume(PrinterConfig printer) { Mesh printerBed; Mesh buildVolume = null; var displayVolumeToBuild = Vector3.ComponentMax(printer.Bed.ViewerVolume, new Vector3(1, 1, 1)); // Temporarily assign a placeholder image as the mesh texture. This will be replaced with a themed image by the view var placeHolderImage = new ImageBuffer(5, 5); var graphics = placeHolderImage.NewGraphics2D(); graphics.Clear(Color.Gray.WithAlpha(40)); switch (printer.Bed.BedShape) { case BedShape.Rectangular: if (displayVolumeToBuild.Z > 0) { buildVolume = PlatonicSolids.CreateCube(displayVolumeToBuild); for (int i = 0; i < buildVolume.Vertices.Count; i++) { buildVolume.Vertices[i] = buildVolume.Vertices[i] + new Vector3Float(0, 0, displayVolumeToBuild.Z / 2); } var bspTree = FaceBspTree.Create(buildVolume); buildVolume.FaceBspTree = bspTree; } printerBed = PlatonicSolids.CreateCube(displayVolumeToBuild.X, displayVolumeToBuild.Y, 1.8); printerBed.PlaceTextureOnFaces(0, placeHolderImage); break; case BedShape.Circular: { if (displayVolumeToBuild.Z > 0) { buildVolume = VertexSourceToMesh.Extrude(new Ellipse(new Vector2(), displayVolumeToBuild.X / 2, displayVolumeToBuild.Y / 2), displayVolumeToBuild.Z); } printerBed = VertexSourceToMesh.Extrude(new Ellipse(new Vector2(), displayVolumeToBuild.X / 2, displayVolumeToBuild.Y / 2), 1.8); printerBed.PlaceTextureOnFaces(0, placeHolderImage); } break; default: throw new NotImplementedException(); } var zTop = printerBed.GetAxisAlignedBoundingBox().MaxXYZ.Z; for (int i = 0; i < printerBed.Vertices.Count; i++) { printerBed.Vertices[i] = printerBed.Vertices[i] - new Vector3Float(-printer.Bed.BedCenter, zTop + .02); } if (buildVolume != null) { for (int i = 0; i < buildVolume.Vertices.Count; i++) { buildVolume.Vertices[i] = buildVolume.Vertices[i] - new Vector3Float(-printer.Bed.BedCenter, zTop + .02); } } return(printerBed, buildVolume); }