OBB กับการตรวจจับการชน OBB


20

สมมติว่าคุณมี Bounding Box Object สองชิ้นแต่ละอันจะเก็บจุดยอดปัจจุบันของกล่องในเวกเตอร์ที่มีจุดยอดทั้งหมดของวัตถุที่หมุนและแปลโดยสัมพันธ์กับแกนทั่วไป

นี่คือภาพเพื่ออธิบายปัญหาของฉัน:

ฉันจะทำงานอย่างไรหาก OBB ทั้งสองวางซ้อนทับลิงก์ใด ๆ เพื่อช่วยอธิบายวิธีการแก้ไขปัญหาจะได้รับการต้อนรับ ไม่มีอะไรซับซ้อนเกินไปโปรด ...

คำตอบ:


16

OBB เป็นตัวเรือนูน ฮัลล์นูนเป็นรูปร่าง 3 มิติที่ไม่มี "crannies" บนพื้นผิว ทุก "ชน" (จุดสุดยอด) บนตัวเรือนูนยื่นออกมาด้านนอกไม่เข้าด้านใน หากคุณหั่นเครื่องบินผ่านตัวถังนูนคุณจะได้รูปหลายเหลี่ยมนูน (เพียงรูปเดียว) หากคุณอยู่ในลำเรือนูนและยิงเลเซอร์ชี้ออกไปด้านนอกคุณจะเจาะทะลุพื้นผิวของลำเรือเพียงหนึ่งครั้งเท่านั้น (ไม่ถึงสองครั้ง)

การทดสอบทฤษฎีการแยกแกนสามารถใช้ตรวจจับการชนของเปลือกนูนได้ การทดสอบ SAT นั้นง่าย มันทำงานได้ใน 2D และ 3D แม้ว่ารูปภาพด้านล่างจะเป็นแบบ 2D แต่ก็สามารถนำไปใช้กับ 3D ได้อย่างง่ายดาย

แนวคิด

นี่คือแนวคิดหลักที่คุณใช้กับ SAT:

  • สองรูปทรงตัดเฉพาะถ้าพวกเขามีการทับซ้อนกันเมื่อ "คาดการณ์" เข้าสู่ทุกแกนปกติของรูปร่างทั้ง

"Projection" ของรูปร่างบนเวกเตอร์ 1D มีลักษณะเช่นนี้ (สิ่งที่ฉันเรียกว่า "crushing")

รูปร่างที่มี verts สีแดงและแกน

ป้อนคำอธิบายรูปภาพที่นี่

"การฉายรูปร่างให้กับแกน" หมายถึงการวางฉากตั้งฉากจากแต่ละจุดบนรูปร่างเพื่อให้ถึงจุดบนแกน คุณสามารถคิดได้ว่านี่คือ "บดขยี้" คะแนนด้วยมือที่รวบรวมทุกอย่างและตั้งฉากกับแกน

ป้อนคำอธิบายรูปภาพที่นี่

สิ่งที่คุณเหลือ: คะแนนบนแกน

ป้อนคำอธิบายรูปภาพที่นี่

SAT พูดว่า:

สำหรับลำตัวนูน 2 ลูกเพื่อตัดกันพวกมันจะต้องทับซ้อนกันในทุกแกน (ที่ทุกรูปร่างปกตินับเป็นแกนที่เราต้องตรวจสอบ)

ใช้รูปทรงเหล่านี้ 2:

ป้อนคำอธิบายรูปภาพที่นี่

คุณเห็นว่าพวกมันไม่ตัดกันดังนั้นให้ลองใช้สองสามแกนเพื่อแสดงว่าการทับซ้อนไม่เกิดขึ้น

ลองใช้ยอดปกติของเพนตากอน:

ป้อนคำอธิบายรูปภาพที่นี่

นี่คือขอบเขต พวกเขาทับซ้อนกัน

ป้อนคำอธิบายรูปภาพที่นี่

ลองทางด้านซ้ายของสี่เหลี่ยม ตอนนี้พวกมันไม่ทับซ้อนกันในแกนนี้ดังนั้นจึงไม่มีสัญญาณรบกวน

ป้อนคำอธิบายรูปภาพที่นี่

ขั้นตอนวิธีการ:

