/// <summary> /// Gibt die am nächsten liegende (vom Mauszeiger überlagerte) GameObject-Instanz inkl. der genauen Mausposition auf dem Objekt zurück /// </summary> /// <typeparam name="T">Beliebige Unterklasse von GameObject</typeparam> /// <param name="ms">Aktueller Mausstatus</param> /// <param name="intersectionPoint">Punkt, an dem der Mauszeiger auf das Objekt trifft</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, out Vector3 intersectionPoint, int offsetX = 0, int offsetY = 0, MouseIntersectionPrecision precision = MouseIntersectionPrecision.Box) where T : GameObject { intersectionPoint = Vector3.Zero; GameObject[] list = KWEngine.CurrentWorld._gameObjects.FindAll(go => go is T).ToArray(); if (list.Length == 0) { return(null); } Vector2 mc = HelperGeneral.GetNormalizedMouseCoords(ms.X + offsetX, ms.Y + offsetY); Vector3 worldRay = KWEngine.CurrentWindow.Get3DMouseCoords(mc.X, mc.Y); Vector3 origin; 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 = GetRayIntersectionPointOnHitbox(list[i], origin, worldRay, out Vector3 iPoint, precision); if (rayHitGameObject) { float currentDistance = (origin - iPoint).LengthSquared; if (currentDistance < minDistance) { intersectionPoint = iPoint; minDistance = currentDistance; minIndex = i; } } } if (minIndex >= 0) { return(list[minIndex] as T); } return(null); }
/// <summary> /// Gibt eine Liste von GameObject-Instanzen zurück, die unter dem Mauszeiger liegen (Instanzen müssen mit IsPickable = true gesetzt haben) /// </summary> /// <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> /// <returns>Liste betroffener GameObject-Instanzen</returns> public static List <GameObject> PickGameObjects(MouseState ms, int offsetX = 0, int offsetY = 0) { List <GameObject> pickedObjects = new List <GameObject>(); GLWindow w = GLWindow.CurrentWindow; if (w == null || w.CurrentWorld == null || !w.Focused) { return(pickedObjects); } Vector2 mouseCoords = HelperGeneral.GetNormalizedMouseCoords(ms.X + offsetX, ms.Y + offsetY); Vector3 ray = KWEngine.CurrentWindow.Get3DMouseCoords(mouseCoords.X, mouseCoords.Y); Vector3 pos; if (KWEngine.Projection == ProjectionType.Perspective) { pos = w.CurrentWorld.GetCameraPosition() + ray; } else { pos = HelperGeneral.GetRayOriginForOrthographicProjection(mouseCoords) + ray; } foreach (GameObject go in w.CurrentWorld.GetGameObjects()) { if (go.IsPickable && go.IsInsideScreenSpace) { if (GameObject.IntersectRaySphere(pos, ray, go.GetCenterPointForAllHitboxes(), go.GetMaxDiameter() / 2)) { pickedObjects.Add(go); } } } return(pickedObjects); }
/// <summary> /// Konvertiert 2D-Mauskoordinaten in 3D-Koordinaten /// </summary> /// <param name="ms">Mausinformationen</param> /// <param name="planeNormal">Kollisionsebene (Standard: Camera)</param> /// <param name="planeHeight">Höhe der Kollisionsebene</param> /// <param name="offsetX">(optionale) Seitenkorrektur in Pixeln</param> /// <param name="offsetY">(optionale) Höhenkorrektur in Pixeln</param> /// <returns>3D-Mauskoordinaten</returns> public static Vector3 GetMouseIntersectionPoint(MouseState ms, Plane planeNormal, float planeHeight, int offsetX = 0, int offsetY = 0) { Vector3 normal; if (planeNormal == Plane.Y) { normal = new Vector3(0, 1, 0.000001f); } else if (planeNormal == Plane.X) { normal = new Vector3(1, 0, 0); } else if (planeNormal == Plane.Z) { normal = new Vector3(0, 0.000001f, 1); } else { if (KWEngine.CurrentWorld != null) { normal = -KWEngine.CurrentWorld.GetCameraLookAtVector(); } else { normal = new Vector3(0, 1, 0.000001f); } } Vector2 mc = HelperGeneral.GetNormalizedMouseCoords(ms.X + offsetX, ms.Y + offsetY); Vector3 worldRay = KWEngine.CurrentWindow.Get3DMouseCoords(mc.X, mc.Y); bool result; Vector3 intersection; if (KWEngine.Projection == ProjectionType.Perspective) { result = GameObject.LinePlaneIntersection(out intersection, worldRay, KWEngine.CurrentWindow.CurrentWorld.GetCameraPosition(), normal, normal * planeHeight); } else { Vector3 rayOrigin = HelperGeneral.GetRayOriginForOrthographicProjection(mc); result = GameObject.LinePlaneIntersection(out intersection, worldRay, rayOrigin, normal, normal * planeHeight); } if (result) { return(intersection); } else { return(normal * planeHeight); } }
/// <summary> /// Gibt das GameObject zurück, das unter dem Mauszeiger liegt (Instanzen müssen mit IsPickable = true gesetzt haben) /// </summary> /// <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> /// <returns>Gewähltes GameObject</returns> public static GameObject PickGameObject(MouseState ms, int offsetX = 0, int offsetY = 0) { GLWindow w = GLWindow.CurrentWindow; if (w == null || w.CurrentWorld == null || !w.Focused) { return(null); } Vector2 mouseCoords = HelperGeneral.GetNormalizedMouseCoords(ms.X + offsetX, ms.Y + offsetY); Vector3 ray = KWEngine.CurrentWindow.Get3DMouseCoords(mouseCoords.X, mouseCoords.Y); Vector3 pos; if (KWEngine.Projection == ProjectionType.Perspective) { pos = w.CurrentWorld.GetCameraPosition() + ray; } else { pos = HelperGeneral.GetRayOriginForOrthographicProjection(mouseCoords) + ray; } GameObject pickedObject = null; float pickedDistance = float.MaxValue; foreach (GameObject go in w.CurrentWorld.GetGameObjects()) { if (go.IsPickable && go.IsInsideScreenSpace) { if (GameObject.IntersectRaySphere(pos, ray, go.GetCenterPointForAllHitboxes(), go.GetMaxDiameter() / 2)) { float distance = (go.GetCenterPointForAllHitboxes() - pos).LengthSquared; if (distance < pickedDistance) { pickedDistance = distance; pickedObject = go; } } } } return(pickedObject); }
/// <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); } }