示例#1
0
        private void ConstrainingForce(ISnapper snapper, out float fingersConstraint, out float wristConstraint)
        {
            ISnapData snap = snapper.SnapData;

            fingersConstraint = wristConstraint = 0;
            if (snap == null)
            {
                return;
            }

            bool isSnapping = snapper.IsSnapping;

            if (isSnapping && snap.HandAlignment != HandAlignType.None)
            {
                fingersConstraint = snap.HandPose != null ? 1f : 0f;
                wristConstraint   = 1f;
            }
            else if (snap.HandAlignment == HandAlignType.AttractOnHover)
            {
                fingersConstraint = snap.HandPose != null ? snapper.SnapStrength : 0f;
                wristConstraint   = snapper.SnapStrength;
            }

            if (fingersConstraint >= 1f && !isSnapping)
            {
                fingersConstraint = 0;
            }

            if (wristConstraint >= 1f && !isSnapping)
            {
                wristConstraint = 0f;
            }
        }
示例#2
0
        private void UpdateHandPose(ISnapper snapper, float fingersConstraint, float wristConstraint)
        {
            ISnapData snap = snapper.SnapData;

            if (snap == null)
            {
                FreeFingers();
                FreeWrist();
                return;
            }

            if (fingersConstraint > 0f &&
                snap.HandPose != null)
            {
                UpdateFingers(snap.HandPose, snapper.SnappingFingers(), fingersConstraint);
                _areFingersFree = false;
            }
            else
            {
                FreeFingers();
            }

            if (wristConstraint > 0f)
            {
                Pose wristLocalPose = GetWristPose(snap.WorldSnapPose, snapper.WristToSnapOffset);
                Pose wristPose      = Transformer.ToTrackingPose(wristLocalPose);
                _syntheticHand.LockWristPose(wristPose, wristConstraint);
                _isWristFree = false;
            }
            else
            {
                FreeWrist();
            }
        }
        /// <summary>
        /// This function is called for every FixedUpdate cycle. It moves the snapper
        /// position towards the target position, but allows it to rotate in the plane
        /// normal to the knob's rotation axis, which is assumed to be the local "up" direction
        /// of the snapping rotation reference transform.
        /// </summary>
        /// <param name="snapper">The snapper in snapping region.</param>
        public override void OnSnappedStay(ISnapper snapper)
        {
            SnapperDexmo snapperDexmo = snapper as SnapperDexmo;

            if (snapperDexmo == null)
            {
                base.OnSnappedStay(snapper);
                return;
            }
            Transform positionReference = GetSnappingPositionReference(snapper);
            Transform rotationReference = GetSnappingRotationReference(snapper);

            if (positionReference == null || rotationReference == null)
            {
                return;
            }
            Transform palmCenterTransform = snapperDexmo.PalmCenter;
            // Find the deltaRotation in world needed to align palmCenterTransform to rotationReference
            // in only y-axis (i.e. "up" direction).
            Quaternion deltaRotation =
                Quaternion.FromToRotation(palmCenterTransform.up, rotationReference.up);
            Quaternion palmCenterTargetRotation = deltaRotation * palmCenterTransform.rotation;

            // Now palm center's local "up" direction will coincide with rotationReference.up,
            // and can rotate around the "up" axis.

            // Move the entire hand root transform to the target position and rotation calculated from
            // the target position and rotation of the palm center.
            Miscellaneous.MoveParentTransformGivenChildTransform(
                snapperDexmo.HandRootTransform, palmCenterTransform,
                positionReference.position, palmCenterTargetRotation,
                HandRootPositionRelativeToPalmCenter, HandRootRotationRelativeToPalmCenter);
        }
 public TestCaseCreator(IEventAggregator eventAggregator, SessionData sessionData, UiState uiState, ISnapper snapper)
 {
     this.sessionData = sessionData;
     this.uiState     = uiState;
     this.snapper     = snapper;
     eventAggregator.GetEvent <TestCaseEvent>().Subscribe(OnTestCase);
 }
        public SketchView(SketchViewModel viewModel, UiState uiState, IEventAggregator eventAggregator, IUnityContainer container, ISnapper snapper, ILoggerFacade logger = null)
            : this()
        {
            this.logger = logger ?? new EmptyLogger();

            DataContext = viewModel;
            viewModel.PropertyChanged  += OnViewModelPropertyChanged;
            this.viewModel              = viewModel;
            this.duplicateEditorFactory = new DuplicateEditorFactory(this);
            this.snapper = snapper;

            sketchModellingView =
                container.Resolve <SketchModellingView>(
                    new DependencyOverride <SketchModellingViewModel>(viewModel.SketchModellingViewModel));
            root3d.Children.Add(sketchModellingView);

            sketchImageView =
                container.Resolve <SketchImageView>(
                    new DependencyOverride <SketchImageViewModel>(viewModel.SketchImageViewModel));
            Grid.SetRow(sketchImageView, 2);
            sketchImageView.Margin = vpRoot.Margin;
            root.Children.Insert(2, sketchImageView);

            newPrimitiveDragStrategy = new PrimitiveDragStrategy(uiState, sketchModellingView, snapper);
            snappedDragStrategy      = new SnappedDragStrategy(uiState, duplicateEditorFactory.Create(), eventAggregator);
            curveDragStrategy        = new CurveDragStrategy(uiState, sketchImageView, selectionRectangle);
            assignDragStrategy       = new AssignDragStrategy(uiState, primitiveCurvesRoot, sketchImageView, eventAggregator);

            eventAggregator.GetEvent <PrimitiveCurvesChangedEvent>().Subscribe(OnPrimitiveCurvesChanged);
        }
