स्थिर अक्ष के चारों ओर वस्तु घुमाएँ


12

मैं अपने ऐप के उपयोगकर्ता को स्क्रीन पर अपनी उंगली को खींचकर स्क्रीन के केंद्र में खींची गई 3 डी ऑब्जेक्ट को घुमाने देने की कोशिश कर रहा हूं। स्क्रीन पर एक क्षैतिज आंदोलन का अर्थ है एक निश्चित Y अक्ष के चारों ओर घूमना, और एक ऊर्ध्वाधर आंदोलन का मतलब X अक्ष के चारों ओर घूमना है। मुझे जो समस्या हो रही है, वह यह है कि अगर मैं सिर्फ एक धुरी के चारों ओर घूमने की अनुमति देता हूं, तो वस्तु ठीक घूमती है, लेकिन जैसे ही मैं दूसरी घुमाव देता हूं, वस्तु अपेक्षा के अनुरूप नहीं घूमती है।

यहाँ क्या हो रहा है की एक तस्वीर है:

यहाँ छवि विवरण दर्ज करें

नीला अक्ष मेरे निश्चित अक्ष का प्रतिनिधित्व करता है। इस निश्चित नीले अक्ष वाले चित्र को स्क्रीन करें। यही वह चीज है जिसके संबंध में मैं वस्तु को घुमाना चाहता हूं। जो हो रहा है वह लाल रंग में है।

यहाँ मुझे पता है:

  1. Y (0, 1, 0) के चारों ओर पहला घुमाव मॉडल को नीले स्थान से स्थानांतरित करने का कारण बनता है (इस स्थान को A) दूसरे स्थान पर कॉल करें (इस स्थान को B कहें)
  2. वेक्टर (1, 0, 0) का उपयोग करके फिर से घुमाने की कोशिश कर रहा है, स्पेस एक्स में चारों ओर घूमता है बी नॉट स्पेस ए में जो कि मेरे कहने का मतलब नहीं है।

यहाँ मैंने जो कोशिश की है, वह दी है जो मुझे लगता है कि मुझे पता है (संक्षिप्तता के लिए डब्ल्यू समन्वय छोड़कर):

  1. पहले एक चतुर्भुज का उपयोग करके Y (0, 1, 0) के चारों ओर घुमाएं।
  2. रोटेशन Y Quaternion को एक मैट्रिक्स में परिवर्तित करें।
  3. नई जगह के संबंध में एक्स अक्ष प्राप्त करने के लिए मेरे स्थिर अक्ष x वेक्टर (1, 0, 0) द्वारा वाई रोटेशन मैट्रिक्स को गुणा करें।
  4. एक चतुर्भुज का उपयोग करके इस नए एक्स वेक्टर के चारों ओर घुमाएं।

यहाँ कोड है:

private float[] rotationMatrix() {

    final float[] xAxis = {1f, 0f, 0f, 1f};
    final float[] yAxis = {0f, 1f, 0f, 1f};
    float[] rotationY = Quaternion.fromAxisAngle(yAxis, -angleX).toMatrix();

    // multiply x axis by rotationY to put it in object space
    float[] xAxisObjectSpace = new float[4];
    multiplyMV(xAxisObjectSpace, 0, rotationY, 0, xAxis, 0);

    float[] rotationX = Quaternion.fromAxisAngle(xAxisObjectSpace, -angleY).toMatrix();

    float[] rotationMatrix = new float[16];
    multiplyMM(rotationMatrix, 0, rotationY, 0, rotationX, 0);
    return rotationMatrix;
  }

यह मेरी अपेक्षा के अनुरूप काम नहीं कर रहा है। रोटेशन काम करने लगता है, लेकिन कुछ बिंदु पर क्षैतिज गति Y अक्ष के बारे में नहीं घूमती है, यह Z अक्ष के बारे में घूमता प्रतीत होता है।

मुझे यकीन नहीं है कि अगर मेरी समझ गलत है, या अगर कुछ और समस्या पैदा कर रही है। मेरे पास कुछ अन्य परिवर्तन हैं जो मैं रोटेशन के अलावा ऑब्जेक्ट के लिए कर रहा हूं। मैं रोटेशन को लागू करने से पहले वस्तु को केंद्र में ले जाता हूं। मैं इसे अपने फ़ंक्शन से ऊपर दिए गए मैट्रिक्स का उपयोग करके घुमाता हूं, फिर मैं इसे Z दिशा में -2 अनुवाद करता हूं ताकि मैं ऑब्जेक्ट देख सकूं। मुझे नहीं लगता कि यह मेरे घुमावों को गड़बड़ कर रहा है, लेकिन यहाँ वैसे भी इसके लिए कोड है:

