?? dxmutmisc.cs
字號:
case NativeMethods.WindowMessage.LeftButtonDown:
case NativeMethods.WindowMessage.RightButtonDoubleClick:
case NativeMethods.WindowMessage.RightButtonDown:
case NativeMethods.WindowMessage.MiddleButtonDoubleClick:
case NativeMethods.WindowMessage.MiddleButtonDown:
{
// Compute the drag rectangle in screen coord.
System.Drawing.Point cursor = new System.Drawing.Point(
NativeMethods.LoWord((uint)lParam.ToInt32()),
NativeMethods.HiWord((uint)lParam.ToInt32()));
// Update the variable state
if ( ((msg == NativeMethods.WindowMessage.LeftButtonDown) ||
(msg == NativeMethods.WindowMessage.LeftButtonDoubleClick) )
&& dragRectangle.Contains(cursor) )
{
isMouseLButtonDown = true; currentButtonMask |= (int)MouseButtonMask.Left;
}
if ( ((msg == NativeMethods.WindowMessage.MiddleButtonDown) ||
(msg == NativeMethods.WindowMessage.MiddleButtonDoubleClick) )
&& dragRectangle.Contains(cursor) )
{
isMouseMButtonDown = true; currentButtonMask |= (int)MouseButtonMask.Middle;
}
if ( ((msg == NativeMethods.WindowMessage.RightButtonDown) ||
(msg == NativeMethods.WindowMessage.RightButtonDoubleClick) )
&& dragRectangle.Contains(cursor) )
{
isMouseRButtonDown = true; currentButtonMask |= (int)MouseButtonMask.Right;
}
// Capture the mouse, so if the mouse button is
// released outside the window, we'll get the button up messages
NativeMethods.SetCapture(hWnd);
lastMousePosition = System.Windows.Forms.Cursor.Position;
return true;
}
case NativeMethods.WindowMessage.LeftButtonUp:
case NativeMethods.WindowMessage.RightButtonUp:
case NativeMethods.WindowMessage.MiddleButtonUp:
{
// Update member var state
if (msg == NativeMethods.WindowMessage.LeftButtonUp) { isMouseLButtonDown = false; currentButtonMask &= ~(int)MouseButtonMask.Left; }
if (msg == NativeMethods.WindowMessage.RightButtonUp) { isMouseRButtonDown = false; currentButtonMask &= ~(int)MouseButtonMask.Right; }
if (msg == NativeMethods.WindowMessage.MiddleButtonUp) { isMouseMButtonDown = false; currentButtonMask &= ~(int)MouseButtonMask.Middle; }
// Release the capture if no mouse buttons are down
if (!isMouseLButtonDown && !isMouseMButtonDown && !isMouseRButtonDown)
{
NativeMethods.ReleaseCapture();
}
}
break;
// Handle the mouse wheel
case NativeMethods.WindowMessage.MouseWheel:
mouseWheelDelta = NativeMethods.HiWord((uint)wParam.ToInt32()) / 120;
break;
}
return false;
}
/// <summary>
/// Reset the camera's position back to the default
/// </summary>
public virtual void Reset()
{
SetViewParameters(defaultEye, defaultLookAt);
}
/// <summary>
/// Client can call this to change the position and direction of camera
/// </summary>
public unsafe virtual void SetViewParameters(Vector3 eyePt, Vector3 lookAtPt)
{
// Store the data
defaultEye = eye = eyePt;
defaultLookAt = lookAt = lookAtPt;
// Calculate the view matrix
viewMatrix = Matrix.LookAtLH(eye, lookAt, UpDirection);
// Get the inverted matrix
Matrix inverseView = Matrix.Invert(viewMatrix);
// The axis basis vectors and camera position are stored inside the
// position matrix in the 4 rows of the camera's world matrix.
// To figure out the yaw/pitch of the camera, we just need the Z basis vector
Vector3* pZBasis = (Vector3*)&inverseView.M31;
cameraYawAngle = (float)Math.Atan2(pZBasis->X, pZBasis->Z);
float len = (float)Math.Sqrt(pZBasis->Z * pZBasis->Z + pZBasis->X * pZBasis->X);
cameraPitchAngle = -(float)Math.Atan2(pZBasis->Y, len);
}
/// <summary>
/// Calculates the projection matrix based on input params
/// </summary>
public virtual void SetProjectionParameters(float fov, float aspect, float near, float far)
{
// Set attributes for the projection matrix
fieldOfView = fov;
aspectRatio = aspect;
nearPlane = near;
farPlane = far;
projMatrix = Matrix.PerspectiveFovLH(fov, aspect, near, far);
}
/// <summary>
/// Figure out the mouse delta based on mouse movement
/// </summary>
protected void UpdateMouseDelta(float elapsedTime)
{
// Get the current mouse position
System.Drawing.Point current = System.Windows.Forms.Cursor.Position;
// Calculate how far it's moved since the last frame
System.Drawing.Point delta = new System.Drawing.Point(current.X - lastMousePosition.X,
current.Y - lastMousePosition.Y);
// Record the current position for next time
lastMousePosition = current;
if (isResetCursorAfterMove)
{
// Set position of camera to center of desktop,
// so it always has room to move. This is very useful
// if the cursor is hidden. If this isn't done and cursor is hidden,
// then invisible cursor will hit the edge of the screen
// and the user can't tell what happened
System.Windows.Forms.Screen activeScreen = System.Windows.Forms.Screen.PrimaryScreen;
System.Drawing.Point center = new System.Drawing.Point(activeScreen.Bounds.Width / 2,
activeScreen.Bounds.Height / 2);
System.Windows.Forms.Cursor.Position = center;
lastMousePosition = center;
}
// Smooth the relative mouse data over a few frames so it isn't
// jerky when moving slowly at low frame rates.
float percentOfNew = 1.0f / framesToSmoothMouseData;
float percentOfOld = 1.0f - percentOfNew;
mouseDelta.X = mouseDelta.X*percentOfNew + delta.X*percentOfNew;
mouseDelta.Y = mouseDelta.Y*percentOfNew + delta.Y*percentOfNew;
rotationVelocity = mouseDelta * rotationScaler;
}
/// <summary>
/// Figure out the velocity based on keyboard input & drag if any
/// </summary>
protected void UpdateVelocity(float elapsedTime)
{
Vector3 accel = Vector3.Empty;
if (isEnablePositionMovement)
{
// Update acceleration vector based on keyboard state
if (keys[(int)CameraKeys.MoveForward])
accel.Z += 1.0f;
if (keys[(int)CameraKeys.MoveBackward])
accel.Z -= 1.0f;
if (isEnableYAxisMovement)
{
if (keys[(int)CameraKeys.MoveUp])
accel.Y += 1.0f;
if (keys[(int)CameraKeys.MoveDown])
accel.Y -= 1.0f;
}
if (keys[(int)CameraKeys.StrafeRight])
accel.X += 1.0f;
if (keys[(int)CameraKeys.StrafeLeft])
accel.X -= 1.0f;
}
// Normalize vector so if moving 2 dirs (left & forward),
// the camera doesn't move faster than if moving in 1 dir
accel.Normalize();
// Scale the acceleration vector
accel *= moveScaler;
if (isMovementDrag)
{
// Is there any acceleration this frame?
if (accel.LengthSq() > 0)
{
// If so, then this means the user has pressed a movement key
// so change the velocity immediately to acceleration
// upon keyboard input. This isn't normal physics
// but it will give a quick response to keyboard input
velocity = accel;
dragTimer = totalDragTimeToZero;
velocityDrag = accel * (1 / dragTimer);
}
else
{
// If no key being pressed, then slowly decrease velocity to 0
if (dragTimer > 0)
{
velocity -= (velocityDrag * elapsedTime);
dragTimer -= elapsedTime;
}
else
{
// Zero velocity
velocity = Vector3.Empty;
}
}
}
else
{
// No drag, so immediately change the velocity
velocity = accel;
}
}
/// <summary>
/// Clamps V to lie inside boundaries
/// </summary>
protected void ConstrainToBoundary(ref Vector3 v)
{
// Constrain vector to a bounding box
v.X = Math.Max(v.X, minBoundary.X);
v.Y = Math.Max(v.Y, minBoundary.Y);
v.Z = Math.Max(v.Z, minBoundary.Z);
v.X = Math.Min(v.X, maxBoundary.X);
v.Y = Math.Min(v.Y, maxBoundary.Y);
v.Z = Math.Min(v.Z, maxBoundary.Z);
}
}
/// <summary>
/// Simple first person camera class that moves and rotates.
/// It allows yaw and pitch but not roll. It uses keyboard and
/// cursor to respond to keyboard and mouse input and updates the
/// view matrix based on input.
/// </summary>
public class FirstPersonCamera : Camera
{
// Mask to determine which button to enable for rotation
protected int activeButtonMask = (int)(MouseButtonMask.Left | MouseButtonMask.Middle | MouseButtonMask.Right);
// World matrix of the camera (inverse of the view matrix)
protected Matrix cameraWorld;
/// <summary>
/// Update the view matrix based on user input & elapsed time
/// </summary>
public override void FrameMove(float elapsedTime)
{
// Reset the camera if necessary
if (keys[(int)CameraKeys.Reset])
Reset();
// Get the mouse movement (if any) if the mouse buttons are down
if ((activeButtonMask & currentButtonMask) != 0)
UpdateMouseDelta(elapsedTime);
// Get amount of velocity based on the keyboard input and drag (if any)
UpdateVelocity(elapsedTime);
// Simple euler method to calculate position delta
Vector3 posDelta = velocity * elapsedTime;
// If rotating the camera
if ((activeButtonMask & currentButtonMask) != 0)
{
// Update the pitch & yaw angle based on mouse movement
float yawDelta = rotationVelocity.X;
float pitchDelta = rotationVelocity.Y;
// Invert pitch if requested
if (isInvertPitch)
pitchDelta = -pitchDelta;
cameraPitchAngle += pitchDelta;
cameraYawAngle += yawDelta;
// Limit pitch to straight up or straight down
cameraPitchAngle = Math.Max(-(float)Math.PI/2.0f, cameraPitchAngle);
cameraPitchAngle = Math.Min(+(float)Math.PI/2.0f, cameraPitchAngle);
}
// Make a rotation matrix based on the camera's yaw & pitch
Matrix cameraRotation = Matrix.RotationYawPitchRoll(cameraYawAngle, cameraPitchAngle, 0 );
// Transform vectors based on camera's rotation matrix
Vector3 localUp = new Vector3(0,1,0);
Vector3 localAhead = new Vector3(0,0,1);
Vector3 worldUp = Vector3.TransformCoordinate(localUp, cameraRotation);
Vector3 worldAhead = Vector3.TransformCoordinate(localAhead, cameraRotation);
// Transform the position delta by the camera's rotation
Vector3 posDeltaWorld = Vector3.TransformCoordinate(posDelta, cameraRotation);
if (!isEnableYAxisMovement)
posDeltaWorld.Y = 0.0f;
// Move the eye position
eye += posDeltaWorld;
if (isClipToBoundary)
ConstrainToBoundary(ref eye);
// Update the lookAt position based on the eye position
lookAt = eye + worldAhead;
// Update the view matrix
viewMatrix = Matrix.LookAtLH(eye, lookAt, worldUp);
cameraWorld = Matrix.Invert(viewMatrix);
}
/// <summary>
/// Enable or disable each of the mouse buttons for rotation drag.
/// </summary>
public void SetRotationButtons(bool left, bool middle, bool right)
{
activeButtonMask = (left ? (int)MouseButtonMask.Left : 0) |
(mi
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -