मैं एक गोले और विमान के बीच टकराव की प्रतिक्रिया की गणना कैसे करूं?


9

मैं एक साधारण 3 डी गेम बनाने की कोशिश कर रहा हूं और खेल की दुनिया की सीमा के भीतर खिलाड़ी को विवश करने की जरूरत है। जब खिलाड़ी दुनिया के किनारों से टकराता है तो मैं चाहता हूं कि खिलाड़ी का जहाज थोड़ा उछल जाए।

वास्तव में मैं एक बॉक्स के भीतर खिलाड़ी को फंसाने की कोशिश कर रहा हूं, और उन्हें पक्षों से भागने से रोक सकता हूं ...

मैं विमानों के संग्रह के रूप में गैमवर्ल्ड की सीमाओं को परिभाषित करने में कामयाब रहा हूं, मूल से मानदंडों और दूरी के साथ। खिलाड़ी के पास एक गोलाकार बाउंडिंग क्षेत्र है और इस वेबसाइट का अनुसरण करने से 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) जोड़ सकते हैं। यदि आप कोणीय वेग को शामिल करना चाहते हैं (शायद आपका गोला घूम रहा है), तो समीकरण थोड़ा और अधिक जटिल हो जाते हैं।

अधिक जानकारी के लिए, मैं आपको रिगिड बॉडी डायनेमिक्स पर क्रिस हेकर के लेखों का संदर्भ दूंगा । यदि आपने पहले क्रिस हेकर के बारे में नहीं सुना है, तो वह खेल भौतिकी के साथ-साथ प्रक्रियात्मक चरित्र निर्माण और स्पोर में एनीमेशन पर अपने काम के लिए जाना जाता है।


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

ठीक है यह ज्यादातर काम करने लगता है, लेकिन यह थोड़ा अजीब है। मुझे लगता है कि मैं अपने कोड में गलत बिंदु पर ऐसा कर सकता हूं। क्या मुझे अपने सभी ऑब्जेक्ट्स के माध्यम से लूप करना चाहिए और परीक्षण करना चाहिए कि क्या मैं उन्हें ले जाने से पहले टकरा जाऊंगा (इस आधार पर कि वे अगले फ्रेम में कहां जा रहे हैं) या उन्हें स्थानांतरित करें और फिर बाद में टकराव के लिए परीक्षण करें?
पिकु

@ पिकु, नहीं पता नहीं कि वे टकराएंगे या नहीं। यदि टकराव होता है तो याद रखें कि एक बहुत अच्छा मौका है कि दो वस्तुएं अब उस जगह से बहुत अधिक ओवरलैप हो रही हैं जहां वास्तविक टक्कर हुई होगी। आपको अनिवार्य रूप से यह पता लगाने की आवश्यकता है कि टक्कर कहाँ हुई है जैसे कि आपके पास अनंत फ्रैमरेट (जो आप नहीं करते हैं) और ऑब्जेक्ट को उस स्थिति में वापस ले जाएं जहां टक्कर शुरू में हुई होगी। यदि आप वस्तुओं को इस तरह अलग नहीं करते हैं तो आप लगातार उसी टकराव पर प्रतिक्रिया करेंगे और वस्तु अटक जाएगी।
जोनाथन डिकिंसन

@ पिकु और ऐसा करने के लिए हम उस समय का पता लगाते हैं, जहां टक्कर हुई थी (जिसे TOI / प्रभाव का समय कहा जाता है)। एक बार जब हमारे पास होता है कि हम इसे वापस ले जाने के लिए ऑब्जेक्ट के वेग का उपयोग कर सकते हैं ( distance = speed * time, आमतौर पर त्रुटि से बचने के लिए एक अतिरिक्त छोटी दूरी के साथ) और फिर टकराव का परिणाम क्या है, इसके वेग को अपडेट करें।
जोनाथन डिकिंसन

@ पिकू का यह भी पता नहीं है कि हम अगले फ्रेम में कहां होंगे (मैंने ऐसा कभी नहीं देखा है जो व्यक्तिगत रूप से किया हो), लेकिन, आम तौर पर, हम टकराव का पता लगाते हैं और प्रतिक्रिया देते हैं: हम इस फ्रेम के लिए नई स्थिति की गणना करते हैं, लेकिन पहले हम इस फ्रेम के लिए नई स्थिति लागू करते हैं।
जोनाथन डिकिंसन

1

एफ = मा, या ए = एफ / एम। क्षेत्र और विमान के बीच टकराव बिंदु की गणना करें। यह आमतौर पर क्षेत्र केंद्र - सामान्य * त्रिज्या है। यदि आप अधिक सटीकता चाहते हैं, तो गणना करें कि गोला विमान में कितना दूर चला गया है, और अपनी गणना समायोजित करें। यह काफी हद तक वैकल्पिक है, जब तक आप वास्तव में सटीक भौतिकी नहीं चाहते। अब सामान्य के साथ सापेक्ष वेग की गणना करें। एक स्थैतिक विमान के लिए यह है: 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;?
शीतल शाह

वास्तव में हां, मुझे वह हिस्सा याद आ गया। इस पर ध्यान दिलाने के लिए धन्यवाद।
इयान यंग

0

मैं आपको पहले विमान से दूरी की गणना करने का सुझाव दूंगा; और फिर जब दूरी = = त्रिज्या से टकराव की प्रतिक्रिया को पूरा करती है।

फिर आप दूरी की गणना करने के लिए इसे बदल सकते हैं और यदि दूरी कम है कि त्रिज्या (जिसका अर्थ है कि ऑब्जेक्ट ओवरलैपिंग है) गेंदों की स्थिति को शिफ्ट करें और फिर टकराव की प्रतिक्रिया करें।

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