private float[] getMvpMatrix() {
    // translates the object to where we can see it
    final float[] translationMatrix = new float[16];
    setIdentityM(translationMatrix, 0);
    translateM(translationMatrix, 0, translationMatrix, 0, 0f, 0f, -2);

    float[] rotationMatrix = rotationMatrix();

    // centers the object
    final float[] centeringMatrix = new float[16];
    setIdentityM(centeringMatrix, 0);
    float moveX = (extents.max[0] + extents.min[0]) / 2f;
    float moveY = (extents.max[1] + extents.min[1]) / 2f;
    float moveZ = (extents.max[2] + extents.min[2]) / 2f;
    translateM(centeringMatrix, 0, //
      -moveX, //
      -moveY, //
      -moveZ //
    );

    // apply the translations/rotations
    final float[] modelMatrix = new float[16];
    multiplyMM(modelMatrix, 0, translationMatrix, 0, rotationMatrix, 0);
    multiplyMM(modelMatrix, 0, modelMatrix, 0, centeringMatrix, 0);

    final float[] mvpMatrix = new float[16];
    multiplyMM(mvpMatrix, 0, projectionMatrix, 0, modelMatrix, 0);
    return mvpMatrix;
  }

मैं कुछ दिनों के लिए इस पर अटक गया। मदद काफी सराहना की है।

================================================== ================

अपडेट करें:

एकता में काम करने के लिए यह सीधा है। यहाँ कुछ कोड है जो एक घन को मूल पर केंद्रित करता है:

public class CubeController : MonoBehaviour {

    Vector3 xAxis = new Vector3 (1f, 0f, 0f);
    Vector3 yAxis = new Vector3 (0f, 1f, 0f);

    // Update is called once per frame
    void FixedUpdate () {
        float horizontal = Input.GetAxis ("Horizontal");
        float vertical = Input.GetAxis ("Vertical");

        transform.Rotate (xAxis, vertical, Space.World);
        transform.Rotate (yAxis, -horizontal, Space.World);
    }
}

जिस हिस्से से घुमाव आता है वह व्यवहार करता है जैसा कि मैं उम्मीद कर रहा हूं Space.Worldकि Rotateयह परिवर्तन पर फ़ंक्शन का पैरामीटर है ।

अगर मैं एकता का उपयोग कर सकता हूं, तो दुर्भाग्य से मुझे इस व्यवहार को खुद कोड करना होगा।


1
यहाँ मेरा जवाब gamedev.stackexchange.com/questions/67199/… आपकी मदद कर सकता है ..
अवधारणा 3d

मैं आपके उत्तर के पीछे की अवधारणा को समझता हूं, लेकिन कैसे लागू किया जाए, इससे मैं बच रहा हूं।
क्रिस्टोफर पेरी

यदि आपने अन्य उत्तरों की जांच की तो वाक्य रचना उत्तर उस विचार को लागू करता है जो मैंने समझाया था।
कॉन्सेप्ट

नहीं, ऐसा नहीं है, यह विभिन्न अक्षों के बारे में कई घुमाव दे रहा है। आप एकल रोटेशन करने का सुझाव देते हैं।
क्रिस्टोफर पेरी

जवाबों:


3

आपकी समस्या को समस्यापूर्ण लॉक कहा जाता है । मुझे लगता है कि आपकी तलाश क्या है इसे आर्केडबॉल रोटेशन कहा जाता है । आर्कबॉल के लिए गणित जटिल हो सकता है।

इसे करने का एक सरल तरीका स्क्रीन पर 2d swipe के लिए 2d वेक्टर लंबवत मिल रहा है।

वेक्टर लें और इसे विश्व अंतरिक्ष में 3 डी वेक्टर प्राप्त करने के लिए विमान के पास कैमरे पर प्रोजेक्ट करें। विश्व अंतरिक्ष के लिए स्क्रीन अंतरिक्ष

फिर इस वेक्टर के साथ एक quaternion बनाएं और इसे गेमबजेक्ट में गुणा करें। संभवत: कुछ स्लर्प या लेरप संक्रमण के साथ।

संपादित करें:

एकता उदाहरण: एकता उदाहरण में, गेमबॉजेक्ट्स रोटेशन की आंतरिक स्थिति एक चतुर्भुज है जो मैट्रिक्स नहीं है। ट्रांस्फॉर्मेशन विधि, वेक्टर और कोण के आधार पर एक क्वाटर्नेशन उत्पन्न करती है और गेमबजेक्ट्स रोटेशन क्वाटरनियन के साथ उस क्वाटर्नियन को गुणा करती है। यह केवल बाद के बिंदु पर रेंडरिंग या भौतिकी के लिए रोटेशन मैट्रिक्स उत्पन्न करता है। Quaternions additive हैं और gimble लॉक से बचें।

आपका कोड कुछ इस तरह दिखना चाहिए:

private float[] rotationMatrix() {

    final float[] xAxis = {1f, 0f, 0f, 1f};
    final float[] yAxis = {0f, 1f, 0f, 1f};

    Quaternion qY = Quaternion.fromAxisAngle(yAxis, angleX);
    Quaternion qX = Quaternion.fromAxisAngle(xAxis, -angleY);

    return (qX * qY).getMatrix(); // should probably represent the gameobjects rotation as a quaternion(not a matrix) and multiply all 3 quaternions before generating the matrix. 
  }

आर्कबेल रोटेशन ओपेंगल ट्यूटोरियल


