예제 #1
0
        public void Update(double delta_time)
        {
            if (MouseLook)
            {
                var window_center = WindowCenter;
                var mouse_x_delta = window_center.X - Window.Mouse.X;
                var mouse_y_delta = window_center.Y - Window.Mouse.Y;

                if (mouse_x_delta != 0)
                {
                    Orientation = Quaterniond.FromAxisAngle(Up, (InvertXAxis ? -1 : 1) * SensitivityX * mouse_x_delta * delta_time * Fov) * Orientation;
                }
                if (mouse_y_delta != 0)
                {
                    Orientation = Orientation * Quaterniond.FromAxisAngle(Right, (InvertYAxis ? -1 : 1) * SensitivityY * mouse_y_delta * delta_time * Fov);
                }

                // Clamp Orientation
                var pitch = Vector3d.Dot(ForwardRelative, Vector3d.Cross(Up, RightRelative));
                if (pitch < 0)
                {
                    var sign = Vector3d.Dot(Vector3d.Cross(Forward, ForwardRelative), Right) < 0 ? -1 : 1;
                    Orientation = Orientation * Quaterniond.FromAxisAngle(Right, sign * pitch);
                }

                if (Window.WindowState == WindowState.Fullscreen)
                {
                    Cursor.Position = window_center;
                }
                else
                {
                    Cursor.Position = Window.PointToScreen(window_center);
                }
            }
        }
예제 #2
0
        // http://stackoverflow.com/questions/12435671/quaternion-lookat-function
        // http://gamedev.stackexchange.com/questions/15070/orienting-a-model-to-face-a-target
        public static Quaterniond LookRot(this Vector3d dir)
        {
            //return LookRot(dir, Constants.Vector3dUp);

            var up  = Constants.Vector3dUp;
            var fwd = Constants.Vector3dForward;

            dir.Normalize();
            double dot = Vector3d.Dot(fwd, dir);

            if (Math.Abs(dot - (-1.0f)) < 0.000001f)
            {
                return(new Quaterniond(up.X, up.Y, up.Z, 3.1415926535897932f));
            }
            if (Math.Abs(dot - (1.0f)) < 0.000001f)
            {
                return(Quaterniond.Identity);
            }

            double   rotAngle = (double)Math.Acos(dot);
            Vector3d rotAxis  = Vector3d.Cross(fwd, dir);

            rotAxis = Vector3d.Normalize(rotAxis);
            return(Quaterniond.FromAxisAngle(rotAxis, rotAngle));
        }
예제 #3
0
        public void Draw(Vector3d location)
        {
            //Quaterniond q = Quaterniond.Identity;
            Quaterniond q = Quaterniond.FromAxisAngle(Graphics.OutOfScreen, -Misc.PIOVER2);

            Draw(location, q);
        }
예제 #4
0
        public override void Draw(WSceneView view)
        {
            base.Draw(view);
            if (m_stairMesh == null)
            {
                return;
            }

            for (int i = 0; i < 4; i++)
            {
                if (ColorOverrides.ColorsEnabled[i])
                {
                    m_stairMesh.SetTevColorOverride(i, ColorOverrides.Colors[i]);
                }

                if (ColorOverrides.ConstColorsEnabled[i])
                {
                    m_stairMesh.SetTevkColorOverride(i, ColorOverrides.ConstColors[i]);
                }
            }

            for (int i = 1; i < GetNumStairs() + 1; i++)
            {
                WTransform transform = new WTransform();
                float      yRot      = Transform.Rotation.ToEulerAngles().Y + 180;
                transform.Rotation = Quaterniond.FromAxisAngle(Vector3d.UnitY, yRot / 180f * Math.PI);
                Vector3 positionOffset = new Vector3(0, i * 25f, i * -50f);
                positionOffset     = Vector3.Transform(positionOffset, transform.Rotation.ToSinglePrecision());
                transform.Position = Transform.Position + positionOffset;

                Matrix4 trs = Matrix4.CreateScale(transform.LocalScale) * Matrix4.CreateFromQuaternion(transform.Rotation.ToSinglePrecision()) * Matrix4.CreateTranslation(transform.Position);

                m_stairMesh.Render(view.ViewMatrix, view.ProjMatrix, trs);
            }
        }
