স্যাট-এর সাথে 3 ডি ওবিবি সংঘর্ষের জন্য কতগুলি এবং কোন অক্ষ ব্যবহার করবে


29

আমি এর উপর ভিত্তি করে স্যাট প্রয়োগ করছি:

Page পৃষ্ঠায়, টেবিলের মধ্যে এটি পরীক্ষার জন্য 15 অক্ষকে বোঝায় যাতে আমরা একটি সংঘর্ষ খুঁজে পেতে পারি তবে কেবল অক্ষ, আয় এবং এজ দিয়ে আমি ইতিমধ্যে সংঘর্ষ পাচ্ছি।

কেন অন্য সমস্ত ক্ষেত্রে আমার পরীক্ষা করা দরকার? এমন কোনও পরিস্থিতি কি যেখানে কেবল অক্ষ, আই এবং এজে যথেষ্ট নয়?

উত্তর:


56

আপনি মিথ্যা ইতিবাচক পেতে পারেন। সংঘর্ষগুলি সনাক্ত হয়েছে তবে সত্যিকারের সংঘর্ষে নয়।

15 নম্বর থেকে আসে

  • বস্তু এ থেকে 3 টি অক্ষ (মুখের নরমাল)
  • অবজেক্ট বি থেকে 3 টি অক্ষ (মুখের নরমাল)
  • এ এর সমস্ত জোড়া এবং বি এর প্রান্ত থেকে 9 টি অক্ষ (3x3)
  • = মোট 15

9 টি অক্ষগুলি A এর প্রান্ত এবং বি এর প্রান্তের ক্রস পণ্যগুলি দিয়ে তৈরি

  1. এই 1 এক্স বি 1 (বি এর ক্রস প্রান্ত 1 এর প্রান্ত 1)
  2. এই 1 এক্স বি 2
  3. এই 1 এক্স বি 3
  4. এই 2 এক্স বি 1
  5. ... ইত্যাদি

প্রথম ax অক্ষটি (মুখের নরমাল থেকে) পরীক্ষা করতে ব্যবহৃত হয় যে সেখানে কোনও একটি বস্তুর কোণ অন্য বস্তুর মুখ ছেদ করছে কিনা। (বা আরও সঠিকভাবে এই ধরণের সংঘর্ষগুলি দূর করতে)

প্রান্তের ক্রস পণ্যগুলি দ্বারা গঠিত 9 টি অক্ষের সেটটি প্রান্তের সংঘর্ষ সনাক্তকরণের প্রান্তটি বিবেচনা করার জন্য ব্যবহৃত হয়, যেখানে অন্য বস্তুতে অনুপ্রবেশকারী একটি শীর্ষবিন্দু নেই। নীচের ফটোতে 'প্রায়' সংঘর্ষের মতো। এই উত্তরের বাকীটির জন্য ধরে নেওয়া যাক ছবির দুটি বাক্স আসলে সংঘর্ষে নয়, তবে একটি ছোট দূরত্ব দ্বারা পৃথক হয়েছে are

এখানে চিত্র বর্ণনা লিখুন

আমরা যদি স্যাট-এর জন্য কেবল 6 মুখের নরমাল ব্যবহার করি তবে কী ঘটে তা দেখা যাক। নীচের প্রথম চিত্রটি নীল বাক্স থেকে একটি অক্ষ এবং হলুদ বাক্স থেকে 2 অক্ষ দেখায়। যদি আমরা উভয় বস্তু এই অক্ষগুলিতে প্রজেক্ট করি তবে আমরা তিনটিটিতে একটি ওভারল্যাপ পাব। নীচের দ্বিতীয় চিত্রটি নীল বাক্সের বাকী দুটি অক্ষ এবং হলুদ বাক্সের বাকী অক্ষটি দেখায়। আবার এই অক্ষগুলিতে প্রজেক্ট করা সমস্ত 3 এ ওভারল্যাপ প্রদর্শন করবে।

