দুটি ওরিয়েন্টেড বাউন্ডিং বক্স (ওবিবি) এর মধ্যে দ্রুততম 3 ডি সংঘর্ষ সনাক্তকরণ


10

আমি আমার গেমের সেই স্থানে রয়েছি যেখানে আমার একটি সংঘর্ষের সিস্টেম যুক্ত করা দরকার। আমি জবুলেট চেষ্টা করেছিলাম, এবং এটি কাজ করার সময়, আমি যা খুঁজছিলাম তা তা নয়। আমি দুটি পরীক্ষামূলক বাউন্ডিং বাক্স (ওবিবি) গাছের সংঘর্ষে নিরীক্ষণের জন্য একটি সহজ উপায় চাই।

আমি গাছ ব্যবহার করে সংঘর্ষ করতে যাচ্ছিলাম। ব্রডফেজের জন্য একটি এএবিবি করুন, তারপরে যদি পরীক্ষায় পাস হয় তবে গাছের প্রতিটি ওবিবি অন্য গাছের সাথে সংঘর্ষ হয়।

আমি ইন্টারনেটে কয়েকটি জিনিস পেয়েছি তবে আমি সেগুলি পুরোপুরি বুঝতে পারি না। আমি যে ওয়েবসাইট বা সংস্থানটির জন্য জিজ্ঞাসা করছি তা 3 ডি ওবিবি সংঘর্ষগুলি ভালভাবে ব্যাখ্যা করে?

আমি শিখেছি যে জিজেকি স্যাট-এর চেয়ে দ্রুত, এবং বাক্সগুলি একে অপরের মধ্যে কতটা প্রবেশ করে তা আমাকে বলতে সক্ষম হতে পারে appears আমি কিছু জিজেকে স্টাফ পেয়েছি, তবে সেগুলি বাক্সগুলি ছিল না; পরিবর্তে, আরও জটিল এবং বিভ্রান্তিকর জিনিস।

আমি কেবল 3 ভেক্টর থেকে একটি ওবিবি তৈরি করতে সক্ষম হতে চাই: কেন্দ্র, আকার এবং প্রতিটি অক্ষের ঘূর্ণন। তারপরে তাদের সাথে সংঘর্ষের পরীক্ষা করতে সক্ষম হোন। আপনার পোস্টের জন্য যা কিছু আছে তার জন্য আগাম ধন্যবাদ।


আপনি কি নিশ্চিত যে আপনার বাউন্ডিং বাক্সগুলি দরকার? আপনার যদি হাড়ের গাছ থাকে এবং আপনার প্রতিটি হাড়ের পরিমাণ সম্পর্কে কেন্দ্রগুলি এবং মোটামুটি ধারণা থাকে তবে সীমাবদ্ধ ক্ষেত্রগুলি কার্যকর এবং আরও দ্রুত কার্যকর করা যায়।
জনউবিবার্ড

উত্তর:


0

আমি আপনার মন্তব্যে লিঙ্কটি দেখেছি যা জালটির চারপাশে সাজানো ওবিবিগুলির সাথে চরিত্রটি দেখিয়েছে। কখনও কখনও এটি সীমানা গোলকের সাহায্যে করা যেতে পারে এবং তারপরে কোনও অভিমুখী সমস্যা নেই এবং একটি গোলক পরীক্ষা সাধারণত দ্রুত হয়।

তোমার চরিত্র, মত আপনার লিঙ্ক আরো ভালো দেখাবে সীমান্ত কাঠামো দেখাচ্ছে যদি Michelin মানুষ


0

এখানে একটি এএবিবি-র প্রকৃত কার্যকারী উদাহরণ রয়েছে, যা সরাসরি আমার গেম ইঞ্জিন থেকে আসে:

using System;
using OpenTK;
using OpenTK.Graphics.OpenGL;

namespace GrimoireEngine.Framework.Maths
{
    public struct BoundingBox : IEquatable<BoundingBox>
    {
        public Vector3 Min;
        public Vector3 Max;

        public const int CornerCount = 8;

        public static Vector3 MaxVector3
        {
            get
            {
                return new Vector3(float.MaxValue);
            }
        }

        public static Vector3 MinVector3
        {
            get
            {
                return new Vector3(float.MinValue);
            }
        }

