सैट के साथ 3 डी ओबीबी टक्कर के लिए कितने और कौन से कुल्हाड़ियों का उपयोग करना है


29

मैं सैट को लागू कर रहा हूं:

पृष्ठ 7 पर, तालिका में, यह परीक्षण करने के लिए 15 अक्ष को संदर्भित करता है ताकि हम टकराव पा सकें, लेकिन सिर्फ एक्स, आय और अज़ के साथ, मैं पहले से ही टक्कर ले रहा हूं।

मुझे अन्य सभी मामलों का परीक्षण करने की आवश्यकता क्यों है? क्या ऐसी कोई स्थिति है जहाँ सिर्फ कुल्हाड़ी, अय और अज़ पर्याप्त नहीं हैं?

जवाबों:


56

आपको झूठी सकारात्मकता मिल सकती है। टकराव का पता चला लेकिन वास्तव में टकराव नहीं हुआ।

15 नंबर से आता है

  • ऑब्जेक्ट A से 3 अक्ष (चेहरे का मानदंड)
  • ऑब्जेक्ट बी से 3 अक्ष (चेहरे का मानदंड)
  • A और B के किनारों (3x3) के सभी जोड़े से 9 अक्ष
  • = कुल 15

9 अक्षों A के किनारों और B के किनारों के क्रॉस उत्पादों से बने होते हैं

  1. Ae1 x Be1 (B का किनारा 1 का किनारा 1)
  2. ए 1 एक्स बी 2
  3. ए 1 एक्स बी 3
  4. Ae2 x Be1
  5. ... और इसी तरह

पहले 6 अक्षों (चेहरे के मानदंडों से) का उपयोग यह जांचने के लिए किया जाता है कि क्या एक वस्तु का एक कोना दूसरी वस्तु के चेहरे को काट रहा है। (या इन प्रकार के टकरावों को खत्म करने के लिए अधिक सही ढंग से)

किनारों के क्रॉस उत्पादों द्वारा गठित 9 अक्षों के सेट का उपयोग किनारे की टक्कर का पता लगाने के लिए किनारे पर विचार करने के लिए किया जाता है, जहां दूसरी वस्तु को भेदने वाला एक शीर्ष नहीं है। नीचे दिए गए फोटो में 'लगभग' टक्कर की तरह। इस उत्तर के बाकी हिस्सों के लिए मान लें कि चित्र में दो बक्से वास्तव में टकरा नहीं रहे हैं, लेकिन एक छोटी दूरी से अलग हो जाते हैं।

यहाँ छवि विवरण दर्ज करें

यदि हम सिर्फ SAT के लिए 6 फेस नॉर्म्स का उपयोग करते हैं तो क्या होता है, इसे देखें। नीचे दी गई पहली छवि नीले बॉक्स से एक अक्ष और पीले बॉक्स से 2 अक्ष दिखाती है। यदि हम दोनों वस्तुओं को इन अक्षों पर प्रोजेक्ट करते हैं, तो हम तीनों पर एक ओवरलैप प्राप्त करेंगे। नीचे दी गई दूसरी छवि नीले बॉक्स के शेष दो अक्षों और पीले बॉक्स के शेष अक्ष को दिखाती है। इन कुल्हाड़ियों पर फिर से प्रोजेक्ट करना सभी 3 पर ओवरलैप दिखाएगा।

तो केवल 6 फेस नॉर्म्स की जांच करने से सभी 6 एक्सिस पर ओवरलैप दिखाई देंगे, जो कि SAT के अनुसार, इसका मतलब है कि ऑब्जेक्ट टकरा रहे हैं, क्योंकि हम एक पृथक्करण नहीं खोज पाए हैं। लेकिन निश्चित रूप से, ये वस्तु टकरा नहीं रही हैं। अलग होने का कारण हमें नहीं मिला है क्योंकि हमने बहुत कठिन नहीं देखा है!

यहाँ छवि विवरण दर्ज करें यहाँ छवि विवरण दर्ज करें

तो हम इस अंतर को कैसे पाएं? नीचे दी गई छवि एक अक्ष दिखाती है, जिस पर दोनों वस्तुओं का प्रक्षेपण एक अलगाव को प्रकट करेगा।

यहाँ छवि विवरण दर्ज करें

हमें यह धुरी कहां से मिलती है?

यदि आप कड़े कार्ड के टुकड़े को खाई में खिसकाने की कल्पना करते हैं, तो यह कार्ड अलग होने वाले विमान का हिस्सा होगा। यदि हम उस विमान के सामान्य पर (ऊपर चित्र में काला तीर) पर प्रोजेक्ट करते हैं, तो हम अलगाव देखेंगे। हम जानते हैं कि वह विमान क्या है क्योंकि हमारे पास दो वैक्टर हैं जो उस विमान पर लेटे हैं) एक वेक्टर नीले रंग के किनारे के साथ और दूसरा वेक्टर पीले रंग के किनारे के साथ संरेखित है और जैसा कि हम सभी जानते हैं कि एक विमान के लिए सामान्य बस एक विमान है विमान पर पड़ी दो वैक्टरों का क्रॉस उत्पाद।

