Пример #1
0
        /// <summary>
        /// Creates a quaternion from the provided euler angle (pitch/yaw/roll) rotation.
        /// </summary>
        /// <param name="xAngle">Pitch angle of rotation.</param>
        /// <param name="yAngle">Yar angle of rotation.</param>
        /// <param name="zAngle">Roll angle of rotation.</param>
        /// <param name="order">The order in which rotations will be applied. Different rotations can be created depending
        ///                     on the order.</param>
        /// <returns>Quaternion that can rotate an object to the specified angles.</returns>
        public static Quaternion FromEuler(Degree xAngle, Degree yAngle, Degree zAngle, 
            EulerAngleOrder order = EulerAngleOrder.YXZ)
        {
            EulerAngleOrderData l = EA_LOOKUP[(int)order];

            Radian halfXAngle = xAngle * 0.5f;
            Radian halfYAngle = yAngle * 0.5f;
            Radian halfZAngle = zAngle * 0.5f;

            float cx = MathEx.Cos(halfXAngle);
            float sx = MathEx.Sin(halfXAngle);

            float cy = MathEx.Cos(halfYAngle);
            float sy = MathEx.Sin(halfYAngle);

            float cz = MathEx.Cos(halfZAngle);
            float sz = MathEx.Sin(halfZAngle);

            Quaternion[] quats = new Quaternion[3];
            quats[0] = new Quaternion(sx, 0.0f, 0.0f, cx);
            quats[1] = new Quaternion(0.0f, sy, 0.0f, cy);
            quats[2] = new Quaternion(0.0f, 0.0f, sz, cz);

            return (quats[l.a] * quats[l.b]) * quats[l.c];
        }
Пример #2
0
 /// <summary>
 /// Converts the quaternion rotation into axis/angle rotation.
 /// </summary>
 /// <param name="rotation">Quaternion to convert.</param>
 /// <param name="axis">Axis around which the rotation is performed.</param>
 /// <param name="angle">Amount of rotation.</param>
 public static void ToAxisAngle(Quaternion rotation, out Vector3 axis, out Degree angle)
 {
     rotation.ToAxisAngle(out axis, out angle);
 }
Пример #3
0
        private static void DrawSphericalJoint(SphericalJoint joint)
        {
            Vector3 target = GetAnchor(joint, JointBody.Target);
            Vector3 anchor = GetAnchor(joint, JointBody.Anchor);
            Vector3 center = target;

            Rigidbody rigidbody = joint.GetRigidbody(JointBody.Target);
            if (rigidbody != null)
                center = rigidbody.SceneObject.Position;

            Gizmos.Color = Color.White;
            Gizmos.DrawSphere(center, 0.05f);

            Gizmos.Color = Color.Yellow;
            Gizmos.DrawSphere(target, 0.05f);
            Gizmos.DrawSphere(anchor, 0.05f);

            Gizmos.Color = Color.Green;
            Gizmos.DrawLine(target, center);

            Gizmos.Color = Color.Green;
            if (joint.EnableLimit)
            {
                LimitConeRange limit = joint.Limit;

                Radian zAngle = MathEx.Min(new Degree(360), limit.ZLimitAngle * 2.0f);
                Radian yAngle = MathEx.Min(new Degree(360), limit.YLimitAngle * 2.0f);

                Gizmos.Transform = joint.SceneObject.WorldTransform;
                Gizmos.DrawWireArc(Vector3.Zero, Vector3.ZAxis, 0.25f, zAngle * -0.5f + new Degree(90), zAngle);
                Gizmos.DrawWireArc(Vector3.Zero, Vector3.YAxis, 0.25f, yAngle * -0.5f + new Degree(90), yAngle);

                Gizmos.Color = Color.Red;
                Radian remainingZAngle = new Degree(360) - zAngle;
                Radian remainingYAngle = new Degree(360) - yAngle;

                Gizmos.DrawWireArc(Vector3.Zero, Vector3.ZAxis, 0.25f, zAngle * 0.5f + new Degree(90), remainingZAngle);
                Gizmos.DrawWireArc(Vector3.Zero, Vector3.YAxis, 0.25f, yAngle * 0.5f + new Degree(90), remainingYAngle);
            }
            else
            {
                Gizmos.Color = Color.Green;
                Gizmos.Transform = joint.SceneObject.WorldTransform;

                Gizmos.DrawWireDisc(Vector3.Zero, Vector3.ZAxis, 0.25f);
                Gizmos.DrawWireDisc(Vector3.Zero, Vector3.YAxis, 0.25f);
            }
        }
