/// <inheritdoc cref="NotuiElement"/> public override IntersectionPoint PureHitTest(Touch touch, bool prevpos, out IntersectionPoint persistentIspoint) { touch.GetPreviousWorldPosition(Context, out var popos, out var pdir); var sizetr = Matrix4x4.CreateScale(Size); //var invsizetr = Matrix4x4.CreateScale(Vector3.One/Size); var scldisp = sizetr * DisplayMatrix; Matrix4x4.Invert(scldisp, out var invdispmat); var trelpos = Vector3.Transform(prevpos ? popos : touch.WorldPosition, invdispmat); var treldir = Vector3.TransformNormal(prevpos ? pdir : touch.ViewDir, invdispmat); IntersectionPoint ispoint = null; float d = float.MaxValue; for (int i = 0; i < 6; i++) { var pmat = Matrix4x4.CreateWorld(_planeCenters[i] * -0.5f, _planeCenters[i], _planeUps[i]); var hit = Intersections.PlaneRay(trelpos, treldir, pmat, out var aispos, out var pispos); if (!hit) { continue; } hit = pispos.X <= 0.5 && pispos.X >= -0.5 && pispos.Y <= 0.5 && pispos.Y >= -0.5; if (!hit) { continue; } var diff = aispos - trelpos; if (Vector3.Dot(Vector3.Normalize(diff), treldir) < 0) { continue; } if (diff.Length() >= d) { continue; } var locmat = pmat * scldisp; //TODO: create a more analitical method for scale correction, this is dumb Matrix4x4.Decompose(locmat, out var locscl, out var qdummy, out var tdummy); var invlocscl = Vector3.One / (locscl / DisplayTransformation.Scale); var smat = Matrix4x4.CreateScale(invlocscl) * Matrix4x4.CreateTranslation(pispos) * locmat; ispoint = new IntersectionPoint(Vector3.Transform(aispos, scldisp), aispos, pispos, smat, this, touch); d = diff.Length(); } persistentIspoint = ispoint; return(ispoint); }
/// <summary> /// Get the planar velocity of a touch and its current and previous intersection-point in the selected plane's space /// </summary> /// <param name="touch"></param> /// <param name="plane">Arbitrary matrix of the XY plane to do the intersection with</param> /// <param name="context">Notui context to provide screen space/alignment information</param> /// <param name="currpos">Current intersection point in the space of the plane</param> /// <param name="prevpos">Previous intersection point in the space of the plane</param> /// <returns>Velocity of the touch relative to the space of the plane</returns> public static Vector3 GetPlanarVelocity(this TouchContainer touch, Matrix4x4 plane, NotuiContext context, out Vector3 currpos, out Vector3 prevpos) { // get planar coords for current touch position var hit = Intersections.PlaneRay(touch.WorldPosition, touch.ViewDir, plane, out var capos, out var crpos); currpos = crpos; // get planar coords for the previous touch position touch.GetPreviousWorldPosition(context, out var popos, out var pdir); var phit = Intersections.PlaneRay(popos, pdir, plane, out var papos, out var prpos); prevpos = prpos; return(crpos - prpos); }
/// <summary> /// General Hittesting on the infinite plane defined by the element transforms /// </summary> /// <param name="touch">The touch to be tested</param> /// <param name="prevpos">Calculate Intersection point for previous position</param> /// <returns>If the touch hits then an Intersection point otherwise null</returns> public IntersectionPoint PreparePlanarShapeHitTest(Touch touch, bool prevpos) { // when first hit consider the display transformation then // for the rest of the interaction consider the interaction transform touch.GetPreviousWorldPosition(Context, out var popos, out var pdir); var hit = Intersections.PlaneRay( prevpos ? popos : touch.WorldPosition, prevpos ? pdir : touch.ViewDir, DisplayMatrix, out var ispoint, out var planarpoint); return(hit ? new IntersectionPoint(ispoint, planarpoint, this, touch) { SurfaceSpace = planarpoint * 2 } : null); }