示例#6
0
 private void HandleSnapEnded(ISnapper snapper)
 {
     if (_currentSnapper == snapper)
     {
         _currentSnapper = null;
     }
 }
        public SketchViewModel(
            IUnityContainer container,
            IEventAggregator eventAggregator,
            UiState uiState,
            SessionData sessionData,
            ISnapper snapper,
            IClassificationInference classificationInference,
            IUndoHistory undoHistory)
        {
            this.uiState                 = uiState;
            this.sessionData             = sessionData;
            this.eventAggregator         = eventAggregator;
            this.snapper                 = snapper;
            this.classificationInference = classificationInference;
            this.undoHistory             = undoHistory;

            uiState.AddListener(this, () => uiState.SketchPlane);
            sessionData.AddListener(this, () => sessionData.SketchName);

            NewPrimitives = sessionData.NewPrimitives;

            SketchModellingViewModel = container.Resolve <SketchModellingViewModel>();
            SketchImageViewModel     = container.Resolve <SketchImageViewModel>();

            eventAggregator.GetEvent <MarkFeatureEvent>().Subscribe(MarkFeatureHandler);
            eventAggregator.GetEvent <MarkSilhouetteEvent>().Subscribe(MarkSilhouetteHandler);
        }
 public AnnotationsViewModel(IEventAggregator eventAggregator, SessionData sessionData, ILoggerFacade logger, ISnapper snapper, IUndoHistory undoHistory)
     : this()
 {
     this.eventAggregator = eventAggregator;
     this.sessionData     = sessionData;
     this.logger          = logger;
     this.snapper         = snapper;
     this.undoHistory     = undoHistory;
     Annotations          = sessionData.Annotations;
 }
示例#9
0
        /// <summary>
        /// This function will be called for every FixedUpdate cycle when the snapper
        /// is in snapping region. It replaces the position and rotation of the snapper
        /// by the target position and rotation.
        /// </summary>
        /// <remarks>
        /// Even though snapper's transform is modified here, it will not "teleport" to
        /// the target position and rotation immediately. The UnityHandController will
        /// use Vector3.Lerp and Quaternion.Lerp whenever there is a sudden change
        /// of position and rotation of the hand models, so by setting the snapper transform
        /// position and rotation to target ones, the hand controller will handle the
        /// rest of transition movement.
        /// </remarks>
        /// <param name="snapper">The snapper in the snapping transition.</param>
        public virtual void OnSnappedStay(ISnapper snapper)
        {
            Transform positionReference = GetSnappingPositionReference(snapper);
            Transform rotationReference = GetSnappingRotationReference(snapper);

            if (positionReference == null || rotationReference == null)
            {
                return;
            }
            snapper.Transform.position = positionReference.position;
            snapper.Transform.rotation = rotationReference.rotation;
        }