        public static BoundingBox Identity
        {
            get
            {
                return new BoundingBox(Vector3.Zero, Vector3.One);
            }
        }

        public static BoundingBox Zero
        {
            get
            {
                return new BoundingBox();
            }
        }

        public BoundingBox(Vector3 min, Vector3 max)
        {
            Min = min;
            Max = max;
        }

        public BoundingBox(
            float minX, float minY, float minZ,
            float maxX, float maxY, float maxZ)
            : this(
                new Vector3(minX, minY, minZ),
                new Vector3(maxX, maxY, maxZ))
        { }

        public bool Collides(BoundingBox box)
        {
            if (box.Max.X < Min.X
                || box.Min.X > Max.X
                || box.Max.Y < Min.Y
                || box.Min.Y > Max.Y
                || box.Max.Z < Min.Z
                || box.Min.Z > Max.Z)
            {
                return false;
            }
            if (box.Min.X >= Min.X
                && box.Max.X <= Max.X
                && box.Min.Y >= Min.Y
                && box.Max.Y <= Max.Y
                && box.Min.Z >= Min.Z
                && box.Max.Z <= Max.Z)
            {
                return true;
            }
            return true;
        }

        public ContainmentType Contains(BoundingBox box)
        {
            if (box.Max.X < Min.X
                || box.Min.X > Max.X
                || box.Max.Y < Min.Y
                || box.Min.Y > Max.Y
                || box.Max.Z < Min.Z
                || box.Min.Z > Max.Z)
            {
                return ContainmentType.Disjoint;
            }
            if (box.Min.X >= Min.X
                && box.Max.X <= Max.X
                && box.Min.Y >= Min.Y
                && box.Max.Y <= Max.Y
                && box.Min.Z >= Min.Z
                && box.Max.Z <= Max.Z)
            {
                return ContainmentType.Contains;
            }
            return ContainmentType.Intersects;
        }

        public bool Collides(BoundingFrustum frustum)
        {
            int i;
            bool contained;
            Vector3[] corners = frustum.GetCorners();
            for (i = 0; i < corners.Length; i++)
            {
                if (corners[i].X < Min.X
                    || corners[i].X > Max.X
                    || corners[i].Y < Min.Y
                    || corners[i].Y > Max.Y
                    || corners[i].Z < Min.Z
                    || corners[i].Z > Max.Z)
                {
                    contained = false;
                }
                else if (corners[i].X == Min.X
                         || corners[i].X == Max.X
                         || corners[i].Y == Min.Y
                         || corners[i].Y == Max.Y
                         || corners[i].Z == Min.Z
                         || corners[i].Z == Max.Z)
                {
                    contained = true;
                }
                else
                {
                    contained = true;
                }
                if (contained == false)
                {
                    break;
                }
            }
            if (i == corners.Length)
            {
                return true;
            }
            if (i != 0)
            {
                return true;
            }
            i++;
            for (; i < corners.Length; i++)
            {
                if (corners[i].X < Min.X
                    || corners[i].X > Max.X
                    || corners[i].Y < Min.Y
                    || corners[i].Y > Max.Y
                    || corners[i].Z < Min.Z
                    || corners[i].Z > Max.Z)
                {
                    contained = false;
                }
                else if (corners[i].X == Min.X
                         || corners[i].X == Max.X
                         || corners[i].Y == Min.Y
                         || corners[i].Y == Max.Y
                         || corners[i].Z == Min.Z
                         || corners[i].Z == Max.Z)
                {
                    contained = true;
                }
                else
                {
                    contained = true;
                }
                if (contained != true)
                {
                    return true;
                }
            }
            return true;
        }