สำหรับแต่ละใบหน้าปกติทั้งสองรูปร่าง:

  • ค้นหาขอบเขตขั้นต่ำและสูงสุด (ค่าที่มากที่สุดและน้อยที่สุด) ของการฉายภาพของจุดยอดมุมทั้งหมดของรูปร่างทั้งสองบนแกนนั้น
  • หากพวกเขาไม่ได้ทับซ้อนไม่มีสี่แยก

และนั่นเป็นเรื่องจริง รหัสที่ทำให้การทำงานของ SAT นั้นสั้นและง่ายมาก

นี่คือรหัสบางส่วนที่แสดงให้เห็นถึงวิธีการฉายแกน SAT:

void SATtest( const Vector3f& axis, const vector<Vector3f>& ptSet, float& minAlong, float& maxAlong )
{
  minAlong=HUGE, maxAlong=-HUGE;
  for( int i = 0 ; i < ptSet.size() ; i++ )
  {
    // just dot it to get the min/max along this axis.
    float dotVal = ptSet[i].dot( axis ) ;
    if( dotVal < minAlong )  minAlong=dotVal;
    if( dotVal > maxAlong )  maxAlong=dotVal;
  }
}

รหัสโทร:

// Shape1 and Shape2 must be CONVEX HULLS
bool intersects( Shape shape1, Shape shape2 )
{
  // Get the normals for one of the shapes,
  for( int i = 0 ; i < shape1.normals.size() ; i++ )
  {
    float shape1Min, shape1Max, shape2Min, shape2Max ;
    SATtest( normals[i], shape1.corners, shape1Min, shape1Max ) ;
    SATtest( normals[i], shape2.corners, shape2Min, shape2Max ) ;
    if( !overlaps( shape1Min, shape1Max, shape2Min, shape2Max ) )
    {
      return 0 ; // NO INTERSECTION
    }

    // otherwise, go on with the next test
  }

  // TEST SHAPE2.normals as well

  // if overlap occurred in ALL AXES, then they do intersect
  return 1 ;
}

bool overlaps( float min1, float max1, float min2, float max2 )
{
  return isBetweenOrdered( min2, min1, max1 ) || isBetweenOrdered( min1, min2, max2 ) ;
}

inline bool isBetweenOrdered( float val, float lowerBound, float upperBound ) {
  return lowerBound <= val && val <= upperBound ;
}

Hullinatorดำเนินการทดสอบ SAT สำหรับตัว
ถัง

คำอธิบายที่น่ากลัว! ขอบคุณ ฉันคิดว่าคุณอาจจะมีการพิมพ์ผิดในบรรทัด: "เพื่อช่วยให้ลองแกนไม่กี่ที่จะแสดงถูกทับซ้อนไม่ได้เกิดขึ้น." แล้วเพราะคุณดำเนินการต่อไปให้ตัวอย่างที่พวกเขาทำที่ทับซ้อนกัน ขอบคุณอีกครั้ง!

คุณไม่จำเป็นต้องทำการทดสอบสำหรับผลิตภัณฑ์ข้ามทั้งหมดของมาตรฐาน? บทความนี้geometrictools.com/Documentation/DynamicCollisionDetection.pdfพูดอย่างนั้น
iNFINITEi

เป็นมูลค่าที่ระบุว่าวิธีการเฉพาะของ SAT นี้ใช้งานได้ใน 2D เท่านั้น ในแบบ 3 มิติคุณจะต้องได้มากกว่าบรรทัดฐานของแต่ละหน้า เมื่อคุณมีบรรทัดฐานที่ถูกต้องแล้วกระบวนการที่เหลือ (โครงการเปรียบเทียบ) จะเหมือนกันทุกประการ
คดีฟ้องร้องกองทุนโมนิก้า

ยากมากที่จะบอกจากภาพ 2D ของคุณว่าทิศทางใดที่ลูกศรกำลังไป
WDUK

7

คุณควรมองหาทฤษฎีการแยกแกนแยกแกนทฤษฎีบทมันมีไว้สำหรับวัตถุนูน มีกฎอยู่ว่า: "ถ้าวัตถุสองชิ้นไม่ได้ตัดกันจะมีระนาบที่การฉายภาพของวัตถุสองชิ้นนี้จะไม่ตัดกัน"

คุณสามารถหาตัวอย่างได้จากwikiวิกิพีเดียแต่มันซับซ้อนกว่าสำหรับกรณีเล็กน้อย

