/// <summary> /// /// </summary> public override bool HitTest(IRenderMatrices context, Ray rayWS, ref List <HitTestResult> hits) { if (CanHitTest(context)) { if ((this.instanceInternal != null) && (this.instanceInternal.Any())) { bool hit = false; int idx = 0; foreach (var modelMatrix in instanceInternal) { var b = this.Bounds; this.PushMatrix(modelMatrix); if (OnHitTest(context, rayWS, ref hits)) { hit = true; var lastHit = hits[hits.Count - 1]; lastHit.Tag = idx; hits[hits.Count - 1] = lastHit; } this.PopMatrix(); ++idx; } return(hit); } else { return(OnHitTest(context, rayWS, ref hits)); } } else { return(false); } }
protected override bool OnHitTest(IRenderMatrices context, Matrix totalModelMatrix, ref Ray ray, ref List <HitTestResult> hits) { if (ray.Intersects(boundsWithTransform) && ray.Intersects(boundsSphereWithTransform)) { if (BatchedGeometryOctree != null && BatchedGeometryOctree.TreeBuilt) { return(BatchedGeometryOctree.HitTest(context, WrapperSource, null, totalModelMatrix, ray, ref hits)); } else { bool isHit = false; foreach (var geo in Geometries) { if (geo.Geometry is MeshGeometry3D mesh) { isHit |= mesh.HitTest(context, geo.ModelTransform * totalModelMatrix, ref ray, ref hits, WrapperSource); } } return(isHit); } } else { return(false); } }
public override bool HitTestCurrentNodeExcludeChild(IRenderMatrices context, object model, Geometry3D geometry, Matrix modelMatrix, ref Ray rayWS, ref Ray rayModel, ref List <HitTestResult> hits, ref bool isIntersect, float hitThickness) { isIntersect = false; if (!this.treeBuilt) { return(false); } bool isHit = false; //var bound = Bound.Transform(modelMatrix);// BoundingBox.FromPoints(Bound.GetCorners().Select(x => Vector3.TransformCoordinate(x, modelMatrix)).ToArray()); var bound = Bound; var tempHits = new List <HitTestResult>(); if (rayWS.Intersects(ref bound)) { isIntersect = true; foreach (var r in this.Objects) { isHit |= r.HitTest(context, rayWS, ref tempHits); hits.AddRange(tempHits); tempHits.Clear(); } } return(isHit); }
/// <summary> /// Compute hit-testing for all children /// </summary> protected override bool OnHitTest(IRenderMatrices context, Ray ray, ref List <HitTestResult> hits) { bool hit = false; foreach (var item in this.children) { var hc = item as IHitable; if (hc != null) { var tc = item as ITransformable; if (tc != null) { tc.PushMatrix(this.modelMatrix); if (hc.HitTest(context, ray, ref hits)) { hit = true; } tc.PopMatrix(); } else { if (hc.HitTest(context, ray, ref hits)) { hit = true; } } } } return(hit); }
private bool CreateRelativeScreenModeRay(IRenderMatrices context, ref Ray ray, out Ray newRay) { var p = Vector3.TransformCoordinate(ray.Position, context.ScreenViewProjectionMatrix); var screenSpaceCore = RenderCore as ScreenSpacedMeshRenderCore; screenSpacedContext.IsPerspective = screenSpaceCore.IsPerspective; float viewportSize = screenSpaceCore.Size * screenSpaceCore.SizeScale * context.DpiScale; float offx = (float)(context.ActualWidth / 2 * (1 + screenSpaceCore.RelativeScreenLocationX) - viewportSize / 2); float offy = (float)(context.ActualHeight / 2 * (1 - screenSpaceCore.RelativeScreenLocationY) - viewportSize / 2); offx = Math.Max(0, Math.Min(offx, (int)(context.ActualWidth - viewportSize))); offy = Math.Max(0, Math.Min(offy, (int)(context.ActualHeight - viewportSize))); var px = p.X - offx; var py = p.Y - offy; if (px < 0 || py < 0 || px > viewportSize || py > viewportSize) { newRay = new Ray(); return(false); } var viewMatrix = screenSpaceCore.GlobalTransform.View; var projMatrix = screenSpaceCore.GlobalTransform.Projection; newRay = RayExtensions.UnProject(new Vector2(px, py), ref viewMatrix, ref projMatrix, screenSpaceCore.NearPlane, viewportSize, viewportSize, screenSpaceCore.IsPerspective); screenSpacedContext.ViewMatrix = viewMatrix; screenSpacedContext.ProjectionMatrix = projMatrix; screenSpacedContext.ActualWidth = screenSpacedContext.ActualHeight = viewportSize; screenSpacedContext.UpdateScreenViewProjectionMatrix(); return(true); }
protected override bool OnHitTest(IRenderMatrices context, Matrix totalModelMatrix, ref Ray ray, ref List <HitTestResult> hits) { Ray newRay = ray; bool preHit = false; switch (Mode) { case ScreenSpacedMode.RelativeScreenSpaced: preHit = CreateRelativeScreenModeRay(context, ref ray, out newRay); break; case ScreenSpacedMode.AbsolutePosition3D: preHit = CreateAbsoluteModeRay(context, ref ray, out newRay); break; } if (!preHit) { return(false); } screenSpaceHits.Clear(); if (base.OnHitTest(screenSpacedContext, totalModelMatrix, ref newRay, ref screenSpaceHits)) { if (hits == null) { hits = new List <HitTestResult>(); } hits.Clear(); hits.AddRange(screenSpaceHits); return(true); } else { return(false); } }
protected override bool OnHitTest(IRenderMatrices context, Matrix totalModelMatrix, ref Ray ray, ref List <HitTestResult> hits) { //Set hit distance to 0 so event manipulator is inside the model, hit test still works if (base.OnHitTest(context, totalModelMatrix, ref ray, ref hits)) { if (hits.Count > 0) { HitTestResult res = new HitTestResult() { Distance = int.MaxValue }; foreach (var hit in hits) { if (hit.ModelHit == cornerHandle || hit.ModelHit == edgeHandle) { if (res.Distance > hit.Distance) { res = hit; } } } res.Distance = 0; } return(true); } else { return(false); } }
protected virtual bool OnHitTest(IRenderMatrices context, Ray ray, ref List <HitTestResult> hits) { bool hit = false; foreach (var c in this.Items) { var hc = c as IHitable; if (hc != null) { var tc = c as ITransformable; if (tc != null) { tc.PushMatrix(this.modelMatrix); if (hc.HitTest(context, ray, ref hits)) { hit = true; } tc.PopMatrix(); } else { if (hc.HitTest(context, ray, ref hits)) { hit = true; } } } } if (hit) { hits = hits.OrderBy(x => Vector3.DistanceSquared(ray.Position, x.PointHit.ToVector3())).ToList(); } return(hit); }
/// <summary> /// /// </summary> public override bool HitTest(IRenderMatrices context, Ray rayWS, ref List <HitTestResult> hits) { if (CanHitTest(context) && PreHitTestOnBounds(ref rayWS)) { if (this.InstanceBuffer.HasElements) { bool hit = false; int idx = 0; foreach (var modelMatrix in InstanceBuffer.Elements) { if (OnHitTest(context, modelMatrix * TotalModelMatrixInternal, ref rayWS, ref hits)) { hit = true; var lastHit = hits[hits.Count - 1]; lastHit.Tag = idx; hits[hits.Count - 1] = lastHit; } ++idx; } return(hit); } else { return(OnHitTest(context, TotalModelMatrixInternal, ref rayWS, ref hits)); } } else { return(false); } }
/// <summary> /// Checks if the ray hits the geometry of the model. /// If there a more than one hit, result returns the hit which is nearest to the ray origin. /// </summary> /// <param name="rayWS">Hitring ray from the camera.</param> /// <param name="hits">results of the hit.</param> /// <returns>True if the ray hits one or more times.</returns> protected override bool OnHitTest(IRenderMatrices context, Ray rayWS, ref List <HitTestResult> hits) { if (geometryInternal.Octree != null) { return(geometryInternal.Octree.HitTest(context, this, ModelMatrix, rayWS, ref hits)); } else { PointGeometry3D pointGeometry3D = this.geometryInternal as PointGeometry3D; var svpm = context.ScreenViewProjectionMatrix; var smvpm = this.modelMatrix * svpm; var clickPoint4 = new Vector4(rayWS.Position + rayWS.Direction, 1); var pos4 = new Vector4(rayWS.Position, 1); // var dir3 = new Vector3(); Vector4.Transform(ref clickPoint4, ref svpm, out clickPoint4); Vector4.Transform(ref pos4, ref svpm, out pos4); //Vector3.TransformNormal(ref rayWS.Direction, ref svpm, out dir3); //dir3.Normalize(); var clickPoint = clickPoint4.ToVector3(); var result = new HitTestResult { IsValid = false, Distance = double.MaxValue }; var maxDist = this.HitTestThickness; var lastDist = double.MaxValue; var index = 0; foreach (var point in pointGeometry3D.Positions) { var p0 = Vector3.TransformCoordinate(point, smvpm); var pv = p0 - clickPoint; var dist = pv.Length(); if (dist < lastDist && dist <= maxDist) { lastDist = dist; Vector4 res; var lp0 = point; Vector3.Transform(ref lp0, ref this.modelMatrix, out res); var pvv = res.ToVector3(); result.Distance = (rayWS.Position - res.ToVector3()).Length(); result.PointHit = pvv.ToPoint3D(); result.ModelHit = this; result.IsValid = true; result.Tag = index; } index++; } if (result.IsValid) { hits.Add(result); } return(result.IsValid); } }
/// <summary> /// Initializes a new instance of the <see cref="HitTestContext"/> class. /// This calculates screen hit point automatically from metrices and world space ray. /// </summary> /// <param name="metrices">The render metrices.</param> /// <param name="rayWS">The ray in world space.</param> public HitTestContext(IRenderMatrices metrices, ref Ray rayWS) { RenderMatrices = metrices; RayWS = rayWS; if (metrices != null) { HitPointSP = metrices.Project(rayWS.Position); } }
public static Vector2 Project(this IRenderMatrices renderMatrices, Vector3 point) { renderMatrices.Update(); var matrix = renderMatrices.ScreenViewProjectionMatrix; var pointTransformed = Vector3.TransformCoordinate(point, matrix); var pt = new Vector2(pointTransformed.X, pointTransformed.Y) / renderMatrices.DpiScale; return(pt); }
public virtual bool HitTest(IRenderMatrices context, Matrix modelMatrix, ref Ray rayWS, ref List <HitTestResult> hits, object originalSource, float hitTestThickness) { if (Positions == null || Positions.Count == 0 || Indices == null || Indices.Count == 0) { return(false); } if (Octree != null) { return(Octree.HitTest(context, originalSource, this, modelMatrix, rayWS, ref hits, hitTestThickness)); } else { var result = new LineHitTestResult { IsValid = false, Distance = double.MaxValue }; var lastDist = double.MaxValue; var lineIndex = 0; foreach (var line in Lines) { var t0 = Vector3.TransformCoordinate(line.P0, modelMatrix); var t1 = Vector3.TransformCoordinate(line.P1, modelMatrix); var rayToLineDistance = LineBuilder.GetRayToLineDistance(rayWS, t0, t1, out Vector3 sp, out Vector3 tp, out float sc, out float tc); var svpm = context.ScreenViewProjectionMatrix; Vector3.TransformCoordinate(ref sp, ref svpm, out var sp3); Vector3.TransformCoordinate(ref tp, ref svpm, out var tp3); var tv2 = new Vector2(tp3.X - sp3.X, tp3.Y - sp3.Y); var dist = tv2.Length() / context.DpiScale; if (dist < lastDist && dist <= hitTestThickness) { lastDist = dist; result.PointHit = sp; result.NormalAtHit = sp - tp; // not normalized to get length result.Distance = (rayWS.Position - sp).Length(); result.RayToLineDistance = rayToLineDistance; result.ModelHit = originalSource; result.IsValid = true; result.Tag = lineIndex; // For compatibility result.LineIndex = lineIndex; result.TriangleIndices = null; // Since triangles are shader-generated result.RayHitPointScalar = sc; result.LineHitPointScalar = tc; result.Geometry = this; } lineIndex++; } if (result.IsValid) { hits.Add(result); } return(result.IsValid); } }
/// <summary> /// Initializes a new instance of the <see cref="HitTestContext"/> class. /// This calculates ray in world space automatically from metrices and hit point. /// </summary> /// <param name="metrices">The render metrices.</param> /// <param name="hitSP">Screen hit point. Pass in the hit point on viewport region directly. /// <para>Do not scale with DpiScale factor.</para></param> public HitTestContext(IRenderMatrices metrices, ref Vector2 hitSP) { RenderMatrices = metrices; HitPointSP = hitSP; if (metrices != null) { metrices.UnProject(hitSP, out var ray); RayWS = ray; } }
/// <summary> /// Hits the size of the test fixed. /// </summary> /// <param name="context">The context.</param> /// <param name="modelMatrix">The model matrix.</param> /// <param name="rayWS">The ray ws.</param> /// <param name="hits">The hits.</param> /// <param name="originalSource">The original source.</param> /// <param name="count">The count of vertices in <see cref="BillboardBase.BillboardVertices"/>.</param> /// <returns></returns> protected bool HitTestFixedSize(IRenderMatrices context, ref Matrix modelMatrix, ref Ray rayWS, ref List <HitTestResult> hits, object originalSource, int count) { var h = false; var result = new BillboardHitResult { Distance = double.MaxValue }; var visualToScreen = context.ScreenViewProjectionMatrix; var screenPoint3D = Vector3.TransformCoordinate(rayWS.Position, visualToScreen); var screenPoint = new Vector2(screenPoint3D.X, screenPoint3D.Y); if (screenPoint.X < 0 || screenPoint.Y < 0) { return(false); } for (int i = 0; i < count; ++i) { var vert = BillboardVertices[i]; var pos = vert.Position.ToVector3(); var c = Vector3.TransformCoordinate(pos, modelMatrix); var dir = c - rayWS.Position; if (Vector3.Dot(dir, rayWS.Direction) < 0) { continue; } var quad = GetScreenQuad(ref c, ref vert.OffTL, ref vert.OffTR, ref vert.OffBL, ref vert.OffBR, ref visualToScreen, context.DpiScale); if (quad.IsPointInQuad2D(ref screenPoint)) { var v = c - rayWS.Position; var dist = Vector3.Dot(rayWS.Direction, v); if (dist > result.Distance) { continue; } h = true; result.ModelHit = originalSource; result.IsValid = true; result.PointHit = rayWS.Position + rayWS.Direction * dist; result.Distance = dist; result.Geometry = this; AssignResultAdditional(result, i); Debug.WriteLine(string.Format("Hit; HitPoint:{0}; Text={1}", result.PointHit, result.TextInfo == null ? Type.ToString() : result.TextInfo.Text)); } } if (h) { hits.Add(result); } return(h); }
public override bool HitTest(IRenderMatrices context, Matrix modelMatrix, ref Ray rayWS, ref List <HitTestResult> hits, object originalSource, bool fixedSize) { if (!IsInitialized || context == null || Width == 0 || Height == 0 || (!fixedSize && !BoundingSphere.TransformBoundingSphere(modelMatrix).Intersects(ref rayWS))) { return(false); } return(fixedSize ? HitTestFixedSize(context, ref modelMatrix, ref rayWS, ref hits, originalSource, textInfo.Count) : HitTestNonFixedSize(context, ref modelMatrix, ref rayWS, ref hits, originalSource, textInfo.Count)); }
public virtual bool HitTest(IRenderMatrices context, Matrix modelMatrix, ref Ray rayWS, ref List <HitTestResult> hits, object originalSource, float hitThickness) { if (Positions == null || Positions.Count == 0) { return(false); } if (Octree != null) { return(Octree.HitTest(context, originalSource, this, modelMatrix, rayWS, ref hits, hitThickness)); } else { var svpm = context.ScreenViewProjectionMatrix; var smvpm = modelMatrix * svpm; var clickPoint3 = rayWS.Position + rayWS.Direction; Vector3.TransformCoordinate(ref clickPoint3, ref svpm, out var clickPoint); var result = new HitTestResult { IsValid = false, Distance = double.MaxValue }; var maxDist = hitThickness; var lastDist = double.MaxValue; var index = 0; foreach (var point in Positions) { var p0 = Vector3.TransformCoordinate(point, smvpm); var pv = p0 - clickPoint; var dist = pv.Length() / context.DpiScale; if (dist < lastDist && dist <= maxDist) { lastDist = dist; var lp0 = point; Vector3.TransformCoordinate(ref lp0, ref modelMatrix, out var pvv); result.Distance = (rayWS.Position - pvv).Length(); result.PointHit = pvv; result.ModelHit = originalSource; result.IsValid = true; result.Tag = index; result.Geometry = this; } index++; } if (result.IsValid) { hits.Add(result); } return(result.IsValid); } }
/// <summary> /// Checks if the ray hits the geometry of the model. /// If there a more than one hit, result returns the hit which is nearest to the ray origin. /// </summary> /// <param name="context">Render context from viewport</param> /// <param name="rayWS">Hitring ray from the camera.</param> /// <param name="hits">results of the hit.</param> /// <returns>True if the ray hits one or more times.</returns> public virtual bool HitTest(IRenderMatrices context, Ray rayWS, ref List <HitTestResult> hits) { if (CanHitTest(context)) { return(OnHitTest(context, rayWS, ref hits)); } else { return(false); } }
/// <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, Matrix totalModelMatrix, ref Ray ray, ref List <HitTestResult> hits) { if (Material is BillboardMaterialCore c) { return((Geometry as BillboardBase).HitTest(context, totalModelMatrix, ref ray, ref hits, this.WrapperSource, c.FixedSize)); } else { return(false); } }
/// <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, Matrix totalModelMatrix, ref Ray ray, ref List <HitTestResult> hits) { bool hit = false; foreach (var c in this.ItemsInternal) { if (c.HitTest(context, ray, ref hits)) { hit = true; } } return(hit); }
protected override bool OnHitTest(IRenderMatrices context, Ray rayWS, ref List <HitTestResult> hits) { var lineGeometry3D = this.geometryInternal as LineGeometry3D; var result = new LineHitTestResult { IsValid = false, Distance = double.MaxValue }; var lastDist = double.MaxValue; var lineIndex = 0; foreach (var line in lineGeometry3D.Lines) { var t0 = Vector3.TransformCoordinate(line.P0, this.ModelMatrix); var t1 = Vector3.TransformCoordinate(line.P1, this.ModelMatrix); Vector3 sp, tp; float sc, tc; var rayToLineDistance = LineBuilder.GetRayToLineDistance(rayWS, t0, t1, out sp, out tp, out sc, out tc); var svpm = context.ScreenViewProjectionMatrix; Vector4 sp4; Vector4 tp4; Vector3.Transform(ref sp, ref svpm, out sp4); Vector3.Transform(ref tp, ref svpm, out tp4); var sp3 = sp4.ToVector3(); var tp3 = tp4.ToVector3(); var tv2 = new Vector2(tp3.X - sp3.X, tp3.Y - sp3.Y); var dist = tv2.Length(); if (dist < lastDist && dist <= this.HitTestThickness) { lastDist = dist; result.PointHit = sp.ToPoint3D(); result.NormalAtHit = (sp - tp).ToVector3D(); // not normalized to get length result.Distance = (rayWS.Position - sp).Length(); result.RayToLineDistance = rayToLineDistance; result.ModelHit = this; result.IsValid = true; result.Tag = lineIndex; // For compatibility result.LineIndex = lineIndex; result.TriangleIndices = null; // Since triangles are shader-generated result.RayHitPointScalar = sc; result.LineHitPointScalar = tc; } lineIndex++; } if (result.IsValid) { hits.Add(result); } return(result.IsValid); }
public override bool HitTest(IRenderMatrices context, object model, Matrix modelMatrix, Ray rayWS, ref List <HitTestResult> hits) { if (Octree == null) { return(false); } var hit = Octree.HitTest(context, model, null, modelMatrix, rayWS, ref hits); foreach (var item in NonBoundableItems) { hit |= item.HitTest(context, rayWS, ref hits); } return(hit); }
private bool CreateAbsoluteModeRay(IRenderMatrices context, ref Ray ray, out Ray newRay) { var screenSpaceCore = RenderCore as ScreenSpacedMeshRenderCore; screenSpacedContext.IsPerspective = screenSpaceCore.IsPerspective; var viewMatrix = screenSpaceCore.GlobalTransform.View; var projMatrix = screenSpaceCore.GlobalTransform.Projection; screenSpacedContext.ViewMatrix = viewMatrix; screenSpacedContext.ProjectionMatrix = projMatrix; if (context.IsPerspective) { var point2d = Vector3.TransformCoordinate(ray.Position, context.ScreenViewProjectionMatrix); newRay = RayExtensions.UnProject(new Vector2(point2d.X, point2d.Y), ref viewMatrix, ref projMatrix, screenSpaceCore.NearPlane, context.ActualWidth, context.ActualHeight, screenSpaceCore.IsPerspective); screenSpacedContext.ActualWidth = context.ActualWidth; screenSpacedContext.ActualHeight = context.ActualHeight; screenSpacedContext.UpdateScreenViewProjectionMatrix(); return(true); } else { var p = Vector3.TransformCoordinate(ray.Position, context.ScreenViewProjectionMatrix); float viewportSize = screenSpaceCore.Size * screenSpaceCore.SizeScale * context.DpiScale; var abs = Vector3.TransformCoordinate(AbsolutePosition3D, context.ScreenViewProjectionMatrix); float offx = (float)(abs.X - viewportSize / 2); float offy = (float)(abs.Y - viewportSize / 2); var px = p.X - offx; var py = p.Y - offy; if (px < 0 || py < 0 || px > viewportSize || py > viewportSize) { newRay = new Ray(); return(false); } newRay = RayExtensions.UnProject(new Vector2(px, py), ref viewMatrix, ref projMatrix, screenSpaceCore.NearPlane, viewportSize, viewportSize, screenSpaceCore.IsPerspective); screenSpacedContext.ActualWidth = viewportSize; screenSpacedContext.ActualHeight = viewportSize; screenSpacedContext.ViewMatrix = viewMatrix; screenSpacedContext.ProjectionMatrix = projMatrix; screenSpacedContext.UpdateScreenViewProjectionMatrix(); return(true); } }
/// <summary> /// Hits the size of the test non fixed. /// </summary> /// <param name="context">The context.</param> /// <param name="modelMatrix">The model matrix.</param> /// <param name="rayWS">The ray ws.</param> /// <param name="hits">The hits.</param> /// <param name="originalSource">The original source.</param> /// <param name="count">The count of vertices in <see cref="BillboardBase.BillboardVertices"/>.</param> /// <returns></returns> protected bool HitTestNonFixedSize(IRenderMatrices context, ref Matrix modelMatrix, ref Ray rayWS, ref List <HitTestResult> hits, object originalSource, int count) { var h = false; var result = new BillboardHitResult { Distance = double.MaxValue }; var viewMatrix = context.ViewMatrix; var viewMatrixInv = viewMatrix.PsudoInvert(); for (int i = 0; i < count; ++i) { var vert = BillboardVertices[i]; var pos = vert.Position.ToVector3(); var c = Vector3.TransformCoordinate(pos, modelMatrix); var dir = c - rayWS.Position; if (Vector3.Dot(dir, rayWS.Direction) < 0) { continue; } var quad = GetHitTestQuad(ref c, ref vert.OffTL, ref vert.OffTR, ref vert.OffBL, ref vert.OffBR, ref viewMatrix, ref viewMatrixInv); if (Collision.RayIntersectsTriangle(ref rayWS, ref quad.TL, ref quad.TR, ref quad.BR, out Vector3 hitPoint) || Collision.RayIntersectsTriangle(ref rayWS, ref quad.TL, ref quad.BR, ref quad.BL, out hitPoint)) { var dist = (rayWS.Position - hitPoint).Length(); if (dist > result.Distance) { continue; } h = true; result.ModelHit = originalSource; result.IsValid = true; result.PointHit = hitPoint; result.Distance = dist; result.Geometry = this; AssignResultAdditional(result, i); Debug.WriteLine(string.Format("Hit; HitPoint:{0}; Text={1}", result.PointHit, result.TextInfo == null ? Type.ToString() : result.TextInfo.Text)); } } if (h) { hits.Add(result); } return(h); }
protected override bool OnHitTest(IRenderMatrices context, Matrix totalModelMatrix, ref Ray ray, ref List <HitTestResult> hits) { if (base.OnHitTest(context, totalModelMatrix, ref ray, ref hits)) { Debug.WriteLine("View box hit."); var hit = hits[0]; Vector3 normal = Vector3.Zero; int inv = isRightHanded ? 1 : -1; if (hit.ModelHit == ViewBoxMeshModel) { normal = -hit.NormalAtHit * inv; //Fix the normal if returned normal is reversed if (Vector3.Dot(normal, context.Camera.LookDirection) < 0) { normal *= -1; } } else if (hit.Tag is int index) { if (hit.ModelHit == EdgeModel && index < edgeInstances.Length) { Matrix transform = edgeInstances[index]; normal = -transform.TranslationVector; } else if (hit.ModelHit == CornerModel && index < cornerInstances.Length) { Matrix transform = cornerInstances[index]; normal = -transform.TranslationVector; } else { return(false); } } else { return(false); } normal.Normalize(); hit.NormalAtHit = normal; return(true); } else { return(false); } }
public override bool HitTest(IRenderMatrices context, Ray rayWS, ref List <HitTestResult> hits) { if (initialColor == null) { initialColor = this.Color; } var result = base.HitTest(context, rayWS, ref hits); // this.HitTest2D(rayWS, ref hits); var pressedMouseButtons = Viewport3DX.GetPressedMouseButtons(); if (pressedMouseButtons == 0 || pressedMouseButtons.HasFlag(MouseButtons.Left)) { this.Color = result ? Color.Red : this.initialColor.Value; } return(result); }
/// <summary> /// /// </summary> /// <param name="ray"></param> /// <param name="hits"></param> /// <returns></returns> protected override bool OnHitTest(IRenderMatrices context, Ray ray, ref List <HitTestResult> hits) { bool hit = false; foreach (var c in this.Children) { var hc = c as IHitable; if (hc != null) { if (hc.HitTest(context, ray, ref hits)) { hit = true; } } } return(hit); }
protected override bool OnHitTest(IRenderMatrices context, Matrix totalModelMatrix, ref Ray rayWS, ref List <HitTestResult> hits) { if (BoneMatrices.Length > 0 && Geometry is BoneSkinnedMeshGeometry3D skGeometry) { if (RenderCore is BoneSkinRenderCore skCore) { if (skinnedVerticesCache.Length < skGeometry.Positions.Count) { skinnedVerticesCache = new Vector3[skGeometry.Positions.Count]; } if (skCore.CopySkinnedToArray(context.RenderHost.ImmediateDeviceContext, skinnedVerticesCache) > 0) { return(skGeometry.HitTestWithSkinnedVertices(context, skinnedVerticesCache, totalModelMatrix, ref rayWS, ref hits, WrapperSource)); } } } return(base.OnHitTest(context, totalModelMatrix, ref rayWS, ref hits)); }
/// <summary> /// Un-project 2D screen point onto 3D space by camera. /// </summary> /// <param name="renderMatrices">The renderMatrices.</param> /// <param name="point2d">The point2d.</param> /// <param name="ray">The ray.</param> /// <returns></returns> public static bool UnProject(this IRenderMatrices renderMatrices, Vector2 point2d, out Ray ray)//, out Vector3 pointNear, out Vector3 pointFar) { if (renderMatrices == null) { ray = new Ray(); return(false); } renderMatrices.Update(); var px = point2d.X; var py = point2d.Y; var viewInv = renderMatrices.ViewMatrixInv; var projMatrix = renderMatrices.ProjectionMatrix; var w = renderMatrices.ActualWidth / renderMatrices.DpiScale; var h = renderMatrices.ActualHeight / renderMatrices.DpiScale; var v = new Vector3 { X = (2 * px / w - 1) / projMatrix.M11, Y = -(2 * py / h - 1) / projMatrix.M22, Z = 1 / projMatrix.M33 }; Vector3.TransformCoordinate(ref v, ref viewInv, out var zf); Vector3 zn; if (renderMatrices.IsPerspective) { zn = viewInv.Row4.ToVector3(); } else { v.Z = 0; Vector3.TransformCoordinate(ref v, ref viewInv, out zn); } var r = zf - zn; r.Normalize(); ray = new Ray(zn + r * renderMatrices.CameraParams.ZNear, r); return(true); }
/// <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); }