예제 #5
0
        private void RollRight(double seconds)
        {
            Quaterniond rotation = Quaterniond.FromAxisAngle(_look, seconds);

            _up    = Vector3d.Transform(_up, rotation);
            _right = Vector3d.Cross(_look, _up);

            _up.Normalize();
            _right.Normalize();
        }
예제 #6
0
        public void SetRoomTransform(WRoomTransform roomTransform)
        {
            List <J3DNode> m_roomModelNodes = GetChildrenOfType <J3DNode>();

            RoomTransform = roomTransform;
            foreach (J3DNode j3d_node in m_roomModelNodes)
            {
                j3d_node.Transform.Position      = new Vector3(RoomTransform.Translation.X, 0, RoomTransform.Translation.Y);
                j3d_node.Transform.LocalRotation = Quaterniond.FromAxisAngle(Vector3d.UnitY, WMath.DegreesToRadians(RoomTransform.YRotation));
            }
        }
예제 #7
0
 public virtual void Draw(double dt)
 {
     // XXX: This is a leetle bit of a hack, since the only thing with a null mesh is
     // the DummyObj used for testing...
     if (Mesh != null)
     {
         Vector2d    lerploc    = Misc.LerpVector2d(OldLoc, Loc, dt);
         double      lerpfacing = Misc.LerpDouble(OldFacing, Facing, dt);
         Vector3d    v          = new Vector3d(lerploc);
         Quaterniond q          = Quaterniond.FromAxisAngle(Graphics.OutOfScreen, lerpfacing);
         Mesh.Draw(v, q);
     }
 }
예제 #8
0
        // Have to move the billboard so the middle of the billboard is in the middle of the ray,
        // instead of the middle of the billboard being at the start of the ray.

        public override void Draw(double dt)
        {
            Vector2d lerploc     = Misc.LerpVector2d(OldLoc, Loc, dt);
            double   lerpfacing  = Misc.LerpDouble(OldFacing, Facing, dt);
            double   offsetrange = Range / 2;
            Vector2d offsetv     = Misc.Vector2dFromDirection(lerpfacing);

            offsetv = Vector2d.Multiply(offsetv, offsetrange);
            Vector2d    loc = Vector2d.Add(lerploc, offsetv);
            Vector3d    v   = new Vector3d(loc);
            Quaterniond q   = Quaterniond.FromAxisAngle(Graphics.OutOfScreen, lerpfacing);

            Mesh.Draw(v, q);
        }
예제 #9
0
        public static Quaterniond FromEulerAnglesRobust(this Quaterniond quat, Vector3 eulerAngles, string rotationOrder, bool usesX, bool usesY, bool usesZ)
        {
            quat = Quaterniond.Identity;

            foreach (var axis in rotationOrder)
            {
                int axisIndex = "XYZ".IndexOf(axis);
                if (new[] { usesX, usesY, usesZ }[axisIndex])
                {
                    float       thisAxisRot    = new[] { eulerAngles.X, eulerAngles.Y, eulerAngles.Z }[axisIndex];
                    Vector3d    axisUnitVector = new Vector3d(axis == 'X' ? 1 : 0, axis == 'Y' ? 1 : 0, axis == 'Z' ? 1 : 0);
                    Quaterniond thisAxisRotQ   = Quaterniond.FromAxisAngle(axisUnitVector, WMath.DegreesToRadians(thisAxisRot));
                    quat *= thisAxisRotQ;
                }
                ;
            }

            return(quat);
        }
