internal HitTestResultBehavior RaiseCallback(HitTestResultCallback resultCallback, HitTestFilterCallback filterCallback, HitTestResultBehavior lastResult, double distanceAdjustment) { results.Sort(RayHitTestResult.CompareByDistanceToRayOrigin); for (int i = 0, count = results.Count; i < count; i++) { RayHitTestResult result = results[i]; result.SetDistanceToRayOrigin(result.DistanceToRayOrigin + distanceAdjustment); Viewport2DVisual3D viewport2DVisual3D = result.VisualHit as Viewport2DVisual3D; if (viewport2DVisual3D != null) { Point intersectionPoint; Visual viewport2DVisual3DChild = viewport2DVisual3D.Visual; if (viewport2DVisual3DChild != null) { if (Viewport2DVisual3D.GetIntersectionInfo(result, out intersectionPoint)) { // convert the resulting point to visual coordinates Point visualPoint = Viewport2DVisual3D.TextureCoordsToVisualCoords(intersectionPoint, viewport2DVisual3DChild); GeneralTransform gt = viewport2DVisual3DChild.TransformToOuterSpace().Inverse; Point pointOnChild; if (gt != null && gt.TryTransform(visualPoint, out pointOnChild)) { HitTestResultBehavior behavior2D = viewport2DVisual3DChild.HitTestPoint(filterCallback, resultCallback, new PointHitTestParameters(pointOnChild)); if (behavior2D == HitTestResultBehavior.Stop) { return(HitTestResultBehavior.Stop); } } } } } HitTestResultBehavior behavior = resultCallback(results[i]); if (behavior == HitTestResultBehavior.Stop) { return(HitTestResultBehavior.Stop); } } return(lastResult); }
/// <summary> /// Returns true and the intersection point for the given rayHitResult if there is an intersection, /// and false otherwise. /// </summary> /// <param name="rayHitResult"></param> /// <param name="outputPoint">The output point if there was an intersection</param> /// <returns> /// Returns the point of intersection in outputPoint if there is one, and returns true /// to indicate this. /// </returns> internal static bool GetIntersectionInfo(RayHitTestResult rayHitResult, out Point outputPoint) { bool success = false; outputPoint = new Point(); // try to cast to a RaymeshGeometry3DHitTestResult RayMeshGeometry3DHitTestResult rayMeshResult = rayHitResult as RayMeshGeometry3DHitTestResult; if (rayMeshResult != null) { // we can now extract the mesh and visual for the object we hit MeshGeometry3D geom = rayMeshResult.MeshHit; // pull the barycentric coordinates of the intersection point double vertexWeight1 = rayMeshResult.VertexWeight1; double vertexWeight2 = rayMeshResult.VertexWeight2; double vertexWeight3 = rayMeshResult.VertexWeight3; // the indices in to where the actual intersection occurred int index1 = rayMeshResult.VertexIndex1; int index2 = rayMeshResult.VertexIndex2; int index3 = rayMeshResult.VertexIndex3; PointCollection textureCoordinates = geom.TextureCoordinates; // texture coordinates of the three vertices hit // in the case that no texture coordinates are supplied we will simply // treat it as if no intersection occurred if (textureCoordinates != null && index1 < textureCoordinates.Count && index2 < textureCoordinates.Count && index3 < textureCoordinates.Count) { Point texCoord1 = textureCoordinates[index1]; Point texCoord2 = textureCoordinates[index2]; Point texCoord3 = textureCoordinates[index3]; // get the final uv values based on the barycentric coordinates outputPoint = new Point(texCoord1.X * vertexWeight1 + texCoord2.X * vertexWeight2 + texCoord3.X * vertexWeight3, texCoord1.Y * vertexWeight1 + texCoord2.Y * vertexWeight2 + texCoord3.Y * vertexWeight3); success = true; } } return(success); }
internal static int CompareByDistanceToRayOrigin(RayHitTestResult x, RayHitTestResult y) { return Math.Sign(x.DistanceToRayOrigin - y.DistanceToRayOrigin); }
/// <summary> /// Returns true and the intersection point for the given rayHitResult if there is an intersection, /// and false otherwise. /// </summary> /// <param name="rayHitResult"></param> /// <param name="outputPoint">The output point if there was an intersection</param> /// <returns> /// Returns the point of intersection in outputPoint if there is one, and returns true /// to indicate this. /// </returns> internal static bool GetIntersectionInfo(RayHitTestResult rayHitResult, out Point outputPoint) { bool success = false; outputPoint = new Point(); // try to cast to a RaymeshGeometry3DHitTestResult RayMeshGeometry3DHitTestResult rayMeshResult = rayHitResult as RayMeshGeometry3DHitTestResult; if (rayMeshResult != null) { // we can now extract the mesh and visual for the object we hit MeshGeometry3D geom = rayMeshResult.MeshHit; // pull the barycentric coordinates of the intersection point double vertexWeight1 = rayMeshResult.VertexWeight1; double vertexWeight2 = rayMeshResult.VertexWeight2; double vertexWeight3 = rayMeshResult.VertexWeight3; // the indices in to where the actual intersection occurred int index1 = rayMeshResult.VertexIndex1; int index2 = rayMeshResult.VertexIndex2; int index3 = rayMeshResult.VertexIndex3; PointCollection textureCoordinates = geom.TextureCoordinates; // texture coordinates of the three vertices hit // in the case that no texture coordinates are supplied we will simply // treat it as if no intersection occurred if (textureCoordinates != null && index1 < textureCoordinates.Count && index2 < textureCoordinates.Count && index3 < textureCoordinates.Count) { Point texCoord1 = textureCoordinates[index1]; Point texCoord2 = textureCoordinates[index2]; Point texCoord3 = textureCoordinates[index3]; // get the final uv values based on the barycentric coordinates outputPoint = new Point(texCoord1.X * vertexWeight1 + texCoord2.X * vertexWeight2 + texCoord3.X * vertexWeight3, texCoord1.Y * vertexWeight1 + texCoord2.Y * vertexWeight2 + texCoord3.Y * vertexWeight3); success = true; } } return success; }
public HitTestResultBehavior resultCallback(HitTestResult result) { rayResult = result as RayHitTestResult; if (rayResult != null) { // Did we hit a MeshGeometry3D? RayMeshGeometry3DHitTestResult rayMeshResult = rayResult as RayMeshGeometry3DHitTestResult; } return HitTestResultBehavior.Stop; }
internal static int CompareByDistanceToRayOrigin(RayHitTestResult x, RayHitTestResult y) { return(Math.Sign(x.DistanceToRayOrigin - y.DistanceToRayOrigin)); }
/// <summary> /// Returns the intersection info for the given rayHitResult. Intersection info /// only exists for an InteractiveModelVisual3D, so if an InteractiveModelVisual3D /// is not hit, then the return value is null. /// </summary> /// <param name="rayHitResult"></param> /// <returns> /// Returns ClosestIntersectionInfo if an InteractiveModelVisual3D is hit, otherwise /// returns null. /// </returns> private ClosestIntersectionInfo GetIntersectionInfo(RayHitTestResult rayHitResult) { ClosestIntersectionInfo isectInfo = null; // try to cast to a RaymeshGeometry3DHitTestResult RayMeshGeometry3DHitTestResult rayMeshResult = rayHitResult as RayMeshGeometry3DHitTestResult; if (rayMeshResult != null) { // see if we hit an InteractiveVisual3D InteractiveVisual3D imv3D = rayMeshResult.VisualHit as InteractiveVisual3D; if (imv3D != null) { // we can now extract the mesh and visual for the object we hit MeshGeometry3D geom = rayMeshResult.MeshHit; UIElement uiElem = imv3D.InternalVisual; if (uiElem != null) { // pull the barycentric coordinates of the intersection point double vertexWeight1 = rayMeshResult.VertexWeight1; double vertexWeight2 = rayMeshResult.VertexWeight2; double vertexWeight3 = rayMeshResult.VertexWeight3; // the indices in to where the actual intersection occurred int index1 = rayMeshResult.VertexIndex1; int index2 = rayMeshResult.VertexIndex2; int index3 = rayMeshResult.VertexIndex3; // texture coordinates of the three vertices hit // in the case that no texture coordinates are supplied we will simply // treat it as if no intersection occurred if (geom.TextureCoordinates != null && index1 < geom.TextureCoordinates.Count && index2 < geom.TextureCoordinates.Count && index3 < geom.TextureCoordinates.Count) { Point texCoord1 = geom.TextureCoordinates[index1]; Point texCoord2 = geom.TextureCoordinates[index2]; Point texCoord3 = geom.TextureCoordinates[index3]; // get the final uv values based on the barycentric coordinates Point finalPoint = new Point(texCoord1.X * vertexWeight1 + texCoord2.X * vertexWeight2 + texCoord3.X * vertexWeight3, texCoord1.Y * vertexWeight1 + texCoord2.Y * vertexWeight2 + texCoord3.Y * vertexWeight3); // create and return a valid intersection info isectInfo = new ClosestIntersectionInfo(finalPoint, uiElem, imv3D); } } } } return isectInfo; }
private static HitTestResultBehavior ResultCallback(HitTestResult result) { rayResult = result as RayHitTestResult; return HitTestResultBehavior.Stop; // Nearest }
/// <summary> /// Perform a hit test in the 3DView. /// A negative value for the coordinates defaults to the screen centre (camera view). /// </summary> /// <param name="shapeName">The 3DView object.</param> /// <param name="x">The x coordinate in the GraphicsWindow coordinates within the 3DView.</param> /// <param name="y">The y coordinate in the GraphicsWindow coordinates within the 3DView.</param> /// <returns>An array with the hit object name and its distance or "" for no hit.</returns> public static Primitive HitTest(Primitive shapeName, Primitive x, Primitive y) { UIElement obj; try { if (_objectsMap.TryGetValue((string)shapeName, out obj)) { InvokeHelperWithReturn ret = new InvokeHelperWithReturn(delegate { try { if (obj.GetType() == typeof(Viewport3D)) { Viewport3D viewport3D = (Viewport3D)obj; ProjectionCamera camera = (ProjectionCamera)viewport3D.Camera; ModelVisual3D modelVisual3D = (ModelVisual3D)viewport3D.Children[0]; Model3DGroup model3DGroup = (Model3DGroup)modelVisual3D.Content; if (x < 0) x = viewport3D.Width / 2; if (y < 0) y = viewport3D.Height / 2; PointHitTestParameters hitParams = new PointHitTestParameters(new Point(x, y)); rayResult = null; VisualTreeHelper.HitTest(viewport3D, null, ResultCallback, hitParams); if (null != rayResult) { RayMeshGeometry3DHitTestResult rayResultMesh = rayResult as RayMeshGeometry3DHitTestResult; string result = ""; foreach (Geometry i in Geometries) { if (i.geometryModel3D == rayResultMesh.ModelHit) { result += "1=" + i.name + ";"; break; } } result += "2=" + Utilities.ArrayParse(rayResultMesh.DistanceToRayOrigin.ToString(CultureInfo.InvariantCulture)) + ";"; return result; } return ""; } } catch (Exception ex) { Utilities.OnError(Utilities.GetCurrentMethod(), ex); } return ""; }); return FastThread.InvokeWithReturn(ret).ToString(); } else { Utilities.OnShapeError(Utilities.GetCurrentMethod(), shapeName); } } catch (Exception ex) { Utilities.OnError(Utilities.GetCurrentMethod(), ex); } return ""; }