public override Task <Tuple <bool, double> > CheckPanelIntersectionAsync(bool targetLinkState, Vector3D linkDirection) { if (targetLinkState) { var ptPanel = ColliderExtensions.GetPanel(); if (ptPanel.HasValue) { if (Points.Count > 0) { var zDir = GetPanelFaceDirectionForLinkImpact(linkDirection); var retPanel = ptPanel.Value; var panelMin = retPanel.Location.ToVector3(); var panelMax = panelMin + new Vector3((float)retPanel.SizeX, (float)retPanel.SizeY, (float)retPanel.SizeZ); var panel = new Box3(panelMin, panelMax); var tt = TotalTransformation.Value; var planePoint = panelMax; var tasks = new List <Task <Tuple <bool, double> > >(); foreach (var p in Points) { var point = p; tasks.Add(Task.Run(() => { var pp = tt.Transform(point); var ray = new Ray3D(pp.ToVector3(), linkDirection.ToVector3()); if (ray.PlaneIntersection(planePoint, zDir.ToVector3(), out Vector3 intersect) && panel.Intersects(new Sphere3(intersect, 0.001f))) { var pi = intersect.ToPoint3D(); var intersectValue = Vector3D.DotProduct(pi - pp, linkDirection); return(new Tuple <bool, double>(true, intersectValue)); } else { return(new Tuple <bool, double>(false, 0.0)); } })); } return(Task.WhenAll(tasks).ContinueWith((t) => t.Result.FirstOrDefault(r => r.Item1) ?? new Tuple <bool, double>(false, 0.0))); } else { throw new ArgumentOutOfRangeException("The number of points of collider must be greater than 0!"); } } } return(Task.FromResult(new Tuple <bool, double>(false, 0.0))); }
/// <summary> /// Finds the intersection with a plane. /// </summary> /// <param name="position">The position.</param> /// <param name="normal">The normal.</param> /// <param name="ray"></param> /// <returns>The intersection point.</returns> public static Vector3?PlaneIntersection(this Ray ray, Vector3 position, Vector3 normal) { // http://paulbourke.net/geometry/planeline/ var dn = Vector3.Dot(normal, ray.Direction); if (dn == 0) { return(null); } var u = Vector3.Dot(normal, position - ray.Position) / dn; return(ray.Position + u * ray.Direction); }
protected override bool OnHitTest(IRenderMatrices context, global::SharpDX.Ray ray, ref List <HitTestResult> hits) { bool isHit = false; if (Octree != null) { isHit = Octree.HitTest(context, this, modelMatrix, ray, ref hits); #if DEBUG if (isHit) { Debug.WriteLine("Octree hit test, hit at " + hits[0].PointHit); } #endif } else { isHit = base.OnHitTest(context, ray, ref hits); } return(isHit); }
public override Tuple <bool, double> CheckPanelIntersection(bool targetLinkState, Vector3D linkDirection) { bool result = false; double intersectValue = 0.0; var zDir = new Vector3D(0.0, 0.0, 1.0); if (targetLinkState) { var ptPanel = ColliderExtensions.GetPanel(); if (ptPanel.HasValue) { var retPanel = ptPanel.Value; var panelMin = retPanel.Location.ToVector3(); var panelMax = panelMin + new Vector3((float)retPanel.SizeX, (float)retPanel.SizeY, (float)retPanel.SizeZ); var panel = new Box3(panelMin, panelMax); var tt = TotalTransformation.Value; var planePoint = panelMax; foreach (var p in Points) { var pp = tt.Transform(p); var ray = new Ray3D(pp.ToVector3(), linkDirection.ToVector3()); if (ray.PlaneIntersection(planePoint, zDir.ToVector3(), out Vector3 intersect) && panel.Intersects(new Sphere3(intersect, 0.001f))) { var pi = intersect.ToPoint3D(); result = true; intersectValue = Vector3D.DotProduct(pi - pp, linkDirection); break; } } } } return(new Tuple <bool, double>(result, intersectValue)); }
/// <summary> /// Called when [hit test]. /// </summary> /// <param name="context">The context.</param> /// <param name="totalModelMatrix">The total model matrix.</param> /// <param name="ray">The ray.</param> /// <param name="hits">The hits.</param> /// <returns></returns> protected override bool OnHitTest(IRenderMatrices context, global::SharpDX.Matrix totalModelMatrix, ref global::SharpDX.Ray ray, ref List <HitTestResult> hits) { bool isHit = false; if (octreeManager != null) { isHit = octreeManager.HitTest(context, this.WrapperSource, totalModelMatrix, ray, ref hits); #if DEBUG if (isHit) { Debug.WriteLine("Octree hit test, hit at " + hits[0].PointHit); } #endif } else { isHit = base.OnHitTest(context, totalModelMatrix, ref ray, ref hits); } return(isHit); }
public override bool HitTest(IRenderMatrices context, global::SharpDX.Ray ray, ref List <HitTestResult> hits) { return(false); }
/// <summary> /// Chamfers the specified corner (experimental code). /// </summary> /// <param name="p"> /// The corner point. /// </param> /// <param name="d"> /// The chamfer distance. /// </param> /// <param name="eps"> /// The corner search limit distance. /// </param> /// <param name="chamferPoints"> /// If this parameter is provided, the collection will be filled with the generated chamfer points. /// </param> public void ChamferCorner(Point3D p, double d, double eps = 1e-6, IList<Point3D> chamferPoints = null) { this.NoSharedVertices(); this.normals = null; this.textureCoordinates = null; var cornerNormal = this.FindCornerNormal(p, eps); var newCornerPoint = p - (cornerNormal * (float)d); int index0 = this.positions.Count; this.positions.Add(newCornerPoint); var plane = new Plane3D(newCornerPoint, cornerNormal); int ntri = this.triangleIndices.Count; for (int i = 0; i < ntri; i += 3) { int i0 = i; int i1 = i + 1; int i2 = i + 2; var p0 = this.positions[this.triangleIndices[i0]]; var p1 = this.positions[this.triangleIndices[i1]]; var p2 = this.positions[this.triangleIndices[i2]]; var d0 = (p - p0).LengthSquared(); var d1 = (p - p1).LengthSquared(); var d2 = (p - p2).LengthSquared(); var mind = Math.Min(d0, Math.Min(d1, d2)); if (mind > eps) { continue; } if (d1 < eps) { i0 = i + 1; i1 = i + 2; i2 = i; } if (d2 < eps) { i0 = i + 2; i1 = i; i2 = i + 1; } p0 = this.positions[this.triangleIndices[i0]]; p1 = this.positions[this.triangleIndices[i1]]; p2 = this.positions[this.triangleIndices[i2]]; // p0 is the corner vertex (at index i0) // find the intersections between the chamfer plane and the two edges connected to the corner var line1 = new Ray(p0, p1 - p0); var line2 = new Ray(p0, p2 - p0); Point3D p01, p02; if (!plane.Intersects(ref line1, out p01)) { continue; } if (!plane.Intersects(ref line2, out p02)) { continue; } if (chamferPoints != null) { // add the chamfered points if (!chamferPoints.Contains(p01)) { chamferPoints.Add(p01); } if (!chamferPoints.Contains(p02)) { chamferPoints.Add(p02); } } int i01 = i0; // change the original triangle to use the first chamfer point this.positions[this.triangleIndices[i01]] = p01; int i02 = this.positions.Count; this.positions.Add(p02); // add a new triangle for the other chamfer point this.triangleIndices.Add(i01); this.triangleIndices.Add(i2); this.triangleIndices.Add(i02); // add a triangle connecting the chamfer points and the new corner point this.triangleIndices.Add(index0); this.triangleIndices.Add(i01); this.triangleIndices.Add(i02); } this.NoSharedVertices(); }