public void Initialize_AutoFitBox() { DMeshSO TargetMeshSO = TargetSO as DMeshSO; // initialize w/ auto-fit box DMesh3 mesh = TargetMeshSO.Mesh; DMeshAABBTree3 spatial = TargetMeshSO.Spatial; meshBounds = mesh.CachedBounds; create_preview_so(); ContOrientedBox3 boxFitter = new ContOrientedBox3( new RemapItr <Vector3d, int>(mesh.TriangleIndices(), (tid) => { return(mesh.GetTriCentroid(tid)); }), new RemapItr <double, int>(mesh.TriangleIndices(), (tid) => { return(mesh.GetTriArea(tid)); })); //DebugUtil.EmitDebugBox("fitbox", boxFitter.Box, Colorf.Red, TargetSO.RootGameObject, false); Box3d fitBox = boxFitter.Box; int longest = 0; if (fitBox.Extent.y > fitBox.Extent.x) { longest = 1; } if (fitBox.Extent.z > fitBox.Extent[longest]) { longest = 2; } Vector3d vTop = fitBox.Center + fitBox.Extent[longest] * fitBox.Axis(longest); Vector3d vBottom = fitBox.Center - fitBox.Extent[longest] * fitBox.Axis(longest); int base_tid = spatial.FindNearestTriangle(vBottom); int top_tid = spatial.FindNearestTriangle(vTop); if (vTop.y < vBottom.y) { int tmp = base_tid; base_tid = top_tid; top_tid = tmp; } Vector3d vBasePt = mesh.GetTriCentroid(base_tid); Vector3d vTopPt = mesh.GetTriCentroid(top_tid); int other1 = (longest + 1) % 3, other2 = (longest + 2) % 3; int front_tid = spatial.FindNearestHitTriangle(new Ray3d(fitBox.Center, fitBox.Axis(other1))); Vector3d vFrontPt = mesh.GetTriCentroid(front_tid); int back_tid = spatial.FindNearestHitTriangle(new Ray3d(fitBox.Center, -fitBox.Axis(other1))); Vector3d vBackPt = mesh.GetTriCentroid(back_tid); int right_tid = spatial.FindNearestHitTriangle(new Ray3d(fitBox.Center, fitBox.Axis(other2))); Vector3d vRightPt = mesh.GetTriCentroid(right_tid); int left_tid = spatial.FindNearestHitTriangle(new Ray3d(fitBox.Center, -fitBox.Axis(other2))); Vector3d vLeftPt = mesh.GetTriCentroid(left_tid); initialFrontPt = (Vector3f)vFrontPt; SetPointPosition_Internal(BasePointID, MeshQueries.SurfaceFrame(mesh, base_tid, vBasePt), CoordSpace.ObjectCoords); SetPointPosition_Internal(FrontPointID, MeshQueries.SurfaceFrame(mesh, front_tid, vFrontPt), CoordSpace.ObjectCoords); SetPointPosition(TopPointID, MeshQueries.SurfaceFrame(mesh, top_tid, vTopPt), CoordSpace.ObjectCoords); }
List <Polygon2d> decompose_cluster_up(DMesh3 mesh) { optimize_mesh(mesh); mesh.CompactInPlace(); mesh.DiscardTriangleGroups(); mesh.EnableTriangleGroups(0); double minLength = Settings.MaxBridgeWidthMM * 0.75; double minArea = minLength * minLength; Dictionary <int, double> areas = new Dictionary <int, double>(); Dictionary <int, HashSet <int> > trisets = new Dictionary <int, HashSet <int> >(); HashSet <int> active_groups = new HashSet <int>(); Action <int, int> add_tri_to_group = (tid, gid) => { mesh.SetTriangleGroup(tid, gid); areas[gid] = areas[gid] + mesh.GetTriArea(tid); trisets[gid].Add(tid); }; Action <int, int> add_group_to_group = (gid, togid) => { var set = trisets[togid]; foreach (int tid in trisets[gid]) { mesh.SetTriangleGroup(tid, togid); set.Add(tid); } areas[togid] += areas[gid]; active_groups.Remove(gid); }; Func <IEnumerable <int>, int> find_min_area_group = (tri_itr) => { int min_gid = -1; double min_area = double.MaxValue; foreach (int tid in tri_itr) { int gid = mesh.GetTriangleGroup(tid); double a = areas[gid]; if (a < min_area) { min_area = a; min_gid = gid; } } return(min_gid); }; foreach (int eid in MeshIterators.InteriorEdges(mesh)) { Index2i et = mesh.GetEdgeT(eid); if (mesh.GetTriangleGroup(et.a) != 0 || mesh.GetTriangleGroup(et.b) != 0) { continue; } int gid = mesh.AllocateTriangleGroup(); areas[gid] = 0; trisets[gid] = new HashSet <int>(); active_groups.Add(gid); add_tri_to_group(et.a, gid); add_tri_to_group(et.b, gid); } foreach (int tid in mesh.TriangleIndices()) { if (mesh.GetTriangleGroup(tid) != 0) { continue; } int gid = find_min_area_group(mesh.TriTrianglesItr(tid)); add_tri_to_group(tid, gid); } IndexPriorityQueue pq = new IndexPriorityQueue(mesh.MaxGroupID); foreach (var pair in areas) { pq.Insert(pair.Key, (float)pair.Value); } while (pq.Count > 0) { int gid = pq.First; pq.Remove(gid); if (areas[gid] > minArea) // ?? { break; } List <int> nbr_groups = find_neighbour_groups(mesh, gid, trisets[gid]); int min_gid = -1; double min_area = double.MaxValue; foreach (int ngid in nbr_groups) { double a = areas[ngid]; if (a < min_area) { min_area = a; min_gid = ngid; } } if (min_gid != -1) { add_group_to_group(gid, min_gid); pq.Remove(min_gid); pq.Insert(min_gid, (float)areas[min_gid]); } } List <Polygon2d> result = new List <Polygon2d>(); int[][] sets = FaceGroupUtil.FindTriangleSetsByGroup(mesh); foreach (var set in sets) { result.Add(make_poly(mesh, set)); } return(result); }