मुझे गिमबल लॉक नहीं मिल रहा है, पहला घुमाव धुरी को स्थानांतरित करता है इसलिए दूसरा घुमाव स्थानांतरित धुरी पर आधारित है। कृपया मेरे द्वारा प्रदान की गई तस्वीर पर एक दूसरा नज़र डालें।
क्रिस्टोफर पेरी

मुझे आशा है कि आप इसे समझ गए होंगे। संक्षेप में। रोटेशन को लागू करने के लिए Quaternions को एक साथ गुणा किया जा सकता है। आपको केवल सभी रोटेशन गणनाओं के अंत में मैट्रिक्स उत्पन्न करना चाहिए। इसके अलावा xQ * yQ yQ * xQ के बराबर नहीं है। क्रिस्टोफर पेरी ने कहा कि कोटेशन नॉन कम्यूटेटिव हैं।
एंथनी रायमोंडो

मैंने अपना सभी कोड यहाँ रखा है । मुझे लगता है कि मैंने सब कुछ करने की कोशिश की है। हो सकता है इस पर किसी और की नजर मेरी गलती को पकड़ ले।
क्रिस्टोफर पेरी

मैंने इसे स्वीकार नहीं किया, ढेर एक्सचेंज एल्गोरिथम ऑटो ने आपको अंक दिए। : /
क्रिस्टोफर पेरी

इस अन्याय के लिए मुझे खेद है।
एंथनी रायमोंडो

3

मैं संचित रोटेशन मैट्रिक्स को घुमाकर अपेक्षित घुमाव प्राप्त करने में सक्षम था।

setIdentityM(currentRotation, 0);
rotateM(currentRotation, 0, angleY, 0, 1, 0);
rotateM(currentRotation, 0, angleX, 1, 0, 0);

// Multiply the current rotation by the accumulated rotation,
// and then set the accumulated rotation to the result.
multiplyMM(temporaryMatrix, 0, currentRotation, 0, accumulatedRotation, 0);
arraycopy(temporaryMatrix, 0, accumulatedRotation, 0, 16);

1

आपकी छवि आपके रोटेशनमैट्रिक्स कोड के साथ मेल खाती है, अपने पिछले y रोटेशन के साथ x अक्ष को घुमाकर आपको स्थानीय x अक्ष प्राप्त होता है, जब आप तब ऑब्जेक्ट को चारों ओर घुमाते हैं तो आपको वह परिणाम मिलेगा जो आप अपनी छवि में दिखाते हैं। उपयोगकर्ताओं के दृष्टिकोण से रोटेशन तार्किक होना चाहिए, आप इसके बजाय विश्व समन्वय अक्ष का उपयोग करके ऑब्जेक्ट को घुमाना चाहेंगे।

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

बस प्रारंभिक मूल्य के रूप में पहचान चतुर्भुज का उपयोग करें, और हर बार जब उपयोगकर्ता स्क्रीन को स्वाइप करता है तो आप Quaternion.fromAxisAngle(yAxis, -angleX)कोड के साथ अपने चतुर्भुज को घुमाते हैं । हमेशा एक्स रोटेशन के लिए (1,0,0,1) और वाई रोटेशन के लिए (0,1,0,1) का उपयोग करना।

static final float[] xAxis = {1f, 0f, 0f, 1f};
static final float[] yAxis = {0f, 1f, 0f, 1f};

private void rotateObject(float angleX, float angleY) {
  Quaternion rotationY = Quaternion.fromAxisAngle(yAxis, -angleX);
  Quaternion rotationX = Quaternion.fromAxisAngle(xAxis, -angleY);

  myRotation = myRotation.rotate(rotationY).rotate(rotationX).normalize();
}
private float[] rotationMatrix() {
  return myRotation.toMatrix();
}

चूंकि आपने भाषा या किसी विशिष्ट ढांचे का उल्लेख नहीं किया है, इसलिए Quaternion के तरीकों को अलग तरीके से कुछ कहा जा सकता है, और सामान्य रूप से इसे कॉल करने के लिए आवश्यक नहीं है, लेकिन चूंकि रोटेशन उपयोगकर्ता द्वारा स्क्रीन को स्वाइप करने से आता है, वे नहीं होंगे धीमी गति से चीजें बहुत कम हो जाती हैं और इस तरह से क्वाटरनियन को एक यूनिट क्वाटरनियन से खिसकने का कोई मौका नहीं मिलता है।


मुझे ऐसा ही व्यवहार मिल रहा है।
क्रिस्टोफर पेरी

1
@ChristopherPerry रोटेशन ऑर्डर को उलटने की कोशिश करें: myRotation = rotationX.rotate(rotationY).rotate(myRotation).normalize()वे कम्यूटेटिव नहीं हैं, इसलिए आप जो ऑर्डर करते हैं, वह मायने रखता है। अपने ढांचे / भाषा के साथ एक और टिप्पणी जोड़ें अगर वह काम नहीं करता है और बीमार इसे थोड़ा और खोदते हैं।
डेनियल कार्ल्ससन

यह भी काम नहीं करता है, मैं एक ही व्यवहार मिलता है।
क्रिस्टोफर पेरी

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