Beispiel #1
0
        /// <summary>
        /// Returns the inverse of the transform, under the assumption that
        /// the transformation is composed of rotation, scaling, and translation.
        /// </summary>
        /// <seealso cref="Inverse"/>
        /// <returns>The inverse transformation matrix.</returns>
        public Transform2D AffineInverse()
        {
            real_t det = BasisDeterminant();

            if (det == 0)
            {
                throw new InvalidOperationException("Matrix determinant is zero and cannot be inverted.");
            }

            Transform2D inv = this;

            real_t temp = inv[0, 0];

            inv[0, 0] = inv[1, 1];
            inv[1, 1] = temp;

            real_t detInv = 1.0f / det;

            inv[0] *= new Vector2(detInv, -detInv);
            inv[1] *= new Vector2(-detInv, detInv);

            inv[2] = inv.BasisXform(-inv[2]);

            return(inv);
        }
Beispiel #2
0
 /// <summary>
 /// Constructs a new <see cref="Vector4"/> with the given components.
 /// </summary>
 /// <param name="x">The vector's X component.</param>
 /// <param name="y">The vector's Y component.</param>
 /// <param name="z">The vector's Z component.</param>
 /// <param name="w">The vector's W component.</param>
 public Vector4(real_t x, real_t y, real_t z, real_t w)
 {
     this.x = x;
     this.y = y;
     this.z = z;
     this.w = w;
 }
Beispiel #3
0
        public static Projection CreateForHmd(int eye, real_t aspect, real_t intraocularDist, real_t displayWidth, real_t displayToLens, real_t oversample, real_t zNear, real_t zFar)
        {
            real_t f1 = (intraocularDist * (real_t)0.5) / displayToLens;
            real_t f2 = ((displayWidth - intraocularDist) * (real_t)0.5) / displayToLens;
            real_t f3 = (displayWidth / (real_t)4.0) / displayToLens;

            real_t add = ((f1 + f2) * (oversample - (real_t)1.0)) / (real_t)2.0;

            f1 += add;
            f2 += add;
            f3 *= oversample;

            f3 /= aspect;

            switch (eye)
            {
            case 1:
                return(CreateFrustum(-f2 * zNear, f1 * zNear, -f3 * zNear, f3 * zNear, zNear, zFar));

            case 2:
                return(CreateFrustum(-f1 * zNear, f2 * zNear, -f3 * zNear, f3 * zNear, zNear, zFar));

            default:
                return(Zero);
            }
        }
Beispiel #4
0
        /// <summary>
        /// Interpolates this transform to the other <paramref name="transform"/> by <paramref name="weight"/>.
        /// </summary>
        /// <param name="transform">The other transform.</param>
        /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
        /// <returns>The interpolated transform.</returns>
        public Transform3D InterpolateWith(Transform3D transform, real_t weight)
        {
            Basis   retBasis  = basis.Lerp(transform.basis, weight);
            Vector3 retOrigin = origin.Lerp(transform.origin, weight);

            return(new Transform3D(retBasis, retOrigin));
        }
Beispiel #5
0
        /// <summary>
        /// Returns an AABB transformed (multiplied) by the transformation matrix.
        /// </summary>
        /// <param name="transform">The transformation to apply.</param>
        /// <param name="aabb">An AABB to transform.</param>
        /// <returns>The transformed AABB.</returns>
        public static AABB operator *(Transform3D transform, AABB aabb)
        {
            Vector3 min = aabb.Position;
            Vector3 max = aabb.Position + aabb.Size;

            Vector3 tmin = transform.origin;
            Vector3 tmax = transform.origin;

            for (int i = 0; i < 3; i++)
            {
                for (int j = 0; j < 3; j++)
                {
                    real_t e = transform.basis[i][j] * min[j];
                    real_t f = transform.basis[i][j] * max[j];
                    if (e < f)
                    {
                        tmin[i] += e;
                        tmax[i] += f;
                    }
                    else
                    {
                        tmin[i] += f;
                        tmax[i] += e;
                    }
                }
            }

            return(new AABB(tmin, tmax - tmin));
        }
