การชนวัตถุขนาดเล็กและความเร็วสูง: หลีกเลี่ยงการขุดอุโมงค์


14

แก้ไข / อัปเดต:คำถามที่ใหญ่ที่สุดของฉันตอนนี้คือสมการของ t = ... ที่ว่าเป็นขั้นตอนที่ 3 หรือไม่เป็นวิธีที่ดีกว่า ปัญหาอื่น ๆ ส่วนใหญ่ได้รับการแก้ไขเพียงบางส่วนหรือทั้งหมด แต่ไม่มีความคิดเห็นหรือคำตอบใด ๆ ที่สัมผัสกับปัญหานี้ได้ อาจต้องใช้วิธีการวิเคราะห์อีกครั้งความเร็วและระยะทางมีขนาดใหญ่เกินไปและวัตถุนั้นเล็กเกินไปสำหรับการแก้ปัญหาแบบวนซ้ำ / แบบเรียกซ้ำ (recursive solution) ใด ๆ วิธีแก้ปัญหาแบบวนซ้ำ / แบบวนซ้ำที่จะจัดการกับสถานการณ์ประเภทนี้ได้ดีแล้วฉันก็เปิดรับแน่นอน) ขอบคุณมากสำหรับความช่วยเหลือของคุณทุกคนยอดเยี่ยมและฉันซาบซึ้งในความคิดและความช่วยเหลือของคุณ!

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

เรย์แคสต์จะไม่ทำงานเนื่องจากนี่เป็นการตรวจจับการชนกันระหว่างวัตถุความเร็วสูงสองชิ้นไม่ใช่ระหว่างวัตถุหนึ่งกับผนังนิ่ง (ถ้าฉันไม่เข้าใจผิดว่าการส่งสเรย์?) ประสิทธิภาพเป็นสิ่งที่ต้องพิจารณาอย่างมาก ถ้าเป็นไปได้ทั้งหมดฉันต้องการหลีกเลี่ยงการตีที่ยิ่งใหญ่ ฉันมี quadtree ใช้งานได้ดีและมีประสิทธิภาพมาก ( http://en.wikipedia.org/wiki/Quadtree ) ดังนั้นฉันจะแก้ไขและใช้ตามที่อธิบายไว้ด้านล่าง

แก้ไข: การลดช่วงเวลาจะไม่ทำงาน ความเร็วที่สูงเกินไปสำหรับการแก้ปัญหานี้ซึ่งหมายความว่าฮิตประสิทธิภาพการทำงานจะดีเกินไปในขณะที่ยังขาดหายไปส่วนใหญ่ของชนอุโมงค์ (ตัวอย่างเช่นฉันอาจมีวัตถุที่มีขนาดประมาณ 1 หน่วยไปด้วยความเร็วที่วัดได้ในหน่วยล้านต่อช่วงเวลา ... )

โซลูชั่นที่เสนอ:

ขั้นตอนที่ 1:

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

ขั้นตอนที่ 2: (อาจต้องการข้ามขั้นตอนนี้หรือไม่)

ผ่านรายการของการชนกันที่เป็นไปได้ที่สร้างขึ้นโดย quadtree ดูว่าสี่เหลี่ยมตัดกันในการชนกันที่เป็นไปได้หรือไม่ ถ้าเป็นเช่นนั้นดำเนินการขั้นตอนที่ 3

แก้ไข: ด้านล่าง Sean Middleditch แนะนำให้ใช้วอลุ่มกวาด / จุดตัดของแคปซูล (หากวัตถุเป็นวงกลม) มีสามตัวเลือก: 1) ข้ามขั้นตอนที่ 2 โดยสิ้นเชิง 2) ทำตามขั้นตอนที่ 2 ในแบบของฉัน 3) ทำในแบบของฌอน วิธีของฌอนจะมีค่าใช้จ่ายในการคำนวณสูงกว่าที่คิดไว้ในกล่องของฉัน แต่มันจะกำจัดข้อดีที่ผิดพลาดมากกว่าวิธีของฉัน

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

ขั้นตอนที่ 3:

