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); } } }
// 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)); }
public void Draw(Vector3d location) { //Quaterniond q = Quaterniond.Identity; Quaterniond q = Quaterniond.FromAxisAngle(Graphics.OutOfScreen, -Misc.PIOVER2); Draw(location, q); }
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); } }
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(); }
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)); } }
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); } }
// 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); }
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); }
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(); }
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(); }
public void Rotate(Vector3 axis, float angleInDegrees) { Quaterniond rotQuat = Quaterniond.FromAxisAngle((Vector3d)axis, WMath.DegreesToRadians(angleInDegrees)); Rotation = rotQuat * Rotation; }
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); }
/// <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))); }
/// <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))); }