예제 #1
0
        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);
        }
예제 #2
0
        /// <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);
        }
예제 #3
0
        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);
                }
            }
        }
예제 #4
0
        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;
        }
예제 #5
0
        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);
        }
예제 #6
0
        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;
            }
        }
예제 #7
0
        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);
        }
예제 #8
0
        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);
            }
        }
예제 #9
0
        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);
        }
예제 #10
0
        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();
        }