public IEnumerator RunMainThreadProcessing(bool bSpawnBackgroundWrite = true) { int N = ExportMeshSOs.Count; ExportMeshes = new DMesh3[N]; MeshFrames = new Frame3f[N]; for (int k = 0; k < N; ++k) { DMeshSO so = ExportMeshSOs[k]; DMesh3 copy = new DMesh3(so.Mesh, false, MeshComponents.VertexColors | MeshComponents.VertexNormals); // if we have scaling or parent hierarchy, need to transform to scene in main // thread, because we have no way of storing transform stack currently if (so.GetLocalScale() != Vector3f.One || so.Parent != so.GetScene()) { foreach (int vid in copy.VertexIndices()) { Vector3d v = copy.GetVertex(vid); Vector3f n = copy.GetVertexNormal(vid); Frame3f f = new Frame3f(v, n); f = SceneTransforms.ObjectToScene(so, f); copy.SetVertex(vid, f.Origin); copy.SetVertexNormal(vid, f.Z); } MeshFrames[k] = Frame3f.Identity; } else { MeshFrames[k] = ExportMeshSOs[k].GetLocalFrame(CoordSpace.ObjectCoords); } ExportMeshes[k] = copy; yield return(null); } if (MainThreadWorkCompletedF != null) { MainThreadWorkCompletedF(); } DebugUtil.Log("MeshExporter: completed main thread processing"); if (bSpawnBackgroundWrite) { ThreadPool.QueueUserWorkItem((state) => { var result = RunBackgroundWrite(); if (OnCompletedF != null) { OnCompletedF(result); } }); } }
public override void PreRender() { base.PreRender(); // for fixed preview orientation, we keep preview "on the right" of scan. if (FixedPreviewOrientation && previewSO != null) { fCamera cam = previewSO.GetScene().ActiveCamera; Vector3f camRightW = cam.Right(); Vector3f camRightS = previewSO.GetScene().ToSceneN(camRightW); Frame3f previewF = lastPreviewFrameS; Frame3f targetF = TargetSO.GetLocalFrame(CoordSpace.SceneCoords); Vector3f dv = previewF.Origin - targetF.Origin; dv.y = 0; float dist = dv.Length; Frame3f rightF = targetF.Translated(dist * camRightS); rightF.Rotation = previewF.Rotation; previewSO.SetLocalFrame(rightF, CoordSpace.SceneCoords); } }
/// <summary> /// This is the action we give to the trim-scan tool, to run on accept /// </summary> public static void CropScanFromSelection(DMeshSO so, MeshFaceSelection selection, object tool) { DMesh3 beforeMesh = new DMesh3(so.Mesh); DMesh3 mesh = so.Mesh; // [RMS] if we are using the two-point tool, then we can use the user input points to // try to figure out an up axis, by assuming the first point is on the base of the scan. Steps are: // 1) guess a midpoint. Currently centroid of upper-half of geodesic selection. // 2) construct up axis as (midpoint-basepoint). this axis to Y-up. Vector3f upAxisS = Vector3f.AxisY; TwoPointFaceSelectionTool ptool = tool as TwoPointFaceSelectionTool; if (ptool != null) { var cache = ptool.SelectionCache; Interval1d range = new Interval1d(cache.CurrentScalarThreshold / 2, cache.CurrentScalarThreshold); List <int> triangles = new List <int>(selection.Count); cache.FindTrianglesInScalarInterval(range, triangles); Vector3d c = MeshMeasurements.Centroid(triangles, mesh.GetTriCentroid); Vector3d cS = SceneTransforms.ObjectToSceneP(so, c); Vector3d basePosS = ptool.SourcePositionS.Origin; upAxisS = (Vector3f)(cS - basePosS).Normalized; } // crop scan and fill top hole List <int> borderTris = selection.FindBorderTris(); MeshEditor editor = new MeshEditor(mesh); editor.RemoveTriangles((tid) => { return(selection.IsSelected(tid) == false); }, true); if (OGActions.FillHoleInScan) { SmoothedHoleFill fill = new SmoothedHoleFill(mesh) { TargetEdgeLength = 2.5f, SmoothAlpha = 0.5f, BorderHintTris = borderTris, OffsetDirection = SceneTransforms.SceneToObjectN(so, upAxisS), OffsetDistance = (ptool != null) ? 25.0 : 0.0 }; fill.Apply(); } so.NotifyMeshEdited(); DMesh3 afterMesh = new DMesh3(so.Mesh); so.GetScene().History.PushChange(new ReplaceEntireMeshChange(so, beforeMesh, afterMesh), true); mesh = so.Mesh; // Now we auto-align the scan so it points upwards, and then // recenter pivot and shift to above ground plane if (ptool != null) { Vector3d basePosS = ptool.SourcePositionS.Origin; Quaternionf alignUp = Quaternionf.FromTo(upAxisS, Vector3f.AxisY); // rotate part so that axis points up Frame3f curF = so.GetLocalFrame(CoordSpace.SceneCoords); Frame3f newF = curF.Rotated(alignUp); TransformSOChange alignUpChange = new TransformSOChange(so, curF, newF, CoordSpace.SceneCoords); basePosS = newF.FromFrameP(curF.ToFrameP(basePosS)); // map to new frame so.GetScene().History.PushChange(alignUpChange, false); // recenter pivot at bbox center // [RMS] previously was using vertex centroid, but this is then affected by mesh density // (maybe tri centroid? but bbox makes more sense...and below we assume box center) Vector3d centerL = mesh.CachedBounds.Center; Vector3d centerO = newF.FromFrameP(centerL); Frame3f newPivotO = new Frame3f(centerO); so.GetScene().History.PushChange(new RepositionPivotChangeOp(newPivotO, so), false); // position above ground plane AxisAlignedBox3d bounds = so.Mesh.CachedBounds; float h = (float)bounds.Height; Vector3f o = newPivotO.Origin; Vector3f translateO = new Vector3f(-o.x, h * 0.5f - o.y + BaseHeightAboveGroundPlaneMM, -o.z); //Vector3f translateO = new Vector3f(0, h * 0.5f - o.y + BaseHeightAboveGroundPlaneMM, 0); newPivotO.Translate(translateO); so.GetScene().History.PushChange(new TransformSOChange(so, newPivotO, CoordSpace.ObjectCoords), false); // save base point in frame of scan basePosS += translateO; Vector3d basePosL = SceneTransforms.SceneToObjectP(so, basePosS); OG.Scan.UserBasePoint = basePosL; } so.GetScene().History.PushInteractionCheckpoint(); }