Пример #1
0
        public static double AngleRad(Vector v1, Vector v2)
        {
            Debug.Assert(v1.IsValid());
            Debug.Assert(v2.IsValid());

            double dot = Dot(v1, v2);
            double dotNormalize = dot / (v1.Length * v2.Length);
            double acos = Math.Acos(dotNormalize);

            return acos;
        }
Пример #2
0
        public static double Dot(Vector v1, Vector v2)
        {
            Debug.Assert(v1.IsValid());
            Debug.Assert(v2.IsValid());

            return v1.X * v2.X + v1.Y * v2.Y;
        }
Пример #3
0
        public static bool Animate(
            Point currentValue, Vector currentVelocity, Point targetValue,
            double attractionFator, double dampening,
            double terminalVelocity, double minValueDelta, double minVelocityDelta,
            out Point newValue, out Vector newVelocity)
        {
            Debug.Assert(currentValue.IsValid());
            Debug.Assert(currentVelocity.IsValid());
            Debug.Assert(targetValue.IsValid());

            Debug.Assert(dampening.IsValid());
            Debug.Assert(dampening > 0 && dampening < 1);

            Debug.Assert(attractionFator.IsValid());
            Debug.Assert(attractionFator > 0);

            Debug.Assert(terminalVelocity > 0);

            Debug.Assert(minValueDelta > 0);
            Debug.Assert(minVelocityDelta > 0);

            Vector diff = targetValue.Subtract(currentValue);

            if (diff.Length > minValueDelta || currentVelocity.Length > minVelocityDelta)
            {
                newVelocity = currentVelocity * (1 - dampening);
                newVelocity += diff * attractionFator;
                if (currentVelocity.Length > terminalVelocity)
                {
                    newVelocity *= terminalVelocity / currentVelocity.Length;
                }

                newValue = currentValue + newVelocity;

                return true;
            }
            else
            {
                newValue = targetValue;
                newVelocity = new Vector();
                return false;
            }
        }
Пример #4
0
        public bool TickData(Vector lastMouse, bool isFlipped)
        {
            bool somethingChanged = false;

            //active means nothing in the "flipped" mode
            bool isActiveItem = IsMouseOver && !isFlipped;
            bool goodMouse = lastMouse.IsValid();

            #region rotation

            Quaternion rotationTarget = new Quaternion(new Vector3D(1, 0, 0), 0);

            //apply forces
            rotationTarget.Normalize();
            m_rotationCurrent.Normalize();

            double angle = 0;
            Vector3D axis = new Vector3D(0, 0, 1);
            if (lastMouse.IsValid() && !isFlipped)
            {
                Point3D mouse = new Point3D(lastMouse.X, lastMouse.Y, 1);
                Vector3D line = mouse - m_locationCurrent;
                Vector3D straight = new Vector3D(0, 0, 1);

                angle = Vector3D.AngleBetween(line, straight);
                axis = Vector3D.CrossProduct(line, straight);
            }
            Quaternion rotationForceTowardsMouse = new Quaternion(axis, -angle);

            Quaternion rotationForceToDesired = rotationTarget - m_rotationCurrent;

            Quaternion rotationForce = rotationForceToDesired + rotationForceTowardsMouse;

            m_rotationVelocity *= new Quaternion(rotationForce.Axis, rotationForce.Angle * .2);

            //dampenning
            m_rotationVelocity = new Quaternion(m_rotationVelocity.Axis, m_rotationVelocity.Angle * (m_weird - .3));

            //apply terminal velocity
            m_rotationVelocity = new Quaternion(m_rotationVelocity.Axis, m_rotationVelocity.Angle);

            m_rotationVelocity.Normalize();

            //apply to position
            m_rotationCurrent *= m_rotationVelocity;
            m_rotationCurrent.Normalize();

            //see if there is any real difference between what we calculated and what actually exists
            if (AnyDiff(m_quaternionRotation3D.Quaternion.Axis, m_rotationCurrent.Axis, c_diff) ||
                AnyDiff(m_quaternionRotation3D.Quaternion.Angle, m_rotationCurrent.Angle, c_diff))
            {
                //if the angles are both ~0, the axis may be way off but the result is basically the same
                //check for this and forget animating in this case
                if (AnyDiff(m_quaternionRotation3D.Quaternion.Angle, 0, c_diff) || AnyDiff(m_rotationCurrent.Angle, 0, c_diff))
                {
                    m_quaternionRotation3D.Quaternion = m_rotationCurrent;
                    somethingChanged = true;
                }
            }

            #endregion

            #region flip
            double verticalFlipTarget = isFlipped ? 180 : 0;
            double verticalFlipCurrent = m_verticalFlipRotation.Angle;

            //force
            double verticalFlipForce = verticalFlipTarget - verticalFlipCurrent;

            //velocity
            m_flipVerticalVelocity += .3 * verticalFlipForce;

            //dampening
            m_flipVerticalVelocity *= (m_weird - .3);

            //terminal velocity
            m_flipVerticalVelocity = limitDouble(m_flipVerticalVelocity, 10);

            //apply
            verticalFlipCurrent += m_flipVerticalVelocity;

            if (AnyDiff(verticalFlipCurrent, m_verticalFlipRotation.Angle, c_diff) && AnyDiff(m_flipVerticalVelocity, 0, c_diff))
            {
                m_verticalFlipRotation.Angle = verticalFlipCurrent;
            }

            #endregion

            #region scale
            if (isActiveItem && !isFlipped)
            {
                this.m_scaleDesired = 2;
            }
            else
            {
                this.m_scaleDesired = 1;
            }

            double scaleForce = this.m_scaleDesired - this.m_scaleCurrent;
            this.m_scaleVelocity += .1 * scaleForce;
            //dampening
            this.m_scaleVelocity *= .8;
            //terminal velocity
            this.m_scaleVelocity = limitDouble(this.m_scaleVelocity, .05);
            this.m_scaleCurrent += this.m_scaleVelocity;

            if (AnyDiff(m_scaleTransform.ScaleX, m_scaleCurrent, c_diff) || AnyDiff(m_scaleTransform.ScaleY, m_scaleCurrent, c_diff))
            {
                this.m_scaleTransform.ScaleX = this.m_scaleCurrent;
                this.m_scaleTransform.ScaleY = this.m_scaleCurrent;
                somethingChanged = true;
            }

            #endregion

            #region location
            Vector3D locationForce;

            //apply forces
            if (isActiveItem)
            {
                m_locationDesired.Z = .1;
            }
            else
            {
                m_locationDesired.Z = 0;
            }
            locationForce = m_locationDesired - m_locationCurrent;

            //only repel the non-active items
            if (!isActiveItem && goodMouse && !isFlipped)
            {
                locationForce += .025 * invertVector(this.CurrentLocationVector - new Vector3D(lastMouse.X, lastMouse.Y, 0));
            }

            m_locationVelocity += .1 * locationForce;

            //apply dampenning
            m_locationVelocity *= (m_weird - .3);

            //apply terminal velocity
            m_locationVelocity = limitVector3D(m_locationVelocity, .3);

            //apply velocity to location
            m_locationCurrent += m_locationVelocity;

            if ((GetVector(m_translate) - (Vector3D)m_locationCurrent).Length > c_diff)
            {
                m_translate.OffsetX = m_locationCurrent.X;
                m_translate.OffsetY = m_locationCurrent.Y;
                m_translate.OffsetZ = m_locationCurrent.Z;
                somethingChanged = true;
            }
            #endregion

            return somethingChanged;
        }