示例#10
0
        /// <summary>
        /// Get the snapping rotation reference for hand models.
        /// </summary>
        /// <param name="snapper">The snapper in snapping region.</param>
        /// <returns>Transform of snapping position reference..</returns>
        public override Transform GetSnappingRotationReference(ISnapper snapper)
        {
            SnapperDexmo snapperDexmo = snapper as SnapperDexmo;

            if (snapperDexmo == null)
            {
                return(base.GetSnappingRotationReference(snapper));
            }
            return(snapperDexmo.IsRight
                ? SnappingRotationReferenceList[0]
                : SnappingRotationReferenceList[1]);
        }
示例#11
0
 private void UpdateHand(ISnapper constrainingSnapper)
 {
     if (constrainingSnapper != null)
     {
         ConstrainingForce(constrainingSnapper, out float fingersConstraint, out float wristConstraint);
         UpdateHandPose(constrainingSnapper, fingersConstraint, wristConstraint);
     }
     else
     {
         FreeFingers();
         FreeWrist();
     }
 }
示例#12
0
        /// <summary>
        /// Check if the snapper is still moving towards the target snapping position.
        /// </summary>
        /// <remarks>
        /// The snapper is in transition when the distance between the snapper and
        /// the target snapping position is greater than _snappingTransitionDistanceMin.
        /// </remarks>
        /// <param name="snapper">The snapper that is in snapping region.</param>
        /// <returns>True if the snapper is still moving towards the target snapping
        /// position.</returns>
        public virtual bool CheckInSnappingTransition(ISnapper snapper)
        {
            Transform positionReference = GetSnappingPositionReference(snapper);

            if (positionReference == null)
            {
                return(false);
            }
            SnapperDexmo snapperDexmo    = snapper as SnapperDexmo;
            Vector3      snapperPosition = snapperDexmo == null
                ? snapper.Transform.position
                : snapperDexmo.PalmCenter.position;
            float dist = Vector3.Distance(positionReference.position,
                                          snapperPosition);
            bool inSnappingTransition = dist >= _snappingTransitionDistanceMin;

            return(inSnappingTransition);
        }
        /// <summary>
        /// This function will be called for every FixedUpdate cycle when snapper
        /// is in snapping region. It fixes the snapper's rotation to that of
        /// snapping rotation reference and allows the snapper to move between
        /// start position constraint and end position constraint.
        /// </summary>
        /// <param name="snapper">The snapper in the snapping region.</param>
        public override void OnSnappedStay(ISnapper snapper)
        {
            SnapperDexmo snapperDexmo = snapper as SnapperDexmo;

            if (snapperDexmo == null)
            {
                base.OnSnappedStay(snapper);
                return;
            }
            Transform positionReference = GetSnappingPositionReference(snapper);

            // Adjust snapping position according to the current position of the snapper.
            // Snapping position will only move in a linear section between start point and
            // end point.
            if (positionReference == null)
            {
                return;
            }
            float vectorProjectionValueNormalized =
                Miscellaneous.GetVectorProjectionValueNormalized(
                    _startPositionConstraintTransform.position,
                    _endPositionConstraintTransform.position,
                    snapperDexmo.PalmCenter.position);

            positionReference.position = Vector3.Lerp(
                _startPositionConstraintTransform.position,
                _endPositionConstraintTransform.position,
                vectorProjectionValueNormalized);
            Transform rotationReference = GetSnappingRotationReference(snapper);

            if (rotationReference == null)
            {
                return;
            }

            // Move the entire hand root transform to the target position and rotation calculated from
            // the target position and rotation of the palm center.
            Miscellaneous.MoveParentTransformGivenChildTransform(
                snapperDexmo.HandRootTransform, snapperDexmo.PalmCenter,
                positionReference.position, rotationReference.rotation,
                HandRootPositionRelativeToPalmCenter, HandRootRotationRelativeToPalmCenter);
        }