ใช้สมการ t = ด้านล่างหากการเลือกปฏิบัติ (เช่นส่วนที่อยู่ใต้รากที่สอง) เป็นลบหรือ 0 ไม่มีการชนกันถ้าเป็นบวกให้ใช้ค่า t เป็นเวลาของการชนกัน (หลังจากนั้นจึงปรับตำแหน่งได้ง่าย .. หากวัตถุทั้งสองยังคงอยู่หลังจากการชนกัน) สมการ:

t = (-1/2 sqrt ((2 a w-2 a x + 2 b y-2 b z-2 c w + 2 c x-2 d y + 2 dz) ^ 2-4 (w ^ 2- 2 w x + x ^ 2 + y ^ 2-2 y z + z ^ 2) (a ^ 2-2 a c + b ^ 2-2 b d + c ^ 2 + d ^ 2-r ^ 2-2 r ss ^ 2)) - w + a xb y + b z + c wc x + d yd z) / (w ^ 2-2 w x + x ^ 2 + y ^ 2-2 y z + z ^ 2 ) .

โดยที่ (1 และ 2 ใช้เพื่อแสดงว่าวัตถุ 1 และ 2):

t เป็นค่าลบเวลาระหว่าง 0 ถึง -1 โดยที่ 0 คือเฟรมปัจจุบันและ -1 คือเฟรมก่อนหน้า

a = x ตำแหน่ง 1;

b = y ตำแหน่ง 1;

c = x ตำแหน่ง 2;

d = y ตำแหน่ง 2;

w = x velocity 1;

x = x velocity 2;

y = y velocity 1;

z = y velocity 2;

r = รัศมี 1;

s = รัศมี 2;

ที่มา: (^ 2 หมายถึงกำลังสอง)

ใช้สมการพารามิเตอร์ (ตัวอย่างเช่น newxpos1 = a + t w) สำหรับการเคลื่อนไหวของวัตถุและเสียบเข้ากับสูตรระยะทาง (กำลังสองทั้งสองข้าง): สูตรระยะทางกำลังสอง = (a + t w - (c + t x)) ^ 2 + (b + t y - (d + t * z)) ^ 2 จำไว้ว่า t จะเป็นค่าลบ เพื่อหาเวลาปะทะกันของวัตถุทรงกลมสองตัวเราตั้งค่าด้านซ้ายเท่ากับ (r + s) ^ 2 การแก้สมการ t โดยใช้สมการกำลังสอง (และพีชคณิตน่าเบื่อมาก) เราได้สมการข้างบน "t = ... "

คำถามของฉัน:

1) วิธีนี้เป็นวิธีที่ดีหรือไม่? มันจะทำงานได้ทั้งหมดหรือไม่ ฉันจะเจอปัญหาที่ไม่คาดคิดหรือไม่? (ฉันรู้ว่าฉันกำลังจะมีปัญหาเมื่อวัตถุมากกว่า 2 ชิ้นชนกันในเวลาเดียวกัน แต่ฉันไม่สนใจเพราะในกรณีเดียวที่ฉันคัดค้านอย่างแท้จริงคือเมื่อพวกเขามีความเร็วสัมพัทธ์ต่ำ (ถ้าความเร็วสัมพัทธ์สูง จากนั้นโซลูชัน "โง่" ที่อัลกอริทึมให้จะ "ดีพอ" และเป็นไปไม่ได้ที่มนุษย์จะเห็นข้อผิดพลาด) และถ้ามากกว่า 2 ชนกับความเร็วสัมพัทธ์ต่ำในขั้นตอนเดียวกันการแก้ปัญหาส่วนใหญ่จะ อยู่ใกล้พออย่างไรก็ตามเนื่องจากฉันไม่ได้วางแผนว่าจะมีการชนแบบไม่ยืดหยุ่นจำนวนมาก)

2) การแสดงของฉันจะประสบมากหรือไม่? ฉันไม่คิดว่ามันจะ แต่ถ้ามันจะมีวิธีที่ดีกว่าที่จะทำมันได้หรือไม่

3) ฉันควรข้ามขั้นตอนที่ 2 และตรงจากขั้นตอนที่ 1 ถึง 3 หรือไม่ เห็นได้ชัดว่าขั้นตอนที่ 2 ไม่สำคัญ แต่อาจช่วยให้ประสิทธิภาพ (หรืออาจใช้เวลา CPU มากกว่าที่บันทึกไว้)