Beispiel #6
0
        /// <summary>
        /// Constructs a <see cref="Quaternion"/> that will rotate around the given axis
        /// by the specified angle. The axis must be a normalized vector.
        /// </summary>
        /// <param name="axis">The axis to rotate around. Must be normalized.</param>
        /// <param name="angle">The angle to rotate, in radians.</param>
        public Quaternion(Vector3 axis, real_t angle)
        {
#if DEBUG
            if (!axis.IsNormalized())
            {
                throw new ArgumentException("Argument is not normalized.", nameof(axis));
            }
#endif

            real_t d = axis.Length();

            if (d == 0f)
            {
                x = 0f;
                y = 0f;
                z = 0f;
                w = 0f;
            }
            else
            {
                real_t sinAngle = Mathf.Sin(angle * 0.5f);
                real_t cosAngle = Mathf.Cos(angle * 0.5f);
                real_t s        = sinAngle / d;

                x = axis.x * s;
                y = axis.y * s;
                z = axis.z * s;
                w = cosAngle;
            }
        }
Beispiel #7
0
 /// <summary>
 /// Constructs a <see cref="Quaternion"/> defined by the given values.
 /// </summary>
 /// <param name="x">X component of the quaternion (imaginary <c>i</c> axis part).</param>
 /// <param name="y">Y component of the quaternion (imaginary <c>j</c> axis part).</param>
 /// <param name="z">Z component of the quaternion (imaginary <c>k</c> axis part).</param>
 /// <param name="w">W component of the quaternion (real part).</param>
 public Quaternion(real_t x, real_t y, real_t z, real_t w)
 {
     this.x = x;
     this.y = y;
     this.z = z;
     this.w = w;
 }
Beispiel #8
0
        /// <summary>
        /// Returns the result of the spherical linear interpolation between
        /// this quaternion and <paramref name="to"/> by amount <paramref name="weight"/>, but without
        /// checking if the rotation path is not bigger than 90 degrees.
        /// </summary>
        /// <param name="to">The destination quaternion for interpolation. Must be normalized.</param>
        /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
        /// <returns>The resulting quaternion of the interpolation.</returns>
        public Quaternion Slerpni(Quaternion to, real_t weight)
        {
#if DEBUG
            if (!IsNormalized())
            {
                throw new InvalidOperationException("Quaternion is not normalized");
            }
            if (!to.IsNormalized())
            {
                throw new ArgumentException("Argument is not normalized", nameof(to));
            }
#endif

            real_t dot = Dot(to);

            if (Mathf.Abs(dot) > 0.9999f)
            {
                return(this);
            }

            real_t theta     = Mathf.Acos(dot);
            real_t sinT      = 1.0f / Mathf.Sin(theta);
            real_t newFactor = Mathf.Sin(weight * theta) * sinT;
            real_t invFactor = Mathf.Sin((1.0f - weight) * theta) * sinT;

            return(new Quaternion
                   (
                       (invFactor * x) + (newFactor * to.x),
                       (invFactor * y) + (newFactor * to.y),
                       (invFactor * z) + (newFactor * to.z),
                       (invFactor * w) + (newFactor * to.w)
                   ));
        }
Beispiel #9
0
        public static Projection CreateFrustum(real_t left, real_t right, real_t bottom, real_t top, real_t near, real_t far)
        {
            if (right <= left)
            {
                throw new ArgumentException("right is less or equal to left.");
            }
            if (top <= bottom)
            {
                throw new ArgumentException("top is less or equal to bottom.");
            }
            if (far <= near)
            {
                throw new ArgumentException("far is less or equal to near.");
            }

            real_t x = 2 * near / (right - left);
            real_t y = 2 * near / (top - bottom);

            real_t a = (right + left) / (right - left);
            real_t b = (top + bottom) / (top - bottom);
            real_t c = -(far + near) / (far - near);
            real_t d = -2 * far * near / (far - near);

            return(new Projection(
                       new Vector4(x, 0, 0, 0),
                       new Vector4(0, y, 0, 0),
                       new Vector4(a, b, c, -1),
                       new Vector4(0, 0, d, 0)
                       ));
        }
Beispiel #10
0
 /// <summary>
 /// Constructs a transformation matrix from a <paramref name="rotation"/> value and
 /// <paramref name="origin"/> vector.
 /// </summary>
 /// <param name="rotation">The rotation of the new transform, in radians.</param>
 /// <param name="origin">The origin vector, or column index 2.</param>
 public Transform2D(real_t rotation, Vector2 origin)
 {
     x.x         = y.y = Mathf.Cos(rotation);
     x.y         = y.x = Mathf.Sin(rotation);
     y.x        *= -1;
     this.origin = origin;
 }