সুতরাং কেবলমাত্র 6 টি মুখের নরমালগুলি পরীক্ষা করে সমস্ত 6 টি অক্ষের উপরে ওভারল্যাপগুলি প্রদর্শিত হবে, যা স্যাট অনুসারে বোঝায় যে বস্তুগুলির সংঘর্ষ হয়, কারণ আমরা কোনও বিচ্ছেদ খুঁজে পাইনি to তবে অবশ্যই, এই বিষয়গুলি সংঘর্ষে নয়। আমরা পৃথকীকরণের সন্ধান না পাবার কারণটি আমরা যথেষ্ট শক্তভাবে দেখিনি!

এখানে চিত্র বর্ণনা লিখুন এখানে চিত্র বর্ণনা লিখুন

তাহলে আমরা কীভাবে এই ফাঁকটি খুঁজে পাব? নীচের চিত্রটি একটি অক্ষ দেখায় যার উপর উভয় বস্তুর অভিক্ষেপ একটি বিচ্ছেদ প্রকাশ করবে।

এখানে চিত্র বর্ণনা লিখুন

আমরা এই অক্ষটি কোথা থেকে পাব?

যদি আপনি কল্পনা করে থাকেন যে কোনও শক্ত কার্ডের ফাঁকে ফাঁকে ফাঁকে ফেলা হয়, তবে সেই কার্ডটি পৃথককারী বিমানের অংশ হবে। যদি আমরা সেই বিমানের স্বাভাবিকের দিকে প্রজেক্ট করি (উপরে ছবিতে কালো তীর), আমরা বিচ্ছিন্নতা দেখতে পাব। আমরা জানি যে উড়োজাহাজটি কী কারণ আমাদের দুটি ভেক্টর রয়েছে যা সেই বিমানে থাকে) একটি ভেক্টর নীল প্রান্তের সাথে প্রান্তিক হয় এবং অপর ভেক্টরটি হলুদ প্রান্তের সাথে প্রান্তিক হয় এবং আমরা সবাই জানি যে একটি বিমানের সাধারণটি কেবলমাত্র বিমানে শুয়ে থাকা দুটি ভেক্টরের ক্রস প্রোডাক্ট।

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


2
অসাধারণ ব্যাখ্যা! এবং ছবিগুলির জন্য ধন্যবাদ। @ অ্যাসিগিকমো নোট হিসাবে, আপনি যখন বলছেন যে "9 টি অক্ষগুলি বি এবং এর কিনারার ক্রস পণ্যগুলি দ্বারা তৈরি করা হয়" তখন কিছুটা বিভ্রান্তি হয়, যেহেতু আমরা প্রান্তগুলির পরিবর্তে কেবল সাধারণগুলি ব্যবহার করতে পারি। আবার ধন্যবাদ :)

5
@ জো ররক কিউবিডের জন্য আপনি সঠিক, কেবল নরমালগুলি ব্যবহার করুন, কারণ নরমাল এবং প্রান্তগুলি একত্রিত করা হয়েছে, তবে অন্যান্য আকারগুলির জন্য (যেমন টেট্রহেড্রনস, অন্যান্য পলিহেড্রন) সাধারণগুলি প্রান্তগুলির সাথে একত্রিত হয় না।
কেন

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

11

কেনের উত্তর নোট:

9 টি অক্ষগুলি A এর প্রান্ত এবং বি এর প্রান্তের ক্রস পণ্যগুলি দিয়ে তৈরি

এটি প্রান্তগুলি উল্লেখ করতে কিছুটা বিভ্রান্তিকর, কারণ 6 টি স্বাভাবিকের তুলনায় 12 টি প্রান্ত রয়েছে, যখন আপনি খুব একই আউটপুটের জন্য তিনটি প্রধান নরমাল ব্যবহার করতে পারেন - প্রান্তগুলি সমস্ত নরমালগুলির সাথে একত্রিত হয়, তাই আমি পরিবর্তে সেগুলি ব্যবহার করার পরামর্শ দিই !

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

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