        public ContainmentType Contains(BoundingFrustum frustum)
        {
            int i;
            ContainmentType contained;
            Vector3[] corners = frustum.GetCorners();
            for (i = 0; i < corners.Length; i++)
            {
                if (corners[i].X < Min.X
                    || corners[i].X > Max.X
                    || corners[i].Y < Min.Y
                    || corners[i].Y > Max.Y
                    || corners[i].Z < Min.Z
                    || corners[i].Z > Max.Z)
                {
                    contained = ContainmentType.Disjoint;
                }
                else if (corners[i].X == Min.X
                         || corners[i].X == Max.X
                         || corners[i].Y == Min.Y
                         || corners[i].Y == Max.Y
                         || corners[i].Z == Min.Z
                         || corners[i].Z == Max.Z)
                {
                    contained = ContainmentType.Intersects;
                }
                else
                {
                    contained = ContainmentType.Contains;
                }
                if (contained == ContainmentType.Disjoint)
                {
                    break;
                }
            }
            if (i == corners.Length)
            {
                return ContainmentType.Contains;
            }
            if (i != 0)
            {
                return ContainmentType.Intersects;
            }
            i++;
            for (; i < corners.Length; i++)
            {
                if (corners[i].X < Min.X
                    || corners[i].X > Max.X
                    || corners[i].Y < Min.Y
                    || corners[i].Y > Max.Y
                    || corners[i].Z < Min.Z
                    || corners[i].Z > Max.Z)
                {
                    contained = ContainmentType.Disjoint;
                }
                else if (corners[i].X == Min.X
                         || corners[i].X == Max.X
                         || corners[i].Y == Min.Y
                         || corners[i].Y == Max.Y
                         || corners[i].Z == Min.Z
                         || corners[i].Z == Max.Z)
                {
                    contained = ContainmentType.Intersects;
                }
                else
                {
                    contained = ContainmentType.Contains;
                }
                if (contained != ContainmentType.Contains)
                {
                    return ContainmentType.Intersects;
                }
            }
            return ContainmentType.Contains;
        }

        public bool Collides(BoundingSphere sphere)
        {
            if (sphere.Center.X - Min.X >= sphere.Radius
                && sphere.Center.Y - Min.Y >= sphere.Radius
                && sphere.Center.Z - Min.Z >= sphere.Radius
                && Max.X - sphere.Center.X >= sphere.Radius
                && Max.Y - sphere.Center.Y >= sphere.Radius
                && Max.Z - sphere.Center.Z >= sphere.Radius)
            {
                return true;
            }
            double dmin = 0;
            double e = sphere.Center.X - Min.X;
            if (e < 0)
            {
                if (e < -sphere.Radius)
                {
                    return false;
                }
                dmin += e * e;
            }
            else
            {
                e = sphere.Center.X - Max.X;
                if (e > 0)
                {
                    if (e > sphere.Radius)
                    {
                        return false;
                    }
                    dmin += e * e;
                }
            }
            e = sphere.Center.Y - Min.Y;
            if (e < 0)
            {
                if (e < -sphere.Radius)
                {
                    return false;
                }
                dmin += e * e;
            }
            else
            {
                e = sphere.Center.Y - Max.Y;
                if (e > 0)
                {
                    if (e > sphere.Radius)
                    {
                        return false;
                    }
                    dmin += e * e;
                }
            }
            e = sphere.Center.Z - Min.Z;
            if (e < 0)
            {
                if (e < -sphere.Radius)
                {
                    return false;
                }
                dmin += e * e;
            }
            else
            {
                e = sphere.Center.Z - Max.Z;
                if (e > 0)
                {
                    if (e > sphere.Radius)
                    {
                        return false;
                    }
                    dmin += e * e;
                }
            }
            return dmin <= sphere.Radius * sphere.Radius;
        }

        public ContainmentType Contains(BoundingSphere sphere)
        {
            if (sphere.Center.X - Min.X >= sphere.Radius
                && sphere.Center.Y - Min.Y >= sphere.Radius
                && sphere.Center.Z - Min.Z >= sphere.Radius
                && Max.X - sphere.Center.X >= sphere.Radius
                && Max.Y - sphere.Center.Y >= sphere.Radius
                && Max.Z - sphere.Center.Z >= sphere.Radius)
            {
                return ContainmentType.Contains;
            }
            double dmin = 0;
            double e = sphere.Center.X - Min.X;
            if (e < 0)
            {
                if (e < -sphere.Radius)
                {
                    return ContainmentType.Disjoint;
                }
                dmin += e * e;
            }
            else
            {
                e = sphere.Center.X - Max.X;
                if (e > 0)
                {
                    if (e > sphere.Radius)
                    {
                        return ContainmentType.Disjoint;
                    }
                    dmin += e * e;
                }
            }
            e = sphere.Center.Y - Min.Y;
            if (e < 0)
            {
                if (e < -sphere.Radius)
                {
                    return ContainmentType.Disjoint;
                }
                dmin += e * e;
            }
            else
            {
                e = sphere.Center.Y - Max.Y;
                if (e > 0)
                {
                    if (e > sphere.Radius)
                    {
                        return ContainmentType.Disjoint;
                    }
                    dmin += e * e;
                }
            }
            e = sphere.Center.Z - Min.Z;
            if (e < 0)
            {
                if (e < -sphere.Radius)
                {
                    return ContainmentType.Disjoint;
                }
                dmin += e * e;
            }
            else
            {
                e = sphere.Center.Z - Max.Z;
                if (e > 0)
                {
                    if (e > sphere.Radius)
                    {
                        return ContainmentType.Disjoint;
                    }
                    dmin += e * e;
                }
            }
            return dmin <= sphere.Radius * sphere.Radius ? ContainmentType.Intersects : ContainmentType.Disjoint;
        }