Beispiel #11
0
        /// <summary>
        /// Linearly interpolates between two angles (in radians) by a normalized value.
        ///
        /// Similar to <see cref="Lerp(real_t, real_t, real_t)"/>,
        /// but interpolates correctly when the angles wrap around <see cref="Tau"/>.
        /// </summary>
        /// <param name="from">The start angle for interpolation.</param>
        /// <param name="to">The destination angle for interpolation.</param>
        /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
        /// <returns>The resulting angle of the interpolation.</returns>
        public static real_t LerpAngle(real_t from, real_t to, real_t weight)
        {
            real_t difference = (to - from) % Mathf.Tau;
            real_t distance   = ((2 * difference) % Mathf.Tau) - difference;

            return(from + (distance * weight));
        }
Beispiel #12
0
        /// <summary>
        /// Returns the position of the first non-zero digit, after the
        /// decimal point. Note that the maximum return value is 10,
        /// which is a design decision in the implementation.
        /// </summary>
        /// <param name="step">The input value.</param>
        /// <returns>The position of the first non-zero digit.</returns>
        public static int StepDecimals(real_t step)
        {
            double[] sd = new double[]
            {
                0.9999,
                0.09999,
                0.009999,
                0.0009999,
                0.00009999,
                0.000009999,
                0.0000009999,
                0.00000009999,
                0.000000009999,
            };
            double abs  = Abs(step);
            double decs = abs - (int)abs; // Strip away integer part

            for (int i = 0; i < sd.Length; i++)
            {
                if (decs >= sd[i])
                {
                    return(i);
                }
            }
            return(0);
        }
Beispiel #13
0
        /// <summary>
        /// Easing function, based on exponent. The <paramref name="curve"/> values are:
        /// <c>0</c> is constant, <c>1</c> is linear, <c>0</c> to <c>1</c> is ease-in, <c>1</c> or more is ease-out.
        /// Negative values are in-out/out-in.
        /// </summary>
        /// <param name="s">The value to ease.</param>
        /// <param name="curve">
        /// <c>0</c> is constant, <c>1</c> is linear, <c>0</c> to <c>1</c> is ease-in, <c>1</c> or more is ease-out.
        /// </param>
        /// <returns>The eased value.</returns>
        public static real_t Ease(real_t s, real_t curve)
        {
            if (s < 0f)
            {
                s = 0f;
            }
            else if (s > 1.0f)
            {
                s = 1.0f;
            }

            if (curve > 0f)
            {
                if (curve < 1.0f)
                {
                    return(1.0f - Pow(1.0f - s, 1.0f / curve));
                }

                return(Pow(s, curve));
            }

            if (curve < 0f)
            {
                if (s < 0.5f)
                {
                    return(Pow(s * 2.0f, -curve) * 0.5f);
                }

                return(((1.0f - Pow(1.0f - ((s - 0.5f) * 2.0f), -curve)) * 0.5f) + 0.5f);
            }

            return(0f);
        }
Beispiel #14
0
 /// <summary>
 /// Helper method for deconstruction into a tuple.
 /// </summary>
 public void Deconstruct(out real_t x, out real_t y, out real_t z, out real_t w)
 {
     x = this.x;
     y = this.y;
     z = this.z;
     w = this.w;
 }
Beispiel #15
0
        public static Projection CreatePerspective(real_t fovyDegrees, real_t aspect, real_t zNear, real_t zFar, bool flipFov)
        {
            if (flipFov)
            {
                fovyDegrees = GetFovy(fovyDegrees, (real_t)1.0 / aspect);
            }
            real_t radians = Mathf.DegToRad(fovyDegrees / (real_t)2.0);
            real_t deltaZ  = zFar - zNear;
            real_t sine    = Mathf.Sin(radians);

            if ((deltaZ == 0) || (sine == 0) || (aspect == 0))
            {
                return(Zero);
            }

            real_t cotangent = Mathf.Cos(radians) / sine;

            Projection proj = Projection.Identity;

            proj.x.x = cotangent / aspect;
            proj.y.y = cotangent;
            proj.z.z = -(zFar + zNear) / deltaZ;
            proj.z.w = -1;
            proj.w.z = -2 * zNear * zFar / deltaZ;
            proj.w.w = 0;

            return(proj);
        }
Beispiel #16
0
        /// <summary>
        /// Access vector components using their index.
        /// </summary>
        /// <exception cref="IndexOutOfRangeException">
        /// Thrown when the given the <paramref name="index"/> is not 0 or 1.
        /// </exception>
        /// <value>
        /// <c>[0]</c> is equivalent to <see cref="x"/>,
        /// <c>[1]</c> is equivalent to <see cref="y"/>.
        /// </value>
        public        real_t this[int index]
        {
            get
            {
                switch (index)
                {
                case 0:
                    return(x);

                case 1:
                    return(y);

                default:
                    throw new ArgumentOutOfRangeException(nameof(index));
                }
            }
            set
            {
                switch (index)
                {
                case 0:
                    x = value;
                    return;

                case 1:
                    y = value;
                    return;

                default:
                    throw new ArgumentOutOfRangeException(nameof(index));
                }
            }
        }
