예제 #1
0
        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);
            }
        }
예제 #3
0
        /// <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();
        }