পরীক্ষার জন্য অক্ষগুলির একটি সম্পূর্ণ তালিকা এখানে দুটি ওবিবি দেওয়া হয়েছে, এ এবং বি, যেখানে x, y এবং z ভিত্তি ভেক্টর / তিনটি অনন্য নরমালকে বোঝায়। 0 = x অক্ষ, 1 = y অক্ষ, 2 = z অক্ষ

  1. A0
  2. A1
  3. A2
  4. B0
  5. B1
  6. B2
  7. ক্রস (a0, বি 0)
  8. ক্রস (a0, বি 1)
  9. ক্রস (a0, বি 2)
  10. ক্রস (এ 1, বি 0)
  11. ক্রস (এ 1, বি 1)
  12. ক্রস (এ 1, বি 2)
  13. ক্রস (a2, b0)
  14. ক্রস (এ 2, বি 1)
  15. ক্রস (এ 2, বি 2)

এখানে একটি সামান্য সতর্কতাও রয়েছে, যা সম্পর্কে আপনার সচেতন হওয়া উচিত।

যখন বস্তুর মধ্যে যে কোনও দুটি অক্ষ একই দিকে নির্দেশ করে তখন ক্রস পণ্য আপনাকে শূন্য ভেক্টর দেয় {0,0,0।।

এছাড়াও, যেহেতু এই অংশটি বাদ ছিল, তাই প্রজেকশনটি ওভারল্যাপ হচ্ছে কিনা তা যাচাই করার জন্য আমার বাস্তবায়নটি এখানে। সম্ভবত আরও ভাল উপায় আছে, কিন্তু এটি আমার পক্ষে কাজ করেছিল! (ইউনিটি এবং এর সি # এপিআই ব্যবহার করে)

// aCorn and bCorn are arrays containing all corners (vertices) of the two OBBs
private static bool IntersectsWhenProjected( Vector3[] aCorn, Vector3[] bCorn, Vector3 axis ) {

    // Handles the cross product = {0,0,0} case
    if( axis == Vector3.zero ) 
        return true;

    float aMin = float.MaxValue;
    float aMax = float.MinValue;
    float bMin = float.MaxValue;
    float bMax = float.MinValue;

    // Define two intervals, a and b. Calculate their min and max values
    for( int i = 0; i < 8; i++ ) {
        float aDist = Vector3.Dot( aCorn[i], axis );
        aMin = ( aDist < aMin ) ? aDist : aMin;
        aMax = ( aDist > aMax ) ? aDist : aMax;
        float bDist = Vector3.Dot( bCorn[i], axis );
        bMin = ( bDist < bMin ) ? bDist : bMin;
        bMax = ( bDist > bMax ) ? bDist : bMax;
    }

    // One-dimensional intersection test between a and b
    float longSpan = Mathf.Max( aMax, bMax ) - Mathf.Min( aMin, bMin );
    float sumSpan = aMax - aMin + bMax - bMin;
    return longSpan < sumSpan; // Change this to <= if you want the case were they are touching but not overlapping, to count as an intersection
}

1
সাইটে স্বাগতম। দয়া করে দেখুন সহায়তা কেন্দ্রটি দেখুন এবং বিশেষত নোট করুন যে এই সাইটটি কোনও ফোরাম নয় এবং অন্যান্য উত্তরের "জবাব দেওয়া" ভাল ধারণা নয় (কারণ আপনার উত্তর দেওয়া পোস্টের আগে আপনার "উত্তর" উপস্থিত নাও হতে পারে)। আপনার উত্তরগুলি এমনভাবে লিখতে ভাল যা একা দাঁড়িয়ে থাকে, এবং আপনি যদি বিশেষভাবে কোনও বিদ্যমান পোস্ট স্পষ্ট করতে চান তবে মন্তব্যগুলি ব্যবহার করুন।
জোশ

স্পষ্টীকরণ Acegikmo জন্য ধন্যবাদ! প্রান্তগুলি খুব রেফারেন্স দ্বারা আমি কিছুটা বিভ্রান্ত হয়ে পড়েছিলাম। @ জোশ পেট্রি আপনার মন্তব্যের শেষে হাসি ফেলা উচিত যাতে নবাগতরা জানেন যে আপনি সেগুলি বন্ধ করছেন না :)

আমার মন্তব্যগুলি প্রান্তের তুলনায় বনাম স্বাভাবিকগুলি দেখুন
কেন

2

Acegikmo এর উত্তরের উপর ভিত্তি করে সি # উদাহরণ কাজ করা (কিছু একতা এপিআই ব্যবহার করে):

using UnityEngine;

public class ObbTest : MonoBehaviour
{
 public Transform A;
 public Transform B;

 void Start()
 {
      Debug.Log(Intersects(ToObb(A), ToObb(B)));
 }

 static Obb ToObb(Transform t)
 {
      return new Obb(t.position, t.localScale, t.rotation);
 }

 class Obb
 {
      public readonly Vector3[] Vertices;
      public readonly Vector3 Right;
      public readonly Vector3 Up;
      public readonly Vector3 Forward;

      public Obb(Vector3 center, Vector3 size, Quaternion rotation)
      {
           var max = size / 2;
           var min = -max;

           Vertices = new[]
           {
                center + rotation * min,
                center + rotation * new Vector3(max.x, min.y, min.z),
                center + rotation * new Vector3(min.x, max.y, min.z),
                center + rotation * new Vector3(max.x, max.y, min.z),
                center + rotation * new Vector3(min.x, min.y, max.z),
                center + rotation * new Vector3(max.x, min.y, max.z),
                center + rotation * new Vector3(min.x, max.y, max.z),
                center + rotation * max,
           };

           Right = rotation * Vector3.right;
           Up = rotation * Vector3.up;
           Forward = rotation * Vector3.forward;
      }
 }

 static bool Intersects(Obb a, Obb b)
 {
      if (Separated(a.Vertices, b.Vertices, a.Right))
           return false;
      if (Separated(a.Vertices, b.Vertices, a.Up))
           return false;
      if (Separated(a.Vertices, b.Vertices, a.Forward))
           return false;

      if (Separated(a.Vertices, b.Vertices, b.Right))
           return false;
      if (Separated(a.Vertices, b.Vertices, b.Up))
           return false;
      if (Separated(a.Vertices, b.Vertices, b.Forward))
           return false;

      if (Separated(a.Vertices, b.Vertices, Vector3.Cross(a.Right, b.Right)))
           return false;
      if (Separated(a.Vertices, b.Vertices, Vector3.Cross(a.Right, b.Up)))
           return false;
      if (Separated(a.Vertices, b.Vertices, Vector3.Cross(a.Right, b.Forward)))
           return false;

      if (Separated(a.Vertices, b.Vertices, Vector3.Cross(a.Up, b.Right)))
           return false;
      if (Separated(a.Vertices, b.Vertices, Vector3.Cross(a.Up, b.Up)))
           return false;
      if (Separated(a.Vertices, b.Vertices, Vector3.Cross(a.Up, b.Forward)))
           return false;

      if (Separated(a.Vertices, b.Vertices, Vector3.Cross(a.Forward, b.Right)))
           return false;
      if (Separated(a.Vertices, b.Vertices, Vector3.Cross(a.Forward, b.Up)))
           return false;
      if (Separated(a.Vertices, b.Vertices, Vector3.Cross(a.Forward, b.Forward)))
           return false;

      return true;
 }

 static bool Separated(Vector3[] vertsA, Vector3[] vertsB, Vector3 axis)
 {
      // Handles the cross product = {0,0,0} case
      if (axis == Vector3.zero)
           return false;

      var aMin = float.MaxValue;
      var aMax = float.MinValue;
      var bMin = float.MaxValue;
      var bMax = float.MinValue;

      // Define two intervals, a and b. Calculate their min and max values
      for (var i = 0; i < 8; i++)
      {
           var aDist = Vector3.Dot(vertsA[i], axis);
           aMin = aDist < aMin ? aDist : aMin;
           aMax = aDist > aMax ? aDist : aMax;
           var bDist = Vector3.Dot(vertsB[i], axis);
           bMin = bDist < bMin ? bDist : bMin;
           bMax = bDist > bMax ? bDist : bMax;
      }

      // One-dimensional intersection test between a and b
      var longSpan = Mathf.Max(aMax, bMax) - Mathf.Min(aMin, bMin);
      var sumSpan = aMax - aMin + bMax - bMin;
      return longSpan >= sumSpan; // > to treat touching as intersection
 }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.