        public bool Collides(Vector3 point)
        {
            if (point.X < Min.X
                || point.X > Max.X
                || point.Y < Min.Y
                || point.Y > Max.Y
                || point.Z < Min.Z
                || point.Z > Max.Z)
            {
                return false;
            }
            if (point.X == Min.X
                || point.X == Max.X
                || point.Y == Min.Y
                || point.Y == Max.Y
                || point.Z == Min.Z
                || point.Z == Max.Z)
            {
                return true;
            }
            return true;
        }

        public ContainmentType Contains(Vector3 point)
        {
            ContainmentType result;
            if (point.X < Min.X
                || point.X > Max.X
                || point.Y < Min.Y
                || point.Y > Max.Y
                || point.Z < Min.Z
                || point.Z > Max.Z)
            {
                result = ContainmentType.Disjoint;
            }
            else if (point.X == Min.X
                     || point.X == Max.X
                     || point.Y == Min.Y
                     || point.Y == Max.Y
                     || point.Z == Min.Z
                     || point.Z == Max.Z)
            {
                result = ContainmentType.Intersects;
            }
            else
            {
                result = ContainmentType.Contains;
            }
            return result;
        }

        public bool Equals(BoundingBox other)
        {
            return (Min == other.Min) && (Max == other.Max);
        }

        public override bool Equals(object obj)
        {
            return (obj is BoundingBox) && Equals((BoundingBox)obj);
        }

        public Vector3[] GetCorners()
        {
            return new[] {
                new Vector3(Min.X, Max.Y, Max.Z),
                new Vector3(Max.X, Max.Y, Max.Z),
                new Vector3(Max.X, Min.Y, Max.Z),
                new Vector3(Min.X, Min.Y, Max.Z),
                new Vector3(Min.X, Max.Y, Min.Z),
                new Vector3(Max.X, Max.Y, Min.Z),
                new Vector3(Max.X, Min.Y, Min.Z),
                new Vector3(Min.X, Min.Y, Min.Z)
            };
        }

        public override int GetHashCode()
        {
            return Min.GetHashCode() + Max.GetHashCode();
        }

        public bool Intersects(BoundingBox box)
        {
            if ((Max.X >= box.Min.X) && (Min.X <= box.Max.X))
            {
                if ((Max.Y < box.Min.Y) || (Min.Y > box.Max.Y))
                {
                    return false;
                }
                return (Max.Z >= box.Min.Z) && (Min.Z <= box.Max.Z);
            }
            return false;
        }

        public bool Intersects(BoundingFrustum frustum)
        {
            return frustum.Intersects(this);
        }

