internal static bool IsMouseCursorInsideHitbox(GameObject g, ref Vector3 worldRay, ref Vector3 origin, MouseIntersectionPrecision precision) { bool result; Vector3 intersection; result = GameObject.LinePlaneIntersection( out intersection, worldRay, origin, -worldRay, g.GetCenterPointForAllHitboxes() ); if (result) { foreach (Hitbox hb in g.Hitboxes) { if (IsPointInsideBox(ref intersection, hb)) { return(true); } } return(false); } else { return(false); } }
/// <summary> /// Prüft, ob ein Strahl die Hitbox einer GameObject-Instanz trifft und gibt die genaue Position des Schnittpunkts an /// </summary> /// <param name="g">Zu prüfende GameObject-Instanz</param> /// <param name="origin">Ursprung des Strahls</param> /// <param name="worldRay">Richtung des Strahls (muss normalisiert sein)</param> /// <param name="intersectionPoint">Ergebnis der Prüfung (Position des Schnittpunkts)</param> /// <param name="precision">Präzision der Prüfung</param> /// <returns>true, wenn der Strahl das Objekt trifft</returns> public static bool GetRayIntersectionPointOnHitbox(GameObject g, Vector3 origin, Vector3 worldRay, out Vector3 intersectionPoint, MouseIntersectionPrecision precision = MouseIntersectionPrecision.Box) { bool result; Vector3 intersection; for (int i = 0; i < g.Hitboxes.Count; i++) { Hitbox currentHitbox = g.Hitboxes[i]; for (int j = 0; j < currentHitbox.mMesh.Faces.Length; j++) { GeoMeshFace currentFace = g.Hitboxes[i].mMesh.Faces[j]; Vector3 currentFaceNormal = currentFace.Flip ? -currentHitbox.Normals[currentFace.Normal] : currentHitbox.Normals[currentFace.Normal]; Vector3 pointOnFaceNormal = currentHitbox.GetPointOnFace(j, ref currentFaceNormal, currentFace.Flip); result = GameObject.LinePlaneIntersection(out intersection, worldRay, origin, currentFaceNormal, pointOnFaceNormal); if (result) { if (precision == MouseIntersectionPrecision.Box) { if (IsPointInsideBox(ref intersection, currentHitbox)) { intersectionPoint = intersection; return(true); } } else { IsPointInsideSphere(ref intersection, g.GetCenterPointForAllHitboxes(), g._sceneDiameter); } } } } intersectionPoint = g.GetCenterPointForAllHitboxes(); return(false); }
/// <summary> /// Erfragt, ob der Mauszeiger (näherungsweise) auf dem Objekt liegt /// </summary> /// <param name="g">Zu untersuchendes GameObject</param> /// <param name="ms">Mausinformationen</param> /// <param name="offsetX">optionale Verschiebung des Cursors auf der X-Achse in Pixeln (Standard: 0)</param> /// <param name="offsetY">optionale Verschiebung des Cursors auf der X-Achse in Pixeln (Standard: 0)</param> /// <param name="precision">Genauigkeit der Prüfung (Standard: Box für eine genauere Prüfung)</param> /// <returns>true, wenn der Mauszeiger auf dem Objekt liegt</returns> public static bool IsMouseCursorInsideHitbox(GameObject g, MouseState ms, int offsetX = 0, int offsetY = 0, MouseIntersectionPrecision precision = MouseIntersectionPrecision.Box) { Vector2 mc = HelperGeneral.GetNormalizedMouseCoords(ms.X + offsetX, ms.Y + offsetY); Vector3 worldRay = KWEngine.CurrentWindow.Get3DMouseCoords(mc.X, mc.Y); Vector3 normal; bool result; Vector3 intersection; if (KWEngine.CurrentWindow.CurrentWorld != null && KWEngine.CurrentWindow.CurrentWorld.IsFirstPersonMode) { normal = HelperCamera.GetLookAtVector(); normal.Y += 0.000001f; normal.Z += 0.000001f; if (KWEngine.Projection == ProjectionType.Perspective) { Vector3 fpPos = KWEngine.CurrentWindow.CurrentWorld.GetFirstPersonObject().Position; fpPos.Y += KWEngine.CurrentWindow.CurrentWorld.GetFirstPersonObject().FPSEyeOffset; result = GameObject.LinePlaneIntersection(out intersection, worldRay, fpPos, normal, g.GetCenterPointForAllHitboxes()); } else { Vector3 fpPos = HelperGeneral.GetRayOriginForOrthographicProjection(mc); result = GameObject.LinePlaneIntersection(out intersection, worldRay, fpPos, normal, g.GetCenterPointForAllHitboxes()); } } else { normal = -KWEngine.CurrentWindow.CurrentWorld.GetCameraLookAtVector(); normal.Y += 0.000001f; normal.Z += 0.000001f; if (KWEngine.Projection == ProjectionType.Perspective) { result = GameObject.LinePlaneIntersection(out intersection, worldRay, KWEngine.CurrentWindow.CurrentWorld.GetCameraPosition(), normal, g.GetCenterPointForAllHitboxes()); } else { Vector3 rayOrigin = HelperGeneral.GetRayOriginForOrthographicProjection(mc); result = GameObject.LinePlaneIntersection(out intersection, worldRay, rayOrigin, normal, g.GetCenterPointForAllHitboxes()); } } if (result) { foreach (Hitbox hb in g.Hitboxes) { if (precision == MouseIntersectionPrecision.Box) { if (IsPointInsideBox(ref intersection, hb)) { return(true); } } else { if (IsPointInsideSphere(ref intersection, hb.GetCenter(), hb.DiameterAveraged)) { return(true); } } } return(false); } else { return(false); } }
/// <summary> /// Gibt die am nächsten liegende (vom Mauszeiger überlagerte) GameObject-Instanz zurück /// </summary> /// <typeparam name="T">Beliebige Unterklasse von GameObject</typeparam> /// <param name="ms">Aktueller Mausstatus</param> /// <param name="offsetX">optionale Verschiebung des Cursors auf der X-Achse in Pixeln (Standard: 0)</param> /// <param name="offsetY">optionale Verschiebung des Cursors auf der X-Achse in Pixeln (Standard: 0)</param> /// <param name="precision">Präzision der Messung (Standard: Box für genauere Messung)</param> /// <returns>Die GameObject-Instanz, die der Kamera am nächsten ist</returns> public static T IsMouseCursorOnAny <T>(MouseState ms, int offsetX = 0, int offsetY = 0, MouseIntersectionPrecision precision = MouseIntersectionPrecision.Box) where T : GameObject { GameObject[] list = KWEngine.CurrentWorld._gameObjects.FindAll(go => go is T).ToArray(); if (list.Length == 0) { return(null); } Vector3 origin; Vector2 mc = HelperGeneral.GetNormalizedMouseCoords(ms.X + offsetX, ms.Y + offsetY); Vector3 worldRay = KWEngine.CurrentWindow.Get3DMouseCoords(mc.X, mc.Y); if (KWEngine.CurrentWorld != null && KWEngine.CurrentWorld.IsFirstPersonMode) { if (KWEngine.Projection == ProjectionType.Perspective) { origin = KWEngine.CurrentWorld.GetFirstPersonObject().Position; origin.Y += KWEngine.CurrentWorld.GetFirstPersonObject().FPSEyeOffset; } else { origin = HelperGeneral.GetRayOriginForOrthographicProjection(mc); } } else { if (KWEngine.Projection == ProjectionType.Perspective) { origin = KWEngine.CurrentWorld.GetCameraPosition(); } else { origin = HelperGeneral.GetRayOriginForOrthographicProjection(mc); } } float minDistance = float.MaxValue; int minIndex = -1; for (int i = 0; i < list.Length; i++) { bool rayHitGameObject = IsMouseCursorInsideHitbox(list[i], ref worldRay, ref origin, precision); if (rayHitGameObject) { float currentDistance = (origin - list[i].GetCenterPointForAllHitboxes()).LengthSquared; if (currentDistance < minDistance) { minDistance = currentDistance; minIndex = i; } } } if (minIndex >= 0) { return(list[minIndex] as T); } return(null); }