Пример #4
0
        /// <summary>
        /// Creates a quaternion from axis/angle rotation.
        /// </summary>
        /// <param name="axis">Axis around which the rotation is performed.</param>
        /// <param name="angle">Amount of rotation.</param>
        /// <returns>Quaternion that rotates an object around the specified axis for the specified amount.</returns>
        public static Quaternion FromAxisAngle(Vector3 axis, Degree angle)
        {
            Quaternion quat;

            float halfAngle = (float)(0.5f*angle.Radians);
            float sin = (float)MathEx.Sin(halfAngle);
            quat.w = (float)MathEx.Cos(halfAngle);
            quat.x = sin * axis.x;
            quat.y = sin * axis.y;
            quat.z = sin * axis.z;

            return quat;
        }
Пример #5
0
 private static extern void Internal_SetFieldOfView(IntPtr instance, ref Degree value);
Пример #6
0
        private static void DrawHingeJoint(HingeJoint joint)
        {
            Vector3 target = GetAnchor(joint, JointBody.Target);
            Vector3 anchor = GetAnchor(joint, JointBody.Anchor);
            Vector3 center = target;

            Rigidbody rigidbody = joint.GetRigidbody(JointBody.Target);
            if (rigidbody != null)
                center = rigidbody.SceneObject.Position;

            Gizmos.Color = Color.White;
            Gizmos.DrawSphere(center, 0.05f);

            Gizmos.Color = Color.Yellow;
            Gizmos.DrawSphere(target, 0.05f);
            Gizmos.DrawSphere(anchor, 0.05f);

            Gizmos.Color = Color.Green;
            Gizmos.DrawLine(target, center);

            const float radius = 0.25f;
            const float height = 0.5f;

            if (joint.EnableLimit)
            {
                Gizmos.Transform = joint.SceneObject.WorldTransform;

                LimitAngularRange limit = joint.Limit;

                Action<float> drawLimitedArc = x =>
                {
                    Degree lower = MathEx.WrapAngle(limit.Lower);
                    Degree upper = MathEx.WrapAngle(limit.Upper);

                    lower = MathEx.Min(lower, upper);
                    upper = MathEx.Max(upper, lower);

                    // Arc zero to lower limit
                    Gizmos.Color = Color.Red;
                    Gizmos.DrawWireArc(Vector3.XAxis * x, Vector3.XAxis, radius, new Degree(0.0f), lower);

                    // Arc lower to upper limit
                    Degree validRange = upper - lower;

                    Gizmos.Color = Color.Green;
                    Gizmos.DrawWireArc(Vector3.XAxis * x, Vector3.XAxis, radius, lower, validRange);

                    // Arc upper to full circle
                    Degree remainingRange = new Degree(360) - upper;

                    Gizmos.Color = Color.Red;
                    Gizmos.DrawWireArc(Vector3.XAxis * x, Vector3.XAxis, radius, upper, remainingRange);
                };

                drawLimitedArc(-height);
                drawLimitedArc(height);
            }
            else
            {
                Gizmos.Color = Color.Green;
                Gizmos.Transform = joint.SceneObject.WorldTransform;

                Gizmos.DrawWireDisc(Vector3.XAxis * -height, Vector3.XAxis, radius);
                Gizmos.DrawWireDisc(Vector3.XAxis * height, Vector3.XAxis, radius);
            }

            Vector3[] lineStartPoints = new Vector3[4];
            lineStartPoints[0] = new Vector3(-height, radius, 0);
            lineStartPoints[1] = new Vector3(-height, -radius, 0);
            lineStartPoints[2] = new Vector3(-height, 0, radius);
            lineStartPoints[3] = new Vector3(-height, 0, -radius);

            Vector3[] lineEndPoints = new Vector3[4];
            lineEndPoints[0] = new Vector3(height, radius, 0);
            lineEndPoints[1] = new Vector3(height, -radius, 0);
            lineEndPoints[2] = new Vector3(height, 0, radius);
            lineEndPoints[3] = new Vector3(height, 0, -radius);

            Gizmos.Color = Color.Green;
            for (int i = 0; i < 4; i++)
                Gizmos.DrawLine(lineStartPoints[i], lineEndPoints[i]);
        }