示例#14
0
        /// <summary>
        /// This function will be called when snapper just enters the snapping
        /// region. It sets some variables for later use.
        /// </summary>
        /// <param name="snapper">The snapper that just enters the snapping region.</param>
        public override void OnSnappedEnter(ISnapper snapper)
        {
            SnapperDexmo snapperDexmo = snapper as SnapperDexmo;

            if (snapperDexmo == null)
            {
                base.OnSnappedEnter(snapper);
                return;
            }
            Transform handRootTransform = snapperDexmo.HandRootTransform;
            Transform palmCenter        = snapperDexmo.PalmCenter;

            if (handRootTransform != null)
            {
                HandRootPositionRelativeToPalmCenter = palmCenter.InverseTransformPoint(
                    handRootTransform.position);
                HandRootRotationRelativeToPalmCenter = Quaternion.Inverse(palmCenter.rotation) *
                                                       handRootTransform.rotation;
            }
        }
示例#15
0
        /// <summary>
        /// Check if the snapper is still moving towards the target position.
        /// </summary>
        /// <remarks>
        /// The snapper is in transition when the distance between the snapper and
        /// the target snapping position is greater than _snappingTransitionDistanceMin.
        /// </remarks>
        /// <param name="snapper">The snapper in the snapping region.</param>
        /// <returns>True if snapper is still moving towards the target position.</returns>
        public override bool CheckInSnappingTransition(ISnapper snapper)
        {
            SnapperDexmo snapperDexmo = snapper as SnapperDexmo;

            if (snapperDexmo == null)
            {
                return(base.CheckInSnappingTransition(snapper));
            }
            Transform positionReference = GetSnappingPositionReference(snapper);

            if (positionReference == null)
            {
                return(false);
            }
            float dist = Vector3.Distance(positionReference.position,
                                          snapperDexmo.PalmCenter.position);
            bool inSnappingTransition = dist >= SnappingTransitionDistanceMin;

            return(inSnappingTransition);
        }
示例#16
0
        /// <summary>
        /// This function will be called for every FixedUpdate cycle when snapper is
        /// in the snapping region. It finds the target snapping position and rotation
        /// for the hand model and move the hand towards it.
        /// </summary>
        /// <param name="snapper">The snapper in the snapping region.</param>
        public override void OnSnappedStay(ISnapper snapper)
        {
            SnapperDexmo snapperDexmo = snapper as SnapperDexmo;

            if (snapperDexmo == null)
            {
                base.OnSnappedStay(snapper);
                return;
            }
            Transform positionReference = GetSnappingPositionReference(snapper);
            Transform rotationReference = GetSnappingRotationReference(snapper);

            if (positionReference == null || rotationReference == null)
            {
                return;
            }
            Miscellaneous.MoveParentTransformGivenChildTransform(
                snapperDexmo.HandRootTransform, snapperDexmo.PalmCenter,
                positionReference.position, rotationReference.rotation,
                HandRootPositionRelativeToPalmCenter, HandRootRotationRelativeToPalmCenter);
        }
 public PrimitiveDragStrategy(UiState uiState, SketchModellingView sketchModellingView, ISnapper snapper)
     : base(uiState)
 {
     this.sketchModellingView = sketchModellingView;
     this.snapper             = snapper;
 }
示例#18
0
 /// <summary>
 /// Get the snapping rotation reference according to the snapper type.
 /// </summary>
 /// <remarks>
 /// Currently, snappers are for hands, but in the future, it may extend
 /// to other types, so this function can be overridden to support other
 /// types of snappers.
 /// </remarks>
 /// <param name="snapper">The snapper that is in the snapping region.</param>
 /// <returns>Transform of snapping rotation reference.</returns>
 public virtual Transform GetSnappingRotationReference(ISnapper snapper)
 {
     return(_snappingRotationReferenceList[0]);
 }
示例#19
0
 /// <summary>
 /// This function will be called when the snapper just enters the snapping
 /// region. It is empty now, but can be overridden by derived classes.
 /// </summary>
 /// <param name="snapper">The snapper in the snapping region.</param>
 public virtual void OnSnappedEnter(ISnapper snapper)
 {
 }