ความคิดเห็นข้อเสนอแนะหรือคำวิจารณ์อื่น ๆ ยินดีต้อนรับ ขอขอบคุณสำหรับความช่วยเหลือของคุณ!


1
Christer Ericson มีข้อมูลบางอย่างเกี่ยวกับการทดสอบทรงกลม swept / sphere ในหนังสือสีส้มของเขา มีสองสามวิธีในการแก้ปัญหา แต่ฉันคิดว่าคุณจะชอบช่วงเวลาที่ลดลงครึ่งหนึ่งมากที่สุด มันเป็นเรื่องดีที่จะพยายามหาสิ่งนี้ด้วยตัวคุณเอง แต่คุณควรไปดูที่สมุดสีส้มและเปรียบเทียบเพื่อรับรูทีนการตรวจจับที่ดีจริงๆและเรียนรู้เพิ่มเติม
RandyGaul

ดูเหมือนคุณจะมีแผน .. ลองดูแล้วมันใช้งานอย่างไร?
Trevor Powell

ฉันคิดว่าวิธี "ปกติ" คือการมีช่วงเวลาสูงสุดเล็กน้อยในเวลาเดลต้าของคุณ ดังนั้นหากคุณมี 1000ms ล่วงเลยไปเพียงแค่จำลอง 10x 100ms (หรือ 100x10ms หรือ 33x30ms หรืออะไรทำนองนั้น)
ashes999

@RandyGaul ฉันดูอัลกอริทึมที่อธิบายในหน้า 215-218 โดยเฉพาะหน้า 218 (ตัวอย่าง Google) มันค่อนข้างสง่างามถึงแม้ว่าฉันจะยังไม่ได้คิดถึงความหมายจุดแข็งและจุดอ่อนของมัน มันจะเร็วกว่าของฉันหรือไม่ ถ้าเป็นเช่นนั้นส่วนไหนของอัลกอริทึมของฉันที่ช้ากว่าการเรียกซ้ำของ Ericson สมการในขั้นตอนที่ 3 จะช้าเกินไปหรือไม่ การเรียกซ้ำทำให้ฉันลังเลเนื่องจากวัตถุบางอย่างอาจเคลื่อนที่เร็วมากดังนั้นจึงจำเป็นต้องใช้การเรียกซ้ำเป็นจำนวนมากในบางกรณี (เช่น OUCH, $ 70 สำหรับหนังสือเล่มนั้น ... )
MindSeeker

1
@MindSeeker ฉันไม่มีเวลาดูที่มาของคุณ แต่ฉันมั่นใจว่าอัลกอริทึมในหนังสือของ Ericson ทุกคนจะทำงานได้ดีจริง ๆ และอาจเร็วกว่าและแข็งแกร่งกว่าสิ่งของของคุณ คุณสามารถค้นหารุ่น PDF ออนไลน์ได้ฟรีหากคุณต้องการสาธิตหน้าอื่น ๆ นอกจากนี้หากคุณกำลังทำการตรวจจับการชนบ่อยๆสมุดสีส้มเป็นวัตถุดิบ
RandyGaul

คำตอบ:


9

คุณได้เป็นหลักสร้างรุ่นค่อนข้างมากกว่าความกระตือรือร้นของปริมาณการกวาด

รับสองตำแหน่งของวัตถุ "Sweep" วัตถุตั้งแต่เริ่มต้นจนจบ สำหรับทรงกลมนี่จะสร้างแคปซูล สำหรับกล่องสิ่งนี้จะสร้างเป็นรูปหกเหลี่ยม (หรือกล่องที่ยาวกว่าคือการเคลื่อนไหวเป็นไปตามแกนเดียว) สำหรับรูปหลายเหลี่ยมนูนทั่วไปนี้จะสร้างรูปหลายเหลี่ยมนูนที่แตกต่างกัน

ตอนนี้คุณสามารถทำการทดสอบทางแยก (รวมถึงการค้นหาควอดทรี) โดยใช้โวลุ่ม swept นี้ คุณสามารถคำนวณได้ว่าเกิดการปะทะเมื่อใดส่งต่อการจำลองจากเวลาเริ่มต้นไปจนถึงเวลาการชนและทำซ้ำ