Пример #7
0
 /// <summary>
 /// Converts the quaternion rotation into axis/angle rotation.
 /// </summary>
 /// <param name="rotation">Quaternion to convert.</param>
 /// <param name="axis">Axis around which the rotation is performed.</param>
 /// <param name="angle">Amount of rotation.</param>
 public static void ToAxisAngle(Quaternion rotation, out Vector3 axis, out Degree angle)
 {
     rotation.ToAxisAngle(out axis, out angle);
 }
Пример #8
0
        /// <summary>
        /// Applies the animation target state depending on the interpolation parameter. <see cref="SetState"/>.
        /// </summary>
        /// <param name="t">Interpolation parameter ranging [0, 1] that interpolated between the start state and the
        ///                 target state.</param>
        private void ApplyState(float t)
        {
            animation.Update(t);

            SceneObject.Position = animation.State.Position;
            SceneObject.Rotation = animation.State.Rotation;
            frustumWidth = animation.State.FrustumWidth;

            Vector3 eulerAngles = SceneObject.Rotation.ToEuler();
            pitch = (Degree)eulerAngles.x;
            yaw = (Degree)eulerAngles.y;

            Degree FOV = (Degree)(1.0f - animation.State.OrtographicPct)*FieldOfView;
            if (FOV < (Degree)5.0f)
            {
                camera.ProjectionType = ProjectionType.Orthographic;
                camera.OrthoHeight = frustumWidth * 0.5f / camera.AspectRatio;
            }
            else
            {
                camera.ProjectionType = ProjectionType.Perspective;
                camera.FieldOfView = FOV;
            }

            // Note: Consider having a global setting for near/far planes as changing it here might confuse the user
            float distance = CalcDistanceForFrustumWidth(frustumWidth);
            if (distance < 1)
            {
                camera.NearClipPlane = 0.005f;
                camera.FarClipPlane = 1000f;
            }
            if (distance < 100)
            {
                camera.NearClipPlane = 0.05f;
                camera.FarClipPlane = 2500f;
            }
            else if (distance < 1000)
            {
                camera.NearClipPlane = 0.5f;
                camera.FarClipPlane = 10000f;
            }
            else
            {
                camera.NearClipPlane = 5.0f;
                camera.FarClipPlane = 1000000f;
            }
        }
Пример #9
0
        /// <summary>
        /// Rotates around local Y axis.
        /// </summary>
        /// <param name="angle">Angle to rotate by.</param>
        public void Yaw(Degree angle)
        {
            Radian radianAngle = angle;

            Internal_Yaw(mCachedPtr, ref radianAngle);
        }
Пример #10
0
        /// <summary>
        /// Rotates around local X axis.
        /// </summary>
        /// <param name="angle">Angle to rotate by.</param>
        public void Pitch(Degree angle)
        {
            Radian radianAngle = angle;

            Internal_Pitch(mCachedPtr, ref radianAngle);
        }
Пример #11
0
        /// <summary>
        /// Rotates around local Z axis.
        /// </summary>
        /// <param name="angle">Angle to rotate by.</param>
        public void Roll(Degree angle)
        {
            Radian radianAngle = angle;

            Internal_Roll(mCachedPtr, ref radianAngle);
        }
Пример #12
0
 /// <summary>
 /// Creates a new radian value.
 /// </summary>
 /// <param name="d">Value in degrees.</param>
 public Radian(Degree d)
 {
     this.value = d.Radians;
 }
Пример #13
0
 private static extern void Internal_SetFieldOfView(IntPtr instance, ref Degree value);
Пример #14
0
 /// <summary>
 /// Converts the quaternion rotation into axis/angle rotation.
 /// </summary>
 /// <param name="axis">Axis around which the rotation is performed.</param>
 /// <param name="angle">Amount of rotation.</param>
 public void ToAxisAngle(out Vector3 axis, out Degree angle)
 {
     float fSqrLength = x*x+y*y+z*z;
     if (fSqrLength > 0.0f)
     {
         angle = 2.0f * MathEx.Acos(w);
         float fInvLength = MathEx.InvSqrt(fSqrLength);
         axis.x = x*fInvLength;
         axis.y = y*fInvLength;
         axis.z = z*fInvLength;
     }
     else
     {
         // Angle is 0, so any axis will do
         angle = (Degree)0.0f;
         axis.x = 1.0f;
         axis.y = 0.0f;
         axis.z = 0.0f;
     }
 }
