예제 #1
0
        void Control_MouseMove(object sender, MouseEventArgs e)
        {
            if (EnableMouseAction != null && !EnableMouseAction(e))
            {
                return;                 // Don't do anything
            }
            float4x4 CameraMatrixBeforeBaseCall = CameraTransform;

//			base.OnMouseMove( e );

            m_Control.Focus();

//          if ( m_ButtonsDown == MouseButtons.None )
//              return;		// Can't manipulate...

            float2 MousePos = ComputeNormalizedScreenPosition(e.X, e.Y, (float)m_Control.Width / m_Control.Height);

            // Check for FIRST PERSON switch
            if (m_bLastManipulationWasFirstPerson ^ FirstPersonKeyDown)
            {                   // There was a switch so we need to copy the current matrix and make it look like the button was just pressed...
                Control_MouseDown(sender, e);
            }
            m_bLastManipulationWasFirstPerson = FirstPersonKeyDown;

            if (!FirstPersonKeyDown)
            {
                //////////////////////////////////////////////////////////////////////////
                // MAYA MANIPULATION MODE
                //////////////////////////////////////////////////////////////////////////
                //
                switch (m_ButtonsDown)
                {
                // ROTATE
                case    MouseButtons.Left:
                {
                    if (!m_bRotationEnabled)
                    {
                        break;                                  // Rotation is disabled!
                    }
                    float fAngleX = (MousePos.y - m_ButtonDownMousePosition.y) * 2.0f * (float)Math.PI * m_ManipulationRotationSpeed;
                    float fAngleY = (MousePos.x - m_ButtonDownMousePosition.x) * 2.0f * (float)Math.PI * m_ManipulationRotationSpeed;

                    float4   AxisX = m_ButtonDownTransform.r0;
                    float4x4 Rot   = float4x4.FromAngleAxis(fAngleX, new float3(-AxisX.x, -AxisX.y, -AxisX.z))
                                     * float4x4.FromAngleAxis(fAngleY, new float3(0f, -1.0f, 0.0f));

                    float4x4 Rotated = m_ButtonDownTransform * m_InvButtonDownTargetObjectMatrix * Rot * TargetObjectMatrix;

                    CameraTransform = Rotated;

                    break;
                }

                // DOLLY => Simply translate along the AT axis
                case    MouseButtons.Right:
                case    MouseButtons.Left | MouseButtons.Middle:
                {
                    float fTrans = m_ButtonDownMousePosition.x - m_ButtonDownMousePosition.y - MousePos.x + MousePos.y;

                    m_NormalizedTargetDistance = m_ButtonDownNormalizedTargetDistance + 4.0f * m_ManipulationZoomSpeed * fTrans;
                    float fTargetDistance = Math.Sign(m_NormalizedTargetDistance) * DeNormalizeTargetDistance(m_NormalizedTargetDistance);
                    if (fTargetDistance > MIN_TARGET_DISTANCE)
                    {                                   // Okay! We're far enough so we can reduce the distance anyway
                        CameraTargetDistance = fTargetDistance;
                        m_bPushingTarget     = false;
                    }
                    else
                    {                                   // Too close! Let's move the camera forward and clamp the target distance... That will push the target along.
                        m_CameraTargetDistance     = MIN_TARGET_DISTANCE;
                        m_NormalizedTargetDistance = NormalizeTargetDistance(m_CameraTargetDistance);

                        if (!m_bPushingTarget)
                        {
                            m_ButtonDownNormalizedTargetDistance = m_NormalizedTargetDistance;
                            fTrans           = 0.0f;
                            m_bPushingTarget = true;
                        }

                        m_ButtonDownMousePosition = MousePos;

                        float4x4 DollyCam = CameraTransform;
                        DollyCam.r3 = DollyCam.r3 - (2.0f * m_ManipulationZoomSpeed * fTrans) * DollyCam.r2;

                        CameraTransform = DollyCam;
                    }
                    break;
                }

                // PAN
                case    MouseButtons.Middle:
                {
                    float2 Trans = new float2(-(MousePos.x - m_ButtonDownMousePosition.x),
                                              MousePos.y - m_ButtonDownMousePosition.y
                                              );

                    float fTransFactor = m_ManipulationPanSpeed * Math.Max(2.0f, m_CameraTargetDistance);

                    // Make the camera pan
                    float4x4 PanCam = m_ButtonDownTransform;
                    PanCam.r3 = m_ButtonDownTransform.r3
                                - fTransFactor * Trans.x * m_ButtonDownTransform.r0
                                - fTransFactor * Trans.y * m_ButtonDownTransform.r1;

                    CameraTransform = PanCam;
                    break;
                }
                }
            }
            else
            {
                //////////////////////////////////////////////////////////////////////////
                // UNREAL MANIPULATION MODE
                //////////////////////////////////////////////////////////////////////////
                //
                switch (m_ButtonsDown)
                {
                // TRANSLATE IN THE ZX PLANE (WORLD SPACE)
                case    MouseButtons.Left:
                {
                    float fTransFactor = m_ManipulationPanSpeed * System.Math.Max(4.0f, CameraTargetDistance);

                    // Compute translation in the view direction
                    float4 Trans = CameraMatrixBeforeBaseCall.r2;
                    Trans.y = 0.0f;
                    if (Trans.Dot(Trans) < 1e-4f)
                    {                                   // Better use Y instead...
                        Trans   = CameraMatrixBeforeBaseCall.r1;
                        Trans.y = 0.0f;
                    }

                    Trans = Trans.Normalized;

                    float4 NewPosition = CameraMatrixBeforeBaseCall.r3 + fTransFactor * (MousePos.y - m_ButtonDownMousePosition.y) * Trans;

                    m_ButtonDownMousePosition.y = MousePos.y;                                   // The translation is a cumulative operation...

                    // Compute rotation about the the Y WORLD axis
                    float fAngleY = (m_ButtonDownMousePosition.x - MousePos.x) * 2.0f * (float)Math.PI * m_ManipulationRotationSpeed * 0.2f;                                            // [PATAPATCH] Multiplied by 0.2 as it's REALLY too sensitive otherwise!
                    if (m_ButtonDownTransform.r1.y < 0.0f)
                    {
                        fAngleY = -fAngleY;                                             // Special "head down" case...
                    }
                    float4x4 RotY = float4x4.RotationY(fAngleY);

                    float4x4 FinalMatrix = m_ButtonDownTransform;
                    FinalMatrix.r3 = new float4(0, 0, 0, 0);                                                    // Clear translation...
                    FinalMatrix    = FinalMatrix * RotY;
                    FinalMatrix.r3 = NewPosition;

                    CameraTransform = FinalMatrix;

                    break;
                }

                // ROTATE ABOUT CAMERA
                case    MouseButtons.Right:
                {
                    float fAngleY = (m_ButtonDownMousePosition.x - MousePos.x) * 2.0f * (float)Math.PI * m_ManipulationRotationSpeed;
                    float fAngleX = (m_ButtonDownMousePosition.y - MousePos.y) * 2.0f * (float)Math.PI * m_ManipulationRotationSpeed;

                    float3   Euler         = GetEuler(m_ButtonDownTransform);
                    float4x4 CamRotYMatrix = float4x4.RotationY(fAngleY + Euler.y);
                    float4x4 CamRotXMatrix = float4x4.RotationX(fAngleX + Euler.x);
                    float4x4 CamRotZMatrix = float4x4.RotationZ(Euler.z);

                    float4x4 RotateMatrix = CamRotXMatrix * CamRotYMatrix * CamRotZMatrix;

                    RotateMatrix.r3 = CameraTransform.r3;
                    CameraTransform = RotateMatrix;

                    break;
                }

                // Translate in the ( Z-world Y-camera ) plane
                case    MouseButtons.Middle:
                case    MouseButtons.Left | MouseButtons.Right:
                {
                    float fTransFactor = m_ManipulationPanSpeed * System.Math.Max(4.0f, CameraTargetDistance);

                    float4 NewPosition = m_ButtonDownTransform.r3 + fTransFactor *
                                         ((MousePos.y - m_ButtonDownMousePosition.y) * new float4(0, 1, 0, 0)
                                          + (m_ButtonDownMousePosition.x - MousePos.x) * m_ButtonDownTransform.r0);

                    float4x4 NewMatrix = m_ButtonDownTransform;
                    NewMatrix.r3 = NewPosition;

                    CameraTransform = NewMatrix;

                    break;
                }
                }
            }
        }