示例#20
0
 /// <summary>
 /// This function is called when the snapper exits the snapping region.
 /// It is empty now, but can be overridden by derived classes.
 /// </summary>
 /// <param name="snapper">The snapper in snapping region.</param>
 public virtual void OnSnappedExit(ISnapper snapper)
 {
 }
示例#21
0
 private void HandleSnapStarted(ISnapper snapper)
 {
     _currentSnapper = snapper;
 }
示例#22
0
        private async Task StartInternal(RecordSettings settings)
        {
            try
            {
                try
                {
                    Thread.CurrentThread.Priority = ThreadPriority.Highest;
                }
                catch (Exception ex) { }
                _stopwatch = _stopwatch ?? new Stopwatch();
                _stopwatch.Reset();
                _stopwatch.Start();
                _stopWaiter.Reset();

                if (!Directory.Exists(settings.OutputPath))
                {
                    Directory.CreateDirectory(settings.OutputPath);
                }

                const double second            = 1000;
                const double minute            = second * 60;
                const int    quant             = 10;                                                                                //timeouts don't include process switching
                var          inputSnapInterval = (int)Math.Max((settings.Realtime ? second / settings.Fps : settings.Interval), 0); //snap every N ms
                var          splitInterval     = settings.SplitInterval * minute / inputSnapInterval;                               //split every N frames
                var          inputExpectedFps  = inputSnapInterval > 0 ? second / inputSnapInterval : 0;
                var          sourceRect        = settings.CaptureRectangle;

                var framesWritten = 0L;
                using (var tmr = new Timer())
                {
                    tmr.Interval = 100;
                    tmr.Elapsed += (a, b) => settings.OnFrameWritten(_stopwatch.Elapsed);
                    tmr.Start();
                    while (Recording)
                    {
                        var outfile = Path.Combine(settings.OutputPath, DateTime.Now.ToFileTime().ToString() + ".avi");
                        using (var outstream = new VideoFileWriter())
                        {
                            outstream.Open(outfile, sourceRect.Width, sourceRect.Height, settings.Fps, settings.Codec, settings.Bitrate);
                            using (ISnapper snapper = GetSnapper(settings))
                            {
                                using (var processingSemaphore = new SemaphoreSlim(snapper.MaxProcessingThreads))
                                {
                                    using (var writeSemaphore = new SemaphoreSlim(1))
                                    {
                                        snapper.SetSource(sourceRect);
                                        var    dropNextNFrames            = 0;
                                        var    lastSyncFrames             = framesWritten;
                                        double lastSyncTime               = _stopwatch.ElapsedMilliseconds;
                                        var    emptyFramesSinceLastSync   = 0;
                                        var    crashedFramesSinceLastSync = 0;
                                        var    slowFramewsSinceLastSync   = 0;

                                        for (var i = 0L; (splitInterval == null || i < splitInterval) && Recording; i++)
                                        {
                                            Task   tsk          = null;
                                            Bitmap currentFrame = null;
                                            try
                                            {
                                                framesWritten++;

                                                //drop frame if required
                                                if (dropNextNFrames > 0 && currentFrame != null)
                                                {
                                                    dropNextNFrames--;
                                                    lastSyncTime   = _stopwatch.ElapsedMilliseconds;
                                                    lastSyncFrames = framesWritten;
                                                    outstream.WriteVideoFrame(currentFrame);
                                                    continue;
                                                }
                                                tsk = Task.Delay(inputSnapInterval - quant);

                                                /*
                                                 * these bitmaps are actually the same object or null -> we only have to dispose it once
                                                 */
                                                var elapsedBeforeCurrentSnap = _stopwatch.Elapsed.TotalMilliseconds;
                                                await processingSemaphore.WaitAsync().ConfigureAwait(false);

                                                var tmp = await snapper.Snap(inputSnapInterval).ConfigureAwait(false);

                                                var elapsedAfterCurrentSnap = _stopwatch.Elapsed.TotalMilliseconds;
                                                if (elapsedAfterCurrentSnap - elapsedBeforeCurrentSnap > inputSnapInterval)
                                                {
                                                    //Debug.WriteLine($"[F**K] slow snap: {elapsedAfterCurrentSnap - elapsedBeforeCurrentSnap}ms");
                                                    slowFramewsSinceLastSync++;
                                                }
                                                if (tmp == null)
                                                {
                                                    //Debug.WriteLine("[F**K] empty snap");
                                                    emptyFramesSinceLastSync++;
                                                }
                                                currentFrame = tmp ?? currentFrame;
                                                //Debug.WriteLine($"[SNAP] {_stopwatch.ElapsedMilliseconds} ms");
                                                //settings.OnFrameWritten?.Invoke(_stopwatch.Elapsed);
                                            }
                                            catch (Exception ex)
                                            {
                                                //Debug.WriteLine($"[F**K] crashed on snap: {ex.Message}");
                                                crashedFramesSinceLastSync++;
                                            }
                                            try
                                            {
                                                Task.Run(async() =>
                                                {
                                                    try
                                                    {
                                                        if (currentFrame != null)
                                                        {//offload to separate thread
                                                            PreprocessFrame(currentFrame, settings);
                                                            await writeSemaphore.WaitAsync().ConfigureAwait(false);
                                                            try
                                                            {
                                                                outstream.WriteVideoFrame(currentFrame);
                                                            }
                                                            finally
                                                            {
                                                                writeSemaphore.Release();
                                                            }
                                                        }
                                                    }
                                                    finally
                                                    {
                                                        processingSemaphore.Release();
                                                    }
                                                }).ConfigureAwait(false);
                                            }
                                            catch (Exception ex)
                                            {
                                                //todo: crashed frame logging
                                            }

                                            double elapsedNow           = _stopwatch.ElapsedMilliseconds;
                                            var    elapsedSinceLastSync = elapsedNow - lastSyncTime;
                                            if (elapsedSinceLastSync >= second)
                                            {
                                                var framesSinceLastSync = framesWritten - lastSyncFrames;
                                                //only relevant for realtime+ recordings
                                                var recentFps      = framesSinceLastSync * second / elapsedSinceLastSync;
                                                var recentFpsDelta = recentFps - inputExpectedFps;
                                                Console.WriteLine($"{framesSinceLastSync} frames({emptyFramesSinceLastSync} empty, {crashedFramesSinceLastSync} crashed, {slowFramewsSinceLastSync} slow) in last {elapsedSinceLastSync.ToString("F")} ms ({recentFps.ToString("F")} fps). Total FPS: {(framesWritten * second / elapsedNow).ToString("F")}. Expected: {inputExpectedFps.ToString("F")}");
#if !PERF
                                                if (recentFpsDelta > 1) //faster than expected && at least one actual frame
                                                {
                                                    tsk.Wait();         //wait for the current loop
                                                                        //Debug.WriteLine($"[F**K] Slow down, fella: {recentFpsDelta} frames");
                                                    Task.Delay((int)(inputSnapInterval * recentFpsDelta - quant)).Wait();
                                                }
                                                else if (recentFpsDelta < -1)//too slow
                                                {
                                                    dropNextNFrames = -(int)recentFpsDelta;
                                                    //Debug.WriteLine($"[F**K] dropping {dropNextNFrames} frames");
                                                }
#endif
                                                lastSyncFrames             = framesWritten;
                                                lastSyncTime               = elapsedNow;
                                                emptyFramesSinceLastSync   = 0;
                                                crashedFramesSinceLastSync = 0;
                                                slowFramewsSinceLastSync   = 0;
                                            }
#if !PERF
                                            tsk?.Wait();
#endif
                                        }
                                        await writeSemaphore.WaitAsync().ConfigureAwait(false);
                                    }
                                }
                            }
                        }
                    }
                    tmr.Stop();
                }
            }
            catch (Exception ex)
            {
                //Debug.WriteLine(ex.Message);
                //global
            }
            finally
            {
                _stopwatch?.Stop();
                _stopWaiter.Set();
            }
        }