Пример #15
0
 /// <summary>
 /// Enables or disables a cut-off plane that can allow the disc to be intersected with only in a 180 degree arc.
 /// </summary>
 /// <param name="angle">Angle at which to start the cut-off. Points on the dist at the specified angle and the next
 ///                     180 degrees won't be interactable.</param>
 /// <param name="enabled">Should the cutoff plane be enabled or disabled.</param>
 public void SetCutoffPlane(Degree angle, bool enabled)
 {
     Internal_SetCutoffPlane(mCachedPtr, angle.Degrees, enabled);
 }
Пример #16
0
 /// <summary>
 /// Snaps an angle value to the specified increments.
 /// </summary>
 /// <param name="value">Value to snap.</param>
 /// <param name="snapAmount">Increment to which to snap the value to.</param>
 /// <returns>Value snapped to the provided increments.</returns>
 public static Degree SnapValue(Degree value, Degree snapAmount)
 {
     return (Degree)SnapValue(value.Degrees, snapAmount.Degrees);
 }
Пример #17
0
 /// <summary>
 /// Creates a new radian value.
 /// </summary>
 /// <param name="d">Value in degrees.</param>
 public Radian(Degree d)
 {
     this.value = d.Radians;
 }
Пример #18
0
        private void OnUpdate()
        {
            bool isOrtographic = camera.ProjectionType == ProjectionType.Orthographic;

            if (inputEnabled)
            {
                bool goingForward = VirtualInput.IsButtonHeld(moveForwardBtn);
                bool goingBack = VirtualInput.IsButtonHeld(moveBackwardBtn);
                bool goingLeft = VirtualInput.IsButtonHeld(moveLeftBtn);
                bool goingRight = VirtualInput.IsButtonHeld(moveRightBtn);
                bool goingUp = VirtualInput.IsButtonHeld(moveUpBtn);
                bool goingDown = VirtualInput.IsButtonHeld(moveDownBtn);
                bool fastMove = VirtualInput.IsButtonHeld(fastMoveBtn);
                bool camActive = VirtualInput.IsButtonHeld(activeBtn);
                bool isPanning = VirtualInput.IsButtonHeld(panBtn);

                bool hideCursor = camActive || isPanning;
                if (hideCursor != lastButtonState)
                {
                    if (hideCursor)
                    {
                        Cursor.Hide();

                        Rect2I clipRect;
                        clipRect.x = Input.PointerPosition.x - 2;
                        clipRect.y = Input.PointerPosition.y - 2;
                        clipRect.width = 4;
                        clipRect.height = 4;

                        Cursor.ClipToRect(clipRect);
                    }
                    else
                    {
                        Cursor.Show();
                        Cursor.ClipDisable();
                    }

                    lastButtonState = hideCursor;
                }

                float frameDelta = Time.FrameDelta;
                if (camActive)
                {
                    float horzValue = VirtualInput.GetAxisValue(horizontalAxis);
                    float vertValue = VirtualInput.GetAxisValue(verticalAxis);

                    float rotationAmount = RotationalSpeed * EditorSettings.MouseSensitivity * frameDelta;

                    yaw += new Degree(horzValue * rotationAmount);
                    pitch += new Degree(vertValue * rotationAmount);

                    yaw = MathEx.WrapAngle(yaw);
                    pitch = MathEx.WrapAngle(pitch);

                    Quaternion yRot = Quaternion.FromAxisAngle(Vector3.YAxis, yaw);
                    Quaternion xRot = Quaternion.FromAxisAngle(Vector3.XAxis, pitch);

                    Quaternion camRot = yRot*xRot;
                    camRot.Normalize();

                    SceneObject.Rotation = camRot;

                    // Handle movement using movement keys
                    Vector3 direction = Vector3.Zero;

                    if (goingForward) direction += SceneObject.Forward;
                    if (goingBack) direction -= SceneObject.Forward;
                    if (goingRight) direction += SceneObject.Right;
                    if (goingLeft) direction -= SceneObject.Right;
                    if (goingUp) direction += SceneObject.Up;
                    if (goingDown) direction -= SceneObject.Up;

                    if (direction.SqrdLength != 0)
                    {
                        direction.Normalize();

                        float multiplier = 1.0f;
                        if (fastMove)
                            multiplier = FastModeMultiplier;

                        currentSpeed = MathEx.Clamp(currentSpeed + Acceleration*frameDelta, StartSpeed, TopSpeed);
                        currentSpeed *= multiplier;
                    }
                    else
                    {
                        currentSpeed = 0.0f;
                    }

                    const float tooSmall = 0.0001f;
                    if (currentSpeed > tooSmall)
                    {
                        Vector3 velocity = direction*currentSpeed;
                        SceneObject.Move(velocity*frameDelta);
                    }
                }

                // Pan
                if (isPanning)
                {
                    float horzValue = VirtualInput.GetAxisValue(horizontalAxis);
                    float vertValue = VirtualInput.GetAxisValue(verticalAxis);

                    Vector3 direction = new Vector3(horzValue, -vertValue, 0.0f);
                    direction = camera.SceneObject.Rotation.Rotate(direction);

                    SceneObject.Move(direction*PanSpeed*frameDelta);
                }
            }
            else
            {
                Cursor.Show();
                Cursor.ClipDisable();
            }

            SceneWindow sceneWindow = EditorWindow.GetWindow<SceneWindow>();
            if (sceneWindow.Active)
            {
                Rect2I bounds = sceneWindow.Bounds;

                // Move using scroll wheel
                if (bounds.Contains(Input.PointerPosition))
                {
                    float scrollAmount = VirtualInput.GetAxisValue(scrollAxis);
                    if (!isOrtographic)
                    {
                        SceneObject.Move(SceneObject.Forward*scrollAmount*ScrollSpeed);
                    }
                    else
                    {
                        float orthoHeight = MathEx.Max(1.0f, camera.OrthoHeight - scrollAmount);
                        camera.OrthoHeight = orthoHeight;
                    }
                }
            }

            UpdateAnim();
        }
