/// <summary> /// Hits the size of the test fixed. /// </summary> /// <param name="context">The context.</param> /// <param name="modelMatrix">The model matrix.</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(HitTestContext context, ref Matrix modelMatrix, ref List <HitTestResult> hits, object originalSource, int count) { if (BillboardVertices == null || BillboardVertices.Count == 0) { return(false); } var h = false; var result = new BillboardHitResult { Distance = double.MaxValue }; var visualToScreen = context.RenderMatrices.ScreenViewProjectionMatrix; var screenPoint = context.HitPointSP * context.RenderMatrices.DpiScale; if (screenPoint.X < 0 || screenPoint.Y < 0) { return(false); } for (var i = 0; i < count; ++i) { var vert = BillboardVertices[i]; var pos = vert.Position.ToVector3(); var c = Vector3.TransformCoordinate(pos, modelMatrix); var dir = c - context.RayWS.Position; if (Vector3.Dot(dir, context.RayWS.Direction) < 0) { continue; } var quad = GetScreenQuad(ref c, ref vert.OffTL, ref vert.OffTR, ref vert.OffBL, ref vert.OffBR, ref visualToScreen, context.RenderMatrices.DpiScale); if (quad.IsPointInQuad2D(ref screenPoint)) { var v = c - context.RayWS.Position; var dist = Vector3.Dot(context.RayWS.Direction, v); if (dist > result.Distance) { continue; } h = true; result.ModelHit = originalSource; result.IsValid = true; result.PointHit = context.RayWS.Position + context.RayWS.Direction * dist; result.Distance = dist; result.Geometry = this; AssignResultAdditional(result, i); if (logger.IsEnabled(LogLevel.Trace)) { logger.LogTrace("Hit; HitPoint:{}; Text={}", result.PointHit, (result.TextInfo == null ? Type.ToString() : result.TextInfo.Text)); } } } if (h) { hits.Add(result); } return(h); }
/// <summary> /// Hits the test. /// </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="fixedSize">if set to <c>true</c> [fixed size].</param> /// <returns></returns> public virtual bool HitTest(RenderContext context, Matrix modelMatrix, ref Ray rayWS, ref List <HitTestResult> hits, object originalSource, bool fixedSize) { var h = false; var result = new BillboardHitResult { Distance = double.MaxValue }; if (context == null || Width == 0 || Height == 0 || (!fixedSize && !BoundingSphere.TransformBoundingSphere(modelMatrix).Intersects(ref rayWS))) { return(false); } var scale = modelMatrix.ScaleVector; var left = -(Width * scale.X) / 2; var right = -left; var top = -(Height * scale.Y) / 2; var bottom = -top; var projectionMatrix = context.ProjectionMatrix; var viewMatrix = context.ViewMatrix; var viewMatrixInv = viewMatrix.PsudoInvert(); var visualToScreen = context.ScreenViewProjectionMatrix; foreach (var center in BillboardVertices.Select(x => x.Position)) { var c = Vector3.TransformCoordinate(center.ToVector3(), modelMatrix); var dir = c - rayWS.Position; dir.Normalize(); if (Vector3.Dot(dir, rayWS.Direction.Normalized()) < 0) { continue; } var b = GetHitTestBound(c, left, right, top, bottom, ref projectionMatrix, ref viewMatrix, ref viewMatrixInv, ref visualToScreen, fixedSize, (float)context.ActualWidth, (float)context.ActualHeight); if (rayWS.Intersects(ref b)) { if (Collision.RayIntersectsBox(ref rayWS, ref b, out float distance)) { h = true; result.ModelHit = originalSource; result.IsValid = true; result.PointHit = rayWS.Position + (rayWS.Direction * distance); result.Distance = distance; result.Geometry = this; Debug.WriteLine(string.Format("Hit; HitPoint:{0}; Bound={1}; Distance={2}", result.PointHit, b, distance)); break; } } } if (h) { hits.Add(result); } return(h); }
/// <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); }
/// <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="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(HitTestContext context, ref Matrix modelMatrix, ref List <HitTestResult> hits, object originalSource, int count) { if (BillboardVertices == null || BillboardVertices.Count == 0) { return(false); } var h = false; var result = new BillboardHitResult { Distance = double.MaxValue }; var viewMatrix = context.RenderMatrices.ViewMatrix; var viewMatrixInv = viewMatrix.PsudoInvert(); var rayWS = context.RayWS; for (var 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); if (logger.IsEnabled(LogLevel.Trace)) { logger.LogTrace("Hit; HitPoint:{}; Text={}", result.PointHit, result.TextInfo == null ? Type.ToString() : result.TextInfo.Text); } } } if (h) { hits.Add(result); } return(h); }
/// <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(RenderContext 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(); var scale3D = modelMatrix.ScaleVector; var scale = new Vector2(scale3D.X, scale3D.Y); 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, ref scale); 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 void AssignResultAdditional(BillboardHitResult result, int index) { base.AssignResultAdditional(result, index); result.TextInfo = this.TextInfo; result.TextInfoIndex = index; }
public override bool HitTest(RenderContext context, Matrix modelMatrix, ref Ray rayWS, ref List <HitTestResult> hits, object originalSource, bool fixedSize) { var h = false; var result = new BillboardHitResult(); result.Distance = double.MaxValue; if (context == null || Width == 0 || Height == 0) { return(false); } var scale = modelMatrix.ScaleVector; var projectionMatrix = context.ProjectionMatrix; var viewMatrix = context.ViewMatrix; var viewMatrixInv = viewMatrix.PsudoInvert(); var visualToScreen = context.ScreenViewProjectionMatrix; int index = -1; foreach (var info in TextInfo) { ++index; var c = Vector3.TransformCoordinate(info.Origin, modelMatrix); var dir = c - rayWS.Position; dir.Normalize(); if (Vector3.Dot(dir, rayWS.Direction.Normalized()) < 0) { continue; } if (!fixedSize && !info.BoundSphere.TransformBoundingSphere(modelMatrix).Intersects(ref rayWS)) { continue; } var left = -(info.ActualWidth * scale.X) / 2; var right = -left; var top = -(info.AcutalHeight * scale.Y) / 2; var bottom = -top; var b = GetHitTestBound(c, left, right, top, bottom, ref projectionMatrix, ref viewMatrix, ref viewMatrixInv, ref visualToScreen, fixedSize, (float)context.ActualWidth, (float)context.ActualHeight); if (rayWS.Intersects(ref b)) { float distance; if (Collision.RayIntersectsBox(ref rayWS, ref b, out distance)) { h = true; result.ModelHit = originalSource; result.IsValid = true; result.PointHit = rayWS.Position + (rayWS.Direction * distance); result.Distance = distance; result.TextInfo = info; result.TextInfoIndex = index; Debug.WriteLine($"Hit; Text:{info.Text}; HitPoint:{result.PointHit};"); break; } } } if (h) { hits.Add(result); } return(h); }
protected virtual void AssignResultAdditional(BillboardHitResult result, int index) { result.TextInfoIndex = index; result.Type = Type; }