गुणन
कम से कम एकता के Quaternions के कार्यान्वयन के संदर्भ में, प्रश्न में वर्णित गुणन क्रम सही नहीं है। यह महत्वपूर्ण है क्योंकि 3D रोटेशन कम्यूटेटिव नहीं है ।
इसलिए, अगर मैं rotationChange
इसके शुरू होने से एक वस्तु को घुमाना चाहता हूं, तो मैं currentOrientation
इसे इस तरह लिखूंगा:
Quaternion newOrientation = rotationChange * currentOrientation;
(यानी। ट्रांसफ़ॉर्मेशन बायीं ओर स्टैक होता है - एकता के मैट्रिक्स कन्वेंशन के समान। सबसे दाएं घुमाव को "सबसे स्थानीय" छोर पर पहले लागू किया जाता है)
और अगर मैं एक रोटेशन द्वारा एक दिशा या ऑफसेट वेक्टर को बदलना चाहता था, तो मैं इसे इस तरह लिखूंगा:
Vector3 rotatedOffsetVector = rotationChange * currentOffsetVector;
(यदि आप इसके विपरीत करते हैं तो एकता एक संकलित त्रुटि उत्पन्न करेगी)
सम्मिश्रण
अधिकांश मामलों के लिए आप लेरपिंग घुमावों से दूर हो सकते हैं। ऐसा इसलिए है क्योंकि एक चतुर्भुज में "हुड के नीचे" का उपयोग किया गया कोण रोटेशन का आधा कोण है, जिससे यह मैट्रिक्स की तरह कुछ की तुलना में लार्प के रैखिक सन्निकटन के काफी करीब हो जाता है (जो सामान्य रूप से लार्प अच्छी तरह से नहीं होगा !)। अधिक स्पष्टीकरण के लिए इस वीडियो में लगभग 40 मिनट देखें ।
एक मामला जब आपको वास्तव में स्लेर्प की आवश्यकता होती है, जब आपको समय के साथ लगातार गति की आवश्यकता होती है, जैसे एनीमेशन टाइमलाइन पर कीफ्रेम के बीच इंटरपोलिंग। उन मामलों के लिए जहां आप सिर्फ यह ध्यान रखते हैं कि एक आउटपुट दो इनपुट्स (जैसे एक एनीमेशन की परतों के बीच) के बीच मध्यवर्ती है, तो आमतौर पर लेरप काफी अच्छी तरह से कार्य करता है।
और क्या?
दो यूनिट चतुर्भुजों का डॉट उत्पाद उनके बीच के कोण का कोसाइन देता है, इसलिए यदि आप घुमावों की तुलना करना चाहते हैं तो आप समानता के माप के रूप में डॉट उत्पाद का उपयोग कर सकते हैं। हालांकि यह थोड़ा अस्पष्ट है, इसलिए अधिक सुपाठ्य कोड के लिए मैं अक्सर Quaternion.Angle (a, b) का उपयोग करता हूं , जो कि अधिक स्पष्ट रूप से व्यक्त करता है कि हम कोणों की तुलना कर रहे हैं, परिचित इकाइयों (डिग्री) में।
इस प्रकार की सुविधा विधियाँ जो कि एकता के लिए प्रदान करती हैं, सुपर उपयोगी हैं। लगभग हर परियोजना में मैं इसका उपयोग कम से कम कुछ बार करता हूं :
Quaternion.LookRotation(Vector3 forward, Vector3 up)
यह एक चतुर्भुज बनाता है कि:
forward
सदिश तर्क के साथ इंगित करने के लिए स्थानीय z + अक्ष को घुमाता है
up
सदिश तर्क के लिए संभव के रूप में करीब इंगित करने के लिए स्थानीय y + अक्ष को घुमाता है, यदि प्रदान किया गया है, या (0, 1, 0)
यदि छोड़ा गया है
"अप" केवल "जितना संभव हो उतना करीब" होने का कारण यह है कि सिस्टम अतिव्यापी है। Z + का forward
उपयोग करके स्वतंत्रता की दो डिग्री का उपयोग किया जाता है (जैसे कि जम्हाई और पिच) इसलिए हमारे पास स्वतंत्रता की केवल एक डिग्री शेष है (रोल)।
मुझे बहुत बार लगता है कि मैं विपरीत सटीकता गुणों के साथ कुछ चाहता हूं: मैं चाहता हूं कि स्थानीय y + बिल्कुल साथ-साथ इंगित करें up
, और स्थानीय z + forward
शेष स्वतंत्रता के साथ जितना संभव हो सके ।
यह उदाहरण के लिए आता है जब आंदोलन इनपुट के लिए एक कैमरा-सापेक्ष समन्वय फ्रेम बनाने की कोशिश की जाती है: मैं चाहता हूं कि मेरी स्थानीय दिशा मंजिल या झुकी हुई सतह के लिए लंबवत बनी रहे, इसलिए मेरा इनपुट इलाके में चरित्र को सुरंग करने की कोशिश नहीं करता है। या उन्हें इससे दूर करना।
आपको यह भी मिल सकता है यदि आप चाहते हैं कि टारगेट के बुर्ज हाउसिंग एक टारगेट का सामना करें, बिना टंकी के शरीर के ऊपर से नीचे जाने पर / नीचे निशाना लगाने पर।
हम ऐसा करने के लिए अपने स्वयं के सुविधा समारोह का निर्माण कर सकते हैं, LookRotation
जिसका उपयोग भारी उठाने के लिए किया जाता है:
Quaternion TurretLookRotation(Vector3 approximateForward, Vector3 exactUp)
{
Quaternion rotateZToUp = Quaternion.LookRotation(exactUp, -approximateForward);
Quaternion rotateYToZ = Quaternion.Euler(90f, 0f, 0f);
return rotateZToUp * rotateYToZ;
}
यहाँ हम सबसे पहले लोकल y + से z +, और लोकल z + से y- घुमाते हैं।
फिर हम नए z + को अपनी दिशा में घुमाते हैं (इसलिए शुद्ध परिणाम स्थानीय y + अंक सीधे साथ होता है exactUp
), और नया y + जितना संभव हो उतना ही आगे की ओर नकारात्मक दिशा में जाता है (इसलिए शुद्ध परिणाम स्थानीय z + बिंदु जितना संभव हो उतना करीब है approximateForward
)
एक और आसान सुविधा विधि है Quaternion.RotateTowards
, जिसका मैं अक्सर उपयोग करता हूं:
Quaternion newRotation = Quaternion.RotateTowards(
oldRotation,
targetRotation,
maxDegreesPerSecond * Time.deltaTime
);
यह हमें targetRotation
फ्रैमरेट की परवाह किए बिना एक सुसंगत, नियंत्रणीय गति पर बंद होने देता है - घुमाव के लिए महत्वपूर्ण है जो गेमप्ले यांत्रिकी के परिणाम / निष्पक्षता को प्रभावित करता है (जैसे एक चरित्र के आंदोलन को मोड़ना, या एक बुर्ज ट्रैक-इन खिलाड़ी पर होना)। इस स्थिति में Naively Lerping / Slerping आसानी से उन मामलों को जन्म दे सकती है जहां आंदोलन उच्च स्तर पर स्नैपर हो जाता है, जिससे खेल संतुलन प्रभावित होता है। (यह कहना गलत नहीं है कि ये तरीके गलत हैं - निष्पक्षता को बदले बिना उनका सही तरीके से उपयोग करने के तरीके हैं, इसके लिए बस देखभाल की आवश्यकता है। RotateTowards
एक सुविधाजनक शॉर्टकट देता है जो हमारे लिए इस बात का ध्यान रखता है)
n
विभिन्न झुकाव (दृष्टिकोण, पोज़ आदि) हैं। फिर आप उन्हें भार का उपयोग करके औसत कर सकते हैं, प्रभावी रूप से स्लैप / एलआरपी को सामान्य कर सकते हैं। आप एक रोटर को एक रोटर में भी बदल सकते हैं, जो एक कठोर शरीर के लिए एक निश्चित समय के लिए कोणीय वेग को लागू करने के बराबर है। इसलिए आप चतुर्धातुक के साथ कोणीय वेग एकीकरण का भी वर्णन कर सकते हैं। आप यह भी अनुमान लगा सकते हैं कि असमानता दो झुकाव कैसे हैं (हाइपरस्फियर पर दो चतुर्धातुक द्वारा छोड़े गए चाप की लंबाई की गणना करें)।