/// <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> /// Prüft, ob sich ein Punkt innerhalb der Hitbox einer GameObject-Instanz befindet /// </summary> /// <param name="point">Zu prüfender Punkt in der Welt</param> /// <param name="g">GameObject-Instanz für die die Prüfung durchgeführt werden soll</param> /// <returns>true, wenn sich der Punkt innerhalb der Hitbox befindet</returns> public static bool IsPointInsideGameObject(Vector3 point, GameObject g) { foreach (Hitbox h in g.Hitboxes) { bool isInsideCurrentHitbox = true; for (int boxFaceIndex = 0; boxFaceIndex < h.mMesh.Faces.Length; boxFaceIndex++) { GeoMeshFace boxFace = h.mMesh.Faces[boxFaceIndex]; Vector3 vertexOnFace = h.Vertices[boxFace.Vertices[0]]; Vector3 boxNormal = boxFace.Flip ? h.Normals[boxFace.Normal] : -h.Normals[boxFace.Normal]; // really flip this way? bool tmpResult = IsInFrontOfPlane(ref point, ref boxNormal, ref vertexOnFace); if (tmpResult == false) { isInsideCurrentHitbox = false; break; } } if (isInsideCurrentHitbox) { return(true); } } return(false); }
internal static List <Vector3> ClipFaces(Hitbox caller, Hitbox collider) { List <Vector3> callerVertices = new List <Vector3>(caller.mVertices); List <Vector3> collisionVolumeVertices = new List <Vector3>(); // Clip caller against collider faces: for (int colliderFaceIndex = 0; colliderFaceIndex < collider.mMesh.Faces.Length; colliderFaceIndex++) { GeoMeshFace colliderClippingFace = collider.mMesh.Faces[colliderFaceIndex]; Vector3 colliderClippingFaceVertex = collider.mVertices[colliderClippingFace.Vertices[0]]; Vector3 colliderClippingFaceNormal = colliderClippingFace.Flip ? collider.mNormals[colliderClippingFace.Normal] : -collider.mNormals[colliderClippingFace.Normal]; for (int callerVertexIndex = 0; callerVertexIndex < callerVertices.Count; callerVertexIndex++) { Vector3 callerVertex1 = callerVertices[callerVertexIndex]; Vector3 callerVertex2 = callerVertices[(callerVertexIndex + 1) % callerVertices.Count]; Vector3 lineDirection = Vector3.NormalizeFast(callerVertex2 - callerVertex1); bool callerVertex1InsideRegion = HelperIntersection.IsInFrontOfPlane(ref callerVertex1, ref colliderClippingFaceNormal, ref colliderClippingFaceVertex); bool callerVertex2InsideRegion = HelperIntersection.IsInFrontOfPlane(ref callerVertex2, ref colliderClippingFaceNormal, ref colliderClippingFaceVertex); if (callerVertex1InsideRegion) { if (callerVertex2InsideRegion) { if (!collisionVolumeVertices.Contains(callerVertex2)) { collisionVolumeVertices.Add(callerVertex2); } } else { Vector3?clippedVertex = ClipLineToPlane(ref callerVertex2, ref lineDirection, ref colliderClippingFaceVertex, ref colliderClippingFaceNormal); if (clippedVertex != null && !collisionVolumeVertices.Contains(clippedVertex.Value)) { collisionVolumeVertices.Add(clippedVertex.Value); } } } else { if (callerVertex2InsideRegion) { Vector3?clippedVertex = ClipLineToPlane(ref callerVertex1, ref lineDirection, ref colliderClippingFaceVertex, ref colliderClippingFaceNormal); if (clippedVertex != null && !collisionVolumeVertices.Contains(clippedVertex.Value)) { collisionVolumeVertices.Add(clippedVertex.Value); } if (!collisionVolumeVertices.Contains(callerVertex2)) { collisionVolumeVertices.Add(callerVertex2); } } } } callerVertices.Clear(); for (int i = 0; i < collisionVolumeVertices.Count; i++) { callerVertices.Add(collisionVolumeVertices[i]); } collisionVolumeVertices.Clear(); } return(callerVertices); }