/// <summary> /// Initializes the 'turn-ball' rotation axes from the specified point. /// </summary> /// <param name="p1"> /// The point. /// </param> private void InitTurnballRotationAxes(Point p1) { double fx = p1.X / this.Viewport.ActualWidth; double fy = p1.Y / this.Viewport.ActualHeight; var up = this.Camera.UpDirection; var dir = this.Camera.LookDirection; dir.Normalize(); var right = Vector3D.Cross(dir, this.Camera.UpDirection); right.Normalize(); this.rotationAxisX = up; this.rotationAxisY = right; if (fy > 0.8 || fy < 0.2) { // delta.Y = 0; } if (fx > 0.8) { // delta.X = 0; this.rotationAxisY = dir; } if (fx < 0.2) { // delta.X = 0; this.rotationAxisY = -dir; } }
/// <summary> /// The rotate trackball. /// </summary> /// <param name="p1"> /// The previous mouse position. /// </param> /// <param name="p2"> /// The current mouse position. /// </param> /// <param name="rotateAround"> /// The point to rotate around. /// </param> private void RotateTrackball(Point p1, Point p2, Point3D rotateAround) { // http://viewport3d.com/trackball.htm // http://www.codeplex.com/3DTools/Thread/View.aspx?ThreadId=22310 var v1 = ProjectToTrackball(p1, this.Viewport.ActualWidth, this.Viewport.ActualHeight); var v2 = ProjectToTrackball(p2, this.Viewport.ActualWidth, this.Viewport.ActualHeight); // transform the trackball coordinates to view space var viewZ = this.Camera.LookDirection; var viewX = Vector3D.Cross(this.Camera.UpDirection, viewZ); var viewY = Vector3D.Cross(viewX, viewZ); viewX.Normalize(); viewY.Normalize(); viewZ.Normalize(); var u1 = (viewZ * v1.Z) + (viewX * v1.X) + (viewY * v1.Y); var u2 = (viewZ * v2.Z) + (viewX * v2.X) + (viewY * v2.Y); // Could also use the Camera ViewMatrix // var vm = Viewport3DHelper.GetViewMatrix(this.ActualCamera); // vm.Invert(); // var ct = new MatrixTransform3D(vm); // var u1 = ct.Transform(v1); // var u2 = ct.Transform(v2); // Find the rotation axis and angle var axis = Vector3D.Cross(u1, u2); if (axis.LengthSquared() < 1e-8) { return; } var angle = u1.AngleBetween(u2); // Create the transform var delta = Quaternion.RotationAxis(axis, -(float)(angle * this.RotationSensitivity * 5)); var rotate = Matrix.RotationQuaternion(delta); // Find vectors relative to the rotate-around point var relativeTarget = rotateAround - this.Camera.Target; var relativePosition = rotateAround - this.Camera.Position; // Rotate the relative vectors var newRelativeTarget = Vector3D.Transform(relativeTarget, rotate).ToVector3(); var newRelativePosition = Vector3D.Transform(relativePosition, rotate).ToVector3(); var newUpDirection = Vector3D.Transform(this.Camera.UpDirection, rotate).ToVector3(); // Find new camera position var newTarget = rotateAround - newRelativeTarget; var newPosition = rotateAround - newRelativePosition; this.Camera.LookDirection = newTarget - newPosition; if (this.CameraMode == CameraMode.Inspect) { this.Camera.Position = newPosition; } this.Camera.UpDirection = newUpDirection; }
/// <summary> /// Changes the camera position by the specified vector. /// </summary> /// <param name="delta">The translation vector in camera space (z in look direction, y in up direction, and x perpendicular to the two others)</param> /// <param name="stopOther">Stop other manipulation</param> public void MoveCameraPosition(Vector3D delta, bool stopOther = true) { if (stopOther) { this.Controller.StopSpin(); this.Controller.StopPanning(); } var z = this.Camera.CameraInternal.LookDirection; z.Normalize(); var x = Vector3D.Cross(this.Camera.CameraInternal.LookDirection, this.Camera.CameraInternal.UpDirection); var y = Vector3D.Cross(x, z); y.Normalize(); x = Vector3D.Cross(z, y); // delta *= this.ZoomSensitivity; switch (this.CameraMode) { case CameraMode.Inspect: case CameraMode.WalkAround: this.Camera.Position += (x * delta.X) + (y * delta.Y) + (z * delta.Z); break; } }
//https://stackoverflow.com/questions/18558910/direction-vector-to-rotation-matrix //Vector3 column1; //Vector3 column2; //Vector3 column3; public static Matrix3x3 makeRotationDir(Vector3 direction, Vector3 up) // Vector3 up = 0,1,0 { Matrix3x3 mat = Matrix3x3.Identity; Vector3 xaxis = Vector3.Cross(up, direction); xaxis.Normalize(); Vector3 yaxis = Vector3.Cross(direction, xaxis); yaxis.Normalize(); mat.M11 = xaxis.X; mat.M12 = yaxis.X; mat.M13 = direction.X; mat.M21 = xaxis.Y; mat.M21 = yaxis.Y; mat.M21 = direction.Y; mat.M31 = xaxis.Z; mat.M31 = yaxis.Z; mat.M31 = direction.Z; return(mat); }
/// <summary> /// Rotate around three axes. /// </summary> /// <param name="p1"> /// The previous mouse position. /// </param> /// <param name="p2"> /// The current mouse position. /// </param> /// <param name="rotateAround"> /// The point to rotate around. /// </param> public void RotateTurnball(Point p1, Point p2, Point3D rotateAround) { this.InitTurnballRotationAxes(p1); Vector2 delta = p2.ToVector2() - p1.ToVector2(); var relativeTarget = rotateAround - this.Camera.Target; var relativePosition = rotateAround - this.Camera.Position; float d = -1f; if (this.CameraMode != CameraMode.Inspect) { d = 0.2f; } d *= (float)this.RotationSensitivity; var q1 = Quaternion.RotationAxis(this.rotationAxisX, (float)(d * delta.X / 180 * Math.PI)); var q2 = Quaternion.RotationAxis(this.rotationAxisY, (float)(d * delta.Y / 180 * Math.PI)); Quaternion q = q1 * q2; var m = Matrix.RotationQuaternion(q); var newLookDir = Vector3D.Transform(this.Camera.LookDirection, m).ToVector3(); var newUpDirection = Vector3D.Transform(this.Camera.UpDirection, m).ToVector3(); var newRelativeTarget = Vector3D.Transform(relativeTarget, m).ToVector3(); var newRelativePosition = Vector3D.Transform(relativePosition, m).ToVector3(); var newRightVector = Vector3D.Cross(newLookDir, newUpDirection); newRightVector.Normalize(); var modUpDir = Vector3D.Cross(newRightVector, newLookDir); modUpDir.Normalize(); if ((newUpDirection - modUpDir).Length() > 1e-8) { newUpDirection = modUpDir; } var newTarget = rotateAround - newRelativeTarget; var newPosition = rotateAround - newRelativePosition; var newLookDirection = newTarget - newPosition; this.Camera.LookDirection = newLookDirection; if (this.CameraMode == CameraMode.Inspect) { this.Camera.Position = newPosition; } this.Camera.UpDirection = newUpDirection; }
/// <summary> /// Finds the pan vector. /// </summary> /// <param name="dx"> /// The delta x. /// </param> /// <param name="dy"> /// The delta y. /// </param> /// <returns> /// The <see cref="Vector3D"/> . /// </returns> private Vector3D FindPanVector(double dx, double dy) { var axis1 = Vector3D.Cross(this.CameraLookDirection, this.CameraUpDirection); var axis2 = Vector3D.Cross(axis1, this.CameraLookDirection); axis1.Normalize(); axis2.Normalize(); var l = this.CameraLookDirection.Length(); var f = l * 0.001f; var move = (-axis1 * f * (float)dx) + (axis2 * f * (float)dy); // this should be dependent on distance to target? return(move); }
/// <summary> /// Rotate camera using 'Turntable' rotation. /// </summary> /// <param name="delta"> /// The relative change in position. /// </param> /// <param name="rotateAround"> /// The point to rotate around. /// </param> public void RotateTurntable(Vector2 delta, Point3D rotateAround) { var relativeTarget = rotateAround - this.Camera.Target; var relativePosition = rotateAround - this.Camera.Position; var up = this.ModelUpDirection; var dir = this.Camera.LookDirection; dir.Normalize(); var right = Vector3D.Cross(dir, this.Camera.UpDirection); right.Normalize(); var d = -0.5f; if (this.CameraMode != CameraMode.Inspect) { d *= -0.2f; } d *= (float)this.RotationSensitivity; var q1 = Quaternion.RotationAxis(up, (float)(d * delta.X / 180 * Math.PI)); var q2 = Quaternion.RotationAxis(right, (float)(d * delta.Y / 180 * Math.PI)); Quaternion q = q1 * q2; var m = Matrix.RotationQuaternion(q); var newUpDirection = Vector3D.Transform(this.Camera.UpDirection, m).ToVector3(); var newRelativeTarget = Vector3D.Transform(relativeTarget, m).ToVector3(); var newRelativePosition = Vector3D.Transform(relativePosition, m).ToVector3(); var newTarget = rotateAround - newRelativeTarget; var newPosition = rotateAround - newRelativePosition; this.Camera.LookDirection = newTarget - newPosition; if (this.CameraMode == CameraMode.Inspect) { this.Camera.Position = newPosition; } this.Camera.UpDirection = newUpDirection; }
private void ProcessTranslationDrag() { if (m_activeAxis == EGizmoAxis.None) { return; } if (m_activeAxisList.Count <= 0) { return; } Ray pickRay = CreateMouseRay(in m_frameViewInfo); if (m_activeAxisList.Count > 1) { Vector3 planeNormal = Vector3.Cross(m_activeAxisList[0], m_activeAxisList[1]); Plane intersectionPlane = new Plane(m_startLocation, planeNormal); if (intersectionPlane.Intersects(ref pickRay, out Vector3 intersection)) { m_controlledTransform.SetWorldPosition(intersection - m_clickOffset); } } else { Vector3 planeTangent = Vector3.Cross(m_activeAxisList[0], m_frameViewInfo.ViewLocation - m_gizmoLocation); Vector3 planeNormal = Vector3.Cross(m_activeAxisList[0], planeTangent); Plane intersectionPlane = new Plane(m_startLocation, planeNormal); if (intersectionPlane.Intersects(ref pickRay, out Vector3 intersection)) { intersection -= m_originalPosition + m_clickOffset; m_controlledTransform.SetWorldPosition(m_originalPosition + m_activeAxisList[0] * Vector3.Dot(intersection, m_activeAxisList[0])); } } }
public void UpdateMesh() { Vector3 point = new Vector3(); //Updates Terrainmesh for (int x = 0; x < TerrainSize; x++) { for (int z = 0; z < TerrainSize; z++) { point = terrainMesh.Positions[z + (x * TerrainSize)]; point.Y = (TerrainHeights[z + x * TerrainSize] * HeightMultiplicator); terrainMesh.Positions[z + x * TerrainSize] = point; } } TerrainMeshMainGeometry3D = terrainMesh.ToMeshGeometry3D(); for (int x = 1; x < TerrainSize - 1; x++) { for (int z = 1; z < TerrainSize - 1; z++) { Vector3 neighbour0 = terrainMesh.Positions[z + (x * TerrainSize) - 1]; Vector3 neighbour1 = terrainMesh.Positions[z + (x * TerrainSize) + 1]; Vector3 neighbour2 = terrainMesh.Positions[z + (x * TerrainSize) - TerrainSize]; Vector3 neighbour3 = terrainMesh.Positions[z + (x * TerrainSize) + TerrainSize]; Vector3 vec0 = neighbour0 - neighbour1; Vector3 vec1 = neighbour2 - neighbour3; terrainMesh.Normals[z + x * TerrainSize] = Vector3.Cross(vec0, vec1); } } //Updates Bordermesh for (int z = 0; z < TerrainSize; z++) { point = borderMesh.Positions[(z * 2) + 1]; point.Y = (TerrainHeights[z] * HeightMultiplicator); borderMesh.Positions[(z * 2) + 1] = point; } for (int x = 0; x < TerrainSize; x++) { point = borderMesh.Positions[(x * 2) + 1 + (2 * TerrainSize)]; point.Y = (TerrainHeights[x * TerrainSize + TerrainSize - 1] * HeightMultiplicator); borderMesh.Positions[(x * 2) + 1 + (2 * TerrainSize)] = point; } for (int z = TerrainSize; z > 0; z--) { point = borderMesh.Positions[(z * 2) - 1 + (4 * TerrainSize)]; point.Y = (TerrainHeights[(TerrainSize * TerrainSize) - z] * HeightMultiplicator); borderMesh.Positions[(z * 2) - 1 + (4 * TerrainSize)] = point; } for (int x = TerrainSize; x > 0; x--) { point = borderMesh.Positions[(x * 2) - 1 + (6 * TerrainSize)]; point.Y = (TerrainHeights[(TerrainSize - x) * TerrainSize] * HeightMultiplicator); borderMesh.Positions[(x * 2) - 1 + (6 * TerrainSize)] = point; } TerrainMeshBorderGeometry3D = borderMesh.ToMeshGeometry3D(); }
private void ProcessLeftMouse(EButtonEvent buttonEvent) { if (buttonEvent == EButtonEvent.Pressed && m_controlledTransform != null) { if (IsHovered) { Plane axisPlane; if (m_activeAxisList.Count > 1) { Vector3 planeNormal = Vector3.Cross(m_activeAxisList[0], m_activeAxisList[1]); axisPlane = new Plane(m_gizmoLocation, planeNormal); } else { Vector3 planeNormal; if (Mode == EGizmoMode.Rotation) { // Rotation planeNormal = m_activeAxisList[0]; } else { //Translation / Scale Vector3 toCamera = m_frameViewInfo.ViewLocation - m_gizmoLocation; Vector3 planeTangent = Vector3.Cross(m_activeAxisList[0], toCamera); planeNormal = Vector3.Cross(m_activeAxisList[0], planeTangent); } axisPlane = new Plane(m_gizmoLocation, planeNormal); } World.ViewManager.GetViewInfo(out SSceneViewInfo viewInfo); Ray ray = CreateMouseRay(viewInfo); if (ray.Intersects(ref axisPlane, out Vector3 intersectionPoint)) { m_startLocation = intersectionPoint; switch (Mode) { case EGizmoMode.Translation: m_clickOffset = intersectionPoint - m_gizmoLocation; m_originalPosition = m_controlledTransform.WorldPosition; break; case EGizmoMode.Rotation: Vector3 toStart = m_startLocation - m_gizmoLocation; m_rotationDragAxis = Vector3.Cross(toStart, m_activeAxisList[0]); m_rotationDragAxis.Normalize(); m_originalRotation = m_controlledTransform.WorldRotation; break; case EGizmoMode.Scale: m_originalScale = m_controlledTransform.WorldScale; m_scaleAxis = Vector3.Zero; foreach (Vector3 axis in m_activeAxisList) { m_scaleAxis += Vector3.Transform(axis, Quaternion.Invert(m_controlledTransform.WorldRotation)); } m_scaleAxis.Normalize(); m_scaleSizeFactor = m_originalScale.Length(); break; default: throw new ArgumentOutOfRangeException(); } IsClicked = true; } } } else if (m_controlledTransform != null) { if (IsClicked) { switch (Mode) { case EGizmoMode.Translation: Vector3 newPosition = m_controlledTransform.WorldPosition; if (newPosition != m_originalPosition) { OnTranslationChanged?.Invoke(m_controlledTransform, m_originalPosition, newPosition); } break; case EGizmoMode.Rotation: Quaternion newRotation = m_controlledTransform.WorldRotation; if (newRotation != m_originalRotation) { OnRotationChanged?.Invoke(m_controlledTransform, m_originalRotation, newRotation); } break; case EGizmoMode.Scale: Vector3 newScale = m_controlledTransform.WorldScale; if (newScale != m_originalScale) { OnScaleChanged?.Invoke(m_controlledTransform, m_originalScale, newScale); } break; } } IsClicked = false; m_totalAngleDelta = 0.0f; m_totalScaleDelta = 0.0f; } }