public void Set(Quaterniond quat) { QuaternionValue = quat; VectorEdit.UseDecimalIncrement = true; VectorEdit.Set(QuaternionValue.Xyz); RotationValue.Value = (decimal)(QuaternionValue.W / (Math.PI / 180.0)); CheckPreset(); }
/// <summary> /// Creates a new quaternion from a scaled vector, where the magnitude is the angle and the direction is the axis. /// </summary> /// <param name="scaledAxis">The scaled vector.</param> public Quaternion(Vector3 scaledAxis) : this() { if (scaledAxis.LengthSquared == 0) { OpenTKEquivalent = Quaterniond.Identity; } else { OpenTKEquivalent = Quaterniond.FromAxisAngle(scaledAxis.Normalized.OpenTKEquivalent, scaledAxis.Length); } }
/// <summary> /// Returns the rotation component of this instance. Quite slow. /// </summary> /// <param name="row_normalise">Whether the method should row-normalise (i.e. remove scale from) the Matrix. Pass false if you know it's already normalised.</param> public Quaterniond ExtractRotation(bool row_normalise = true) { var row0 = Row0; var row1 = Row1; var row2 = Row2; if (row_normalise) { row0 = row0.Normalized(); row1 = row1.Normalized(); row2 = row2.Normalized(); } // code below adapted from Blender Quaterniond q = new Quaterniond(); double trace = 0.25 * (row0[0] + row1[1] + row2[2] + 1.0); if (trace > 0) { double sq = Math.Sqrt(trace); q.W = sq; sq = 1.0 / (4.0 * sq); q.X = (row1[2] - row2[1]) * sq; q.Y = (row2[0] - row0[2]) * sq; q.Z = (row0[1] - row1[0]) * sq; } else if (row0[0] > row1[1] && row0[0] > row2[2]) { double sq = 2.0 * Math.Sqrt(1.0 + row0[0] - row1[1] - row2[2]); q.X = 0.25 * sq; sq = 1.0 / sq; q.W = (row2[1] - row1[2]) * sq; q.Y = (row1[0] + row0[1]) * sq; q.Z = (row2[0] + row0[2]) * sq; } else if (row1[1] > row2[2]) { double sq = 2.0 * Math.Sqrt(1.0 + row1[1] - row0[0] - row2[2]); q.Y = 0.25 * sq; sq = 1.0 / sq; q.W = (row2[0] - row0[2]) * sq; q.X = (row1[0] + row0[1]) * sq; q.Z = (row2[1] + row1[2]) * sq; } else { double sq = 2.0 * Math.Sqrt(1.0 + row2[2] - row0[0] - row1[1]); q.Z = 0.25 * sq; sq = 1.0 / sq; q.W = (row1[0] - row0[1]) * sq; q.X = (row2[0] + row0[2]) * sq; q.Y = (row2[1] + row1[2]) * sq; } q.Normalize(); return(q); }
public static double Angle(Quaterniond _a, Quaterniond _b) { double f = Dot(_a, _b); return(Mathd.Acos(Mathd.Min(Mathd.Abs(f), 1.0f)) * 2.0f * 57.295788f); }
public RotationRequestEvent(Quaterniond inRot) { Rotation = inRot; }
public void Rotate(Vector3 axis, float angleInDegrees) { Quaterniond rotQuat = Quaterniond.FromAxisAngle((Vector3d)axis, WMath.DegreesToRadians(angleInDegrees)); Rotation = rotQuat * Rotation; }
public static Quaterniond Conjugate(Quaterniond p, Quaterniond q) { // NOTE: p assumed to be normalized! return p * q * p.Conjugated; }
/// <summary> /// Gets rigid body information. /// </summary> /// <param name="position"></param> /// <param name="orientation"></param> public void GetInfo(out Vector3d position, out Quaterniond orientation) { position = this.position; orientation = this.orientation; }
public void GetRotation(out Quaterniond result) { result = new Quaterniond(rotation.X, rotation.Y, rotation.Z, rotation.W); }
protected override void OnUpdateFrame(FrameEventArgs e) { double displacement = 500; base.OnUpdateFrame(e); Planet.Update(CamPos); if (Focused) { var Keyboard = OpenTK.Input.Keyboard.GetState(); Matrix4d rot = Matrix4d.CreateFromQuaternion(CamRot); Vector3d left = rot.Row0.Xyz; Vector3d up = rot.Row1.Xyz; Vector3d front = rot.Row2.Xyz; ; if (Keyboard[OpenTK.Input.Key.ShiftLeft]) displacement *= 100; if (Keyboard[OpenTK.Input.Key.W]) CamPos -= front * displacement; if (Keyboard[OpenTK.Input.Key.S]) CamPos += front * displacement; if (Keyboard[OpenTK.Input.Key.D]) CamPos += left * displacement; if (Keyboard[OpenTK.Input.Key.A]) CamPos -= left * displacement; if (Keyboard[OpenTK.Input.Key.Q]) CamPos -= up * displacement; if (Keyboard[OpenTK.Input.Key.E]) CamPos += up * displacement; Vector3d NewCamRot = new Vector3d(); if (Keyboard[OpenTK.Input.Key.I]) NewCamRot.X -= 0.1; if (Keyboard[OpenTK.Input.Key.K]) NewCamRot.X += 0.1; if (Keyboard[OpenTK.Input.Key.J]) NewCamRot.Y -= 0.1; if (Keyboard[OpenTK.Input.Key.L]) NewCamRot.Y += 0.1; if (Keyboard[OpenTK.Input.Key.U]) NewCamRot.Z -= 0.1; if (Keyboard[OpenTK.Input.Key.O]) NewCamRot.Z += 0.1; if (Keyboard[OpenTK.Input.Key.Space]) { CamPos = DefaultPos; CamRot = Quaterniond.Identity; } if (Keyboard[OpenTK.Input.Key.R]) { Shader.Recompile(); } if (Keyboard[OpenTK.Input.Key.X]) { if (IsLine) { GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill); IsLine = false; } else { GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); IsLine = true; } } if (Keyboard[OpenTK.Input.Key.Z]) { Integrator.Reset(); Planet.Layers[0].RegeneratePlanet(); } if (Keyboard[OpenTK.Input.Key.Escape]) { Exit(); } Frustum.SetCamDef(CamPos, CamPos + front, up); CamRot *= Quaterniond.FromMatrix(Matrix3d.CreateRotationX(NewCamRot.X) * Matrix3d.CreateRotationY(NewCamRot.Y) * Matrix3d.CreateRotationZ(NewCamRot.Z)); } }
// Unity quaternion conversion public static Quaternion ToUnityQuaternion(Quaterniond q) { // Swap Y/Z axes on conversion return new Quaternion((float)q.b, (float)q.d, (float)q.c, (float)q.a); }
static Quaterniond() { Identity = new Quaterniond(1.0, 0.0, 0.0, 0.0); }
// Rotation matrix public static Matrix3d RotationMatrix(Quaterniond q) { // Kinda useful, dontcha know double aa = q.a*q.a; double bb = q.b*q.b; double cc = q.c*q.c; double dd = q.d*q.d; double ab2 = 2.0*q.a*q.b; double ac2 = 2.0*q.a*q.c; double ad2 = 2.0*q.a*q.d; double bc2 = 2.0*q.b*q.c; double bd2 = 2.0*q.b*q.d; double cd2 = 2.0*q.c*q.d; return new Matrix3d ( aa + bb - cc - dd, bc2 - ad2, bd2 + ac2, bc2 + ad2, aa - bb + cc - dd, cd2 - ab2, bd2 - ac2, cd2 + ab2, aa - bb - cc + dd ); }
// Vector rotation public static Vector3d RotateVector(Quaterniond q, Vector3d v) { // The other way to actually use these things // With q = (w, R): // Vrot = V + 2*R x (R x V + w*V) // R' = (rx, ry, rz) = 2*R double rx = q.b + q.b; double ry = q.c + q.c; double rz = q.d + q.d; // P = (px, py, pz) = R x V + w*V double px = q.c*v.z - q.d*v.y + q.a*v.x; double py = q.d*v.x - q.b*v.z + q.a*v.y; double pz = q.b*v.y - q.c*v.x + q.a*v.z; // Vrot = V + R' x P return new Vector3d( v.x + ry*pz - rz*py, v.y + rz*px - rx*pz, v.z + rx*py - ry*px ); }
// Normalized value public static Quaterniond Normalize(Quaterniond q) { double norm = Math.Sqrt(q.a*q.a + q.b*q.b + q.c*q.c + q.d*q.d); if (norm < Epsilon) // IOW if normalized version is close to zero return new Quaterniond(1.0, 0.0, 0.0, 0.0); // Equal in value to Quateriond.Identity else return new Quaterniond (q.a/norm, q.b/norm, q.c/norm, q.d/norm); }
/// <summary> /// Build a rotation matrix from the specified quaternion. /// </summary> /// <param name="q">Quaternion to translate.</param> /// <returns>A matrix instance.</returns> public static Matrix3d CreateFromQuaternion(Quaterniond q) { CreateFromQuaternion(ref q, out Matrix3d result); return(result); }
/// <summary> /// A static object constructor. /// </summary> /// <param name="scene">The scene this object belongs to.</param> /// <param name="material">The material of object.</param> /// <param name="position">The position of object.</param> /// <param name="orientation">The orientation of object.</param> /// <param name="shapes">Shapes, in local coordinates. /// The driver list the supported shapes. This shapes will be modified.</param> public StaticObject(PhysicsScene scene, Material material, Vector3d position, Quaterniond orientation, params object[] shapes) : this(scene, material, Matrix4x4d.From(position, orientation), shapes) { }
public static void MoveAvatarRequest(object sender, string InstanceID, Vector3d pos, Quaterniond rot) { MoveAvatarRequestEventHandler?.Invoke(sender, new MoveEvent(InstanceID, pos, rot)); }
public BookmarkEvent(string sName, Vector3d inPosition, Quaterniond inRot) { Name = sName; Position = inPosition; Rotation = inRot; }
public static void Rotate(object sender, Quaterniond newRot) { RotateEventHandler?.Invoke(sender, new RotationRequestEvent(newRot)); }
/// <summary> /// Creates a new quaternion from an axis, denoted by i, j, k, and an angle r. /// </summary> /// <param name="i">The x-component of the axis.</param> /// <param name="j">The y-component of the axis.</param> /// <param name="k">The z-component of the axis.</param> /// <param name="r">The angle.</param> public Quaternion(double r, double i, double j, double k) : this() { OpenTKEquivalent = new Quaterniond(i, j, k, r); }
public PositionEvent(string inInstanceID, Vector3d pos, Quaterniond rot) { InstanceID = inInstanceID; Position = pos; Rotation = rot; }
/// <inheritdoc /> public void Calculate(ReadOnlyArrayView <Body> bodies) { _delta = Quaterniond.CreateFromTo(bodies[_index].Rotation.Current, _target).ToAxisAngle(); }
/** * Creates a copy of an existing object from the TemplateRoot * */ public static MSceneObject Spawn(MServerObject mso, Vector3d Pos, Quaterniond Rot) { MSceneObject m = (MSceneObject)MScene.TemplateRoot.FindModuleByInstanceID(mso.TemplateID); if (m == null) { Console.WriteLine("TEMPLATE NOT LOADED INTO MScene.TemplateRoot:" + mso.TemplateID); return(null); } MSceneObject t = null; MObject TargetRoot = MScene.ModelRoot; if (m.IsTransparent) { TargetRoot = MScene.Priority2; } else { TargetRoot = MScene.Priority1; } if (m.Type == MObject.EType.PrimitiveCube) { t = CreateCube(TargetRoot, mso.Name, Pos); } if (m.Type == MObject.EType.PrimitiveSphere) { t = CreateSphere(TargetRoot, 2, mso.Name, Pos); } if (m.Type == MObject.EType.Model) { t = SpawnModel(TargetRoot, mso.TemplateID, mso.OwnerID, mso.Name, Pos); } if (m.Type == MObject.EType.AnimatedModel) { t = SpawnAnimatedModel(TargetRoot, mso.TemplateID, mso.OwnerID, mso.Name, Pos); //MAnimatedModel man = (MAnimatedModel)m; //man.BoneOffset = MassiveTools.VectorFromArray(t.BoneOffset); } if (m.Type == MObject.EType.InstanceMesh) { t = SpawnInstanced(TargetRoot, mso.TemplateID, mso.OwnerID, mso.Name, Pos); } t.transform.Position = Pos; t.transform.Rotation = Rot; m.CopyTo(t); t.OwnerID = mso.OwnerID; t.transform.Position = Pos; t.transform.Rotation = Rot; t.Tag = mso.Tag; MClickHandler ch = (MClickHandler)m.FindModuleByType(MObject.EType.ClickHandler); if (ch != null) { MClickHandler ch2 = new MClickHandler(); ch2.Clicked = ch.Clicked; ch2.RightClicked = ch.RightClicked; ch2.DoubleClicked = ch.DoubleClicked; t.Add(ch2); } return(t); }
private void OnRotationBasePropertyChanged(object sender, PropertyChangedEventArgs e) { // Automatically update the quaternion rotation any time the euler rotation base is changed. m_localRotation = Quaterniond.Identity.FromEulerAnglesRobust(RotationBase.BackingVector, RotationOrder, UsesXRotation, UsesYRotation, UsesZRotation); }
/// <summary> /// Transforms a vector by a quaternion rotation. /// </summary> /// <param name="vec">The vector to transform.</param> /// <param name="quat">The quaternion to rotate the vector by.</param> /// <returns>The result of the operation.</returns> public static Vector2d Transform(Vector2d vec, Quaterniond quat) { Transform(ref vec, ref quat, out Vector2d result); return(result); }
public static double Dot(Quaterniond _a, Quaterniond _b) => _a.x * _b.x + _a.y * _b.y + _a.z * _b.z + _a.w * _b.w;
public void StartTransform() { m_isTransforming = true; m_hasTransformed = false; m_hasSetMouseOffset = false; m_wrapOffset = Vector2.Zero; m_totalTranslation = Vector3.Zero; m_totalRotation = Vector3.Zero; m_currentRotation = Quaterniond.Identity; m_totalScale = Vector3.One; // Set the rotation direction. if (m_mode == FTransformMode.Rotation) { // We need to determine which side of the gizmo they are on, so that goes the expected direction when // we pull up/down in screenspace. Vector3 rotAxis; if (m_selectedAxes == FSelectedAxes.X) { rotAxis = Vector3.UnitX; } if (m_selectedAxes == FSelectedAxes.Y) { rotAxis = Vector3.UnitY; } else { rotAxis = Vector3.UnitZ; } Vector3 dirFromGizmoToHitPoint = (m_hitPoint - m_position).Normalized(); m_moveDir = Vector3.Cross(rotAxis, dirFromGizmoToHitPoint); } // Set the scale direction. else if (m_mode == FTransformMode.Scale) { // If we're transforming only on one axis, then the directon is in the selected axis. if (GetNumSelectedAxes() == 1) { if (ContainsAxis(m_selectedAxes, FSelectedAxes.X)) { m_moveDir = Vector3.Transform(Vector3.UnitX, m_rotation.ToSinglePrecision()); } if (ContainsAxis(m_selectedAxes, FSelectedAxes.Y)) { m_moveDir = Vector3.Transform(Vector3.UnitY, m_rotation.ToSinglePrecision()); } else { m_moveDir = Vector3.Transform(Vector3.UnitZ, m_rotation.ToSinglePrecision()); } } // Two axes however, means interpolate between both. if (GetNumSelectedAxes() == 2) { Vector3 axisA = ContainsAxis(m_selectedAxes, FSelectedAxes.X) ? Vector3.Transform(Vector3.UnitX, m_rotation.ToSinglePrecision()) : Vector3.Transform(Vector3.UnitY, m_rotation.ToSinglePrecision()); Vector3 axisB = ContainsAxis(m_selectedAxes, FSelectedAxes.Z) ? Vector3.Transform(Vector3.UnitZ, m_rotation.ToSinglePrecision()) : Vector3.Transform(Vector3.UnitY, m_rotation.ToSinglePrecision()); m_moveDir = (axisA + axisB) / 2f; } } }
/// <summary> /// 设置平移旋转缩放矩阵 /// </summary> /// <param name="pos"></param> /// <param name="q"></param> /// <param name="s"></param> public void SetTRS(Vector3d pos, Quaterniond q, Vector3d s) { this = TRS(pos, q, s); }
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> /// Build a rotation matrix from the specified quaternion. /// </summary> /// <param name="q">Quaternion to translate.</param> /// <param name="result">Matrix result.</param> public static void CreateFromQuaternion(ref Quaterniond q, out Matrix3d result) { q.ToAxisAngle(out Vector3d axis, out double angle); CreateFromAxisAngle(axis, angle, out result); }
/// <summary> /// /// </summary> /// <param name="point"></param> /// <param name="capacity"></param> /// <param name="weight"></param> public OnRotation(int index, Quaterniond rotation, double weight = 1.0) { _handle.Index = index; _rotation = rotation; Weight = weight; }
public void InitializePlanets() { //GravityIndicator = Helper.CreateCube(MScene.AstroRoot, "GravitySphere", Vector3d.Zero); //GravityIndicator.transform.Scale = new Vector3d(0.05, 0.1, 0.1); //GravityIndicator.OwnerID = "MasterAstronomer"; //MScene.AstroRoot.Add(GravityIndicator); //GravityIndicator.SetMaterial((MMaterial)MScene.MaterialRoot.FindModuleByName(MMaterial.DEFAULT_MATERIAL)); CreateShaders(); for (int i = 0; i < Bodies.Count; i++) { MAstroBody m = Bodies[i]; //m.Radius = m.Radius * 0.5; if (m.IsTemplate == true) { continue; } m.ListIndex = i; Vector3d pos = m.Position + new Vector3d(-m.Radius.X, 0, 0) * (m.HasRings == true ? 3.0 : 1.1); MServerZone zone = new MServerZone("MASTER_ASTRONOMER", m.Name, "Astronomical", MassiveTools.ToVector3_Server(pos)); zone.Rotation = MassiveTools.ArrayFromQuaterniond(Quaterniond.Identity); zone.Description = m.Description + " \nRadius:" + m.Radius; MMessageBus.AddZone(this, zone); //Extensions.LookAt(m.Position + m.Radius * 2, m.Position), m.Name)); MSceneObject mo; //planet files contain uvs for mercator if (m.HasAtmosphere) { CurrentNear = m; mo = Helper.CreateModel(MScene.AstroRoot, m.Name, @"Models\planets\earth.3ds", Vector3d.Zero); //mo = Helper.CreateSphere(MScene.AstroRoot, 3, "Planet"); //mo.transform.Scale = m.Radius * 1.00055; mo.transform.Scale = m.Radius; } else { mo = Helper.CreateModel(MScene.AstroRoot, m.Name, @"Models\planets\planet_sphere2.3ds", Vector3d.Zero); mo.transform.Scale = m.Radius; } if (m.HasRings) { MModel ring = Helper.CreateModel(MScene.Priority2, m.Name + "_rings", @"Models\planets\planet_rings.3ds", Vector3d.Zero); ring.transform.Position = m.Position; ring.transform.Rotation = Quaterniond.FromEulerAngles(0, 0, 5 * Math.PI / 180); ring.transform.Scale = m.Radius; ring.InstanceID = m.Name; ring.TemplateID = m.Name; ring.DistanceThreshold = m.Radius.X * 12; ring.OwnerID = "MasterAstronomer"; MMaterial ringmat = new MMaterial(m.Name + "_mat"); ringmat.AddShader((MShader)MScene.MaterialRoot.FindModuleByName(MShader.DEFAULT_SHADER)); MTexture ringtex = Globals.TexturePool.GetTexture(@"Textures\Planets\saturn_rings.png"); ringmat.SetDiffuseTexture(ringtex); ring.SetMaterial(ringmat); MPhysicsObject ringpo = new MPhysicsObject(ring, "Physics", 0, MPhysicsObject.EShape.ConcaveMesh, false, m.Radius); ringpo.SetLinearFactor(0, 0, 0); ringpo.SetRestitution(0.5); } mo.transform.Position = m.Position; //mo.transform.Scale = m.Radius * 1.9999; mo.InstanceID = m.Name; mo.TemplateID = m.Name; mo.OwnerID = "MasterAstronomer"; mo.DistanceThreshold = m.Radius.X * 110002; //distance at which it becomes visible //MModel mod = (MModel)mo.FindModuleByType(EType.Model); //mod.DistanceThreshold = mo.DistanceThreshold; //MMesh met = (MMesh)mod.FindModuleByType(EType.Mesh); //if ( met != null ) { //met.DistanceThreshold = mo.DistanceThreshold; //} mo.Tag = m; m.Tag = mo; //now that we have a 3d model, apply some progressive textures (will auto-switch with smooth transition in shader) MMaterial mat = new MMaterial(m.Name + "_mat"); mat.AddShader((MShader)MScene.MaterialRoot.FindModuleByName(MShader.DEFAULT_SHADER)); MTexture tex = Globals.TexturePool.GetTexture(m.TextureName); mat.SetDiffuseTexture(tex); mo.SetMaterial(mat); MTexture tex2 = Globals.TexturePool.GetTexture("Textures\\terrain\\sand01b.jpg"); mat.SetMultiTexture(tex2); MTexture tex3 = Globals.TexturePool.GetTexture("Textures\\terrain\\water.jpg"); mat.SetNormalMap(tex3); double dia = 2.0 * Math.PI * m.Radius.X * 0.0000001; //double dia = 1; mat.Tex2CoordScale = new Vector2((float)dia, (float)dia); mo.SetMaterial(mat); MScene.MaterialRoot.Add(mat); if (m.HasAtmosphere) { if (Settings.DrawTerrains == true) { m.AddDynamicTerrain(); //adds tile based terrain (from e.g. tile service) } //MPhysicsObject po = new MPhysicsObject(mo, "Physics", 0, MPhysicsObject.EShape.ConcaveMesh, //false, m.Radius); MPhysicsObject po = new MPhysicsObject(mo, "Physics", 0, MPhysicsObject.EShape.Sphere, false, m.Radius); //po.SetLinearFactor(0, 0, 0); //po.SetRestitution(0.5); //MSphere moc = Helper.CreateSphere(MScene.AstroRoot, 3, m.Name+ "Clouds", Vector3d.Zero); MModel moc = Helper.CreateModel(MScene.AstroRoot, m.Name + "_clouds", @"Models\planets\clouds.3ds", Vector3d.Zero); moc.CastsShadow = false; moc.transform.Position = m.Position; moc.transform.Scale = m.Radius; moc.DistanceThreshold = m.Radius.X * 3; //moc.transform.Scale = m.Radius*2.1; moc.InstanceID = m.Name; moc.TemplateID = m.Name; moc.OwnerID = "MasterAstronomer"; moc.Tag = m; MMaterial cmat = new MMaterial("CloudMat"); cmat.AddShader((MShader)MScene.MaterialRoot.FindModuleByName(MShader.DEFAULT_SHADER)); cmat.Opacity = 1; cmat.IsSky = 1; // = new MTexture("CloudTex"); MTexture ctex = Globals.TexturePool.GetTexture(CloudTexURL); ctex.Additive = false; cmat.SetDiffuseTexture(ctex); moc.SetMaterial(cmat); MScene.MaterialRoot.Add(cmat); MModel sky = Helper.CreateModel(MScene.AstroRoot, m.Name + "_sky", @"Models\sky.3ds", Vector3d.Zero); sky.CastsShadow = false; sky.transform.Position = m.Position; sky.transform.Scale = m.Radius; //moc.transform.Scale = m.Radius*2.1; sky.InstanceID = m.Name; sky.TemplateID = m.Name; sky.OwnerID = "MasterAstronomer"; sky.Tag = m; sky.SetMaterial(cmat); sky.DistanceThreshold = m.Radius.X * 4; MObjectAnimation ani = new MObjectAnimation(); ani.AngleOffset = Quaterniond.FromEulerAngles(0, 0.002, 0); ani.Speed = 1; sky.Add(ani); sky.SetMaterial(MSkyMaterial); /*MMaterial csky = new MMaterial("Skymat"); * csky.AddShader((MShader)MScene.MaterialRoot.FindModuleByName(MShader.DEFAULT_SHADER)); * csky.Opacity = 0.5; * csky.IsSky = 1; * // = new MTexture("CloudTex"); * MTexture cSkyTex = Globals.TexturePool.GetTexture(OpaqueCloudTexURL); * cSkyTex.Additive = false; * csky.SetDiffuseTexture(cSkyTex); * sky.SetMaterial(csky); * MScene.MaterialRoot.Add(csky); */ /* MSphere water = Helper.CreateSphere(MScene.ModelRoot, 5, "Water"); * water.transform.Position = m.Position; * water.transform.Scale = m.Radius * 2.00; * MMaterial waterman = new MMaterial("Watermat"); * MShader shader = new MShader("watershader"); * shader.Load("ocean_vs.glsl", "ocean_fs.glsl"); * shader.Bind(); * shader.SetInt("diffuseTexture", 0); * shader.SetInt("shadowMap", 1); * waterman.AddShader(shader); * water.SetMaterial(waterman); */ //water.SetMaterial((MMaterial)MScene.MaterialRoot.FindModuleByName(MMaterial.DEFAULT_MATERIAL)); } else { MPhysicsObject po = new MPhysicsObject(mo, "Physics", 0, MPhysicsObject.EShape.Sphere, false, m.Radius * 0.999); po.SetLinearFactor(0, 0, 0); po.SetRestitution(0.5); } m.Setup(); //Console.WriteLine("Created:" + mo.Name + ":" + (mo.transform.Position) + " R:" + m.Radius); } }
/// <inheritdoc /> public void Calculate(IReadOnlyList <IBody> bodies) { _handle.AngleDelta = Quaterniond.CreateFromTo(bodies[_handle].Rotation, _rotation).ToAxisAngle(); }
public static MSceneObject LoadTemplate(string TemplateID) { MBuildingBlock bb = MBuildParts.GetBlock(TemplateID); if (bb == null) { Console.WriteLine("WARNING: MSpawnHandler.LoadTemplate " + TemplateID + " not found in blocks"); return(null); } MSceneObject o = null; if (bb.Type == MBuildParts.MAnimatedModel) { o = Helper.CreateAnimatedModel(MScene.TemplateRoot, TemplateID, bb.Model, Vector3d.Zero); MAnimatedModel man = (MAnimatedModel)o; man.BoneOffset = MassiveTools.VectorFromArray(bb.BoneOffset); } if (bb.Type == MBuildParts.MModel) { o = Helper.CreateModel(MScene.TemplateRoot, TemplateID, bb.Model, Vector3d.Zero); } MMaterial mat = (MMaterial)MScene.MaterialRoot.FindModuleByName(bb.MaterialID); if (mat == null) { Console.WriteLine("MSpawnHandler.LoadTemplate " + bb.MaterialID + " was null"); } o.SetMaterial(mat); Vector3d size = MassiveTools.VectorFromArray(bb.Size); MPhysicsObject.EShape shape = GetShape(bb.PhysicsShape); if (shape != MPhysicsObject.EShape.NULL) { MPhysicsObject mpo = new MPhysicsObject(o, TemplateID + "_physics", bb.Weight, shape, true, size); mpo.SetSleep(5); mpo.SetFriction(0); if (shape != MPhysicsObject.EShape.Sphere) { mpo.SetAngularFactor(0.0, 0.0, 0.0); mpo.SetDamping(0.1, 0.1); mpo.SetRestitution(0.5); } else { mpo.SetDamping(0.1, 0.1); mpo.SetRestitution(0.8); } } o.TemplateID = TemplateID; o.InstanceID = TemplateID; o.IsTransparent = bb.IsTransparent; o.transform.RotationOffset = Quaterniond.FromEulerAngles(MassiveTools.VectorFromArray(bb.RotationOffset)); o.Setup(); AddSubmodules(bb, o); return(o); }
public void loadModelMatrix(Entity entity, float dt, bool isShadowPass) { EntityPlayer entityPlayer = capi.World.Player.Entity; Mat4f.Identity(ModelMat); Mat4f.Translate(ModelMat, ModelMat, (float)(entity.Pos.X - entityPlayer.CameraPos.X), (float)(entity.Pos.Y - entityPlayer.CameraPos.Y), (float)(entity.Pos.Z - entityPlayer.CameraPos.Z)); float rotX = entity.Properties.Client.Shape != null ? entity.Properties.Client.Shape.rotateX : 0; float rotY = entity.Properties.Client.Shape != null ? entity.Properties.Client.Shape.rotateY : 0; float rotZ = entity.Properties.Client.Shape != null ? entity.Properties.Client.Shape.rotateZ : 0; Mat4f.Translate(ModelMat, ModelMat, 0, entity.CollisionBox.Y2 / 2, 0); // Some weird quick random hack to make creatures rotate their bodies up/down when stepping up stuff or falling down if (eagent != null && !entity.Properties.CanClimbAnywhere && !isShadowPass) { if (entity.Properties.Habitat != EnumHabitat.Air && entity.Alive) { if (entity.ServerPos.Y > entity.Pos.Y + 0.04 && !eagent.Controls.IsClimbing && !entity.FeetInLiquid && !entity.Swimming) { stepPitch = Math.Max(-0.5, stepPitch - 3 * dt); } else { if (stepPitch < 0) { stepPitch = Math.Min(0, stepPitch + 3 * dt); } else { if (!entity.OnGround && !entity.FeetInLiquid && !entity.Swimming) { stepPitch = Math.Min(0.5, stepPitch + 4.5f * dt); } else { stepPitch = Math.Max(0, stepPitch - 3 * dt); } } } } else { stepPitch = GameMath.Clamp(entity.Pos.Y - entity.ServerPos.Y + 0.1, 0, 0.3) - GameMath.Clamp(entity.ServerPos.Y - entity.Pos.Y - 0.1, 0, 0.3); } } double[] quat = Quaterniond.Create(); float bodyPitch = entity is EntityPlayer ? 0 : entity.Pos.Pitch; float yaw = entity.Pos.Yaw + (rotY + 90) * GameMath.DEG2RAD; BlockFacing climbonfacing = entity.ClimbingOnFace; // To fix climbing locust rotation weirdnes on east and west faces. Brute forced fix. There's probably a correct solution to this. bool fuglyHack = (entity as EntityAgent)?.Controls.IsClimbing == true && entity.ClimbingOnFace?.Axis == EnumAxis.X; Quaterniond.RotateX(quat, quat, bodyPitch + rotX * GameMath.DEG2RAD + (fuglyHack ? yaw : 0)); Quaterniond.RotateY(quat, quat, fuglyHack ? 0 : yaw); Quaterniond.RotateZ(quat, quat, entity.Pos.Roll + stepPitch + rotZ * GameMath.DEG2RAD + (fuglyHack ? GameMath.PIHALF * (climbonfacing == BlockFacing.WEST ? -1 : 1) : 0)); float[] qf = new float[quat.Length]; for (int i = 0; i < quat.Length; i++) { qf[i] = (float)quat[i]; } Mat4f.Mul(ModelMat, ModelMat, Mat4f.FromQuat(Mat4f.Create(), qf)); float scale = entity.Properties.Client.Size; Mat4f.Scale(ModelMat, ModelMat, new float[] { scale, scale, scale }); Mat4f.Translate(ModelMat, ModelMat, -0.5f, -entity.CollisionBox.Y2 / 2, -0.5f); }
/// <summary> /// Performs a kinematic move. /// </summary> /// <remarks>The move must be small in order to make physics to function correctly.</remarks> /// <param name="deltaOrientation">The delta orientation.</param> /// <param name="deltaPosition">The delta (move) position.</param> public void KinematicMove(Vector3d deltaPosition, Quaterniond deltaOrientation) { }
/// <summary> /// /// </summary> /// <param name="i0"></param> /// <param name="i1"></param> /// <param name="p0"></param> /// <param name="r0"></param> /// <param name="p1"></param> /// <param name="r1"></param> /// <param name="weight"></param> public RelativeOrientation(int i0, int i1, Vec3d p0, Quaterniond r0, Vec3d p1, Quaterniond r1, double weight = 1.0) : this(i0, i1) { Set(p0, r0, p1, r1); }
public static bool operator ==(Quaterniond lhs, Quaterniond rhs) { return(Quaterniond.Dot(lhs, rhs) > 0.999999f); }
public static Quaternion GetQuaternion(Quaterniond quaterniond) { return(new Quaternion((float)quaterniond.x, (float)quaterniond.y, (float)quaterniond.z, (float)quaterniond.w)); }
/// <summary> /// Creates a new quaternion from a vector representing an axis, and an angle around this axis. /// </summary> /// <param name="axis">The vector axis around which to turn.</param> /// <param name="angle">The angle to turn.</param> public Quaternion(Vector3 axis, double angle) : this() { OpenTKEquivalent = Quaterniond.FromAxisAngle(axis.OpenTKEquivalent, angle); }
/// <summary> /// /// </summary> /// <param name="index"></param> /// <param name="target"></param> /// <param name="weight"></param> public OnRotation(int index, Quaterniond target, double weight = 1.0) { _index = index; _target = target; Weight = weight; }
internal Quaternion(Quaterniond openTKEquivalent) : this() { OpenTKEquivalent = openTKEquivalent; }
// Conjugation // (Vector rotation, alternate long way) public static Vector3d Conjugate(Quaterniond q, Vector3d v) { // NOTE: q assumed to be normalized! // Treating v as imaginary part of quaternion Vq, Vnew = q * Vq * q-1 Quaterniond Vq = new Quaterniond(v); return (q * Vq * q.Conjugated).VectorPart; }