예제 #10
0
        public CollisionGroupNode(EndianBinaryReader reader)
        {
            Children  = new ObservableCollection <CollisionGroupNode>();
            Triangles = new List <CollisionTriangle>();

            int  name_offset = reader.ReadInt32();
            long cur_offset  = reader.BaseStream.Position;

            reader.BaseStream.Seek(name_offset, System.IO.SeekOrigin.Begin);
            Name = Encoding.ASCII.GetString(reader.ReadBytesUntil(0));
            reader.BaseStream.Seek(cur_offset, System.IO.SeekOrigin.Begin);

            m_Scale = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());

            Vector3 eulerRot = new Vector3();

            for (int e = 0; e < 3; e++)
            {
                eulerRot[e] = WMath.RotationShortToFloat(reader.ReadInt16());
            }
            // ZYX order
            m_Rotation = Quaterniond.FromAxisAngle(new Vector3d(0, 0, 1), WMath.DegreesToRadians(eulerRot.Z)) *
                         Quaterniond.FromAxisAngle(new Vector3d(0, 1, 0), WMath.DegreesToRadians(eulerRot.Y)) *
                         Quaterniond.FromAxisAngle(new Vector3d(1, 0, 0), WMath.DegreesToRadians(eulerRot.X));

            m_Unknown1 = reader.ReadUInt16();

            m_Translation = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());

            m_ParentIndex      = reader.ReadInt16();
            m_NextSiblingIndex = reader.ReadInt16();
            m_FirstChildIndex  = reader.ReadInt16();

            m_RoomNum = reader.ReadInt16();

            FirstVertexIndex = reader.ReadInt16();

            reader.SkipInt16(); // Octree index, we don't need it for loading from dzb

            m_Bitfield = reader.ReadInt32();
        }
예제 #11
0
        private void Rotate(Size movement)
        {
            CheckDisposed();

            double horizontalWindowRatio = (double)movement.Width / (double)_window.Width;
            double verticalWindowRatio   = (double)movement.Height / (double)_window.Height;

            // Horizontal movement is rotation around the Up-axis
            // Vertical movement is rotation around the Right-axis
            Quaterniond horizontalRotation = Quaterniond.FromAxisAngle(_up, -horizontalWindowRatio);
            Quaterniond verticalRotation   = Quaterniond.FromAxisAngle(_right, verticalWindowRatio);

            _look  = Vector3d.Transform(_look, horizontalRotation);
            _look  = Vector3d.Transform(_look, verticalRotation);
            _up    = Vector3d.Transform(_up, horizontalRotation);
            _up    = Vector3d.Transform(_up, verticalRotation);
            _right = Vector3d.Cross(_look, _up);

            _look.Normalize();
            _up.Normalize();
            _right.Normalize();
        }
예제 #12
0
        public void Rotate(Vector3 axis, float angleInDegrees)
        {
            Quaterniond rotQuat = Quaterniond.FromAxisAngle((Vector3d)axis, WMath.DegreesToRadians(angleInDegrees));

            Rotation = rotQuat * Rotation;
        }