Пример #5
0
 private static Vector Normalize(Vector v)
 {
     v.Normalize();
       Debug.Assert(v.IsValid());
       return v;
 }
Пример #6
0
        private static Vector GetSpringForce(Vector x)
        {
            Vector force = new Vector();
              //negative is attraction
              force += GetAttractionForce(x);
              //positive is repulsion
              force += GetRepulsiveForce(x);

              Debug.Assert(force.IsValid());

              return force;
        }
Пример #7
0
      /// <summary/>
      protected override Vector GetCurrentValueCore(Vector baseFromValue, Vector baseToValue, AnimationClock animationClock) {
         var progress = animationClock.CurrentProgress;
         if (!progress.HasValue || Interpolator == null) {
            return base.GetCurrentValueCore(baseFromValue, baseToValue, animationClock);
         }

         var fromValue = new Vector();
         var toValue = new Vector();
         var offset = new Vector();
         var isValid = true;

         if (From.HasValue) {
            fromValue = From.Value;
            if (To.HasValue) {
               // from ... to 
               toValue = To.Value;
               if (IsAdditive) {
                  offset = baseFromValue;
                  isValid = offset.IsValid();
               }
            } else if (By.HasValue) {
               // from ... from+by
               toValue = fromValue + By.Value;
               if (IsAdditive) {
                  offset = baseFromValue;
                  isValid = offset.IsValid();
               }
            } else {
               // from ... base
               toValue = baseToValue;
               isValid = toValue.IsValid();
            }
         } else if (To.HasValue) {
            // base ... to
            fromValue = baseFromValue;
            toValue = To.Value;
            isValid = fromValue.IsValid();
         } else if (By.HasValue) {
            // base ... base+by
            toValue = By.Value;
            offset = baseFromValue;
            isValid = offset.IsValid();
         } else {
            // base ... base
            fromValue = baseFromValue;
            toValue = baseToValue;
            isValid = fromValue.IsValid() && toValue.IsValid();
         }
         if (!isValid) {
            throw new InvalidOperationException("GetCurrentValueCore");
         }

         if (IsCumulative) {
            var iteration = animationClock.CurrentIteration;
            if (iteration.HasValue && iteration.Value > 1) {
               offset += (toValue - fromValue) * (iteration.Value - 1);
            }
         }

         var interpolator = Interpolator ?? Interpolators.Linear;
         return fromValue + (toValue - fromValue) * interpolator(progress.Value, 0.0, 1.0) + offset;
      }