Beispiel #17
0
        /// <summary>
        /// Returns the squared length (squared magnitude) of this vector.
        /// This method runs faster than <see cref="Length"/>, so prefer it if
        /// you need to compare vectors or need the squared length for some formula.
        /// </summary>
        /// <returns>The squared length of this vector.</returns>
        public real_t LengthSquared()
        {
            real_t x2 = x * x;
            real_t y2 = y * y;
            real_t z2 = z * z;

            return(x2 + y2 + z2);
        }
Beispiel #18
0
        /// <summary>
        /// Returns the length (magnitude) of this vector.
        /// </summary>
        /// <seealso cref="LengthSquared"/>
        /// <returns>The length of this vector.</returns>
        public real_t Length()
        {
            real_t x2 = x * x;
            real_t y2 = y * y;
            real_t z2 = z * z;

            return(Mathf.Sqrt(x2 + y2 + z2));
        }
Beispiel #19
0
 /// <summary>
 /// Returns the result of the linear interpolation between
 /// this vector and <paramref name="to"/> by amount <paramref name="weight"/>.
 /// </summary>
 /// <param name="to">The destination vector for interpolation.</param>
 /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
 /// <returns>The resulting vector of the interpolation.</returns>
 public Vector2 Lerp(Vector2 to, real_t weight)
 {
     return(new Vector2
            (
                Mathf.Lerp(x, to.x, weight),
                Mathf.Lerp(y, to.y, weight)
            ));
 }
Beispiel #20
0
        /// <summary>
        /// Returns the signed angle to the given vector, in radians.
        /// The sign of the angle is positive in a counter-clockwise
        /// direction and negative in a clockwise direction when viewed
        /// from the side specified by the <paramref name="axis"/>.
        /// </summary>
        /// <param name="to">The other vector to compare this vector to.</param>
        /// <param name="axis">The reference axis to use for the angle sign.</param>
        /// <returns>The signed angle between the two vectors, in radians.</returns>
        public real_t SignedAngleTo(Vector3 to, Vector3 axis)
        {
            Vector3 crossTo       = Cross(to);
            real_t  unsignedAngle = Mathf.Atan2(crossTo.Length(), Dot(to));
            real_t  sign          = crossTo.Dot(axis);

            return((sign < 0) ? -unsignedAngle : unsignedAngle);
        }
Beispiel #21
0
 public static Projection CreateFrustumAspect(real_t size, real_t aspect, Vector2 offset, real_t near, real_t far, bool flipFov)
 {
     if (!flipFov)
     {
         size *= aspect;
     }
     return(CreateFrustum(-size / 2 + offset.x, +size / 2 + offset.x, -size / aspect / 2 + offset.y, +size / aspect / 2 + offset.y, near, far));
 }
Beispiel #22
0
        /// <summary>
        /// Returns a vector composed of the <see cref="Mathf.PosMod(real_t, real_t)"/> of this vector's components
        /// and <paramref name="mod"/>.
        /// </summary>
        /// <param name="mod">A value representing the divisor of the operation.</param>
        /// <returns>
        /// A vector with each component <see cref="Mathf.PosMod(real_t, real_t)"/> by <paramref name="mod"/>.
        /// </returns>
        public Vector2 PosMod(real_t mod)
        {
            Vector2 v;

            v.x = Mathf.PosMod(x, mod);
            v.y = Mathf.PosMod(y, mod);
            return(v);
        }
Beispiel #23
0
 /// <summary>
 /// Cubic interpolates between two values by the factor defined in <paramref name="weight"/>
 /// with pre and post values.
 /// </summary>
 /// <param name="from">The start value for interpolation.</param>
 /// <param name="to">The destination value for interpolation.</param>
 /// <param name="pre">The value which before "from" value for interpolation.</param>
 /// <param name="post">The value which after "to" value for interpolation.</param>
 /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
 /// <returns>The resulting value of the interpolation.</returns>
 public static real_t CubicInterpolate(real_t from, real_t to, real_t pre, real_t post, real_t weight)
 {
     return(0.5f *
            ((from * 2.0f) +
             (-pre + to) * weight +
             (2.0f * pre - 5.0f * from + 4.0f * to - post) * (weight * weight) +
             (-pre + 3.0f * from - 3.0f * to + post) * (weight * weight * weight)));
 }