        public bool Intersects(BoundingSphere sphere)
        {
            if (sphere.Center.X - Min.X > sphere.Radius
                && sphere.Center.Y - Min.Y > sphere.Radius
                && sphere.Center.Z - Min.Z > sphere.Radius
                && Max.X - sphere.Center.X > sphere.Radius
                && Max.Y - sphere.Center.Y > sphere.Radius
                && Max.Z - sphere.Center.Z > sphere.Radius)
            {
                return true;
            }
            double dmin = 0;
            if (sphere.Center.X - Min.X <= sphere.Radius)
            {
                dmin += (sphere.Center.X - Min.X) * (sphere.Center.X - Min.X);
            }
            else if (Max.X - sphere.Center.X <= sphere.Radius)
            {
                dmin += (sphere.Center.X - Max.X) * (sphere.Center.X - Max.X);
            }
            if (sphere.Center.Y - Min.Y <= sphere.Radius)
            {
                dmin += (sphere.Center.Y - Min.Y) * (sphere.Center.Y - Min.Y);
            }
            else if (Max.Y - sphere.Center.Y <= sphere.Radius)
            {
                dmin += (sphere.Center.Y - Max.Y) * (sphere.Center.Y - Max.Y);
            }
            if (sphere.Center.Z - Min.Z <= sphere.Radius)
            {
                dmin += (sphere.Center.Z - Min.Z) * (sphere.Center.Z - Min.Z);
            }
            else if (Max.Z - sphere.Center.Z <= sphere.Radius)
            {
                dmin += (sphere.Center.Z - Max.Z) * (sphere.Center.Z - Max.Z);
            }
            return dmin <= sphere.Radius * sphere.Radius;
        }

        public PlaneIntersectionType Intersects(Plane plane)
        {
            Vector3 positiveVertex;
            Vector3 negativeVertex;
            if (plane.Normal.X >= 0)
            {
                positiveVertex.X = Max.X;
                negativeVertex.X = Min.X;
            }
            else
            {
                positiveVertex.X = Min.X;
                negativeVertex.X = Max.X;
            }
            if (plane.Normal.Y >= 0)
            {
                positiveVertex.Y = Max.Y;
                negativeVertex.Y = Min.Y;
            }
            else
            {
                positiveVertex.Y = Min.Y;
                negativeVertex.Y = Max.Y;
            }
            if (plane.Normal.Z >= 0)
            {
                positiveVertex.Z = Max.Z;
                negativeVertex.Z = Min.Z;
            }
            else
            {
                positiveVertex.Z = Min.Z;
                negativeVertex.Z = Max.Z;
            }
            float distance = plane.Normal.X * negativeVertex.X + plane.Normal.Y * negativeVertex.Y + plane.Normal.Z * negativeVertex.Z + plane.D;
            if (distance > 0)
            {
                return PlaneIntersectionType.Front;
            }
            distance = plane.Normal.X * positiveVertex.X + plane.Normal.Y * positiveVertex.Y + plane.Normal.Z * positiveVertex.Z + plane.D;
            if (distance < 0)
            {
                return PlaneIntersectionType.Back;
            }
            return PlaneIntersectionType.Intersecting;
        }

        public float? Intersects(Ray ray)
        {
            return ray.Intersects(this);
        }

        public static bool operator ==(BoundingBox a, BoundingBox b)
        {
            return a.Equals(b);
        }

        public static bool operator !=(BoundingBox a, BoundingBox b)
        {
            return !a.Equals(b);
        }

        public override string ToString()
        {
            return "{{Min:" + Min + " Max:" + Max + "}}";
        }

        public void DrawImmediate()
        {
            GL.Begin(PrimitiveType.LineLoop);
            GL.Vertex3(Max.X, Max.Y, Min.Z);
            GL.Vertex3(Min.X, Max.Y, Min.Z);
            GL.Vertex3(Min.X, Min.Y, Min.Z);
            GL.Vertex3(Max.X, Min.Y, Min.Z);
            GL.End();
            GL.Begin(PrimitiveType.LineLoop);
            GL.Vertex3(Max.X, Min.Y, Max.Z);
            GL.Vertex3(Max.X, Max.Y, Max.Z);
            GL.Vertex3(Min.X, Max.Y, Max.Z);
            GL.Vertex3(Min.X, Min.Y, Max.Z);
            GL.End();
            GL.Begin(PrimitiveType.LineLoop);
            GL.Vertex3(Max.X, Max.Y, Min.Z);
            GL.Vertex3(Max.X, Max.Y, Max.Z);
            GL.Vertex3(Min.X, Max.Y, Max.Z);
            GL.Vertex3(Min.X, Max.Y, Min.Z);
            GL.End();
            GL.Begin(PrimitiveType.LineLoop);
            GL.Vertex3(Max.X, Min.Y, Max.Z);
            GL.Vertex3(Min.X, Min.Y, Max.Z);
            GL.Vertex3(Min.X, Min.Y, Min.Z);
            GL.Vertex3(Max.X, Min.Y, Min.Z);
            GL.End();
        }
    }
}

