示例#1
0
        public override void ControllerUpdate()
        {
            base.ControllerUpdate();

            if (!model.inputDataProvider)
            {
                return;
            }

            if (!gameObject.activeSelf)
            {
                return;
            }

            masterReprKey = AvatarModel.key;

            model.inputDataProvider.UpdateData();

            // On hand tracked
            if (conf.ignoreTrackingLoss || model.inputDataProvider.confidence > conf.handTrackingLostUnderConfidence)
            {
                if (!model.handIsTracked)
                {
                    model.handIsTracked = true;
                    model.view.onHandTrackingRecovered.Invoke();
                }

                if (model.isPredicting)
                {
                    model.isPredicting = false;
                    model.view.onPredictionInterrupted.Invoke();
                }

                // If recovered from tracking loss
                if (timeSinceLastValidRecord != 0.0f)
                {
                    timeSinceLastValidRecord = 0.0f;

                    if (conf.hideMasterWhenLost)
                    {
                        model.hand.specificView.SetHandVisuals(true, masterReprKey);
                    }

                    if (conf.hideSlaveWhenLost)
                    {
                        model.hand.specificView.SetHandVisuals(true, PuppetModel.key);
                        model.hand.specificView.SetHandPhysics(true);
                    }
                }

                // Calculate clamping
                if (conf.useHandClamping)
                {
                    if (conf.gradualHandClamping)
                    {
                        handClampLerp = Mathf.Lerp(0.0f, conf.startDecreasingHandClampUnderConfidence, model.inputDataProvider.confidence);
                    }
                    else if (model.inputDataProvider.confidence > conf.startDecreasingHandClampUnderConfidence)
                    {
                        handClampLerp = 1.0f; // High confidece. Clamp set to highest
                    }
                    else
                    {
                        handClampLerp = 0.0f; // Low confidence. Clamp set to lowest
                    }
                    maxHandLinearSpeed  = Mathf.Lerp(conf.lowestHandLinearSpeed, model.highestLinearSpeed, handClampLerp);
                    maxHandAngularSpeed = Mathf.Lerp(conf.lowestHandAngularSpeed, model.highestAngularSpeed, handClampLerp);
                }
                else
                {
                    maxHandLinearSpeed  = -1.0f;
                    maxHandAngularSpeed = -1.0f;
                }

                // Update record
                if (model.configuration.recordTracking)
                {
                    InputHelpers.RecordBone(model.boneRecords, model.inputDataProvider.bones[0], 0);
                    // RecordBone(model.inputDataProvider.bones[1], 1);
                }

                // Noise reduction
                if (model.configuration.movingAverage != MovingAverage.None)
                {
                    model.inputDataProvider.bones[0] = ReduceNoise(model.boneRecords[0], 0);
                    // model.inputDataProvider.bones[1] = ReduceNoise(model.boneRecords[1], 1);
                }

                // Use or get what to move as wrist
                if (!model.moveThisAsWrist)
                {
                    model.moveThisAsWrist = model.rigMap.wrist.master.transformRef;
                }

                // Find a point of reference (if neede)
                if (model.replicatedTsf && !model.referenceTsf)
                {
                    model.referenceTsf = HPTK.core.trackingSpace;
                }

                // Update pos and rot for wrist and forearm
                if (conf.updateWrist && model.bonesToUpdate[0] != null)
                {
                    // Update wrist position and rotation
                    UpdateBoneTsfPos(model.rigMap.wrist.master, model.moveThisAsWrist, model.inputDataProvider.bones[0], maxHandLinearSpeed, model.referenceTsf, model.replicatedTsf);
                    UpdateBoneTsfRot(model.rigMap.wrist.master, model.moveThisAsWrist, model.inputDataProvider.bones[0], maxHandAngularSpeed, model.referenceTsf, model.replicatedTsf);
                }

                if (conf.updateForearm && model.bonesToUpdate[1] != null)
                {
                    // Optional
                    if (model.configuration.recordTracking)
                    {
                        InputHelpers.RecordBone(model.boneRecords, model.inputDataProvider.bones[1], 1);
                    }

                    // Update wrist position and rotation
                    UpdateBoneTsfPos(model.rigMap.forearm.master, model.rigMap.forearm.master.transformRef, model.inputDataProvider.bones[1], maxHandLinearSpeed, model.referenceTsf, model.replicatedTsf);
                    UpdateBoneTsfRot(model.rigMap.forearm.master, model.rigMap.forearm.master.transformRef, model.inputDataProvider.bones[1], maxHandAngularSpeed, model.referenceTsf, model.replicatedTsf); // Optional
                }
            }
            // On hand tracking loss
            else
            {
                if (model.handIsTracked)
                {
                    model.handIsTracked = false;
                    model.view.onHandTrackingLost.Invoke();
                }

                if (timeSinceLastValidRecord == 0.0f)
                {
                    if (conf.usePredictiveTrackingWhenLost)
                    {
                        acceleration       = (0.0f - wristSpeed) / conf.maxPredictionTime;
                        predictedDirection = wristVelocityDirection;
                        lastWristPosition  = model.rigMap.wrist.transformRef.position;

                        if (!model.isPredicting)
                        {
                            model.isPredicting = true;
                            model.view.onPredictionStart.Invoke();
                        }
                    }

                    if (conf.hideMasterWhenLost)
                    {
                        model.hand.specificView.SetHandVisuals(false, masterReprKey);
                    }

                    if (conf.hideSlaveWhenLost)
                    {
                        model.hand.specificView.SetHandVisuals(false, PuppetModel.key);
                        model.hand.specificView.SetHandPhysics(false);
                    }
                }

                timeSinceLastValidRecord = Time.timeSinceLevelLoad - timeOfLastRecord;

                if (conf.usePredictiveTrackingWhenLost)
                {
                    if (timeSinceLastValidRecord < conf.maxPredictionTime)
                    {
                        // Predict new position

                        // currentTime - lastRecordTime = 0 -> velocity = initial
                        // currentTime - lastRecordTime = maxPeedictionTime -> velocity = 0

                        newDisplacement    = wristSpeed * timeSinceLastValidRecord + 0.5f * acceleration * timeSinceLastValidRecord * timeSinceLastValidRecord;
                        predictedDirection = Quaternion.Slerp(wristDirectionChange, Quaternion.identity, timeSinceLastValidRecord / conf.maxPredictionTime) * wristVelocityDirection;

                        model.rigMap.wrist.transformRef.position = lastWristPosition + predictedDirection * newDisplacement;
                    }
                    else
                    {
                        if (model.isPredicting)
                        {
                            model.isPredicting = false;
                            model.view.onPredictionTimeLimitReached.Invoke();
                        }
                    }
                }
            }

            // On fingers tracked
            if (conf.ignoreTrackingLoss || model.inputDataProvider.confidence > conf.fingersTrackingLostUnderConfidence)
            {
                if (!model.fingersAreTracked)
                {
                    model.fingersAreTracked = true;
                    model.view.onFingersTrackingRecovered.Invoke();
                }

                // Calculate clamping
                if (conf.useFingerClamping)
                {
                    if (conf.gradualFingerClamping)
                    {
                        fingerClampLerp = Mathf.Lerp(0.0f, conf.startDecreasingFingerClampUnderConfidence, model.inputDataProvider.confidence);
                    }
                    else if (model.inputDataProvider.confidence > conf.startDecreasingFingerClampUnderConfidence)
                    {
                        fingerClampLerp = 1.0f; // High confidece. Clamp set to highest
                    }
                    else
                    {
                        fingerClampLerp = 0.0f; // Low confidence. Clamp set to lowest
                    }
                    // maxFingerLinearSpeed = Mathf.Lerp(model.lowestMasterBoneLinearSpeed, model.highestLinearSpeed, fingerClampLerp);
                    maxFingerAngularSpeed = Mathf.Lerp(conf.lowestFingerAngularSpeed, model.highestAngularSpeed, fingerClampLerp);
                }
                else
                {
                    // maxFingerLinearSpeed = -1.0f;
                    maxFingerAngularSpeed = -1.0f;
                }

                // Finger bones start at i=2 (i=0 -> wrist, i=1 -> forearm)
                for (int i = 2; i < model.bonesToUpdate.Length; i++)
                {
                    // Update record
                    if (model.configuration.recordTracking)
                    {
                        InputHelpers.RecordBone(model.boneRecords, model.inputDataProvider.bones[i], i);
                    }

                    // Noise reduction
                    if (model.configuration.movingAverage != MovingAverage.None)
                    {
                        model.inputDataProvider.bones[i] = ReduceNoise(model.boneRecords[i], i);
                    }

                    // Update only fingers rotation (assuming hierachy)
                    if (model.bonesToUpdate[i] != null)
                    {
                        BoneModel bone = model.bonesToUpdate[i];

                        AbstractTsf inputData = model.inputDataProvider.bones[i];

                        // Estimate rotation. Assuming sorted array of bones (i-1 => thumb0, i => thumb1, i+1 => thumb2)
                        if (!model.rigMap.thumb0 && bone == model.rigMap.thumb1)
                        {
                            inputData.rotation = EstimateLocalRotation(model.inputDataProvider.bones[i - 1], model.inputDataProvider.bones[i]);
                        }
                        else if (!model.rigMap.pinky0 && bone == model.rigMap.pinky1)
                        {
                            inputData.rotation = EstimateLocalRotation(model.inputDataProvider.bones[i - 1], model.inputDataProvider.bones[i]);
                        }

                        UpdateBoneTsfRot(bone.master, bone.master.transformRef, inputData, maxFingerAngularSpeed, null, null);
                    }
                }
            }
            // On fingers tracking loss
            else
            {
                if (model.fingersAreTracked)
                {
                    model.fingersAreTracked = false;
                    model.view.onFingersTrackingLost.Invoke();
                }
            }

            // If we need to record and confidence is good enough to record
            if (conf.usePredictiveTrackingWhenLost && model.inputDataProvider.confidence > conf.saveHandHistoricOverConfidence)
            {
                // Before updating wristVelocityDirection and wristPosition
                wristDirectionChange = Quaternion.FromToRotation(wristVelocityDirection, (model.rigMap.wrist.transformRef.position - wristPosition).normalized);

                // Before updating wristPosition and timeOfLastRecord
                deltaTime              = Time.timeSinceLevelLoad - timeOfLastRecord;
                displacement           = Vector3.Distance(wristPosition, model.rigMap.wrist.transformRef.position);
                displacement           = Mathf.Clamp(displacement, 0.0f, conf.maxPredictionDisplacement * deltaTime);
                wristSpeed             = displacement / deltaTime;
                wristVelocityDirection = (model.rigMap.wrist.transformRef.position - wristPosition).normalized;

                // Update wristPosition
                wristPosition = model.rigMap.wrist.transformRef.position;

                // Update timeOfLastRecord
                timeOfLastRecord = Time.timeSinceLevelLoad;
            }

            // Hand scaling
            if (model.updateRealScale && model.inputDataProvider.scale != model.hand.realScale)
            {
                model.hand.realScale = model.inputDataProvider.scale;
            }
        }