Beispiel #24
0
 public static Projection CreateOrthogonalAspect(real_t size, real_t aspect, real_t zNear, real_t zFar, bool flipFov)
 {
     if (!flipFov)
     {
         size *= aspect;
     }
     return(CreateOrthogonal(-size / 2, +size / 2, -size / aspect / 2, +size / aspect / 2, zNear, zFar));
 }
Beispiel #25
0
 /// <summary>
 /// Performs a cubic interpolation between vectors <paramref name="preA"/>, this vector,
 /// <paramref name="b"/>, and <paramref name="postB"/>, by the given amount <paramref name="weight"/>.
 /// </summary>
 /// <param name="b">The destination vector.</param>
 /// <param name="preA">A vector before this vector.</param>
 /// <param name="postB">A vector after <paramref name="b"/>.</param>
 /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
 /// <returns>The interpolated vector.</returns>
 public Vector2 CubicInterpolate(Vector2 b, Vector2 preA, Vector2 postB, real_t weight)
 {
     return(new Vector2
            (
                Mathf.CubicInterpolate(x, b.x, preA.x, postB.x, weight),
                Mathf.CubicInterpolate(y, b.y, preA.y, postB.y, weight)
            ));
 }
Beispiel #26
0
 /// <summary>
 /// Returns the sign of <paramref name="s"/>: <c>-1</c> or <c>1</c>.
 /// Returns <c>0</c> if <paramref name="s"/> is <c>0</c>.
 /// </summary>
 /// <param name="s">The input number.</param>
 /// <returns>One of three possible values: <c>1</c>, <c>-1</c>, or <c>0</c>.</returns>
 public static int Sign(real_t s)
 {
     if (s == 0)
     {
         return(0);
     }
     return(s < 0 ? -1 : 1);
 }
Beispiel #27
0
        /// <summary>
        /// Snaps float value <paramref name="s"/> to a given <paramref name="step"/>.
        /// This can also be used to round a floating point number to an arbitrary number of decimals.
        /// </summary>
        /// <param name="s">The value to snap.</param>
        /// <param name="step">The step size to snap to.</param>
        /// <returns>The snapped value.</returns>
        public static real_t Snapped(real_t s, real_t step)
        {
            if (step != 0f)
            {
                return(Floor((s / step) + 0.5f) * step);
            }

            return(s);
        }
Beispiel #28
0
 /// <summary>
 /// Returns the result of the linear interpolation between
 /// this vector and <paramref name="to"/> by amount <paramref name="weight"/>.
 /// </summary>
 /// <param name="to">The destination vector for interpolation.</param>
 /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param>
 /// <returns>The resulting vector of the interpolation.</returns>
 public Vector3 Lerp(Vector3 to, real_t weight)
 {
     return(new Vector3
            (
                Mathf.Lerp(x, to.x, weight),
                Mathf.Lerp(y, to.y, weight),
                Mathf.Lerp(z, to.z, weight)
            ));
 }
Beispiel #29
0
        /// <summary>
        /// Moves <paramref name="from"/> toward <paramref name="to"/> by the <paramref name="delta"/> value.
        ///
        /// Use a negative <paramref name="delta"/> value to move away.
        /// </summary>
        /// <param name="from">The start value.</param>
        /// <param name="to">The value to move towards.</param>
        /// <param name="delta">The amount to move by.</param>
        /// <returns>The value after moving.</returns>
        public static real_t MoveToward(real_t from, real_t to, real_t delta)
        {
            if (Abs(to - from) <= delta)
            {
                return(to);
            }

            return(from + (Sign(to - from) * delta));
        }
Beispiel #30
0
        /// <summary>
        /// Returns a vector composed of the <see cref="Mathf.PosMod(real_t, real_t)"/> of this vector's components
        /// and <paramref name="mod"/>.
        /// </summary>
        /// <param name="mod">A value representing the divisor of the operation.</param>
        /// <returns>
        /// A vector with each component <see cref="Mathf.PosMod(real_t, real_t)"/> by <paramref name="mod"/>.
        /// </returns>
        public Vector3 PosMod(real_t mod)
        {
            Vector3 v;

            v.x = Mathf.PosMod(x, mod);
            v.y = Mathf.PosMod(y, mod);
            v.z = Mathf.PosMod(z, mod);
            return(v);
        }