অন্যান্য বাউন্ডিং ধরণের পদ্ধতিগুলি সরিয়ে দিন।


3
এটি আমার কাছে ওওবির মতো দেখাচ্ছে না, তবে একটি এএবিবি, যা ওপি যা খুঁজছিল বলে মনে হয় না?
টিপ্পি_77

@ টিপ্পি_77 question প্রশ্নের শিরোনামটি "দ্রুততম বাউন্ডিং বক্স অ্যালগরিদম" পড়ে। অস্পষ্ট প্রশ্নগুলির সাথে এটিই সমস্যা।
ক্রিথিক

3
প্রশ্ন সংস্থাটি পরিষ্কারভাবে ইঙ্গিত দেয় যে ওপি ওওবি সম্পর্কে জিজ্ঞাসা করছে: "আমি কেবল একটি ওবিবি তৈরি করতে সক্ষম হতে চাই"।
টিপ্পি_77

-2

মলি রকেট চিরকাল তোমার বন্ধু।

http://mollyrocket.com/849

তবে মনে হচ্ছে আপনি কোনও বাউন্ডিং বাক্সের সাধারণ ব্যবহারকে ভুল বুঝছেন। আপনি আসলেই এটি একটি পদার্থবিজ্ঞানের সংঘর্ষের সিস্টেমের জন্য ব্যবহার করবেন না। বিশেষত যখন এই ধরণের ব্যবহারের জন্য এটি মারাত্মকভাবে অক্ষম হতে পারে।

সম্ভবত আপনি কোনও দৃশ্য গ্রাফের সংঘর্ষের ক্যোয়ারীটি ভাবছেন? যেখানে আপনি পরীক্ষা করে দেখুন যে কোনও বস্তু কোয়াডট্রি বা একটি অক্টোবরে প্রবেশ করছে এবং আপনি দ্রুত আপনার গ্রাফটি পুনর্নির্মাণ করছেন।


আমি যদি ভুল বুঝে থাকি তবে দুঃখিত। আমি যেভাবে সংঘর্ষের কথা ভাবছিলাম তা হ'ল জালের প্রতিটি হাড়ের একটি বাউন্ডিং বক্স রয়েছে, যা প্রতিটি হাড়ের ম্যাট্রিক্সের সাথে চলে। উদাহরণস্বরূপ: লিঙ্ক । ত্রিমেশ সংঘর্ষের চেয়ে এটি আরও দ্রুত বলে মনে হচ্ছে, বিশেষত যদি জালটির কঙ্কালের অ্যানিমেশন থাকে। আমি জটিল পদার্থবিজ্ঞান নিয়ে যাচ্ছিলাম না, মেসের মধ্যে সংঘর্ষের বিষয়টি জানাতে কেবল সাধারণ সংঘর্ষ কলব্যাক।
অ্যান্ড্রু 3 ডিএস

1
আপনার উত্তর বহিরাগত লিঙ্কের উপর নির্ভর করে। আমি লিঙ্কটি কোনও দিন নিচে নেমে গেলে এখানে সম্পর্কিত তথ্য অন্তর্ভুক্ত করার জন্য উত্তরটি আপডেট করার পরামর্শ দিচ্ছি।
মাইকেলহাউস

উহু. একটি হিট বাক্স যা আপনি চেয়েছিলেন। হিট বাক্সগুলি প্রয়োজনীয়ভাবে গাছ নয় এবং সত্যই এএবিএসও নয়। এগুলি হাড়ের সাথে সংযুক্ত মূলত অদৃশ্য সংঘর্ষের জাল। আপনি পূর্বে যে পদার্থবিজ্ঞানের লাইব্রেরি ব্যবহার করেছিলেন এটি আপনাকে এটি সহজেই করতে সহায়তা করতে পারে। তবে হ্যাঁ, জিটিকে এখনও এই ধরণের সিস্টেমে মোটামুটি ভালভাবে কাজ করতে পারে। বিশেষত যদি আপনি জানতে চান কী কী করেছে।
মুনশাইনথেলোক্যাট
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.