इसे करने के एक से अधिक तरीके हैं। आप अपने अवतार के सापेक्ष पूर्ण अभिविन्यास या घूर्णन की गणना कर सकते हैं, जिसका अर्थ है कि आपका नया उन्मुखीकरण = avatarOrientation * q। यहाँ एक बाद है:
अपने अवतार की यूनिट फॉरवर्ड वेक्टर के क्रॉस प्रोडक्ट और अवतार से यूनिट वेक्टर को लक्ष्य तक ले जाने के लिए रोटेशन अक्ष की गणना करें।
vector newForwardUnit = vector::normalize(target - avatarPosition);
vector rotAxis = vector::cross(avatarForwardUnit, newForwardUnit);
डॉट-उत्पाद का उपयोग करके रोटेशन कोण की गणना करें
float rotAngle = acos(vector::dot(avatarForwardUnit, newForwardUnit));
रोटाक्सिस और रोटएंगल का उपयोग करके बटेरियन बनाएं और इसे अवतार के वर्तमान अभिविन्यास के साथ गुणा करें
quaternion q(rotAxis, rotAngle);
quaternion newRot = avatarRot * q;
अगर आपको अवतार के वर्तमान फॉरवर्ड वेक्टर को खोजने में मदद की आवश्यकता है, तो इनपुट के लिए 1. बस शूट :)
संपादित करें: पूर्ण अभिविन्यास की गणना करना वास्तव में थोड़ा आसान है, 1) और 2 के इनपुट के रूप में अवतारों के आगे वेक्टर के बजाय पहचान-मैट्रिक्स के आगे वेक्टर का उपयोग करें। और इसे 3 में गुणा न करें), इसके बजाय इसे सीधे नए अभिविन्यास के रूप में उपयोग करें:newRot = q
नोट करने के लिए महत्वपूर्ण: समाधान में क्रॉस-उत्पाद की प्रकृति के कारण 2 विसंगतियां हैं:
अगर आगे वाले वैक्टर बराबर हैं। यहाँ समाधान केवल पहचान के लिए वापसी है
यदि वैक्टर विपरीत दिशा में बिल्कुल इंगित करता है। यहाँ समाधान यह है कि अवतारों को अक्ष के रूप में रोटेशन अक्ष और कोण 180.0 डिग्री का उपयोग करके चतुर्धातुक बनाना है।
यहाँ C ++ में कार्यान्वयन है जो उन बढ़त मामलों की देखभाल करता है। इसे C # में बदलना आसान होना चाहिए।
// returns a quaternion that rotates vector a to vector b
quaternion get_rotation(const vector &a, const vector &b, const vector &up)
{
ASSERT_VECTOR_NORMALIZED(a);
ASSERT_VECTOR_NORMALIZED(b);
float dot = vector::dot(a, b);
// test for dot -1
if(nearly_equal_eps_f(dot, -1.0f, 0.000001f))
{
// vector a and b point exactly in the opposite direction,
// so it is a 180 degrees turn around the up-axis
return quaternion(up, gdeg2rad(180.0f));
}
// test for dot 1
else if(nearly_equal_eps_f(dot, 1.0f, 0.000001f))
{
// vector a and b point exactly in the same direction
// so we return the identity quaternion
return quaternion(0.0f, 0.0f, 0.0f, 1.0f);
}
float rotAngle = acos(dot);
vector rotAxis = vector::cross(a, b);
rotAxis = vector::normalize(rotAxis);
return quaternion(rotAxis, rotAngle);
}
EDIT: मार्क के XNA कोड का सही संस्करण
// the new forward vector, so the avatar faces the target
Vector3 newForward = Vector3.Normalize(Position - GameState.Avatar.Position);
// calc the rotation so the avatar faces the target
Rotation = Helpers.GetRotation(Vector3.Forward, newForward, Vector3.Up);
Cannon.Shoot(Position, Rotation, this);
public static Quaternion GetRotation(Vector3 source, Vector3 dest, Vector3 up)
{
float dot = Vector3.Dot(source, dest);
if (Math.Abs(dot - (-1.0f)) < 0.000001f)
{
// vector a and b point exactly in the opposite direction,
// so it is a 180 degrees turn around the up-axis
return new Quaternion(up, MathHelper.ToRadians(180.0f));
}
if (Math.Abs(dot - (1.0f)) < 0.000001f)
{
// vector a and b point exactly in the same direction
// so we return the identity quaternion
return Quaternion.Identity;
}
float rotAngle = (float)Math.Acos(dot);
Vector3 rotAxis = Vector3.Cross(source, dest);
rotAxis = Vector3.Normalize(rotAxis);
return Quaternion.CreateFromAxisAngle(rotAxis, rotAngle);
}
0*(rotation A) + 1*(rotation B)
दूसरे शब्दों में सेट कर रहे हैं, आप बस रोटेशन को रोटेशन के लिए B लंबा रास्ता तय कर रहे हैं। बीच में जिस तरह से रोटेशन (0% <x <100%) दिखना चाहिए, यह निर्धारित करने के लिए स्लरप केवल है।