কোনও টার্গেটের মুখোমুখি হতে মডেলকে ওরিয়েন্ট করা ing


28

আমার দুটি অবজেক্ট (টার্গেট এবং প্লেয়ার) রয়েছে, উভয়েরই পজিশন (ভেক্টর 3) এবং রোটেশন (কোয়ার্টারিয়ন) রয়েছে। আমি লক্ষ্যটি ঘোরানো এবং সরাসরি প্লেয়ারের মুখোমুখি হতে চাই। লক্ষ্য, যখন এটি কোনও কিছু অঙ্কুর করে ঠিক তখনই প্লেয়ারের দিকে গুলি করা উচিত।

আমি প্লেয়ারের কাছে স্ট্র্যাপিংয়ের প্রচুর উদাহরণ দেখেছি, তবে আমি ইনক্রিমেন্টাল রোটেশন চাই না, ভাল, আমি মনে করি যে যতক্ষণ না আমি স্ট্রিল্পটি 100% করতে পারি এবং যতক্ষণ না এটি বাস্তবে কাজ করে।

এফওয়াইআই - আমি প্রচুর অন্যান্য কাজ করতে পজিশন এবং রোটেশনটি ব্যবহার করতে সক্ষম এবং এই শেষ টুকরোটি ব্যতীত এগুলি সবই দুর্দান্ত কাজ করে figure

কোডের নমুনাগুলি টার্গেটের ক্লাসে চলমান, অবস্থান = লক্ষ্যগুলির অবস্থান, অবতার = প্লেয়ার।

সম্পাদনা

আমি এখন মাইকের সি # কোড ব্যবহার করছি যা তিনি সরবরাহ করেছেন এবং এটি দুর্দান্ত কাজ করে!


4
আপনি যদি 100% slerp করছেন তবে আপনি স্লিপ ব্যবহার করছেন না। আপনি কেবল ঘূর্ণনটি সেট করছেন 0*(rotation A) + 1*(rotation B)- অন্য কথায়, আপনি কেবল ঘূর্ণনটি বি ঘূর্ণন বিতে দীর্ঘ পথ নির্ধারণ করছেন। ঘূর্ণনটি (0% <x <100%) এর মধ্যবর্তী স্থানে দেখতে কেমন হবে তা নির্ধারণের জন্যই স্লের্প।
ডপপেলগ্রিনিয়ার

ঠিক আছে, বোঝায়, কিন্তু, লক্ষ্য এখনও প্লেয়ারের দিকে পুরোপুরি ঘুরছে না ... সেই কোডটি দিয়ে "দীর্ঘ পথ"।
মার্চ

উত্তর:


20

এটি করার একাধিক উপায় রয়েছে। আপনি আপনার অবতারের সাথে সম্পর্কিত নিখুঁত ওরিয়েন্টেশন বা ঘূর্ণন গণনা করতে পারেন, তার অর্থ আপনার নতুন ওরিয়েন্টেশন = অবতার ওরিয়েন্টেশন * কিউ। এখানে দ্বিতীয়টি হল:

  1. আপনার অবতারের ইউনিট ফরোয়ার্ড ভেক্টর এবং ইউনিট ভেক্টরকে অবতার থেকে লক্ষ্য হিসাবে লক্ষ্য হিসাবে নিয়ে যাওয়ার জন্য ক্রস পণ্যটি গ্রহণ করে আবর্তনের অক্ষটি গণনা করুন:

    vector newForwardUnit = vector::normalize(target - avatarPosition);
    vector rotAxis = vector::cross(avatarForwardUnit, newForwardUnit);
    
  2. বিন্দু-পণ্য ব্যবহার করে ঘূর্ণন কোণ গণনা করুন

    float rotAngle = acos(vector::dot(avatarForwardUnit, newForwardUnit));
  3. রোটএক্সিস এবং রোটএঙ্গেল ব্যবহার করে কোয়াটারিয়ন তৈরি করুন এবং এটিকে অবতারের বর্তমান ওরিয়েন্টেশন দিয়ে গুণ করুন

    quaternion q(rotAxis, rotAngle);
    quaternion newRot = avatarRot * q;
    

আপনার যদি অবতারের বর্তমান ফরোয়ার্ড ভেক্টরটি খুঁজে পেতে সহায়তা প্রয়োজন হয় তবে 1 এর জন্য ইনপুটটি কেবল শুট করুন :)

