2012-03-25 22 views
8

मैं ओपनजीएल पर एक बहुत ही सरल परियोजना बना रहा हूं और मैं घूर्णन के साथ फंस गया हूं। मैं सभी 3 अक्षों में एक वस्तु को घुमाने की कोशिश कर रहा हूं: एक्स, वाई, और जेड। मेरे पास एक अक्ष के घूर्णन के बाद "जिम्बल लॉक" समस्या के कारण नींद की रातें हैं। मैंने तब सीखा है कि quaternions मेरी समस्या का समाधान होगा। मैंने quaternions के बारे में शोध किया है और इसे लागू किया है, लेकिन मैं अपने घूर्णन quaternions में बदलने में सक्षम नहीं है। उदाहरण के लिए, अगर मैं 90 डिग्री धुरी के चारों ओर जेड बारी बारी से करना चाहते हैं, मैं तो बस {0,0,1} वेक्टर मेरी चार का समुदाय के लिए बना सकते हैं और यहाँ कोड का उपयोग कर के आसपास है कि अक्ष 90 डिग्री बारी बारी से यह:एक्स वाई जेड रोटेशन से क्वाटरनियन के लिए वेक्टर कैसे खोजें

http://iphonedevelopment.blogspot.com/2009/06/opengl-es-from-ground-up-part-7_04.html (सबसे नीचे की ओर जटिल मैट्रिक्स)

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

अद्यतन: मैं quaternions के बारे में यह अच्छा पृष्ठ मिला और उन्हें इस तरह से लागू करने का फैसला किया है:

void cube::quatmul(float* q1, float* q2, float* resultRef){ 
float w = q1[0]*q2[0] - q1[1]*q2[1] - q1[2]*q2[2] - q1[3]*q2[3]; 
float x = q1[0]*q2[1] + q1[1]*q2[0] + q1[2]*q2[3] - q1[3]*q2[2]; 
float y = q1[0]*q2[2] - q1[1]*q2[3] + q1[2]*q2[0] + q1[3]*q2[1]; 
float z = q1[0]*q2[3] + q1[1]*q2[2] - q1[2]*q2[1] + q1[3]*q2[0]; 

resultRef[0] = w; 
resultRef[1] = x; 
resultRef[2] = y; 
resultRef[3] = z; 
} 

यहाँ के लिए मेरे कोड है: http://www.cprogramming.com/tutorial/3d/quaternions.html

यहाँ चार का समुदाय गुणन के लिए मेरे कोड है

void cube::applyquat(){ 
float& x = quaternion[1]; 
float& y = quaternion[2]; 
float& z = quaternion[3]; 
float& w = quaternion[0]; 
float magnitude = sqrtf(w * w + x * x + y * y + z * z); 
if(magnitude == 0){ 
    x = 1; 
    w = y = z = 0; 
}else 
if(magnitude != 1){ 
    x /= magnitude; 
    y /= magnitude; 
    z /= magnitude; 
    w /= magnitude; 
    } 

tmodelview[0] = 1 - (2 * y * y) - (2 * z * z); 
tmodelview[1] = 2 * x * y + 2 * w * z; 
tmodelview[2] = 2 * x * z - 2 * w * y; 
tmodelview[3] = 0; 

tmodelview[4] = 2 * x * y - 2 * w * z; 
tmodelview[5] = 1 - (2 * x * x) - (2 * z * z); 
tmodelview[6] = 2 * y * z - 2 * w * x; 
tmodelview[7] = 0; 

tmodelview[8] = 2 * x * z + 2 * w * y; 
tmodelview[9] = 2 * y * z + 2 * w * x; 
tmodelview[10] = 1 - (2 * x * x) - (2 * y * y); 
tmodelview[11] = 0; 

glMatrixMode(GL_MODELVIEW); 
glPushMatrix(); 
glLoadMatrixf(tmodelview); 
glMultMatrixf(modelview); 
glGetFloatv(GL_MODELVIEW_MATRIX, tmodelview); 
glPopMatrix(); 
} 
: मेरे modelview मैट्रिक्स के लिए एक चार का समुदाय को लागू करने (मैं एक tmodelview चर रहा है कि मेरा लक्ष्य modelview मैट्रिक्स है)

और रोटेशन के लिए मेरी कोड (है कि मैं बाहर से फोन), जहां quaternion घन के एक वर्ग चर रहा है:

void cube::rotatex(int angle){ 
float quat[4]; 
float ang = angle * PI/180.0; 
quat[0] = cosf(ang/2); 
quat[1] = sinf(ang/2); 
quat[2] = 0; 
quat[3] = 0; 
quatmul(quat, quaternion, quaternion); 
applyquat(); 
} 