ตัวเลือกอื่นที่ค่อนข้างง่ายกว่าคือทำตามที่ @ ashes999 ระบุไว้และเพียงแค่ใช้ช่วงเวลาที่เล็กลงหรือความเร็วที่เล็กลง มีความเร็วสูงสุดในอุดมคติที่ได้รับจากช่วงเวลาที่วัตถุไม่สามารถเคลื่อนที่ได้ไกลกว่าด้านที่แคบที่สุดในการแทรกสอดแบบฟิสิกส์เดียว สำหรับวัตถุขนาดเล็กหรือเร็วโดยเฉพาะคุณอาจไม่สามารถหาช่วงเวลาที่มีขนาดเล็กพอสมควรซึ่งทำงานได้ดี

ดูการตรวจจับการชนกันแบบเรียลไทม์สำหรับหนึ่งในหนังสือเกริ่นนำ / คนกลางที่ดีกว่าในหัวข้อการตรวจจับการชนกัน


ขอบคุณสำหรับการป้อนข้อมูลที่ยอดเยี่ยม! ทำลายคำตอบของคุณลงเพื่อที่ฉันจะได้ถามคำถามเกี่ยวกับมัน: "" กวาด "วัตถุตั้งแต่ต้นจนจบ" จนถึงตอนนี้ฉันกำลังติดตาม; การปรับปรุงวิธีกล่องของฉันดีขึ้นอย่างแน่นอน ฉันจะเลี้ยงรูปร่างเหล่านี้โดยควอดทรีแล้วตรวจสอบการชนกันที่แม่นยำยิ่งขึ้น "คุณสามารถคำนวณได้ว่าเกิดการชนกันเมื่อใด" ฮ่าฮ่าพูดง่ายกว่าทำ :) คุณแนะนำให้ฉันทำตามขั้นตอนที่ 3 สำหรับขั้นตอนนี้หรือไม่? หรือมีวิธีที่ดีกว่า นี่เป็นส่วนที่สำคัญอย่างยิ่ง
MindSeeker

[ดำเนินการต่อ] "ตัวเลือกอื่น ... " ฉันคิดเกี่ยวกับตัวเลือกนั้น แต่น่าเสียดายที่ความเร็วสูงเกินไป ดูการตอบกลับความคิดเห็นของฉันต่อ @ ashes999 และแก้ไขด้านบนสำหรับข้อมูลเพิ่มเติม ขอบคุณมากสำหรับความช่วยเหลือของคุณ!
MindSeeker

วิธีเดียวที่จะรู้เกี่ยวกับประสิทธิภาพการทำงานคือลองวัดและดู ฉันเคยเห็นโค้ดที่ไม่มีประสิทธิภาพ "ชัดเจน" บางรุ่นออกมาอย่างมีประสิทธิภาพอย่างหนาแน่นมาก่อนโดยทั่วไปแล้วด้วยเหตุผลที่ไม่เข้าใจง่าย อย่าถามว่าอะไรเร็วที่สุด; ทดสอบและค้นหา
Sean Middleditch

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

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

2

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

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


1

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

นี่คือลิงค์ไปสู่คำตอบที่ยอดเยี่ยมโดย sam hocevar ที่ให้คำอธิบายที่ดีที่สุดเกี่ยวกับเรื่องนี้ที่ฉันเคยพบ (เขาวาดภาพด้วยเช่นกันไชโย!)

/gamedev//a/55991/112940

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

เพียงเพื่อหลีกเลี่ยงการออกจาก "ลิงก์คำตอบเท่านั้น" ฉันจะให้สรุปความคิดของเขาอย่างรวดเร็ว:

  1. คำนวณความแตกต่าง Minkowski ระหว่างกล่องสองขอบเขต
  2. ใช้ความเร็วสัมพัทธ์ระหว่างนั้นทำการโยนส่วนรังสี / เส้นจากต้นกำเนิดไปยังกล่องที่สร้างโดย Minkowski Difference เพื่อให้ได้จุดตัดกัน
  3. หากรังสีกระทบกันให้แบ่งระยะทางที่รังสีของคุณผ่านด้วยความยาวของเวกเตอร์แทนค่าความเร็วสัมพัทธ์และคุณจะได้ "t"
  4. คลิกที่ลิงก์ที่ฉันให้ไว้ด้านบนและดูคำอธิบายที่สวยงามของทั้งหมดนี้พร้อมรูปภาพจำนวนมาก มันเจ๋งนะ.
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.