तो OOBBs के लिए हमें यह सुनिश्चित करने की आवश्यकता है कि दो वस्तुओं के किनारों के क्रॉस उत्पादों के प्रत्येक संयोजन (उनमें से 9) यह सुनिश्चित करने के लिए कि हम किसी भी किनारे-किनारे अलगाव को याद नहीं कर रहे हैं।


2
बहुत बढ़िया व्याख्या! और चित्रों के लिए धन्यवाद। @Acegikmo नोट के रूप में, यह थोड़ा भ्रमित करने वाला है जब आप कहते हैं कि "9 अक्ष A के किनारों और B के किनारों के क्रॉस उत्पादों से बने होते हैं", क्योंकि हम केवल किनारों के बजाय मानदंडों का उपयोग कर सकते हैं। धन्यवाद फिर से :)

5
@joeRocc के लिए आप सही हैं, बस मानदंडों का उपयोग करें, क्योंकि मानदंड और किनारे संरेखित हैं, लेकिन अन्य आकृतियों (जैसे टेट्राहेड्रोन, अन्य पॉलीहेड्रॉन) के लिए मानदंड किनारों के साथ संरेखित नहीं हैं।
केन

दोस्त बहुत - बहुत धन्यवाद! मैं "गेम फिजिक्स इंजन डेवलपमेंट" नाम की इस अच्छी किताब को पढ़ रहा था और इस समस्या से जूझ रहा था। पता नहीं था कि हम 15 अक्षों का उपयोग क्यों कर रहे हैं। बहुत बहुत धन्यवाद। अब मैं इसके बारे में डींग मारने के लिए पर्याप्त आश्वस्त हूं। ; डी
अंकित सिंह कुशवाह

11

केन के उत्तर नोट:

9 अक्षों A के किनारों और B के किनारों के क्रॉस उत्पादों से बने होते हैं

यह किनारों को संदर्भित करने के लिए कुछ भ्रामक है, क्योंकि 6 मानदंडों की तुलना में 12 किनारे हैं, जब आप बहुत ही आउटपुट के लिए तीन मुख्य मानदंडों का उपयोग कर सकते हैं - किनारों को सभी मानदंडों के साथ गठबंधन किया जाता है, इसलिए मैं इसके बजाय उनका उपयोग करने की सलाह देता हूं !

यह भी ध्यान दें कि एक ही अक्ष के साथ इंगित करने वाले मानदंड, लेकिन एक अलग दिशा में, अनदेखा किए जाते हैं, और इस प्रकार हम तीन अद्वितीय अक्षों के साथ छोड़ दिए जाते हैं।

एक और बात जो मैं जोड़ना चाहूंगा, वह यह है कि यदि आप अलग-अलग अक्ष ढूंढते हैं, तो आप जल्दी से बाहर निकल कर इस गणना को अनुकूलित कर सकते हैं, इससे पहले कि आप उन सभी अक्षों की गणना करें, जिन्हें आप परीक्षण करना चाहते हैं। तो, नहीं, आपको हर मामले में सभी कुल्हाड़ियों का परीक्षण करने की आवश्यकता नहीं है, लेकिन आपको उन सभी का परीक्षण करने के लिए तैयार होने की आवश्यकता है :)

यहां दो ओबीबी, ए और बी, जहां एक्स, वाई और जेड आधार वैक्टर / तीन अद्वितीय मानदंडों का उल्लेख करते हैं, परीक्षण करने के लिए कुल्हाड़ियों की एक पूरी सूची है। 0 = x अक्ष, 1 = y अक्ष, 2 = z अक्ष

  1. a0
  2. a1
  3. a2
  4. B0
  5. बी 1
  6. b2
  7. पार (a0, b0)
  8. पार (a0, b1)
  9. पार (a0, b2)
  10. पार (a1, b0)
  11. पार (ए 1, बी 1)
  12. क्रॉस (ए 1, बी 2)
  13. पार (a2, b0)
  14. पार (a2, b1)
  15. पार (a2, b2)

थोड़ा कैविएट भी है, जिससे आपको अवगत होना चाहिए।

क्रॉस उत्पाद आपको एक शून्य वेक्टर {0,0,0} देगा जब ऑब्जेक्ट्स के बीच कोई भी दो अक्ष एक ही दिशा में इंगित करते हैं।

इसके अलावा, चूंकि यह हिस्सा छोड़ दिया गया था, यहां प्रोजेक्शन ओवरलैपिंग है या नहीं, यह जांचने के लिए मेरा कार्यान्वयन है। वहाँ शायद एक बेहतर तरीका है, लेकिन यह मेरे लिए काम किया! (एकता और उसके C # API का उपयोग करके)

// 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
 }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.