void cube::rotatey(int angle){ 
float quat[4]; 
float ang = angle * PI/180.0; 
quat[0] = cosf(ang/2); 
quat[1] = 0; 
quat[2] = sinf(ang/2); 
quat[3] = 0; 
quatmul(quat, quaternion, quaternion); 
applyquat(); 
} 

void cube::rotatez(int angle){ 
float quat[4]; 
float ang = angle * PI/180.0; 
quat[0] = cosf(ang/2); 
quat[1] = 0; 
quat[2] = 0; 
quat[3] = sinf(ang/2); 
quatmul(quat, quaternion, quaternion); 
applyquat(); 
} 

मैं फोन, कहते हैं कि rotatex, 10-11 बार के लिए केवल 1 डिग्री घूर्णन के लिए, लेकिन मेरे घन 1 डिग्री के 10-11 गुना के बाद लगभग 9 0 डिग्री घूर्णन हो जाता है, जो समझ में नहीं आता है। इसके अलावा, विभिन्न अक्षों में रोटेशन फ़ंक्शन को कॉल करने के बाद, मेरा घन skewed हो जाता है, 2 आयामी हो जाता है, और गायब हो जाता है (मॉडलव्यू मैट्रिक्स में एक कॉलम सभी शून्य हो जाता है) अपरिवर्तनीय रूप से, जो स्पष्ट रूप से quaternions के सही कार्यान्वयन के साथ नहीं हो रहा है।

+0

क्या आप quaternions, या किसी ऑब्जेक्ट को घूर्णन के साथ मदद चाहते हैं? – Beta

+0

अच्छी तरह से मैं quaternions पथ के साथ चला गया है और कोड लिखा है, तो अगर आप रोटेशन के लिए quaternion- शामिल समाधान है तो यह सहायक होगा। जो मुझे बस कार्यान्वित करने की आवश्यकता है वह 3 डी स्पेस –

+0

में 3 डिग्री स्वतंत्रता के साथ किसी ऑब्जेक्ट को घुमाने में सक्षम होना है, शायद जैक कूपर से "Quaternions और Rotations Sequences" पुस्तक आपकी मदद कर सकती है। एक्स-वाई-जेड रोटेशन (उर्फ यूलर कोण) के बारे में बहुत कुछ कहना है। उदाहरण के लिए आप पुराने एक्स अक्ष या नए एक के आसपास घूम रहे हैं (जिस वस्तु को आप घूर्णन कर रहे हैं उस पर अक्ष 'संलग्न')? – ascobol

उत्तर

7

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

आपको अपने वांछित अभिविन्यास को लाभ प्राप्त करने के लिए एक quaternion के रूप में स्टोर करने की आवश्यकता है। यही है, एक quaternion के रूप में एक वर्तमान अभिविन्यास लेना संभव है और फिर सवाल पूछें "मैं जेड अक्ष के आसपास 90 डिग्री से कैसे घूमता हूं और इसे अपने नए अभिविन्यास के रूप में उपयोग करता हूं?", लेकिन यह पूछना उपयोगी नहीं है "मेरे वर्तमान अभिविन्यास इन XYZ यूलर कोणों द्वारा परिभाषित किया गया है, मैं इसे quaternion में कैसे बदल सकता हूं? "।

quaternions के प्रासंगिक भागों का एक पूरा उपचार काफी लंबा होगा। This site may help you out. यह ध्यान देने योग्य है कि जिस साइट से आप लिंक करते हैं वह वास्तव में अक्ष-कोण रोटेशन के बारे में बात कर रहा है, quaternions नहीं।

संपादित करें: कोड आप पोस्ट सही है, सिवाय इसके कि tmodelview[6] और tmodelview[9] के लिए चिह्नों का गलत हैं।

+0

धन्यवाद। मैं समझता हूं कि मुझे अपना अभिविन्यास संग्रहीत करने की आवश्यकता है (इसलिए, एक quaternion), और उस में कोण के बारे में भूल जाओ। आपका लिंक काफी उपयोगी है, लेकिन एक बात जो मुझे अभी भी समझ में नहीं आ रही है वह यह है कि आप जिस प्रश्न के बारे में बात कर रहे हैं: "मैं जेड अक्ष के आसपास 90 डिग्री से कैसे घूमता हूं और इसे अपने नए अभिविन्यास के रूप में उपयोग करता हूं?" –

+3

Quaternion गुणा। यदि आपके पास quaternion 'q' है जो आपके वर्तमान अभिविन्यास को संदर्भित करता है, और एक quaternion' r' जो कि Z अक्ष के आसपास 90 डिग्री से घूर्णन है, तो quaternion 'r * q' आपका नया अभिविन्यास है। वास्तव में मैट्रिक्स गुणा के लिए समानांतर समानांतर। –

+0

मैं उस –

संबंधित मुद्दे