সম্পাদনা: নিখুঁত ওরিয়েন্টেশন গণনা করা কিছুটা সহজ, অবতারদের ফরোয়ার্ড ভেক্টরের পরিবর্তে পরিচয়-ম্যাট্রিক্সের ফরোয়ার্ড ভেক্টরটি 1 এবং 2 এর ইনপুট হিসাবে ব্যবহার করুন)। এবং এটি 3 এ গুণ করবেন না, পরিবর্তে এটি সরাসরি নতুন অভিযোজন হিসাবে ব্যবহার করুন:newRot = q


গুরুত্বপূর্ণ লক্ষণীয়: সমাধানটির ক্রস-প্রোডাক্টের প্রকৃতির কারণে 2 টি অসঙ্গতি রয়েছে:

  1. ফরোয়ার্ড ভেক্টরগুলি সমান হলে। সমাধান এখানে সহজভাবে পরিচয় চতুর্দশী ফিরে

  2. যদি ভেক্টরগুলি ঠিক বিপরীত দিকে নির্দেশ করে। এখানে সমাধানটি হল আবর্তন অক্ষটি আবর্তন অক্ষ এবং 180.0 ডিগ্রি কোণ হিসাবে অবতারগুলি অক্ষর ব্যবহার করে চৌম্বক তৈরি করা।

এখানে 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);
}

সম্পাদনা: মার্কের এক্সএনএ কোডটির সংশোধিত সংস্করণ

// 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);
}

ঠিক আছে, আমি উত্তর দিয়েছি যে শটটি আপনি আমার সম্পাদনা প্রশ্নে দেখতে পারেন কোড সরবরাহ করেছেন। সমস্যাটি আসলে কী তা নিশ্চিত নয়। a এবং b ইনপুটগুলি ফরোয়ার্ড ভেক্টর, বা কমপক্ষে ধরা যাক।
মার্চ

@ মার্ক আমার উত্তরে আপনার এক্সএনএ কোডের সংশোধিত সংস্করণটি দেখুন। 2 টি সমস্যা ছিল: 1) নতুন ফরোয়ার্ড ভেক্টরের গণনাটি ভুল ছিল, অবশ্যই অবতার পজিশন করতে হবে - টার্গেটপেজ 2) রোটএক্সিস অবশ্যই গেটরোটেশনে ক্রস-প্রোডাক্টের পরে স্বাভাবিক করা উচিত
মাইক সেমডার

@ মার্ক, ২ টি সামান্য পরিবর্তন: 3) উত্স এবং গন্তব্য ইতিমধ্যে স্বাভাবিক হয়েছে, গেটরোটেশন 4 এ আবার এগুলিকে সাধারণ করার দরকার নেই) গেটরোটেশনে পরম 1 / -1 এর জন্য পরীক্ষা না করা, বরং কিছুটা সহনশীলতা ব্যবহার করুন, আমি 0.000001f ব্যবহার করেছি
মাইক সেমদার

হুম, এখনও কাজ করছে না। একই স্কেলিংয়ের বিষয়টি মডেলটির সাথে ঘটে এবং লক্ষ্যটি অবতারের দিকে ঘোরে না (যা আমি আপনার মন্তব্যে লক্ষ্য করেছি যে আপনি লক্ষ্যটির দিকে অবতারকে ঘোরানোর চেষ্টা করছেন .... অন্যভাবে হওয়া উচিত) ... মূলত, চেষ্টা করা প্লেয়ারের মুখোমুখি হওয়ার জন্য ভিড় পেতে (তৃতীয় ব্যক্তির ক্যামেরায় অবতার)। গেটরোটেশন পদ্ধতিটি লক্ষ্য এবং অবতারের বর্তমান ঘূর্ণন সম্পর্কে কিছু জানা উচিত নয়, যেমনটি, আপনি কি মনে করেন যে নতুন ফরোয়ার্ডটি সঠিকভাবে তৈরি হচ্ছে?
মার্চ

যদি বস্তুটি পরিমাপ করা হয় তবে এর অর্থ হল যে কোয়ার্ট্রিয়নের একটি ইউনিটের দৈর্ঘ্য নেই, এর অর্থ রোটএক্সিস স্বাভাবিক হয় না। আপনি কি আমার শেষ কোড-পরিবর্তনটি রোটএক্সিসের স্বাভাবিককরণের সাথে যুক্ত করেছেন? তবে দয়া করে আপনার বর্তমান কোডটি দেখান এবং উদাহরণস্বরূপ এটি কাজ করে না এমন ক্ষেত্রে, দয়া করে: newForward rotAngle rotAxisএবং এর মানগুলিও পোস্ট করুন returned quaternion। জনতার জন্য কোডটি একই রকম হবে, একবার আমরা যখন এটি অবতারের সাথে কাজ করব, তখন যেকোন বস্তুর শিরোনাম পরিবর্তন করা সহজ হবে।
মাইক সেমদার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.