using System.Collections.Generic; using System.Numerics; using ACE.Server.Entity; namespace ACE.Server.Physics { /// /// A bounding box for collision detection /// public class BoundingBox { /// /// The model this bounding box encompasses /// public ModelMesh Model; /// /// The minimum values for each dimension /// public Vector3 Min; /// /// The maximum values for each dimension /// public Vector3 Max; /// /// The center of the bounding box /// public Vector3 Center; /// /// The size of the bounding box /// public Vector3 Size; /// /// Empty constructor /// public BoundingBox() { } /// /// Constructs a new bounding box /// for a model /// public BoundingBox(ModelMesh model) { Model = model; BuildBox(model); } /// /// Builds a bounding box for a model /// public void BuildBox(ModelMesh model) { Min = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue); Max = new Vector3(float.MinValue, float.MinValue, float.MinValue); // build the transformation matrix var transform = GetTransform(model); foreach (var gfxObj in model.StaticMesh.GfxObjs) { foreach (var v in gfxObj.VertexArray.Vertices.Values) { var vertex = Vector3.Transform(v.Origin, transform); if (vertex.X < Min.X) Min.X = vertex.X; if (vertex.Y < Min.Y) Min.Y = vertex.Y; if (vertex.Z < Min.Z) Min.Z = vertex.Z; if (vertex.X > Max.X) Max.X = vertex.X; if (vertex.Y > Max.Y) Max.Y = vertex.Y; if (vertex.Z > Max.Z) Max.Z = vertex.Z; } } CalcSize(); } /// /// Calculates the size and center properties /// public void CalcSize() { Size = new Vector3(Max.X - Min.X, Max.Y - Min.Y, Max.Z - Min.Z); Center = new Vector3(Min.X + Size.X / 2, Min.Y + Size.Y / 2, Min.Z + Size.Z / 2); } /// /// Builds the matrix transformation /// public Matrix4x4 GetTransform(ModelMesh model) { var scale = Matrix4x4.CreateScale(model.Scale); var rotate = Matrix4x4.CreateFromQuaternion(new Quaternion(model.Frame.Orientation.X, model.Frame.Orientation.Y, model.Frame.Orientation.Z, model.Frame.Orientation.W)); var cellTranslate = Matrix4x4.CreateTranslation(new Vector3(model.Cell.X * LandblockMesh.CellSize, model.Cell.Y * LandblockMesh.CellSize, 0)); var cellTranslateInner = Matrix4x4.CreateTranslation(new Vector3(model.Position.X, model.Position.Y, model.Position.Z)); var transform = scale * rotate * cellTranslate * cellTranslateInner; return transform; } /// /// Returns TRUE if point is inside box /// on the XY plane /// public bool Contains2D(Vector3 point) { return (point.X >= Min.X && point.X <= Max.X) && (point.Y >= Min.Y && point.Y <= Max.Y); } /// /// Returns TRUE if bounding boxes are touching /// on the XY plane /// public bool Intersect2D(BoundingBox b) { return (Min.X <= b.Max.X && Max.X >= b.Min.X) && (Min.Y <= b.Max.Y && Max.Y >= b.Min.Y); } /// /// Returns TRUE if point is inside box /// public bool Contains(Vector3 point) { return (point.X >= Min.X && point.X <= Max.X) && (point.Y >= Min.Y && point.Y <= Max.Y) && (point.Z >= Min.Z && point.Z <= Max.Z); } /// /// Returns TRUE if bounding boxes are touching /// public bool Intersect(BoundingBox b) { return (Min.X <= b.Max.X && Max.X >= b.Min.X) && (Min.Y <= b.Max.Y && Max.Y >= b.Min.Y) && (Min.Z <= b.Max.Z && Max.Z >= b.Min.Z); } public void ConvertToGlobal() { } /// /// Returns 8 corner points of the bounding box /// public List GetCornerPoints() { // lower corner points var lowerNW = new Vector3(Min.X, Max.Y, Min.Z); var lowerNE = new Vector3(Max.X, Max.Y, Min.Z); var lowerSW = new Vector3(Min.X, Min.Y, Min.Z); var lowerSE = new Vector3(Max.X, Min.Y, Min.Z); // upper corner points var upperNW = new Vector3(Min.X, Max.Y, Max.Z); var upperNE = new Vector3(Max.X, Max.Y, Max.Z); var upperSW = new Vector3(Min.X, Min.Y, Max.Z); var upperSE = new Vector3(Max.X, Min.Y, Max.Z); return new List() { lowerNW, lowerNE, lowerSW, lowerSE, upperNW, upperNE, upperSW, upperSE }; } } }