Example #1
0
            private void SetOnSteeringWheel(Matrix steerMatrix, float swRadius)
            {
                // point on the wheel, matrix
                var l    = Matrix.Translation(swRadius * _side, 0, 0) * steerMatrix;
                var lPos = l.GetTranslationVector();

                // vertical offset of point on the wheel after rotation
                var armUp = Vector3.TransformNormal(Vector3.UnitX, steerMatrix);

                // approximate direction
                var approxDirection = lPos - _approxPoint;

                // move hand
                var handUp = Vector3.Normalize(Vector3.TransformNormal(Vector3.UnitX * 6f + Vector3.UnitY * _side, l));

                var handXFix = Vector3.Normalize(new Vector3(approxDirection.X, Math.Min(approxDirection.Y, 0f) * 5f, approxDirection.Z.Abs() + 0.2f)).X;

                handXFix = ((handXFix.Abs() - 0.1f) * 6f).Saturate() * handXFix.Sign() * 5f;
                var handLookAt = Vector3.TransformCoordinate(Vector3.UnitZ * 5f, steerMatrix) +    // really far into the wheel
                                 Vector3.UnitY * (4f + armUp.Y * 2f) * (armUp.X * 2f).Saturate() + // sort of upwards depending on how high it’s on the wheel
                                 Vector3.UnitX * handXFix;                                         // on the side to avoid breaking

                _hand.LookAt(handLookAt, handUp);

                var downK = (_side * -armUp.Y / 0.5f - 0.5f).Saturate();

                _indexf.Set(0.8f - downK * 0.3f);
                _middle.Set(0.9f - downK * 0.8f);
                _ring.Set(1f - downK);
                _pinkie.Set(1f - downK);

                if (_side > 0f)
                {
                    _ds = $"v: {armUp}\r\nn: {handUp}\r\nx fix: {handXFix}\r\na.p.: {_approxPoint}\r\nl.p.: {lPos}\r\na.d.: {approxDirection}";
                }

                // after moved, update target point
                var targetPoint = _hand.Matrix.GetTranslationVector() + GetThumbsOffset(steerMatrix, swRadius);

                MoveHand(targetPoint, armUp, handUp);

                // move hand, again
                _hand.LookAt(handLookAt, handUp);
            }
Example #2
0
            private void MoveHand(Vector3 targetPoint, Vector3 up, Vector3 handUp)
            {
                _targetPoint = targetPoint;
                _up          = up;
                _handUp      = handUp;

                // static stuff
                var handLength = _armLength + _forearmLength + _forearmEndLength;

                // approximate direction
                var approxDirection = targetPoint - _approxPoint;

                // move shoulder
                var approxDistance = approxDirection.Length();
                var shoulderFix    = Smooth(Math.Max(approxDistance - handLength + 0.1f, 0f) / 0.2f);

                _clave.LocalMatrix =
                    Matrix.RotationYawPitchRoll(_side * 17f.ToRadians(), (-12f - 40f * shoulderFix).ToRadians(), (_side > 0 ? -95f : 95f).ToRadians()) *
                    Matrix.Translation(0.02f * _side, 0.11f + 0.08f * shoulderFix, 0.05f + 0.05f * shoulderFix);


                var armPoint = _arm.Matrix.GetTranslationVector();
                var armDelta = targetPoint - armPoint;

                // comparing distance to point with hand length
                var distance = armDelta.Length();

                var relative = distance / handLength;

                if (relative > _smoothFrom)
                {
                    var leftMax  = 1f - _smoothFrom;
                    var left     = relative - _smoothFrom;
                    var smooth   = left / leftMax;
                    var smoother = -0.5f + MathF.Sqrt(1f + 3f * smooth) / 2f;

                    distance = handLength * (_smoothFrom + smoother * leftMax);
                }

                /*if (distance > handLength * _smoothFrom && distance < handLength * _smoothStretch) {
                 *  var left = handLength - distance;
                 *  var leftK = (left / (1f - _smoothFrom)).Saturate();
                 *
                 *  // leftK = 0 β†’ handLength * _smoothFrom
                 *  // leftK + very small x β†’ handLength * _smoothFrom + very small x
                 *  // leftK = _smoothFrom - 1 β†’ handLength * _smoothStretch
                 *
                 *  // var stretchTo = _smoothStretch;
                 *  distance = handLength * _smoothFrom + leftK * (_smoothStretch - _smoothFrom) * handLength;
                 * }*/

                var overOffset = MathF.Sqrt(Math.Max(MathF.Pow(handLength, 2f) - MathF.Pow(distance, 2f), 0f));

                // normals: direction, bottom normal for elbow offset
                var direction = Vector3.Normalize(armDelta);

                var verticalOffsetFixed = up;

                verticalOffsetFixed.Y  = _side * verticalOffsetFixed.Y.Abs();
                verticalOffsetFixed.Z += _side;
                var armBottom = Vector3.Normalize(Vector3.Cross(direction, -Vector3.Normalize(verticalOffsetFixed)));

                // moving shoulder
                var armUp     = (-armBottom + Vector3.UnitY * 2f) / 3f * _side;
                var armLookAt = armPoint + Vector3.Normalize(targetPoint - armPoint) * _armLength +
                                armBottom * overOffset * _armLength / handLength;

                _arm.LookAt(armLookAt, armUp);


                _forearm.LookAt(targetPoint, Vector3.UnitY * _side);
                _forearmEnd.LookAt(targetPoint, handUp);
            }