สามารถพบสิ่งที่เหมาะสมกว่าสำหรับปัญหาของคุณได้ที่นี่ (รถสองคันชนกัน)


1

บทความSATเพิ่มเติม

บทความล่าสุดในเว็บไซต์นี้มาพร้อมกับรหัสที่สมบูรณ์ฉันคิดว่ามันอยู่ใน FLASH ฉันไม่มีความคิด แต่ฉันมีปัญหา 0 ข้อที่แปลงเป็น C ++ เมื่อฉันต้องใช้ SAT เป็นครั้งแรกไม่ควรยากที่จะ ทำเช่นเดียวกันสำหรับภาษาอื่น ๆ สิ่งเดียวที่คุณจะต้องเพิ่มคือการจัดเก็บเวกเตอร์การกระจัดในแต่ละการคำนวณ (ถ้ามันเล็กที่สุด, แน่นอนคุณจะเข้าใจสิ่งนี้เมื่อคุณเรียนรู้เกี่ยวกับ SAT) โค้ดในบทช่วยสอนนี้ไม่ได้ทำเช่นนั้น คุณท้ายด้วยเวกเตอร์ที่คำนวณล่าสุด

http://rocketmandevelopment.com/tag/separation-axis-theorem/

ดีมากแบบฝึกหัด N-Game เก่า สุดยอดทฤษฎี SAT บนเว็บ

http://www.metanetsoftware.com/technique/tutorialA.html


มันน่ารำคาญเหลือเกินที่ไม่มีใครโพสต์แหล่งข้อมูลที่ใช้งานได้อย่างสมบูรณ์กับคลาสที่ต้องการทั้งหมด ฉันเปลี่ยนรหัสของเขาให้เป็นตัวอย่างของฉันเอง แต่มันก็ไม่ได้ผล :( นี่เป็นโครงการของฉันจนถึงตอนนี้ถ้าใครสามารถช่วยฉันแก้ปัญหาที่มันจะดีมาก link
Joshua Barnett

คุณหมายถึงอะไรมันไม่ทำงาน ให้ความสนใจกับวิธีการจัดเก็บจุดยอดของคุณในภาพที่คุณมีในระบบพิกัดคาร์ทีเซียนในบทช่วยสอนเขาเก็บจุดยอดเป็นเวกเตอร์เทียบกับเซนทรอยด์ (สิ่งที่คุณต้องทำคือลบเซนทรอยด์จากจุดยอดของคุณเองหรือ ลบบรรทัดที่เขาปรับเปลี่ยนจุดยอดของตัวเอง), ฟังก์ชั่นเช่นผลิตภัณฑ์ dot คุณสามารถสร้างตัวเองได้โดยไม่ต้องการคำแนะนำสำหรับสิ่งที่เหลือควรตรงไปข้างหน้าไม่ใช่วัสดุวางสำเนาเรียนรู้ SAT ก่อนที่จะนำไปใช้
dreta

นี่คือวิธีที่ฉันใช้งาน: SAT.as , Shape2D.as , Centroidคุณหมายถึงอะไร? ศูนย์กลางของรูปหลายเหลี่ยมเช่น (x, y)
Joshua Barnett

ในขณะนี้ฉันมีฟังก์ชั่น getOBB () ซึ่งคืนค่าจุดยอดตามรายละเอียดในภาพต้นฉบับของฉัน สิ่งนี้คำนวณจาก Vector <b2Vec2> ที่มีจุดยอดของรูปร่างตัวแปรมุมและตัวแปรตำแหน่ง
Joshua Barnett

ใช่, ศูนย์กลาง, วิธีที่ผู้ชายคนนี้สร้างรูปหลายเหลี่ยมของเขาคือโดยให้ค่าชดเชยจากศูนย์, idk AS3, แต่จากสิ่งที่ฉันเห็นคุณฉายจุดยอดของคุณตามที่, เมื่อคำนวณจุดผลิตภัณฑ์ลองลบเซนทรอยด์จากจุดยอด ) นอกเหนือจากนี้คุณไม่ได้ตรวจสอบเวกเตอร์การแยกใดที่ยังเล็กที่สุดคุณจะเก็บเฉพาะอันสุดท้ายที่คำนวณได้
dreta
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.