ฉันจะคำนวณการตอบสนองการชนระหว่างทรงกลมและระนาบได้อย่างไร


9

ฉันพยายามสร้างเกมสามมิติที่เรียบง่ายและจำเป็นต้อง จำกัด ผู้เล่นให้อยู่ในขอบเขตของโลกของเกม เมื่อผู้เล่นชนด้านข้างของโลกฉันต้องการให้เรือของผู้เล่นกระเด็นเล็กน้อย

ผลที่ตามมาฉันพยายามดักจับผู้เล่นภายในกล่องและหยุดพวกเขาจากการหลบหนีผ่านด้านข้าง ...

ฉันจัดการเพื่อกำหนดขีด จำกัด ของ gameworld เป็นชุดของเครื่องบินที่มีบรรทัดฐานและระยะทางจากแหล่งกำเนิด ผู้เล่นที่มีรูปทรงกลม bounding ทรงกลมและจากการติดตามเว็บไซต์นี้http://www.gamasutra.com/view/feature/3383/simple_intersection_tests_for_games.phpฉันมีการจัดการในการตรวจสอบการชนกัน

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

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

คำตอบ:


4

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

reflected = 2 * plane.normal * (plane.normal * sphere.velocity)
sphere.velocity -= reflected

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

สำหรับข้อมูลเพิ่มเติมผมจะนำคุณไปยังบทความคริส Hecker บนแข็งร่างกาย Dynamics หากคุณไม่เคยได้ยิน Chris Hecker มาก่อนเขาเป็นที่รู้จักกันดีในเรื่องเกมฟิสิกส์รวมถึงผลงานการสร้างตัวละครและภาพเคลื่อนไหวใน Spore


4
นี่เป็นวิธีที่เหมาะสมในการไปอย่างไรก็ตามการคำนวณเวลาของการกระแทก (TOI) สามารถทำให้สิ่งต่าง ๆ มีความแม่นยำมากขึ้นเมื่อ framerates เปลี่ยนแปลงหรือลดลง การรู้โดยอิงตามความเร็วปัจจุบันผลกระทบที่เกิดขึ้นเมื่อนานมาแล้วสามารถช่วยคุณคำนวณเวลาของผลกระทบและการใช้ที่คุณสามารถย้ายทรงกลมกลับไปที่ตำแหน่งของมันในขณะที่มีผลกระทบและปรับความเร็วจากที่นั่น หลังจากปรับตำแหน่งและความเร็วจากจุดกระแทกในเวลาที่กระทบคุณจะเคลื่อนที่ไปตามความเร็วใหม่ตามระยะเวลาที่คุณหักเพื่อไปยัง TOI
Nic Foster

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

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

@Piku และการทำเช่นนั้นเราหาเวลาในอดีตที่การปะทะเกิดขึ้น (เรียกว่า TOI / เวลาของผลกระทบ) เมื่อเรามีสิ่งนั้นแล้วเราสามารถใช้ความเร็วของวัตถุในการเคลื่อนย้ายกลับ ( distance = speed * timeโดยปกติจะมีระยะทางเล็ก ๆ เป็นพิเศษเพื่อหลีกเลี่ยงข้อผิดพลาด) แล้วอัปเดตความเร็วของมันเป็นผลการชน
Jonathan Dickinson

@Piku เราก็ไม่ได้คิดว่าเราจะอยู่ที่ไหนในเฟรมถัดไป (ฉันไม่เคยเห็นมันมาก่อน) แต่โดยทั่วไปแล้วเราทำการตรวจจับการชนและตอบสนอง: หลังจากที่เราคำนวณตำแหน่งใหม่สำหรับเฟรมนี้ แต่ก่อน เราใช้ตำแหน่งใหม่สำหรับเฟรมนี้
Jonathan Dickinson

1

F = ma หรือ a = F / m คำนวณจุดชนระหว่างทรงกลมและระนาบ นี่คือศูนย์กลางของทรงกลม - รัศมี * ปกติ หากคุณต้องการความแม่นยำมากขึ้นให้คำนวณว่าทรงกลมทะลุระนาบเท่าไรและปรับการคำนวณของคุณ แน่นอนว่านี่เป็นทางเลือกส่วนใหญ่เว้นแต่ว่าคุณต้องการฟิสิกส์ที่แม่นยำจริงๆ ตอนนี้คำนวณความเร็วสัมพัทธ์ตามปกติ สำหรับระนาบคงที่นี่คือ: Vball Dot N จากนั้นคูณ VballDotN ด้วย -1 และคูณด้วยมวล ในวิชาฟิสิกส์ในระยะนี้คุณจะคูณมันด้วยค่าสัมประสิทธิ์ของการชดใช้ (ปัจจัยการตีกลับ) คูณสเกลาร์นี้ด้วย N และคุณมีกำลังของคุณ

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

vec3 Vrel = Ball.getVelocity();
float vDotN = Vrel.Dot(CollisionNormal);
vec3 F = -(1.0f+Ball.getRestitution())*vDotN;
F*=Ball.getMass();
Ball.accelerate(F/Ball.getMass());

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

vec3 Ft = -(Ball.getvelocity()+(vDotN*CollisionNormal));
Ft*=Ball.getKineticFriction()+Wall.getKineticFriction(); //you could fudge these numbers
Ft*=Ball.getMass();
vec3 vec2Centre = Ball.getPosition()-ContactPoint;
vec3 Torque = cross(vec2Centre,Ft);
Ball.AngularAccelerate(Torque/Ball.getMomentofInertia(glm::normalize(Torque)));

ตรวจสอบให้แน่ใจว่าได้คำนวณ Ft ก่อนใช้เอฟเฟ็กต์เชิงเส้นใด ๆ มิฉะนั้นแรงเสียดทานจะไม่แม่นยำ


ไม่ควรจะเป็นบรรทัดที่ 3: vec3 F = -CollisionNormal * (1.0f+Ball.getRestitution())*vDotN;?
Shital Shah

ใช่แน่นอนฉันพลาดส่วนนั้นไป ขอบคุณที่ชี้นำ
Ian Young

0

ฉันขอแนะนำให้คำนวณระยะทางจากเครื่องบินก่อน แล้วเมื่อระยะทาง <= ถึงรัศมีทำปฏิกิริยาการชน

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.