fPolylineGameObject make_path <T>(LinearToolpath3 <T> path, fMaterial material, float width, Vector3d origin) where T : IToolpathVertex { Vector3d prev = Vector3d.Zero; tempPolyLine.Clear(); foreach (T vtx in path) { Vector3d v = origin + vtx.Position; v = MeshTransforms.ConvertZUpToYUp(v); v = MeshTransforms.FlipLeftRightCoordSystems(v); // [RMS] because of the sharp turns we make, unity polyline will get twisted up unless we put // in some duplicate vertices =\ if (tempPolyLine.Count > 0) { tempPolyLine.Add((Vector3f)Vector3d.Lerp(prev, v, 0.001)); tempPolyLine.Add((Vector3f)Vector3d.Lerp(prev, v, 0.998)); tempPolyLine.Add((Vector3f)Vector3d.Lerp(prev, v, 0.999)); } tempPolyLine.Add((Vector3f)v); prev = v; } fPolylineGameObject go = PolylinePool.Allocate(); go.SetMaterial(material, true); go.SetLineWidth(width); go.SetVertices(tempPolyLine.ToArray(), false, true); return(go); }
/// <summary> /// Converts g3.SimpleMesh to UnityEngine.Mesh /// </summary> /// <param name="simpleMesh">SimpleMesh</param> /// <returns>UnityEngine.Mesh</returns> public static Mesh ToMesh(this SimpleMesh simpleMesh) { Mesh unityMesh = new Mesh(); MeshTransforms.ConvertZUpToYUp(simpleMesh); Vector3[] vertices = new Vector3[simpleMesh.VertexCount]; Color[] colors = new Color[simpleMesh.VertexCount]; Vector2[] uvs = new Vector2[simpleMesh.VertexCount]; Vector3[] normals = new Vector3[simpleMesh.VertexCount]; NewVertexInfo data; for (int i = 0; i < simpleMesh.VertexCount; i++) { data = simpleMesh.GetVertexAll(i); vertices[i] = (Vector3)data.v; if (data.bHaveC) { colors[i] = (Color)data.c; } if (data.bHaveUV) { uvs[i] = (Vector2)data.uv; } if (data.bHaveN) { normals[i] = (Vector3)data.n; } } unityMesh.vertices = vertices; if (simpleMesh.HasVertexColors) { unityMesh.colors = colors; } if (simpleMesh.HasVertexUVs) { unityMesh.uv = uvs; } if (simpleMesh.HasVertexNormals) { unityMesh.normals = normals; } int[] triangles = new int[simpleMesh.TriangleCount * 3]; int j = 0; foreach (Index3i tri in simpleMesh.TrianglesItr()) { triangles[j * 3] = tri.a; triangles[j * 3 + 1] = tri.b; triangles[j * 3 + 2] = tri.c; j++; } unityMesh.triangles = triangles; return(unityMesh); }
void compute_slice_polylines() { // fMaterial mat1 = MaterialUtil.CreateFlatMaterialF(Colorf.Black); // fMaterial mat2 = MaterialUtil.CreateFlatMaterialF(Colorf.BlueMetal); // [TODO] do we need to hold data_lock here? seems like no since main thread is blocked, // then it would never be the case that we are setting SliceSet = null // create geometry int slice_i = 0; //SlicePolylines = new List<fPolylineGameObject>(); foreach (PlanarSlice slice in SliceSet.Slices) { //DebugUtil.Log(2, "Slice has {0} solids", slice.Solids.Count); Colorf slice_color = (slice_i % 2 == 0) ? Colorf.Black : Colorf.BlueMetal; // fMaterial slice_mat = (slice_i % 2 == 0) ? mat1 : mat2; slice_i++; foreach (GeneralPolygon2d poly in slice.Solids) { List <Vector3f> polyLine = new List <Vector3f>(); for (int pi = 0; pi <= poly.Outer.VertexCount; ++pi) { int i = pi % poly.Outer.VertexCount; Vector2d v2 = poly.Outer[i]; Vector2d n2 = poly.Outer.GetTangent(i).Perp; Vector3d v3 = new Vector3d(v2.x, v2.y, slice.Z); v3 = MeshTransforms.ConvertZUpToYUp(v3); v3 = MeshTransforms.FlipLeftRightCoordSystems(v3); Vector3d n3 = MeshTransforms.ConvertZUpToYUp(new Vector3d(n2.x, n2.y, 0)); n3 = MeshTransforms.FlipLeftRightCoordSystems(n3); n3.Normalize(); v3 += 0.1f * n3; polyLine.Add((Vector3f)v3); } // Do something with polyline.... Console.WriteLine(polyLine); ////DebugUtil.Log(2, "Polyline has {0} vertiecs", polyLine.Count); //fPolylineGameObject go = GameObjectFactory.CreatePolylineGO( // "slice_outer", polyLine, slice_color, 0.1f, LineWidthType.World); //go.SetMaterial(slice_mat, true); //CC.ActiveScene.RootGameObject.AddChild(go, false); //SlicePolylines.Add(go); } } }
public void LinearMoveToRelative3d(LinearMoveData move) { Vector3d nextPos = CurrentPosition + move.position; nextPos = MeshTransforms.ConvertZUpToYUp(nextPos); double dist = CurrentPosition.Distance(nextPos); double speed = move.rate * SpeedScale; double time = dist / speed; if (OnMoveToAtTimeF != null) { OnMoveToAtTimeF(nextPos, CurrentTime + time); } CurrentTime += time; CurrentPosition = nextPos; }
virtual protected DMesh3 make_bunny() { if (cached_bunny == null) { // [RMS] yiiiiiikes MemoryStream stream = FResources.LoadBinary("meshes/unit_height_bunny"); if (stream != null) { cached_bunny = StandardMeshReader.ReadMesh(stream, "obj"); MeshTransforms.ConvertZUpToYUp(cached_bunny); MeshTransforms.FlipLeftRightCoordSystems(cached_bunny); } else { cached_bunny = make_shape_sphere(); MeshTransforms.Scale(cached_bunny, 1 / ShapeHeight); } } DMesh3 mesh = new DMesh3(cached_bunny); MeshTransforms.Scale(mesh, ShapeHeight); return(mesh); }
virtual public void PreRender() { if (in_shutdown()) { return; } if (parameters_dirty) { // offset List <GeneralPolygon2d> offset = ClipperUtil.RoundOffset(combined_all, offset_distance); // aggressively simplify after round offset... foreach (var poly in offset) { poly.Simplify(path_width); } // subtract initial and add tiny gap so these don't get merged by slicer if (SubtractSolids) { offset = ClipperUtil.Difference(offset, combined_solid); offset = ClipperUtil.MiterOffset(offset, -path_width * 0.1); } offset = CurveUtils2.FilterDegenerate(offset, 0.001); foreach (var poly in offset) { poly.Simplify(path_width * 0.02); } DMesh3 mesh = new DMesh3(); MeshEditor editor = new MeshEditor(mesh); foreach (var poly in offset) { TriangulatedPolygonGenerator polygen = new TriangulatedPolygonGenerator() { Polygon = poly }; editor.AppendMesh(polygen.Generate().MakeDMesh()); } MeshTransforms.ConvertZUpToYUp(mesh); if (mesh.TriangleCount > 0) { MeshExtrudeMesh extrude = new MeshExtrudeMesh(mesh); extrude.ExtrudedPositionF = (v, n, vid) => { return(v + Layers * layer_height * Vector3d.AxisY); }; extrude.Extrude(); MeshTransforms.Translate(mesh, -mesh.CachedBounds.Min.y * Vector3d.AxisY); } PreviewSO.ReplaceMesh(mesh, true); //Vector3d translate = scene_bounds.Point(1, -1, 1); //translate.x += spiral.Bounds.Width + PathWidth; //Frame3f sceneF = Frame3f.Identity.Translated((Vector3f)translate); //PreviewSO.SetLocalFrame(sceneF, CoordSpace.SceneCoords); parameters_dirty = false; } }
public void ComputeOnBackgroundThread() { Deviation = null; DebugUtil.Log(SO.GetToolpathStats()); ToolpathSet paths = SO.GetToolpaths(); PlanarSliceStack slices = SO.GetSlices(); var settings = SO.GetSettings(); // AAHHH double bed_width = settings.Machine.BedSizeXMM; double bed_height = settings.Machine.BedSizeYMM; Vector3d origin = new Vector3d(-bed_width / 2, -bed_height / 2, 0); if (settings is gs.info.MakerbotSettings) { origin = Vector3d.Zero; } List <DeviationPt> points = new List <DeviationPt>(); SpinLock pointsLock = new SpinLock(); Action <DeviationPt> appendPointF = (pt) => { bool entered = false; pointsLock.Enter(ref entered); points.Add(pt); pointsLock.Exit(); }; double tolerance = settings.Machine.NozzleDiamMM * 0.5 + DeviationToleranceMM; gParallel.ForEach(Interval1i.Range(slices.Count), (slicei) => { PlanarSlice slice = slices[slicei]; //Interval1d zrange = (slicei < slices.Count - 1) ? // new Interval1d(slice.Z, slices[slicei + 1].Z - 0.5*settings.LayerHeightMM) : // new Interval1d(slice.Z, slice.Z + 0.5*settings.LayerHeightMM); double dz = 0.5 * settings.LayerHeightMM; Interval1d zrange = new Interval1d(slice.Z - dz, slice.Z + dz); double cellSize = 2.0f; ToolpathsLayerGrid grid = new ToolpathsLayerGrid(); grid.Build(paths, zrange, cellSize); foreach (GeneralPolygon2d poly in slice.Solids) { measure_poly(poly.Outer, slice.Z, grid, tolerance, appendPointF); foreach (var hole in poly.Holes) { measure_poly(poly.Outer, slice.Z, grid, tolerance, appendPointF); } } }); int N = points.Count; for (int k = 0; k < N; ++k) { DeviationPt pt = points[k]; Vector3d v = origin + pt.pos; v = MeshTransforms.ConvertZUpToYUp(v); pt.pos = MeshTransforms.FlipLeftRightCoordSystems(v); points[k] = pt; } Deviation = new DeviationData(); Deviation.DeviationPoints = points; OnGeometryUpdateRequired?.Invoke(this); }
public async Task ImportInteractive(string sFilename, Action <string> onCompletedF) { SourceFilePath = sFilename; DMesh3Builder builder = new DMesh3Builder(); StandardMeshReader reader = new StandardMeshReader() { MeshBuilder = builder }; await Task.Run(() => { IOReadResult result = reader.Read(SourceFilePath, ReadOptions.Defaults); if (result.code != IOCode.Ok) { ErrorMessage = "MeshImporter.Import: failed with message " + result.message; return; } }); if (builder.Meshes.Count == 0) { ErrorMessage = "MeshImporter.Import: no meshes in file!"; return; } await Task.Run(() => { // apply unity xforms foreach (DMesh3 mesh in builder.Meshes) { MeshTransforms.ConvertZUpToYUp(mesh); MeshTransforms.FlipLeftRightCoordSystems(mesh); } TriCount = 0; Bounds = AxisAlignedBox3d.Empty; foreach (var m in builder.Meshes) { TriCount += m.TriangleCount; Bounds.Contain(m.CachedBounds); } }); bool bSmall = (Bounds.MaxDim < HeightMinThreshold); bool bTall = (Bounds.Height > CC.Settings.BedSizeYMM); double maxXZ = Math.Max(Bounds.Width, Bounds.Depth); double bedMin = Math.Min(CC.Settings.BedSizeXMM, CC.Settings.BedSizeZMM); bool bLarge = (Bounds.Width > 2 * CC.Settings.BedSizeXMM) || (maxXZ > 2 * bedMin); bool bTriCount = (TriCount > TriCountThreshold); switch (CCPreferences.ImportAssistantMode) { case CCPreferences.ImportAssistantModes.PhysicalSizeOnly: bTriCount = false; break; case CCPreferences.ImportAssistantModes.MeshSizeOnly: bLarge = bSmall = bTall = false; break; case CCPreferences.ImportAssistantModes.Disabled: bLarge = bSmall = bTall = bTriCount = false; break; } if (bTriCount || bSmall || bLarge) { ImportMeshDialog.Show(CotangentUI.MainUICanvas, bSmall, bTall, bLarge, Bounds.Height, bTriCount, TriCount, async(scale, tricount) => { await process_and_complete_import(SourceFilePath, builder, scale, tricount, onCompletedF); }, async() => { await complete_import(SourceFilePath, builder, onCompletedF); } ); } else { await complete_import(SourceFilePath, builder, onCompletedF); } }
public bool ImportAutoUpdate(PrintMeshSO so) { SourceFilePath = so.SourceFilePath; if (!File.Exists(SourceFilePath)) { ErrorMessage = "MeshImporter.ImportAutoUpdate: file does not exist"; return(false); } DMesh3Builder builder = new DMesh3Builder(); StandardMeshReader reader = new StandardMeshReader() { MeshBuilder = builder }; long timestamp = File.GetLastWriteTime(SourceFilePath).Ticks; IOReadResult result = reader.Read(SourceFilePath, ReadOptions.Defaults); if (result.code != IOCode.Ok) { ErrorMessage = "MeshImporter.ImportAutoUpdate: failed with message " + result.message; return(false); } if (builder.Meshes.Count == 0) { ErrorMessage = "MeshImporter.ImportAutoUpdate: no meshes in file!"; return(false); } if (builder.Meshes.Count != 1) { ErrorMessage = "MeshImporter.ImportAutoUpdate: can only auto-update from file with single mesh!"; return(false); } DMesh3 mesh = builder.Meshes[0]; // unity xforms MeshTransforms.ConvertZUpToYUp(mesh); MeshTransforms.FlipLeftRightCoordSystems(mesh); // wait for any active tools to finish // [TODO] do we need to do this? while (CC.ActiveContext.ToolManager.HasActiveTool()) { Thread.Sleep(1000); } if (CC.ActiveScene.SceneObjects.Contains(so) == false) { ErrorMessage = "MeshImporter.ImportAutoUpdate: SO no longer exists"; return(false); } // change event?? so.LastReadFileTimestamp = timestamp; ThreadMailbox.PostToMainThread(() => { so.ReplaceMesh(mesh, true); }); return(true); }
public static void test_uv_insert_segment() { DMesh3 mesh = TestUtil.LoadTestInputMesh("plane_250v.obj"); mesh.EnableVertexUVs(Vector2f.Zero); MeshTransforms.ConvertYUpToZUp(mesh); DMeshAABBTree3 spatial = new DMeshAABBTree3(mesh); spatial.Build(); int tid = spatial.FindNearestTriangle(Vector3d.Zero); //Polygon2d poly = Polygon2d.MakeRectangle(Vector2d.Zero, 5, 5); Polygon2d poly = Polygon2d.MakeCircle(5, 13); //PolyLine2d poly = new PolyLine2d( new Vector2d[] { -5 * Vector2d.One, 5 * Vector2d.One }); //int tri_edge0 = mesh.GetTriEdge(tid, 0); //Index2i edge0_tris = mesh.GetEdgeT(tri_edge0); //Index2i edge0_verts = mesh.GetEdgeV(tri_edge0); //Vector3d v0 = mesh.GetVertex(edge0_verts.a), v1 = mesh.GetVertex(edge0_verts.b); //Vector3d c = mesh.GetTriCentroid(tid); //Polygon2d poly = new Polygon2d(new Vector2d[] { // Vector2d.Lerp(v0.xy, v1.xy, -0.25), // Vector2d.Lerp(v0.xy, v1.xy, 1.5), // c.xy //}); MeshInsertUVPolyCurve insert = new MeshInsertUVPolyCurve(mesh, poly); insert.Apply(); Polygon2d test_poly = new Polygon2d(); List <double> distances = new List <double>(); List <int> nearests = new List <int>(); for (int i = 0; i < insert.Loops[0].VertexCount; ++i) { Vector2d v = mesh.GetVertex(insert.Loops[0].Vertices[i]).xy; test_poly.AppendVertex(v); int iNear; double fNear; distances.Add(poly.DistanceSquared(v, out iNear, out fNear)); nearests.Add(iNear); } System.Console.WriteLine("inserted loop poly has {0} edges", insert.Loops[0].EdgeCount); // find a triangle connected to loop that is inside the polygon // [TODO] maybe we could be a bit more robust about this? at least // check if triangle is too degenerate... int seed_tri = -1; for (int i = 0; i < insert.Loops[0].EdgeCount; ++i) { Index2i et = mesh.GetEdgeT(insert.Loops[0].Edges[i]); Vector3d ca = mesh.GetTriCentroid(et.a); bool in_a = poly.Contains(ca.xy); Vector3d cb = mesh.GetTriCentroid(et.b); bool in_b = poly.Contains(cb.xy); if (in_a && in_b == false) { seed_tri = et.a; break; } else if (in_b && in_a == false) { seed_tri = et.b; break; } } Util.gDevAssert(seed_tri != -1); // flood-fill inside loop HashSet <int> loopEdges = new HashSet <int>(insert.Loops[0].Edges); MeshFaceSelection sel = new MeshFaceSelection(mesh); sel.FloodFill(seed_tri, null, (eid) => { return(loopEdges.Contains(eid) == false); }); // delete inside loop MeshEditor editor = new MeshEditor(mesh); editor.RemoveTriangles(sel, true); MeshTransforms.ConvertZUpToYUp(mesh); TestUtil.WriteTestOutputMesh(mesh, "insert_uv_segment.obj"); //OBJWriter writer = new OBJWriter(); //var s = new System.IO.StreamWriter(Program.TEST_OUTPUT_PATH + "mesh_local_param.obj", false); //List<WriteMesh> wm = new List<WriteMesh>() { new WriteMesh(mesh) }; //WriteOptions opt = new WriteOptions() { // bCombineMeshes = false, bWriteGroups = false, bPerVertexColors = true, bPerVertexUVs = true, // AsciiHeaderFunc = () => { return "mttllib checkerboard.mtl\r\nusemtl checkerboard\r\n"; } //}; //writer.Write(s, wm, opt); //s.Close(); }