/// <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> /// 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> /// Changes the camera distance. /// </summary> /// <param name="delta">The delta.</param> /// <param name="zoomAround">The zoom around point.</param> private bool ChangeCameraDistance(ref double delta, Vector3 zoomAround) { // Handle the 'zoomAround' point var target = this.Camera.CameraInternal.Position + this.Camera.CameraInternal.LookDirection; var relativeTarget = zoomAround - target; var relativePosition = zoomAround - this.Camera.CameraInternal.Position; if (relativePosition.Length() < 1e-4) { if (delta > 0) //If Zoom out from very close distance, increase the initial relativePosition { relativePosition = Vector3.Normalize(relativePosition) / 10; } else//If Zoom in too close, stop it. { return(false); } } var f = (float)Math.Pow(2.5, delta); var newRelativePosition = relativePosition * f; var newRelativeTarget = relativeTarget * f; var newTarget = zoomAround - newRelativeTarget; var newPosition = zoomAround - newRelativePosition; var newDistance = (newPosition - zoomAround).Length(); var oldDistance = (this.Camera.CameraInternal.Position - zoomAround).Length(); if (newDistance > this.Controller.ZoomDistanceLimitFar && (oldDistance < this.Controller.ZoomDistanceLimitFar || newDistance > oldDistance)) { var ratio = (newDistance - (float)Controller.ZoomDistanceLimitFar) / newDistance; f *= 1 - ratio; newRelativePosition = relativePosition * f; newRelativeTarget = relativeTarget * f; newTarget = zoomAround - newRelativeTarget; newPosition = zoomAround - newRelativePosition; delta = Math.Log(f) / Math.Log(2.5); // return false; } if (newDistance < this.Controller.ZoomDistanceLimitNear && (oldDistance > this.Controller.ZoomDistanceLimitNear || newDistance < oldDistance)) { var ratio = ((float)Controller.ZoomDistanceLimitNear - newDistance) / newDistance; f *= (1 + ratio); newRelativePosition = relativePosition * f; newRelativeTarget = relativeTarget * f; newTarget = zoomAround - newRelativeTarget; newPosition = zoomAround - newRelativePosition; delta = Math.Log(f) / Math.Log(2.5); // return false; } var newLookDirection = newTarget - newPosition; this.Camera.LookDirection = newLookDirection.ToVector3D(); this.Camera.Position = newPosition.ToPoint3D(); return(true); }
/// <summary> /// Calculates the normal vectors. /// </summary> /// <param name="positions"> /// The positions. /// </param> /// <param name="triangleIndices"> /// The triangle indices. /// </param> /// <returns> /// Collection of normal vectors. /// </returns> public static Vector3DCollection CalculateNormals(IList <Point3D> positions, IList <int> triangleIndices) { var normals = new Vector3DCollection(positions.Count); for (int i = 0; i < positions.Count; i++) { normals.Add(new Vector3D()); } for (int i = 0; i < triangleIndices.Count; i += 3) { int index0 = triangleIndices[i]; int index1 = triangleIndices[i + 1]; int index2 = triangleIndices[i + 2]; var p0 = positions[index0]; var p1 = positions[index1]; var p2 = positions[index2]; Vector3D u = p1 - p0; Vector3D v = p2 - p0; Vector3D w = SharedFunctions.CrossProduct(ref u, ref v); w.Normalize(); normals[index0] += w; normals[index1] += w; normals[index2] += w; } for (int i = 0; i < normals.Count; i++) { var n = normals[i]; n.Normalize(); normals[i] = n; } return(normals); }
/// <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> /// Moves the camera position. /// </summary> /// <param name="camera">The camera.</param> /// <param name="delta">The delta.</param> public static void MoveCameraPosition(this Camera camera, Vector3D delta) { var z = Vector3.Normalize(camera.CameraInternal.LookDirection); var x = Vector3.Cross(z, camera.CameraInternal.UpDirection); var y = Vector3.Normalize(Vector3.Cross(x, z)); x = Vector3.Cross(z, y); // delta *= this.ZoomSensitivity; camera.Position += ((x * (float)delta.X) + (y * (float)delta.Y) + (z * (float)delta.Z)).ToVector3D(); }
/// <summary> /// Finds the pan vector. /// </summary> /// <param name="dx"> /// The delta x. /// </param> /// <param name="dy"> /// The delta y. /// </param> /// <returns> /// The <see cref="Vector3"/> . /// </returns> private Vector3 FindPanVector(float dx, float dy) { var axis1 = Vector3.Normalize(Vector3.Cross(this.CameraLookDirection, this.CameraUpDirection)); var axis2 = Vector3.Normalize(Vector3.Cross(axis1, this.CameraLookDirection)); axis1 *= (ActualCamera.CreateLeftHandSystem ? -1 : 1); var l = this.CameraLookDirection.Length(); var f = l * 0.001f; var move = (-axis1 * f * dx) + (axis2 * f * dy); // this should be dependent on distance to target? return(move); }
/// <summary> /// Zooms the camera to the specified rectangle. /// </summary> /// <param name="camera"> /// The camera. /// </param> /// <param name="viewport"> /// The viewport. /// </param> /// <param name="zoomRectangle"> /// The zoom rectangle. /// </param> public static void ZoomToRectangle(this Camera camera, Viewport3DX viewport, Rect zoomRectangle) { var topLeftRay = viewport.UnProjectToRay(zoomRectangle.TopLeft); var topRightRay = viewport.UnProjectToRay(zoomRectangle.TopRight); var centerRay = viewport.UnProjectToRay( new Point( (zoomRectangle.Left + zoomRectangle.Right) * 0.5, (zoomRectangle.Top + zoomRectangle.Bottom) * 0.5)); if (topLeftRay == null || topRightRay == null || centerRay == null) { // could not invert camera matrix return; } var u = Vector3.Normalize(topLeftRay.Direction); var v = Vector3.Normalize(topRightRay.Direction); var w = Vector3.Normalize(centerRay.Direction); if (camera is IPerspectiveCameraModel perspectiveCamera) { var distance = camera.LookDirection.Length; // option 1: change distance var newDistance = distance * zoomRectangle.Width / viewport.ActualWidth; var newLookDirection = (float)newDistance * w; var newPosition = camera.CameraInternal.Position + ((float)(distance - newDistance) * w); var newTarget = newPosition + newLookDirection; LookAt(camera, newTarget.ToPoint3D(), newLookDirection.ToVector3D(), 200); // option 2: change fov // double newFieldOfView = Math.Acos(Vector3D.DotProduct(u, v)); // var newTarget = camera.Position + distance * w; // pcamera.FieldOfView = newFieldOfView * 180 / Math.PI; // LookAt(camera, newTarget, distance * w, 0); } else if (camera is IOrthographicCameraModel orthographicCamera) { orthographicCamera.Width *= zoomRectangle.Width / viewport.ActualWidth; var oldTarget = camera.CameraInternal.Position + camera.CameraInternal.LookDirection; var distance = camera.CameraInternal.LookDirection.Length(); var newTarget = centerRay.PlaneIntersection(oldTarget, w); if (newTarget != null) { LookAt(orthographicCamera, newTarget.Value.ToPoint3D(), 200); } } }
/// <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> /// 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> /// Zooms the camera to the specified rectangle. /// </summary> /// <param name="camera"> /// The camera. /// </param> /// <param name="viewport"> /// The viewport. /// </param> /// <param name="zoomRectangle"> /// The zoom rectangle. /// </param> public static void ZoomToRectangle(this Camera camera, Viewport3DX viewport, Rect zoomRectangle) { if (viewport.UnProject(zoomRectangle.TopLeft.ToVector2(), out var topLeftRay) && viewport.UnProject(zoomRectangle.TopRight.ToVector2(), out var topRightRay) && viewport.UnProject(new global::SharpDX.Vector2( (float)(zoomRectangle.Left + zoomRectangle.Right) * 0.5f, (float)(zoomRectangle.Top + zoomRectangle.Bottom) * 0.5f), out var centerRay)) { var u = Vector3.Normalize(topLeftRay.Direction); var v = Vector3.Normalize(topRightRay.Direction); var w = Vector3.Normalize(centerRay.Direction); if (camera is IPerspectiveCameraModel perspectiveCamera) { var distance = camera.LookDirection.Length; // option 1: change distance var newDistance = distance * zoomRectangle.Width / viewport.ActualWidth; var newLookDirection = (float)newDistance * w; var newPosition = camera.CameraInternal.Position + ((float)(distance - newDistance) * w); var newTarget = newPosition + newLookDirection; LookAt(camera, newTarget.ToPoint3D(), newLookDirection.ToVector3D(), 200); // option 2: change fov // double newFieldOfView = Math.Acos(Vector3D.DotProduct(u, v)); // var newTarget = camera.Position + distance * w; // pcamera.FieldOfView = newFieldOfView * 180 / Math.PI; // LookAt(camera, newTarget, distance * w, 0); } else if (camera is IOrthographicCameraModel orthographicCamera) { orthographicCamera.Width *= zoomRectangle.Width / viewport.ActualWidth; var oldTarget = camera.CameraInternal.Position + camera.CameraInternal.LookDirection; var distance = camera.CameraInternal.LookDirection.Length(); if (centerRay.PlaneIntersection(oldTarget, w, out var newTarget)) { LookAt(orthographicCamera, newTarget.ToPoint3D(), 200); } } } }
/// <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(Vector3 delta, bool stopOther = true) { if (stopOther) { Controller.StopPanning(); Controller.StopSpin(); } var z = Vector3.Normalize(this.Camera.CameraInternal.LookDirection); var x = Vector3.Cross(this.Camera.CameraInternal.LookDirection, this.Camera.CameraInternal.UpDirection); var y = Vector3.Normalize(Vector3.Cross(x, z)); x = Vector3.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)).ToVector3D(); break; } }
private bool Flipped(ref Vector3D p, int i0, int i1, ref Vertex v0, ref Vertex v1, IList <bool> deleted) { for (int i = 0; i < v0.tCount; ++i) { var t = triangles[refs[v0.tStart + i].tid]; if (t.deleted) { continue; } int s = refs[v0.tStart + i].tvertex; int id1 = t.v[(s + 1) % 3]; int id2 = t.v[(s + 2) % 3]; if (id1 == i1 || id2 == i1) { deleted[i] = true; continue; } Vector3D d1 = vertices[id1].p - p; d1.Normalize(); Vector3D d2 = vertices[id2].p - p; d2.Normalize(); if (SharedFunctions.DotProduct(ref d1, ref d2) > 0.999) { return(true); } var n = SharedFunctions.CrossProduct(ref d1, ref d2); n.Normalize(); deleted[i] = false; if (SharedFunctions.DotProduct(ref n, ref t.normal) < 0.2) { return(true); } } return(false); }
/// <summary> /// Adds an extruded surface of the specified curve. /// </summary> /// <param name="points"> /// The 2D points describing the curve to extrude. /// </param> /// <param name="xaxis"> /// The x-axis. /// </param> /// <param name="p0"> /// The start origin of the extruded surface. /// </param> /// <param name="p1"> /// The end origin of the extruded surface. /// </param> /// <remarks> /// The y-axis is determined by the cross product between the specified x-axis and the p1-p0 vector. /// </remarks> public void AddExtrudedGeometry(IList<Point> points, Vector3D xaxis, Point3D p0, Point3D p1) { var ydirection = Vector3D.Cross(p1 - p0, xaxis); ydirection.Normalize(); xaxis.Normalize(); int index0 = this.positions.Count; int np = 2 * points.Count; foreach (var p in points) { var v = (xaxis * p.X) + (ydirection * p.Y); this.positions.Add(p0 + v); this.positions.Add(p1 + v); } int ii = 0; for (int i = 0; i < points.Count - 1; i++, ii += 2) { int i0 = index0 + ii; int i1 = i0 + 1; int i2 = i0 + 2; int i3 = i0 + 3; this.triangleIndices.Add(i1); this.triangleIndices.Add(i2); this.triangleIndices.Add(i0); this.triangleIndices.Add(i1); this.triangleIndices.Add(i3); this.triangleIndices.Add(i2); } if (this.textureCoordinates != null) { for (int i = 0; i < np; i++) { this.textureCoordinates.Add(new Point()); } } //foreach (var p in points) //{ // if (this.normals != null) // { // //this.normals.Add(Vector3D.UnitZ); // //this.normals.Add(Vector3D.UnitZ); // } // if (this.textureCoordinates != null) // { // this.textureCoordinates.Add(new Point(0, 0)); // this.textureCoordinates.Add(new Point(1, 0)); // } // int i1 = index0 + 1; // int i2 = (index0 + 2) % np; // int i3 = ((index0 + 2) % np) + 1; // this.triangleIndices.Add(i1); // this.triangleIndices.Add(i2); // this.triangleIndices.Add(index0); // this.triangleIndices.Add(i1); // this.triangleIndices.Add(i3); // this.triangleIndices.Add(i2); //} Vector3D[] normals; ComputeNormals(this.positions, this.triangleIndices, out normals); this.normals = normals.ToList(); }
/// <summary> /// Adds a surface of revolution. /// </summary> /// <param name="points"> /// The points (y coordinates are radius, x coordinates are distance from the origin along the axis of revolution) /// </param> /// <param name="origin"> /// The origin of the revolution axis. /// </param> /// <param name="direction"> /// The direction of the revolution axis. /// </param> /// <param name="thetaDiv"> /// The number of divisions around the mesh. /// </param> /// <remarks> /// See http://en.wikipedia.org/wiki/Surface_of_revolution. /// </remarks> public void AddRevolvedGeometry(IList<Point> points, Point3D origin, Vector3D direction, int thetaDiv) { direction.Normalize(); // Find two unit vectors orthogonal to the specified direction var u = direction.FindAnyPerpendicular(); var v = Vector3D.Cross(direction, u); u.Normalize(); v.Normalize(); var circle = GetCircle(thetaDiv); int index0 = this.positions.Count; int n = points.Count; int totalNodes = (points.Count - 1) * 2 * thetaDiv; int rowNodes = (points.Count - 1) * 2; for (int i = 0; i < thetaDiv; i++) { var w = (v * circle[i].X) + (u * circle[i].Y); for (int j = 0; j + 1 < n; j++) { // Add segment var q1 = origin + (direction * points[j].X) + (w * points[j].Y); var q2 = origin + (direction * points[j + 1].X) + (w * points[j + 1].Y); // todo:should not add segment if q1==q2 (corner point) // const double eps = 1e-6; // if (Point3D.Subtract(q1, q2).LengthSquared < eps) // continue; float tx = points[j + 1].X - points[j].X; float ty = points[j + 1].Y - points[j].Y; var normal = (-direction * ty) + (w * tx); normal.Normalize(); this.positions.Add(q1); this.positions.Add(q2); if (this.normals != null) { this.normals.Add(normal); this.normals.Add(normal); } if (this.textureCoordinates != null) { this.textureCoordinates.Add(new Point((float)i / (thetaDiv - 1), (float)j / (n - 1))); this.textureCoordinates.Add(new Point((float)i / (thetaDiv - 1), (float)(j + 1) / (n - 1))); } int i0 = index0 + (i * rowNodes) + (j * 2); int i1 = i0 + 1; int i2 = index0 + ((((i + 1) * rowNodes) + (j * 2)) % totalNodes); int i3 = i2 + 1; this.triangleIndices.Add(i1); this.triangleIndices.Add(i0); this.triangleIndices.Add(i2); this.triangleIndices.Add(i1); this.triangleIndices.Add(i2); this.triangleIndices.Add(i3); } } }
public static global::SharpDX.Vector3 Normalized(this global::SharpDX.Vector3 vector) { vector.Normalize(); return(vector); }