Пример #19
0
        /// <summary>
        /// Converts an orthonormal matrix to axis angle representation.
        /// </summary>
        /// <param name="axis">Axis around which the rotation is performed.</param>
        /// <param name="angle">Amount of rotation.</param>
        public void ToAxisAngle(out Vector3 axis, out Degree angle)
        {
            float  trace   = m00 + m11 + m22;
            float  cos     = 0.5f * (trace - 1.0f);
            Radian radians = MathEx.Acos(cos);  // In [0, PI]

            angle = radians.Degrees;

            if (radians > 0.0f)
            {
                if (radians < MathEx.Pi)
                {
                    axis.x = m21 - m12;
                    axis.y = m02 - m20;
                    axis.z = m10 - m01;

                    axis.Normalize();
                }
                else
                {
                    // Angle is PI
                    float halfInverse;
                    if (m00 >= m11)
                    {
                        // r00 >= r11
                        if (m00 >= m22)
                        {
                            // r00 is maximum diagonal term
                            axis.x      = 0.5f * MathEx.Sqrt(m00 - m11 - m22 + 1.0f);
                            halfInverse = 0.5f / axis.x;
                            axis.y      = halfInverse * m01;
                            axis.z      = halfInverse * m02;
                        }
                        else
                        {
                            // r22 is maximum diagonal term
                            axis.z      = 0.5f * MathEx.Sqrt(m22 - m00 - m11 + 1.0f);
                            halfInverse = 0.5f / axis.z;
                            axis.x      = halfInverse * m02;
                            axis.y      = halfInverse * m12;
                        }
                    }
                    else
                    {
                        // r11 > r00
                        if (m11 >= m22)
                        {
                            // r11 is maximum diagonal term
                            axis.y      = 0.5f * MathEx.Sqrt(m11 - m00 - m22 + 1.0f);
                            halfInverse = 0.5f / axis.y;
                            axis.x      = halfInverse * m01;
                            axis.z      = halfInverse * m12;
                        }
                        else
                        {
                            // r22 is maximum diagonal term
                            axis.z      = 0.5f * MathEx.Sqrt(m22 - m00 - m11 + 1.0f);
                            halfInverse = 0.5f / axis.z;
                            axis.x      = halfInverse * m02;
                            axis.y      = halfInverse * m12;
                        }
                    }
                }
            }
            else
            {
                // The angle is 0 and the matrix is the identity.  Any axis will
                // work, so just use the x-axis.
                axis.x = 1.0f;
                axis.y = 0.0f;
                axis.z = 0.0f;
            }
        }