예제 #13
0
        public bool TransformFromInput(FRay ray, WSceneView view)
        {
            if (m_mode != FTransformMode.Translation)
            {
                WrapCursor();
            }

            // Store the cursor position in viewport coordinates.
            Vector2 screenDimensions = App.GetScreenGeometry();
            Vector2 cursorPos        = App.GetCursorPosition();
            Vector2 mouseCoords      = new Vector2(((2f * cursorPos.X) / screenDimensions.X) - 1f, (1f - ((2f * cursorPos.Y) / screenDimensions.Y))); //[-1,1] range

            bool shiftPressed = WInput.GetKey(Key.LeftShift) || WInput.GetKey(Key.RightShift);

            if (m_mode == FTransformMode.Translation)
            {
                // Create a Translation Plane
                Vector3 axisA, axisB;

                if (GetNumSelectedAxes() == 1)
                {
                    if (m_selectedAxes == FSelectedAxes.X)
                    {
                        axisB = Vector3.UnitX;
                    }
                    else if (m_selectedAxes == FSelectedAxes.Y)
                    {
                        axisB = Vector3.UnitY;
                    }
                    else
                    {
                        axisB = Vector3.UnitZ;
                    }

                    Vector3 dirToCamera = (m_position - view.GetCameraPos()).Normalized();
                    axisA = Vector3.Cross(axisB, dirToCamera);
                }
                else
                {
                    axisA = ContainsAxis(m_selectedAxes, FSelectedAxes.X) ? Vector3.UnitX : Vector3.UnitZ;
                    axisB = ContainsAxis(m_selectedAxes, FSelectedAxes.Y) ? Vector3.UnitY : Vector3.UnitZ;
                }

                Vector3 planeNormal = Vector3.Cross(axisA, axisB).Normalized();
                m_translationPlane = new FPlane(planeNormal, m_position);

                float intersectDist;
                if (m_translationPlane.RayIntersectsPlane(ray, out intersectDist))
                {
                    Vector3 hitPos     = ray.Origin + (ray.Direction * intersectDist);
                    Vector3 localDelta = Vector3.Transform(hitPos - m_position, m_rotation.Inverted().ToSinglePrecision());

                    // Calculate a new position
                    Vector3 newPos = m_position;
                    if (ContainsAxis(m_selectedAxes, FSelectedAxes.X))
                    {
                        newPos += Vector3.Transform(Vector3.UnitX, m_rotation.ToSinglePrecision()) * localDelta.X;
                    }
                    if (ContainsAxis(m_selectedAxes, FSelectedAxes.Y))
                    {
                        newPos += Vector3.Transform(Vector3.UnitY, m_rotation.ToSinglePrecision()) * localDelta.Y;
                    }
                    if (ContainsAxis(m_selectedAxes, FSelectedAxes.Z))
                    {
                        newPos += Vector3.Transform(Vector3.UnitZ, m_rotation.ToSinglePrecision()) * localDelta.Z;
                    }

                    if (shiftPressed)
                    {
                        // Round to nearest 100 unit increment while shift is held down.
                        newPos.X = (float)Math.Round(newPos.X / 100f) * 100f;
                        newPos.Y = (float)Math.Round(newPos.Y / 100f) * 100f;
                        newPos.Z = (float)Math.Round(newPos.Z / 100f) * 100f;
                    }

                    // Check the new location to see if it's skyrocked off into the distance due to near-plane raytracing issues.
                    Vector3 newPosDirToCamera = (newPos - view.GetCameraPos()).Normalized();
                    float   dot = Math.Abs(Vector3.Dot(planeNormal, newPosDirToCamera));

                    //Console.WriteLine("hitPos: {0} localOffset: {1} newPos: {2}, dotResult: {3}", hitPos, localOffset, newPos, dot);
                    if (dot < 0.02f)
                    {
                        return(false);
                    }

                    // This is used to set the offset to the gizmo the mouse cursor is from the origin of the gizmo on the first frame
                    // that you click on the gizmo.
                    if (!m_hasSetMouseOffset)
                    {
                        m_translateOffset   = m_position - newPos;
                        m_deltaTranslation  = Vector3.Zero;
                        m_hasSetMouseOffset = true;
                        return(false);
                    }

                    // Apply Translation
                    m_deltaTranslation = Vector3.Transform(newPos - m_position + m_translateOffset, m_rotation.Inverted().ToSinglePrecision());

                    if (!ContainsAxis(m_selectedAxes, FSelectedAxes.X))
                    {
                        m_deltaTranslation.X = 0f;
                    }
                    if (!ContainsAxis(m_selectedAxes, FSelectedAxes.Y))
                    {
                        m_deltaTranslation.Y = 0f;
                    }
                    if (!ContainsAxis(m_selectedAxes, FSelectedAxes.Z))
                    {
                        m_deltaTranslation.Z = 0f;
                    }

                    m_totalTranslation += m_deltaTranslation;
                    m_position         += Vector3.Transform(m_deltaTranslation, m_rotation.ToSinglePrecision());

                    if (!m_hasTransformed && (m_deltaTranslation != Vector3.Zero))
                    {
                        m_hasTransformed = true;
                    }

                    return(m_hasTransformed);
                }
                else
                {
                    // Our raycast missed the plane
                    m_deltaTranslation = Vector3.Zero;
                    return(false);
                }
            }
            else if (m_mode == FTransformMode.Rotation)
            {
                Vector3d rotationAxis;
                if (m_selectedAxes == FSelectedAxes.X)
                {
                    rotationAxis = Vector3d.UnitX;
                }
                else if (m_selectedAxes == FSelectedAxes.Y)
                {
                    rotationAxis = Vector3d.UnitY;
                }
                else
                {
                    rotationAxis = Vector3d.UnitZ;
                }

                // Convert these from [0-1] to [-1, 1] to match our mouse coords.
                Vector2 lineOrigin = (view.UnprojectWorldToViewport(m_hitPoint) * 2) - Vector2.One;
                Vector2 lineEnd    = (view.UnprojectWorldToViewport(m_hitPoint + m_moveDir) * 2) - Vector2.One;

                lineOrigin.Y = -lineOrigin.Y;
                lineEnd.Y    = -lineEnd.Y;

                Vector2 lineDir   = (lineEnd - lineOrigin).Normalized();
                float   rotAmount = Vector2.Dot(lineDir, mouseCoords + m_wrapOffset - lineOrigin) * 180f;

                if (float.IsNaN(rotAmount))
                {
                    Console.WriteLine("rotAmountNaN!");
                    return(false);
                }

                if (!m_hasSetMouseOffset)
                {
                    m_rotateOffset      = -rotAmount;
                    m_deltaRotation     = Quaterniond.Identity;
                    m_hasSetMouseOffset = true;
                    return(false);
                }

                // Apply Rotation
                rotAmount += m_rotateOffset;
                if (shiftPressed)
                {
                    // Round to nearest 45 degree increment while shift is held down.
                    rotAmount = (float)Math.Round(rotAmount / 45f) * 45f;
                }
                Quaterniond oldRot = m_currentRotation;
                m_currentRotation = Quaterniond.FromAxisAngle(rotationAxis, WMath.DegreesToRadians(rotAmount));
                m_deltaRotation   = m_currentRotation * oldRot.Inverted();

                if (m_transformSpace == FTransformSpace.Local)
                {
                    m_rotation *= m_deltaRotation;
                }

                // Add to Total Rotation recorded for UI.
                if (m_selectedAxes == FSelectedAxes.X)
                {
                    m_totalRotation.X = rotAmount;
                }
                else if (m_selectedAxes == FSelectedAxes.Y)
                {
                    m_totalRotation.Y = rotAmount;
                }
                else
                {
                    m_totalRotation.Z = rotAmount;
                }

                if (!m_hasTransformed && rotAmount != 0f)
                {
                    m_hasTransformed = true;
                }

                return(m_hasTransformed);
            }
            else if (m_mode == FTransformMode.Scale)
            {
                // Create a line in screen space.
                // Convert these from [0-1] to [-1, 1] to match our mouse coords.
                Vector2 lineOrigin = (view.UnprojectWorldToViewport(m_position) * 2) - Vector2.One;
                lineOrigin.Y = -lineOrigin.Y;

                // Determine the appropriate world space directoin using the selected axes and then conver this for use with
                // screen-space controlls. This has to be done every frame because the axes can be flipped while the gizmo
                // is transforming, so we can't pre-calculate this.
                Vector3 dirX = Vector3.Transform(mFlipScaleX ? -Vector3.UnitX : Vector3.UnitX, m_rotation.ToSinglePrecision());
                Vector3 dirY = Vector3.Transform(mFlipScaleY ? -Vector3.UnitY : Vector3.UnitY, m_rotation.ToSinglePrecision());
                Vector3 dirZ = Vector3.Transform(mFlipScaleZ ? -Vector3.UnitZ : Vector3.UnitZ, m_rotation.ToSinglePrecision());
                Vector2 lineDir;

                // If there is only one axis, then the world space direction is the selected axis.
                if (GetNumSelectedAxes() == 1)
                {
                    Vector3 worldDir;
                    if (ContainsAxis(m_selectedAxes, FSelectedAxes.X))
                    {
                        worldDir = dirX;
                    }
                    if (ContainsAxis(m_selectedAxes, FSelectedAxes.Y))
                    {
                        worldDir = dirY;
                    }
                    else
                    {
                        worldDir = dirZ;
                    }

                    Vector2 worldPoint = (view.UnprojectWorldToViewport(m_position + worldDir) * 2) - Vector2.One;
                    worldPoint.Y = -lineOrigin.Y;

                    lineDir = (worldPoint - lineOrigin).Normalized();
                }
                // If there's two axii selected, then convert both to screen space and average them out to get the line direction.
                else if (GetNumSelectedAxes() == 2)
                {
                    Vector3 axisA = ContainsAxis(m_selectedAxes, FSelectedAxes.X) ? dirX : dirY;
                    Vector3 axisB = ContainsAxis(m_selectedAxes, FSelectedAxes.Z) ? dirZ : dirY;

                    Vector2 screenA = (view.UnprojectWorldToViewport(m_position + axisA) * 2) - Vector2.One;
                    screenA.Y = -screenA.Y;
                    Vector2 screenB = (view.UnprojectWorldToViewport(m_position + axisB) * 2) - Vector2.One;
                    screenB.Y = -screenB.Y;

                    screenA = (screenA - lineOrigin).Normalized();
                    screenB = (screenB - lineOrigin).Normalized();
                    lineDir = ((screenA + screenB) / 2f).Normalized();
                }
                // There's three axis, just use up.
                else
                {
                    lineDir = Vector2.UnitY;
                }

                float scaleAmount = Vector2.Dot(lineDir, mouseCoords + m_wrapOffset - lineOrigin) * 5f;

                if (shiftPressed)
                {
                    // Round to nearest whole number scale while shift is held down.
                    scaleAmount = (float)Math.Round(scaleAmount);
                }

                // Set their initial offset if we haven't already
                if (!m_hasSetMouseOffset)
                {
                    m_scaleOffset       = -scaleAmount;
                    m_deltaScale        = Vector3.One;
                    m_hasSetMouseOffset = true;
                    return(false);
                }

                // Apply the scale
                scaleAmount = scaleAmount + m_scaleOffset + 1f;

                // A multiplier is applied to the scale amount if it's less than one to prevent it dropping into the negatives.
                // ???
                if (scaleAmount < 1f)
                {
                    scaleAmount = 1f / (-(scaleAmount - 1f) + 1f);
                }

                Vector3 oldScale = m_totalScale;
                m_totalScale = Vector3.One;
                if (ContainsAxis(m_selectedAxes, FSelectedAxes.X))
                {
                    m_totalScale.X = scaleAmount;
                }
                if (ContainsAxis(m_selectedAxes, FSelectedAxes.Y))
                {
                    m_totalScale.Y = scaleAmount;
                }
                if (ContainsAxis(m_selectedAxes, FSelectedAxes.Z))
                {
                    m_totalScale.Z = scaleAmount;
                }

                m_deltaScale = new Vector3(m_totalScale.X / oldScale.X, m_totalScale.Y / oldScale.Y, m_totalScale.Z / oldScale.Z);

                if (!m_hasTransformed && (scaleAmount != 1f))
                {
                    m_hasTransformed = true;
                }

                return(m_hasTransformed);
            }

            return(false);
        }
예제 #14
0
 /// <summary>
 /// вращает по часовой
 /// </summary>
 /// <param name="v"></param>
 /// <param name="angleDeg"></param>
 /// <returns></returns>
 public static Vector2d RotateDeg(this Vector2d v, double angleDeg)
 {
     return(Vector2d.Transform(v, Quaterniond.FromAxisAngle(new Vector3d(0, 0, 1), -angleDeg / 180 * Math.PI)));
 }
예제 #15
0
 /// <summary>
 /// вращает по часовой
 /// </summary>
 /// <param name="v"></param>
 /// <param name="angleRad"></param>
 /// <returns></returns>
 public static Vector2d RotateRad(this Vector2d v, double angleRad)
 {
     return(Vector2d.Transform(v, Quaterniond.FromAxisAngle(new Vector3d(0, 0, 1), -angleRad)));
 }