/// <summary> /// Initializes the 'turn-ball' rotation axes from the specified point. /// </summary> /// <param name="p1"> /// The point. /// </param> private void InitTurnballRotationAxes(Vector2 p1) { double fx = p1.X / this.Viewport.ActualWidth; double fy = p1.Y / this.Viewport.ActualHeight; var up = Vector3.Normalize(Camera.CameraInternal.UpDirection); var dir = Vector3.Normalize(Camera.CameraInternal.LookDirection); var right = Vector3.Normalize(Vector3.Cross(dir, up)); 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 add rotate force. /// </summary> /// <param name="dx"> /// The delta x. /// </param> /// <param name="dy"> /// The delta y. /// </param> public void AddRotateForce(float dx, float dy) { if (!this.IsRotationEnabled) { return; } this.PushCameraSetting(); if (this.IsInertiaEnabled) { this.rotationPoint3D = this.CameraTarget; this.rotationPosition = new Vector2((float)Viewport.ActualWidth / 2, (float)Viewport.ActualHeight / 2); this.rotationSpeed.X += dx * 40; this.rotationSpeed.Y += dy * 40; } else if (FixedRotationPointEnabled) { this.rotationPosition = new Vector2((float)Viewport.ActualWidth / 2, (float)Viewport.ActualHeight / 2); this.rotateHandler.Rotate( this.rotationPosition, this.rotationPosition + new Vector2(dx, dy), FixedRotationPoint); } else { this.rotationPosition = new Vector2((float)Viewport.ActualWidth / 2, (float)Viewport.ActualHeight / 2); this.rotateHandler.Rotate( this.rotationPosition, this.rotationPosition + new Vector2(dx, dy), this.CameraTarget); } Viewport.InvalidateRender(); }
/// <summary> /// Calculates for a Point, if it is a convex Point or not /// (the assumption is, that we are dealing with a CCW Polygon orientation!) /// </summary> /// <returns>Returns true, if convex, false if concave (or "reflex" Vertex)</returns> private Boolean isConvexPoint() { // If the Point has no Next- and Last-PolygonPoint, there's an Error if (Next == null || Last == null) { throw new Exception("No closed Polygon"); } // Calculate the necessary Vectors // From-last-to-this Vector var vecFromLast = this.Point - this.Last.Point; vecFromLast.Normalize(); // "Left" Vector (pointing "inward") var vecLeft = new Point(-vecFromLast.Y, vecFromLast.X); // From-this-to-next Vector var vecToNext = this.Next.Point - this.Point; vecToNext.Normalize(); // If the next Vector is pointing to the left Vector's direction, // the current Point is a convex Point (Dot-Product bigger than 0) if ((vecLeft.X * vecToNext.X + vecLeft.Y * vecToNext.Y) >= 0) { return(true); } else { return(false); } }
/// <summary> /// Un-projects a 2D screen point. /// </summary> /// <param name="viewport">The viewport.</param> /// <param name="pointIn">The input point.</param> /// <param name="pointNear">The point at the near clipping plane.</param> /// <param name="pointFar">The point at the far clipping plane.</param> /// <returns>The ray.</returns> public static Ray UnProject(this Viewport3DX viewport, Vector2 point2d)//, out Vector3 pointNear, out Vector3 pointFar) { var camera = viewport.Camera as ProjectionCamera; if (camera != null) { var p = new Vector3((float)point2d.X, (float)point2d.Y, 1); //var wvp = GetViewProjectionMatrix(viewport); //Vector3 r = Vector3.Unproject(p, 0f, 0f, (float)viewport.ActualWidth, (float)viewport.ActualHeight, 0f, 1f, wvp); //r.Normalize(); var vp = GetScreenViewProjectionMatrix(viewport); var vpi = Matrix.Invert(vp); Vector3 zn, zf; p.Z = 0; Vector3.TransformCoordinate(ref p, ref vpi, out zn); p.Z = 1; Vector3.TransformCoordinate(ref p, ref vpi, out zf); Vector3 r = zf - zn; r.Normalize(); if (camera is PerspectiveCamera) { return(new Ray(camera.Position.ToVector3(), r)); } else if (camera is OrthographicCamera) { return(new Ray(zn, r)); } } throw new HelixToolkitException("Unproject camera error."); }
/// <summary> /// Rotates the specified p0. /// </summary> /// <param name="p0">The p0.</param> /// <param name="p1">The p1.</param> /// <param name="rotateAround">The rotate around.</param> /// <param name="stopOther">if set to <c>true</c> [stop other].</param> public void Rotate(Vector2 p0, Vector2 p1, Vector3 rotateAround, bool stopOther = true) { if (!this.Controller.IsRotationEnabled) { return; } if (stopOther) { Controller.StopZooming(); Controller.StopPanning(); } switch (this.Controller.CameraRotationMode) { case CameraRotationMode.Trackball: this.RotateTrackball(p0, p1, rotateAround); break; case CameraRotationMode.Turntable: this.RotateTurntable(p1 - p0, rotateAround); break; case CameraRotationMode.Turnball: this.RotateTurnball(p0, p1, rotateAround); break; } if (Math.Abs(this.Camera.UpDirection.Length - 1) > 1e-8) { this.Camera.UpDirection.Normalize(); } }
/// <summary> /// Starts the spin. /// </summary> /// <param name="speed"> /// The speed. /// </param> /// <param name="position"> /// The position. /// </param> /// <param name="aroundPoint"> /// The spin around point. /// </param> public void StartSpin(Vector2 speed, Point position, Vector3 aroundPoint) { this.spinningSpeed = speed; this.spinningPosition = position.ToVector2(); this.spinningPoint3D = aroundPoint; this.isSpinning = true; }
/// <summary> /// /// </summary> /// <param name="viewport"></param> /// <param name="p"></param> /// <param name="plane"></param> /// <returns></returns> public static Vector3?UnProjectOnPlane(this Viewport3DX viewport, Vector2 p, Plane plane) { var ray = UnProjectToRay(viewport, p); if (ray.Intersects(ref plane, out Vector3 hitPoint)) { return(hitPoint); } return(null); }
/// <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(Vector2 p1, Vector2 p2, Vector3 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); var cUP = Camera.CameraInternal.UpDirection; // transform the trackball coordinates to view space var viewZ = Vector3.Normalize(Camera.CameraInternal.LookDirection * Inv); var viewX = Vector3.Normalize(Vector3.Cross(cUP, viewZ) * Inv); var viewY = Vector3.Normalize(Vector3.Cross(viewX, viewZ)); 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 = Vector3.Cross(u1, u2); if (axis.LengthSquared() < 1e-8) { return; } var angle = VectorExtensions.AngleBetween(u1, u2); // Create the transform var rotate = Matrix.RotationAxis(Vector3.Normalize(axis), -angle * (float)RotationSensitivity * 5); // Find vectors relative to the rotate-around point var relativeTarget = rotateAround - this.Camera.CameraInternal.Target; var relativePosition = rotateAround - this.Camera.CameraInternal.Position; // Rotate the relative vectors var newRelativeTarget = Vector3.TransformCoordinate(relativeTarget, rotate); var newRelativePosition = Vector3.TransformCoordinate(relativePosition, rotate); var newUpDirection = Vector3.TransformCoordinate(cUP, rotate); // Find new camera position var newTarget = rotateAround - newRelativeTarget; var newPosition = rotateAround - newRelativePosition; this.Camera.LookDirection = (newTarget - newPosition).ToVector3D(); if (this.CameraMode == CameraMode.Inspect) { this.Camera.Position = newPosition.ToPoint3D(); } this.Camera.UpDirection = newUpDirection.ToVector3D(); }
/// <summary> /// Called when inertia is starting. /// </summary> /// <param name="elapsedTime"> /// The elapsed time. /// </param> protected override void OnInertiaStarting(double elapsedTime) { var delta = this.LastPoint - this.MouseDownPoint; var deltaV = new Vector2((float)delta.X, (float)delta.Y); // Debug.WriteLine("SpinInertiaStarting: " + elapsedTime + "ms " + delta.Length + "px"); this.Controller.StartSpin( 4 * deltaV * (float)(this.Controller.SpinReleaseTime / elapsedTime), this.MouseDownPoint, this.rotationPoint3D); }
/// <summary> /// /// </summary> /// <param name="viewport"></param> /// <param name="p"></param> /// <param name="plane"></param> /// <returns></returns> public static Vector3?UnProjectOnPlane(this Viewport3DX viewport, Vector2 p, Plane plane) { if (viewport.UnProject(p, out var ray)) { if (plane.Intersects(ref ray, out Vector3 point)) { return(point); } } return(null); }
/// <summary> /// The rotate. /// </summary> /// <param name="delta"> /// The delta. /// </param> public void Rotate(Vector2 delta) { var p0 = this.LastPoint.ToVector2(); var p1 = p0 + delta; if (this.MouseDownPoint3D != null) { this.Rotate(p0, p1, this.MouseDownPoint3D.Value); } this.LastPoint = new Point(p0.X, p0.Y); }
/// <summary> /// Projects a screen position to the trackball unit sphere. /// </summary> /// <param name="point"> /// The screen position. /// </param> /// <param name="w"> /// The width of the viewport. /// </param> /// <param name="h"> /// The height of the viewport. /// </param> /// <returns> /// A trackball coordinate. /// </returns> private static Vector3 ProjectToTrackball(Vector2 point, double w, double h) { // Use the diagonal for scaling, making sure that the whole client area is inside the trackball double r = Math.Sqrt((w * w) + (h * h)) / 2; double x = (point.X - (w / 2)) / r; double y = ((h / 2) - point.Y) / r; double z2 = 1 - (x * x) - (y * y); double z = z2 > 0 ? Math.Sqrt(z2) : 0; return(new Vector3((float)x, (float)y, (float)z)); }
/// <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(Vector2 p1, Vector2 p2, Vector3 rotateAround) { this.InitTurnballRotationAxes(p1); Vector2 delta = p2 - p1; var relativeTarget = rotateAround - this.Camera.CameraInternal.Target; var relativePosition = rotateAround - this.Camera.CameraInternal.Position; float d = -1; if (this.CameraMode != CameraMode.Inspect) { d = 0.2f; } d *= (float)RotationSensitivity; var q1 = Quaternion.RotationAxis(this.rotationAxisX, d * Inv * delta.X / 180 * (float)Math.PI); var q2 = Quaternion.RotationAxis(this.rotationAxisY, d * delta.Y / 180 * (float)Math.PI); Quaternion q = q1 * q2; var m = Matrix.RotationQuaternion(q); Vector3 newLookDir = Vector3.TransformNormal(this.Camera.CameraInternal.LookDirection, m); Vector3 newUpDirection = Vector3.TransformNormal(this.Camera.CameraInternal.UpDirection, m); Vector3 newRelativeTarget = Vector3.TransformCoordinate(relativeTarget, m); Vector3 newRelativePosition = Vector3.TransformCoordinate(relativePosition, m); var newRightVector = Vector3.Normalize(Vector3.Cross(newLookDir, newUpDirection)); var modUpDir = Vector3.Normalize(Vector3.Cross(newRightVector, newLookDir)); if ((newUpDirection - modUpDir).Length() > 1e-8) { newUpDirection = modUpDir; } var newTarget = rotateAround - newRelativeTarget; var newPosition = rotateAround - newRelativePosition; var newLookDirection = newTarget - newPosition; this.Camera.LookDirection = newLookDirection.ToVector3D(); if (this.CameraMode == CameraMode.Inspect) { this.Camera.Position = newPosition.ToPoint3D(); } this.Camera.UpDirection = newUpDirection.ToVector3D(); }
/// <summary> /// For a Point, last used Edge and possible Edges, retrieve the best next Edge /// </summary> /// <param name="point">The current Point</param> /// <param name="lastEdge">The last used Edge</param> /// <param name="possibleEdges">The possible next Edges</param> /// <returns>Best next Edge</returns> internal static PolygonEdge BestEdge(PolygonPoint point, PolygonEdge lastEdge, List <PolygonEdge> possibleEdges) { // If just Starting, return the first possible Edge of the Point // If only one possibility, return that if ((lastEdge.PointOne == null && lastEdge.PointTwo == null) || possibleEdges.Count == 1) { return(possibleEdges[0]); } // Variables needed to determine the next Edge var bestEdge = possibleEdges[0]; var bestAngle = (float)Math.PI * 2; // Vector from last Point to current Point var lastVector = (lastEdge.PointTwo.Point - lastEdge.PointOne.Point); lastVector.Normalize(); // Using CCW Point Order, so the left Vector always points towards the Polygon Center var insideVector = new Point(-lastVector.Y, lastVector.X); // Check all possible Edges foreach (var possibleEdge in possibleEdges) { // Next Edge Vector var edgeVector = (possibleEdge.PointTwo.Point - possibleEdge.PointOne.Point); edgeVector.Normalize(); // Dot determines if the Vector also points towards the Polygon Center or not (> 0, yes, < 0, no) var dot = insideVector.X * edgeVector.X + insideVector.Y * edgeVector.Y; // Cos represents the Angle between the last Edge and the next Edge var cos = lastVector.X * edgeVector.X + lastVector.Y * edgeVector.Y; var angle = 0f; // Depending on the Dot-Value, calculate the actual "inner" Angle if ((insideVector.X * edgeVector.X + insideVector.Y * edgeVector.Y) > 0) { angle = (float)Math.PI - (float)Math.Acos(cos); } else { angle = (float)Math.PI + (float)Math.Acos(cos); } // Replace the old Values if a better Edge was found if (angle < bestAngle) { bestAngle = angle; bestEdge = possibleEdge; } } return(bestEdge); }
/// <summary> /// Rotates the specified p0. /// </summary> /// <param name="p0">The p0.</param> /// <param name="p1">The p1.</param> /// <param name="rotateAround">The rotate around.</param> /// <param name="stopOther">if set to <c>true</c> [stop other].</param> public void Rotate(Vector2 p0, Vector2 p1, Vector3 rotateAround, bool stopOther = true) { if (!this.Controller.IsRotationEnabled) { return; } if (stopOther) { Controller.StopZooming(); Controller.StopPanning(); } p0 = Vector2.Multiply(p0, Controller.AllowRotateXY); p1 = Vector2.Multiply(p1, Controller.AllowRotateXY); Vector3 newPos = Camera.CameraInternal.Position; Vector3 newLook = Camera.CameraInternal.LookDirection; Vector3 newUp = Vector3.Normalize(Camera.CameraInternal.UpDirection); switch (this.Controller.CameraRotationMode) { case CameraRotationMode.Trackball: CameraMath.RotateTrackball(CameraMode, ref p0, ref p1, ref rotateAround, (float)RotationSensitivity, Controller.Width, Controller.Height, Camera, Inv, out newPos, out newLook, out newUp); break; case CameraRotationMode.Turntable: var p = p1 - p0; CameraMath.RotateTurntable(CameraMode, ref p, ref rotateAround, (float)RotationSensitivity, Controller.Width, Controller.Height, Camera, Inv, ModelUpDirection, out newPos, out newLook, out newUp); break; case CameraRotationMode.Turnball: CameraMath.RotateTurnball(CameraMode, ref p0, ref p1, ref rotateAround, (float)RotationSensitivity, Controller.Width, Controller.Height, Camera, Inv, out newPos, out newLook, out newUp); break; default: break; } Camera.LookDirection = newLook.ToVector3D(); Camera.Position = newPos.ToPoint3D(); Camera.UpDirection = newUp.ToVector3D(); }
/// <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, Vector3 rotateAround) { var relativeTarget = rotateAround - this.Camera.CameraInternal.Target; var relativePosition = rotateAround - this.Camera.CameraInternal.Position; var cUp = Camera.CameraInternal.UpDirection; var up = this.ModelUpDirection; var dir = Vector3.Normalize(Camera.CameraInternal.LookDirection); var right = Vector3.Normalize(Vector3.Cross(dir, cUp)); float d = -0.5f; if (this.CameraMode != CameraMode.Inspect) { d *= -0.2f; } d *= (float)this.RotationSensitivity; var q1 = Quaternion.RotationAxis(up, d * Inv * delta.X / 180 * (float)Math.PI); var q2 = Quaternion.RotationAxis(right, d * delta.Y / 180 * (float)Math.PI); Quaternion q = q1 * q2; var m = Matrix.RotationQuaternion(q); var newUpDirection = Vector3.TransformNormal(cUp, m); var newRelativeTarget = Vector3.TransformCoordinate(relativeTarget, m); var newRelativePosition = Vector3.TransformCoordinate(relativePosition, m); var newTarget = rotateAround - newRelativeTarget; var newPosition = rotateAround - newRelativePosition; this.Camera.LookDirection = (newTarget - newPosition).ToVector3D(); if (this.CameraMode == CameraMode.Inspect) { this.Camera.Position = newPosition.ToPoint3D(); } this.Camera.UpDirection = newUpDirection.ToVector3D(); }
/// <summary> /// Un-projects a 2D screen point. /// </summary> /// <param name="viewport">The viewport.</param> /// <param name="point2d">The input point.</param> /// <returns>The ray.</returns> public static Ray UnProject(this Viewport3DX viewport, Vector2 point2d)//, out Vector3 pointNear, out Vector3 pointFar) { var camera = viewport.CameraCore as ProjectionCameraCore; if (camera != null) { var px = (float)point2d.X; var py = (float)point2d.Y; var viewMatrix = camera.GetViewMatrix(); Vector3 v = new Vector3(); var matrix = MatrixExtensions.PsudoInvert(ref viewMatrix); float w = (float)viewport.ActualWidth; float h = (float)viewport.ActualHeight; var aspectRatio = w / h; var projMatrix = camera.GetProjectionMatrix(aspectRatio); Vector3 zn, zf; v.X = (2 * px / w - 1) / projMatrix.M11; v.Y = -(2 * py / h - 1) / projMatrix.M22; v.Z = 1 / projMatrix.M33; Vector3.TransformCoordinate(ref v, ref matrix, out zf); if (camera is PerspectiveCameraCore) { zn = camera.Position; } else { v.Z = 0; Vector3.TransformCoordinate(ref v, ref matrix, out zn); } Vector3 r = zf - zn; r.Normalize(); return(new Ray(zn + r * camera.NearPlaneDistance, r)); } throw new HelixToolkitException("Unproject camera error."); }
/// <summary> /// Pans the camera by the specified 2D vector (screen coordinates). /// </summary> /// <param name="delta"> /// The delta. /// </param> /// <param name="stopOther">Stop other manipulation</param> public void Pan(Vector2 delta, bool stopOther = true) { if (stopOther) { this.Controller.StopSpin(); this.Controller.StopZooming(); } var mousePoint = new Point(LastPoint.X + delta.X, LastPoint.Y + delta.Y); var thisPoint3D = this.UnProject(mousePoint, this.panPoint3D, this.Camera.CameraInternal.LookDirection); if (this.LastPoint3D == null || thisPoint3D == null) { return; } var delta3D = this.LastPoint3D.Value - thisPoint3D.Value; this.Pan(delta3D); this.LastPoint3D = this.UnProject(mousePoint, this.panPoint3D, this.Camera.CameraInternal.LookDirection); this.LastPoint = mousePoint; }
public static global::SharpDX.Color4 ToColor4(this global::SharpDX.Vector2 vector, float z = 1f, float w = 1f) { return(new global::SharpDX.Color4((float)vector.X, (float)vector.Y, z, w)); }
public static Vector3? UnProjectOnPlane(this Viewport3DX viewport, Vector2 p, Plane plane) { var ray = UnProjectToRay(viewport, p); Vector3 hitPoint; if (ray.Intersects(ref plane, out hitPoint)) { return hitPoint; } return null; }
public static Vector3? UnProjectOnPlane(this Viewport3DX viewport, Vector2 p, Vector3 position, Vector3 normal) { var plane = new Plane(position, normal); return UnProjectOnPlane(viewport, p, plane); }
public static Ray UnProjectToRay(this Viewport3DX viewport, Vector2 point2d) { var r = viewport.UnProject(point2d); return new Ray(r.Position, r.Direction); }
/// <summary> /// The on time step. /// </summary> /// <param name="ticks"> /// The time. /// </param> private void OnTimeStep(long ticks) { if (lastTick == 0) { lastTick = ticks; } var time = (float)(ticks - this.lastTick) / Stopwatch.Frequency; time = time == 0 ? 0.016f : time; // should be independent of time var factor = this.IsInertiaEnabled ? (float)Clamp(Math.Pow(this.InertiaFactor, time / 0.02f), 0.1f, 1) : 0; bool needUpdate = false; if (this.rotationSpeed.LengthSquared() > 0.1f) { this.rotateHandler.Rotate( this.rotationPosition, this.rotationPosition + (this.rotationSpeed * time), this.rotationPoint3D, false); this.rotationSpeed *= factor; needUpdate = true; this.spinningSpeed = VectorZero; } else { this.rotationSpeed = VectorZero; if (this.isSpinning && this.spinningSpeed.LengthSquared() > 0.1f) { this.rotateHandler.Rotate( this.spinningPosition, this.spinningPosition + (this.spinningSpeed * time), this.spinningPoint3D, false); if (!this.InfiniteSpin) { this.spinningSpeed *= factor; } needUpdate = true; } else { this.spinningSpeed = VectorZero; } } if (this.panSpeed.LengthSquared() > 0.0001f) { this.panHandler.Pan(this.panSpeed * time, false); this.panSpeed *= factor; needUpdate = true; } else { this.panSpeed = Vector3DZero; } if (this.moveSpeed.LengthSquared() > 0.0001f) { this.zoomHandler.MoveCameraPosition(this.moveSpeed * time, false); this.moveSpeed *= factor; needUpdate = true; } else { this.moveSpeed = Vector3DZero; } if (Math.Abs(this.zoomSpeed) > 0.001f) { this.zoomHandler.Zoom(this.zoomSpeed * time, this.zoomPoint3D, false, false); this.zoomSpeed *= factor; needUpdate = true; } else { zoomSpeed = 0; } if (ActualCamera != null && ActualCamera.OnTimeStep()) { needUpdate = true; } if (needUpdate) { lastTick = ticks; Viewport.InvalidateRender(); } else { lastTick = 0; } }
/// <summary> /// Adds a quadrilateral polygon. /// </summary> /// <param name="p0"> /// The first point. /// </param> /// <param name="p1"> /// The second point. /// </param> /// <param name="p2"> /// The third point. /// </param> /// <param name="p3"> /// The fourth point. /// </param> /// <param name="uv0"> /// The first texture coordinate. /// </param> /// <param name="uv1"> /// The second texture coordinate. /// </param> /// <param name="uv2"> /// The third texture coordinate. /// </param> /// <param name="uv3"> /// The fourth texture coordinate. /// </param> /// <remarks> /// See http://en.wikipedia.org/wiki/Quadrilateral. /// </remarks> public void AddQuad(Point3D p0, Point3D p1, Point3D p2, Point3D p3, Point uv0, Point uv1, Point uv2, Point uv3) { //// The nodes are arranged in counter-clockwise order //// p3 p2 //// +---------------+ //// | | //// | | //// +---------------+ //// p0 p1 int i0 = this.positions.Count; this.positions.Add(p0); this.positions.Add(p1); this.positions.Add(p2); this.positions.Add(p3); if (this.textureCoordinates != null) { this.textureCoordinates.Add(uv0); this.textureCoordinates.Add(uv1); this.textureCoordinates.Add(uv2); this.textureCoordinates.Add(uv3); } if (this.normals != null) { var w = Vector3D.Cross(p3 - p0, p1 - p0); w.Normalize(); this.normals.Add(w); this.normals.Add(w); this.normals.Add(w); this.normals.Add(w); } this.triangleIndices.Add(i0 + 0); this.triangleIndices.Add(i0 + 1); this.triangleIndices.Add(i0 + 2); this.triangleIndices.Add(i0 + 2); this.triangleIndices.Add(i0 + 3); this.triangleIndices.Add(i0 + 0); }
/// <summary> /// Subdivides each triangle into six triangles. Adds a vertex at the midpoint of each triangle. /// </summary> /// <remarks> /// See http://en.wikipedia.org/wiki/Barycentric_subdivision /// </remarks> private void SubdivideBarycentric() { // The BCS of a triangle S divides it into six triangles; each part has one vertex v2 at the // barycenter of S, another one v1 at the midpoint of some side, and the last one v0 at one // of the original vertices. int im = this.positions.Count; int ntri = this.triangleIndices.Count; for (int i = 0; i < ntri; i += 3) { int i0 = this.triangleIndices[i]; int i1 = this.triangleIndices[i + 1]; int i2 = this.triangleIndices[i + 2]; var p0 = this.positions[i0]; var p1 = this.positions[i1]; var p2 = this.positions[i2]; var v01 = p1 - p0; var v12 = p2 - p1; var v20 = p0 - p2; var p01 = p0 + (v01 * 0.5f); var p12 = p1 + (v12 * 0.5f); var p20 = p2 + (v20 * 0.5f); var m = new Point3D((p0.X + p1.X + p2.X) / 3, (p0.Y + p1.Y + p2.Y) / 3, (p0.Z + p1.Z + p2.Z) / 3); int i01 = im + 1; int i12 = im + 2; int i20 = im + 3; this.positions.Add(m); this.positions.Add(p01); this.positions.Add(p12); this.positions.Add(p20); if (this.normals != null) { var n = this.normals[i0]; this.normals.Add(n); this.normals.Add(n); this.normals.Add(n); this.normals.Add(n); } if (this.textureCoordinates != null) { var uv0 = this.textureCoordinates[i0]; var uv1 = this.textureCoordinates[i0 + 1]; var uv2 = this.textureCoordinates[i0 + 2]; var t01 = uv1 - uv0; var t12 = uv2 - uv1; var t20 = uv0 - uv2; var u01 = uv0 + (t01 * 0.5f); var u12 = uv1 + (t12 * 0.5f); var u20 = uv2 + (t20 * 0.5f); var uvm = new Point((uv0.X + uv1.X) * 0.5f, (uv0.Y + uv1.Y) * 0.5f); this.textureCoordinates.Add(uvm); this.textureCoordinates.Add(u01); this.textureCoordinates.Add(u12); this.textureCoordinates.Add(u20); } // TriangleIndices[i ] = i0; this.triangleIndices[i + 1] = i01; this.triangleIndices[i + 2] = im; this.triangleIndices.Add(i01); this.triangleIndices.Add(i1); this.triangleIndices.Add(im); this.triangleIndices.Add(i1); this.triangleIndices.Add(i12); this.triangleIndices.Add(im); this.triangleIndices.Add(i12); this.triangleIndices.Add(i2); this.triangleIndices.Add(im); this.triangleIndices.Add(i2); this.triangleIndices.Add(i20); this.triangleIndices.Add(im); this.triangleIndices.Add(i20); this.triangleIndices.Add(i0); this.triangleIndices.Add(im); im += 4; } }
/// <summary> /// Adds a triangle. /// </summary> /// <param name="p0"> /// The first point. /// </param> /// <param name="p1"> /// The second point. /// </param> /// <param name="p2"> /// The third point. /// </param> /// <param name="uv0"> /// The first texture coordinate. /// </param> /// <param name="uv1"> /// The second texture coordinate. /// </param> /// <param name="uv2"> /// The third texture coordinate. /// </param> public void AddTriangle(Point3D p0, Point3D p1, Point3D p2, Point uv0, Point uv1, Point uv2) { int i0 = this.positions.Count; this.positions.Add(p0); this.positions.Add(p1); this.positions.Add(p2); if (this.textureCoordinates != null) { this.textureCoordinates.Add(uv0); this.textureCoordinates.Add(uv1); this.textureCoordinates.Add(uv2); } if (this.normals != null) { var w = Vector3D.Cross(p1 - p0, p2 - p0); w.Normalize(); this.normals.Add(w); this.normals.Add(w); this.normals.Add(w); } this.triangleIndices.Add(i0 + 0); this.triangleIndices.Add(i0 + 1); this.triangleIndices.Add(i0 + 2); }
/// <summary> /// /// </summary> /// <param name="viewport"></param> /// <param name="point2d"></param> /// <returns></returns> public static Ray UnProjectToRay(this Viewport3DX viewport, Vector2 point2d) { var r = viewport.UnProject(point2d); return(new Ray(r.Position, r.Direction)); }
public static D2D.Brush ToD2DBrush(this Media.Brush brush, global::SharpDX.Vector2 renderSize, D2D.RenderTarget renderTarget) { if (brush == null) { return(null); } if (brush is Media.SolidColorBrush solid) { return(new D2D.SolidColorBrush(renderTarget, solid.Color.ToColor4())); } else if (brush is Media.LinearGradientBrush linear) { var brushProperties = new D2D.LinearGradientBrushProperties() { StartPoint = linear.StartPoint.ToVector2(), EndPoint = linear.EndPoint.ToVector2() }; if (linear.MappingMode == Media.BrushMappingMode.RelativeToBoundingBox) { Point strtPoint = new Point(linear.StartPoint.X * renderSize.X, linear.StartPoint.Y * renderSize.Y); Point endPoint = new Point(linear.EndPoint.X * renderSize.X, linear.EndPoint.Y * renderSize.Y); brushProperties.StartPoint = strtPoint.ToVector2(); brushProperties.EndPoint = endPoint.ToVector2(); } return(new D2D.LinearGradientBrush(renderTarget, brushProperties, new D2D.GradientStopCollection ( renderTarget, linear.GradientStops.Select(x => new D2D.GradientStop() { Color = x.Color.ToColor4(), Position = (float)x.Offset }).ToArray(), linear.ColorInterpolationMode.ToD2DColorInterpolationMode(), linear.SpreadMethod.ToD2DExtendMode() ) )); } #if NETFX_CORE #else else if (brush is Media.RadialGradientBrush radial) { var brushProperties = new D2D.RadialGradientBrushProperties() { Center = radial.Center.ToVector2(), GradientOriginOffset = radial.GradientOrigin.ToVector2(), RadiusX = (float)radial.RadiusX, RadiusY = (float)radial.RadiusY }; if (radial.MappingMode == Media.BrushMappingMode.RelativeToBoundingBox) { Point center = new Point(radial.Center.X * renderSize.X, radial.Center.Y * renderSize.Y); Point gradientOriginOffset = new Point((radial.GradientOrigin.X - 0.5) * renderSize.X, (radial.GradientOrigin.Y - 0.5) * renderSize.Y); brushProperties.Center = center.ToVector2(); brushProperties.GradientOriginOffset = gradientOriginOffset.ToVector2(); brushProperties.RadiusX = (float)(renderSize.X * radial.RadiusX); brushProperties.RadiusY = (float)(renderSize.Y * radial.RadiusY); } return(new D2D.RadialGradientBrush(renderTarget, brushProperties, new D2D.GradientStopCollection ( renderTarget, radial.GradientStops.Select(x => new D2D.GradientStop() { Color = x.Color.ToColor4(), Position = (float)x.Offset }).ToArray(), radial.ColorInterpolationMode.ToD2DColorInterpolationMode(), radial.SpreadMethod.ToD2DExtendMode() ))); } #endif else { throw new NotImplementedException("Brush does not support yet."); } }
/// <summary> /// Create a contour slice through a 3 vertex facet. /// </summary> /// <param name="index0">The 0th point index.</param> /// <param name="index1">The 1st point index.</param> /// <param name="index2">The 2nd point index.</param> /// <param name="newPositions">Any new positions that are created, when the contour plane slices through the vertex.</param> /// <param name="newNormals">Any new normal vectors that are created, when the contour plane slices through the vertex.</param> /// <param name="newTextureCoordinates">Any new texture coordinates that are created, when the contour plane slices through the vertex.</param> /// <param name="triangleIndices">Triangle indices for the triangle(s) above the plane.</param> public void ContourFacet( int index0, int index1, int index2, out Point3D[] newPositions, out Vector3D[] newNormals, out Point[] newTextureCoordinates, out int[] triangleIndices) { this.SetData(index0, index1, index2); var facetResult = this.GetContourFacet(); switch (facetResult) { case ContourFacetResult.ZeroOnly: triangleIndices = new[] { index0, this.positionCount++, this.positionCount++ }; break; case ContourFacetResult.OneAndTwo: triangleIndices = new[] { index1, index2, this.positionCount, this.positionCount++, this.positionCount++, index1 }; break; case ContourFacetResult.OneOnly: triangleIndices = new[] { index1, this.positionCount++, this.positionCount++ }; break; case ContourFacetResult.ZeroAndTwo: triangleIndices = new[] { index2, index0, this.positionCount, this.positionCount++, this.positionCount++, index2 }; break; case ContourFacetResult.TwoOnly: triangleIndices = new[] { index2, this.positionCount++, this.positionCount++ }; break; case ContourFacetResult.ZeroAndOne: triangleIndices = new[] { index0, index1, this.positionCount, this.positionCount++, this.positionCount++, index0 }; break; case ContourFacetResult.All: newPositions = new Point3D[0]; newNormals = new Vector3D[0]; newTextureCoordinates = new Point[0]; triangleIndices = new[] { index0, index1, index2 }; return; default: newPositions = new Point3D[0]; newNormals = new Vector3D[0]; newTextureCoordinates = new Point[0]; triangleIndices = new int[0]; return; } var facetIndices = ResultIndices[facetResult]; newPositions = new[] { this.CreateNewPosition(facetIndices[0, 0], facetIndices[0, 1]), this.CreateNewPosition(facetIndices[1, 0], facetIndices[1, 1]) }; if (this.normals != null) { newNormals = new[] { this.CreateNewNormal(facetIndices[0, 0], facetIndices[0, 1]), this.CreateNewNormal(facetIndices[1, 0], facetIndices[1, 1]) }; } else { newNormals = new Vector3D[0]; } if (this.textures != null) { newTextureCoordinates = new[] { this.CreateNewTexture(facetIndices[0, 0], facetIndices[0, 1]), this.CreateNewTexture(facetIndices[1, 0], facetIndices[1, 1]) }; } else { newTextureCoordinates = new Point[0]; } }
/// <summary> /// Adds a quadrilateral polygon. /// </summary> /// <param name="p0"> /// The first point. /// </param> /// <param name="p1"> /// The second point. /// </param> /// <param name="p2"> /// The third point. /// </param> /// <param name="p3"> /// The fourth point. /// </param> /// <remarks> /// See http://en.wikipedia.org/wiki/Quadrilateral. /// </remarks> public void AddQuad(Point3D p0, Point3D p1, Point3D p2, Point3D p3) { //// The nodes are arranged in counter-clockwise order //// p3 p2 //// +---------------+ //// | | //// | | //// +---------------+ //// p0 p1 var uv0 = new Point(0, 0); var uv1 = new Point(1, 0); var uv2 = new Point(0, 1); var uv3 = new Point(1, 1); this.AddQuad(p0, p1, p2, p3, uv0, uv1, uv2, uv3); }
/// <summary> /// Adds a triangle. /// </summary> /// <param name="p0"> /// The first point. /// </param> /// <param name="p1"> /// The second point. /// </param> /// <param name="p2"> /// The third point. /// </param> public void AddTriangle(Point3D p0, Point3D p1, Point3D p2) { var uv0 = new Point(0, 0); var uv1 = new Point(1, 0); var uv2 = new Point(0, 1); this.AddTriangle(p0, p1, p2, uv0, uv1, uv2); }
public static Windows.Foundation.Point ToPoint(this global::SharpDX.Vector2 p) { return(new Windows.Foundation.Point(p.X, p.Y)); }
/// <summary> /// Constructor using a Point /// </summary> /// <param name="p">The Point-Data to use</param> internal PolygonPoint(Point p) { // Set the Point-Data, the Index must be set later this.mPoint = p; this.mIndex = -1; }
/// <summary> /// Un-projects a 2D screen point. /// </summary> /// <param name="viewport">The viewport.</param> /// <param name="point2d">The input point.</param> /// <returns>The ray.</returns> public static Ray UnProject(this Viewport3DX viewport, Vector2 point2d) { viewport.UnProject(point2d, out var ray); return(ray); }
/// <summary> /// Adds a rectangular mesh defined by a two-dimensional arrary of points. /// </summary> /// <param name="points"> /// The points. /// </param> /// <param name="texCoords"> /// The texture coordinates (optional). /// </param> /// <param name="closed0"> /// set to <c>true</c> if the mesh is closed in the 1st dimension. /// </param> /// <param name="closed1"> /// set to <c>true</c> if the mesh is closed in the 2nd dimension. /// </param> public void AddRectangularMesh(Point3D[,] points, Point[,] texCoords = null, bool closed0 = false, bool closed1 = false) { if (points == null) { throw new ArgumentNullException("points"); } int rows = points.GetUpperBound(0) + 1; int columns = points.GetUpperBound(1) + 1; int index0 = this.positions.Count; for (int i = 0; i < rows; i++) { for (int j = 0; j < columns; j++) { this.positions.Add(points[i, j]); } } this.AddRectangularMeshTriangleIndices(index0, rows, columns, closed0, closed1); if (this.normals != null) { this.AddRectangularMeshNormals(index0, rows, columns); } if (this.textureCoordinates != null) { if (texCoords != null) { for (int i = 0; i < rows; i++) { for (int j = 0; j < columns; j++) { this.textureCoordinates.Add(texCoords[i, j]); } } } else { this.AddRectangularMeshTextureCoordinates(rows, columns); } } }
protected override bool OnHitTest(ref global::SharpDX.Vector2 mousePoint, out HitTest2DResult hitResult) { hitResult = null; return(false); }
/// <summary> /// Un-projects a 2D screen point. /// </summary> /// <param name="viewport">The viewport.</param> /// <param name="pointIn">The input point.</param> /// <param name="pointNear">The point at the near clipping plane.</param> /// <param name="pointFar">The point at the far clipping plane.</param> /// <returns>The ray.</returns> public static Ray UnProject(this Viewport3DX viewport, Vector2 point2d)//, out Vector3 pointNear, out Vector3 pointFar) { var camera = viewport.Camera as ProjectionCamera; if (camera != null) { var p = new Vector3((float)point2d.X, (float)point2d.Y, 1); //var wvp = GetViewProjectionMatrix(viewport); //Vector3 r = Vector3.Unproject(p, 0f, 0f, (float)viewport.ActualWidth, (float)viewport.ActualHeight, 0f, 1f, wvp); //r.Normalize(); var vp = GetScreenViewProjectionMatrix(viewport); var vpi = Matrix.Invert(vp); Vector3 zn, zf; p.Z = 0; Vector3.TransformCoordinate(ref p, ref vpi, out zn); p.Z = 1; Vector3.TransformCoordinate(ref p, ref vpi, out zf); Vector3 r = zf - zn; r.Normalize(); if (camera is PerspectiveCamera) { return new Ray(camera.Position.ToVector3(), r); } else if (camera is OrthographicCamera) { return new Ray(zn, r); } } throw new HelixToolkitException("Unproject camera error."); }
/// <summary> /// Adds a sphere. /// </summary> /// <param name="center"> /// The center of the sphere. /// </param> /// <param name="radius"> /// The radius of the sphere. /// </param> /// <param name="thetaDiv"> /// The number of divisions around the sphere. /// </param> /// <param name="phiDiv"> /// The number of divisions from top to bottom of the sphere. /// </param> public void AddSphere(Point3D center, double radius = 1, int thetaDiv = 32, int phiDiv = 32) { int index0 = this.positions.Count; float dt = (float)(2 * Math.PI / thetaDiv); float dp = (float)(Math.PI / phiDiv); for (int pi = 0; pi <= phiDiv; pi++) { float phi = pi * dp; for (int ti = 0; ti <= thetaDiv; ti++) { // we want to start the mesh on the x axis float theta = ti * dt; // Spherical coordinates // http://mathworld.wolfram.com/SphericalCoordinates.html //float x = (float)(Math.Cos(theta) * Math.Sin(phi)); //float y = (float)(Math.Sin(theta) * Math.Sin(phi)); //float z = (float)(Math.Cos(phi)); float x = (float)(Math.Sin(theta) * Math.Sin(phi)); float y = (float)(Math.Cos(phi)); float z = (float)(Math.Cos(theta) * Math.Sin(phi)); var p = new Point3D(center.X + ((float)radius * x), center.Y + ((float)radius * y), center.Z + ((float)radius * z)); this.positions.Add(p); if (this.normals != null) { var n = new Vector3D(x, y, z); this.normals.Add(n); } if (this.textureCoordinates != null) { var uv = new Point((float)(theta / (2 * Math.PI)), (float)(phi / Math.PI)); this.textureCoordinates.Add(uv); } } } this.AddRectangularMeshTriangleIndices(index0, phiDiv + 1, thetaDiv + 1, true); Console.WriteLine(); }
/// <summary> /// To the assimp vector2d. /// </summary> /// <param name="v">The v.</param> /// <returns></returns> public static Vector2D ToAssimpVector2D(this global::SharpDX.Vector2 v) { return(new Vector2D(v.X, v.Y)); }
/// <summary> /// /// </summary> /// <param name="viewport"></param> /// <param name="p"></param> /// <param name="position"></param> /// <param name="normal"></param> /// <returns></returns> public static Vector3?UnProjectOnPlane(this Viewport3DX viewport, Vector2 p, Vector3 position, Vector3 normal) { var plane = new Plane(position, normal); return(UnProjectOnPlane(viewport, p, plane)); }
public void AddFaceNY() { var positions = new Vector3D[] { new Vector3D(0,0,0), //p0 new Vector3D(0,0,1), //p1 new Vector3D(1,0,1), //p2 new Vector3D(1,0,0), //p3 }; var normals = new Vector3D[] { -Vector3D.UnitY, -Vector3D.UnitY, -Vector3D.UnitY, -Vector3D.UnitY, }; int i0 = this.positions.Count; var indices = new int[] { i0+0,i0+3,i0+2, i0+0,i0+2,i0+1, }; var texcoords = new Point[] { new Point(0,1), new Point(1,1), new Point(1,0), new Point(0,0), }; this.positions.AddRange(positions); this.normals.AddRange(normals); this.triangleIndices.AddRange(indices); this.textureCoordinates.AddRange(texcoords); }
/// <summary> /// Stops the spin. /// </summary> public void StopSpin() { this.isSpinning = false; this.spinningSpeed = new Vector2(); }
/// <summary> /// Adds a single node. /// </summary> /// <param name="position"> /// The position. /// </param> /// <param name="normal"> /// The normal. /// </param> /// <param name="textureCoordinate"> /// The texture coordinate. /// </param> public void AddNode(Point3D position, Vector3D normal, Point textureCoordinate) { this.positions.Add(position); if (this.normals != null) { this.normals.Add(normal); } if (this.textureCoordinates != null) { this.textureCoordinates.Add(textureCoordinate); } }