Exemple #1
0
        /// <summary>
        /// @note Exp should really only be used after Log.
        /// Assumes a quaternion with W=0 and V=theta*v (where |v| = 1).
        /// Exp(q) = (sin(theta)*v, cos(theta))
        /// </summary>
        public FQuat Exp()
        {
            float angle    = FMath.Sqrt(X * X + Y * Y + Z * Z);
            float sinAngle = FMath.Sin(angle);

            FQuat result;

            result.W = FMath.Cos(angle);

            if (FMath.Abs(sinAngle) >= FMath.SmallNumber)
            {
                float scale = sinAngle / angle;
                result.X = scale * X;
                result.Y = scale * Y;
                result.Z = scale * Z;
            }
            else
            {
                result.X = X;
                result.Y = Y;
                result.Z = Z;
            }

            return(result);
        }
Exemple #2
0
        /// <summary>
        /// Returns a random unit vector, uniformly distributed, within the specified cone.
        /// </summary>
        /// <param name="dir">The center direction of the cone</param>
        /// <param name="horizontalConeHalfAngleRad">Horizontal half-angle of cone, in radians.</param>
        /// <param name="verticalConeHalfAngleRad">Vertical half-angle of cone, in radians.</param>
        /// <returns>Normalized vector within the specified cone.</returns>
        public FVector VRandCone(FVector dir, float horizontalConeHalfAngleRad, float verticalConeHalfAngleRad)
        {
            if ((verticalConeHalfAngleRad > 0.0f) && (horizontalConeHalfAngleRad > 0.0f))
            {
                float randU = FRand();
                float randV = FRand();

                // Get spherical coords that have an even distribution over the unit sphere
                // Method described at http://mathworld.wolfram.com/SpherePointPicking.html
                float theta = 2.0f * FMath.PI * randU;
                float phi   = FMath.Acos((2.0f * randV) - 1.0f);

                // restrict phi to [0, ConeHalfAngleRad]
                // where ConeHalfAngleRad is now a function of Theta
                // (specifically, radius of an ellipse as a function of angle)
                // function is ellipse function (x/a)^2 + (y/b)^2 = 1, converted to polar coords
                float coneHalfAngleRad = FMath.Square(FMath.Cos(theta) / verticalConeHalfAngleRad) + FMath.Square(FMath.Sin(theta) / horizontalConeHalfAngleRad);
                coneHalfAngleRad = FMath.Sqrt(1.0f / coneHalfAngleRad);

                // clamp to make a cone instead of a sphere
                phi = FMath.Fmod(phi, coneHalfAngleRad);

                // get axes we need to rotate around
                FMatrix dirMat = FMatrix.CreateRotation(dir.Rotation());
                // note the axis translation, since we want the variation to be around X
                FVector dirZ = dirMat.GetUnitAxis(EAxis.X);
                FVector dirY = dirMat.GetUnitAxis(EAxis.Y);

                FVector result = dir.RotateAngleAxis(phi * 180.0f / FMath.PI, dirY);
                result = result.RotateAngleAxis(theta * 180.0f / FMath.PI, dirZ);

                // ensure it's a unit vector (might not have been passed in that way)
                result = result.GetSafeNormal();

                return(result);
            }
            else
            {
                return(dir.GetSafeNormal());
            }
        }
Exemple #3
0
        /// <summary>
        /// Converts spherical coordinates on the unit sphere into a Cartesian unit length vector.
        /// </summary>
        public FVector SphericalToUnitCartesian()
        {
            float SinTheta = FMath.Sin(X);

            return(new FVector(FMath.Cos(Y) * SinTheta, FMath.Sin(Y) * SinTheta, FMath.Cos(X)));
        }