একটি গোলক সম্পর্কে নির্বিচারে আবর্তন


12

আমি এমন একটি যান্ত্রিক কোডিং করছি যা ব্যবহারকারীরকে একটি গোলকের পৃষ্ঠের চারদিকে ঘুরতে দেয়। গোলকের অবস্থানটি বর্তমানে হিসাবে হিসাবে সংরক্ষণ করা হয় thetaএবং phiযেখানে thetaz- অক্ষ এবং বর্তমান অবস্থানের xz প্রক্ষেপণের মধ্যবর্তী কোণ রয়েছে (অর্থাত্ y অক্ষের সম্পর্কে ঘূর্ণন), এবং phiy- অক্ষ থেকে অবস্থানের কোণ। আমি এটি খারাপভাবে ব্যাখ্যা করেছি, তবে এটি মূলত theta = yaw,phi = pitch

Vector3 position = new Vector3(0,0,1);
position.X = (float)Math.Sin(phi) * (float)Math.Sin(theta);
position.Y = (float)Math.Sin(phi) * (float)Math.Cos(theta);
position.Z = (float)Math.Cos(phi);
position *= r;

আমি বিশ্বাস করি এটি সঠিক, তবে আমি ভুল হতে পারি। ব্যাসার্ধ সহ বিশ্ব মহাশূন্যের উত্সের সময়ে একটি গোলকের পৃষ্ঠের চারপাশে একটি স্বেচ্ছাসেবী ছদ্ম দ্বি-মাত্রিক দিকে যেতে আমার সক্ষম হতে হবে r। উদাহরণস্বরূপ, হোল্ডিংয়ের সাথে Wগোলকের চারপাশে প্লেয়ারের দিকনির্দেশনার সাথে সম্পর্কিত একটি upর্ধ্বমুখী দিকে চলতে হবে।

আমি বিশ্বাস করি যে গোলকের অবস্থান / দৃষ্টিভঙ্গি উপস্থাপনের জন্য আমার একটি কোয়ার্টারিয়ন ব্যবহার করা উচিত, তবে আমি এটি করার সঠিক উপায়টি ভাবতে পারি না। গোলাকার জ্যামিতি আমার শক্ত স্যুট নয়।

মূলত, আমাকে নিম্নলিখিত ব্লকটি পূরণ করতে হবে:

public void Move(Direction dir)
{   
    switch (dir)
    {
        case Direction.Left:
            // update quaternion to rotate left
            break;
        case Direction.Right:   
            // update quaternion to rotate right
            break;
        case Direction.Up:
            // update quaternion to rotate upward
            break;
        case Direction.Down:
            // update quaternion to rotate downward
            break;
    }
}

খেলোয়াড়ের খুঁটিতে পৌঁছলে কী হবে? আমি লক্ষ্য করেছি আপনি "upর্ধ্বমুখী দিক" লিখেছেন, আপনি কি আক্ষরিক অর্থে "উপরের দিকে" (যা গোলকের পৃষ্ঠ থেকে দূরে), "সরাসরি এগিয়ে" বা "উত্তর মেরুর দিকে" (পরের দুটি সমান যদি প্লেয়ার থাকে তবে তাদের দৃষ্টিভঙ্গি এবং "তাদের সামনে" বা স্ক্রিনে "উপরে" কি সর্বদা উত্তরে থাকে?
মার্টিন সোজকা

সম্ভবত এটি খারাপ শব্দ করা হয়েছিল। প্লেয়ারটিকে গোলকের পৃষ্ঠটি ছেড়ে যাওয়া উচিত নয় এবং কার্ডিনাল অক্ষটি সম্পর্কে সচেতন হওয়া উচিত নয়। সুতরাং যখন আপনি "উপরে" সরে যান, আপনি প্লেয়ারের অবস্থানের সাথে সম্পর্কিত হয়ে গোলকের পৃষ্ঠের উপরের দিকে দিকে যান। উদাহরণস্বরূপ আপনি যদি (আর, 0,0) এ থাকেন এবং টিপতে থাকেন তবে আপনি জেড + পোলের দিকে যাবেন, তবে আপনি যদি চালিয়ে যান তবে আপনার চারপাশে মোড়ানো এবং চালিয়ে যাওয়া উচিত।
Azz

এখনও একটি প্রশ্ন রয়ে গেছে: প্লেয়ার কি অভিমুখ পরিবর্তন করতে পারে ("বাম" এবং "ডান" ঘোরান)?
মার্টিন সোজকা

আমি যা যাচ্ছি তার একটি আরও ভাল উদাহরণ হতে পারে: (1,1,1)বাম দিকে ধরে থাকা প্লেয়ারটি গোলকের চারদিকে ঘুরত , তারপরে এবং (~1.2,0,~-1.2)তারপরে চলে যেত । (-1,-1,-1)(~-1.2,0,~1.2)(1,1,1)
Azz

1
আপনি সবসময় ট্র্যাক রাখতে চান, তাহলে thetaএবং phiআপনার অবস্থান আপডেট হিসাবে, আপনি আপনার সমস্যা অকারণে জটিল তৈরি করছেন। প্রতিটি ফ্রেমকে 2 ঘূর্ণন অক্ষগুলি কেবল গণনা করা খুব সহজ (যার মধ্যে একটি (ইয়াও) কখনই পরিবর্তন হয় না) এবং Vector3.Transormগোলকের চারপাশে। এটি আপনার সমস্যাটিকে সহজতর করবে তবে আপনাকে phi& এর সাথে সংযোগ বিচ্ছিন্ন করবে theta
স্টিভ এইচ

উত্তর:


5

প্রকৃতপক্ষে, এটি প্রমাণিত হয়েছে যে আপনি এটি 'উভয় উপায়ে' রাখতে পারবেন না: যদি আপনার উদ্দেশ্যটি গোলকের উপর 'পরম অভিমুখীকরণের' কোনও ধারণা না রাখে (অর্থাৎ, যদি খেলোয়াড়রা সর্বদা দণ্ডগুলির দিকে মুখ না করে থাকে) ), তারপরে আপনার প্লেয়ার ওরিয়েন্টেশনের ধারণা থাকতে হবে। এই কারণ কি স্বজ্ঞা পরামর্শ দিয়ে থাকি বিপরীত, গোলক ওপর চলাচলের হয় না ঠিক একটি প্লেনে আন্দোলন মত, এমনকি স্থানীয়ভাবে না (বেশ); গোলকের অভ্যন্তরীণ বক্রতা মানে প্লেয়াররা এমন পদক্ষেপ নিতে পারে যা নিজেরাই ঘোরবে!

আমি যা বলছি তার চূড়ান্ত উদাহরণের জন্য, কল্পনা করুন যে প্লেয়ারটি নিরক্ষীয় অঞ্চলে একটি বিন্দুতে শুরু হয় (সুবিধার্থে আমরা কল্পনা করব যে একটি ঘড়ির মুখটি উপরে থেকে নিরক্ষীয় অঞ্চলে ম্যাপ করা আছে, এবং খেলোয়াড়টি 6 টা বাজবে ), 'আপ' - এর মুখোমুখি উত্তর মেরুর দিকে towards ধরুন, খেলোয়াড় উত্তর মেরুতে সমস্ত পথে হাঁটছেন; তারপরে তারা সরাসরি 12 টা বাজির দিকে মুখোমুখি হবেন। এখন, খেলোয়াড়কে উত্তর মেরু থেকে সরাসরি নিরক্ষীয় অঞ্চলে ফিরে সরাসরি তাদের ডানে চলে যেতে দিন; তারা 3 টা বাজে পয়েন্টে বাতাসে যাবে - তবে তারা ডানদিকে যাওয়ার সময় তাদের মুখের পরিবর্তন হয় না(ধারণাটি হ'ল তারা যেভাবে চলুক না কেন তাদের মুখের পরিবর্তন হয় না), তারা এখনও 12 টা বাজির মুখোমুখি হবেন - তারা এখন নিরক্ষীয় বরাবর মুখোমুখি! এখন, তাদের 'পূর্বের দিকে' তাদের শুরুতে (6 টা বাজে) পয়েন্টে ফিরে যেতে দিন; তারপরে তারা এখনও নিরক্ষীয় অঞ্চলের সাথে মুখোমুখি হবেন, সুতরাং তারা 3 টা পয়েন্টের দিকে মুখোমুখি হবেন - কেবল তাদের 'ব্যক্তিগত' প্রবণতা পরিবর্তন না করেই গোলকের পাশ দিয়ে অগ্রসর হওয়া তাদের উত্তর মেরুর দিকে মুখ করে ঘোরানো হয়েছে নিরক্ষীয় বরাবর মুখোমুখি! এক অর্থে, এটি পুরানো 'একটি শিকারি এক মাইল দক্ষিণে, এক মাইল পশ্চিমে এবং তারপরে একটি মাইল উত্তরে' রসিকতাটির একটি বিস্তৃততা - তবে এখানে আমরা দিক পরিবর্তনকে প্রভাবিত করতে গোলকের বক্রতাটির সুবিধা নিচ্ছি। নোট করুন যে একই প্রভাব এখনও আরও ছোট আকারের স্কেলগুলিতেও ঘটে;

ভাগ্যক্রমে, কোয়ার্টারিয়নগুলি (যেমন আপনি নিজেরাই উল্লেখ করেছেন) এই পরিস্থিতিটি পরিচালনা করে; যেহেতু একটি চৌবাচ্চা একটি স্বেচ্ছাচারিত আবর্তনকে প্রতিনিধিত্ব করে, এটি কার্যকরভাবে গোলকের একটি স্বেচ্ছাসেবী 'পয়েন্ট প্লাস ওরিয়েন্টেশন'কে উপস্থাপন করে: উৎপত্তিস্থলে একটি' ট্রায়াক্সিস 'দিয়ে শুরু করে কিছুটা স্বেচ্ছাচারী ঘূর্ণায়মান কল্পনা করুন, তারপরে যে একক দিকে ঘোরানো অক্ষটি এক দিকে ঘুরে দেখুন' জেড-অক্ষ পয়েন্টস; কিছুটা ভাবনা আপনাকে বোঝাবে যে এটি আপনাকে কিছু 'ওরিয়েন্টেশন' (যেমন, আপনার ট্রায়াক্সিসের এক্স এবং ওয়াইয়ের কয়েকটি বিন্যাস) দিয়ে ইউনিট গোলকের এক বিন্দুতে নিয়ে আসে এবং আপনি প্রতিটি বিন্দুতে + অভিমুখীকরণে যেতে পারেন ইউনিট গোলকটি এইভাবে (কেবল আপনার জেড অক্ষটি গোলকের উপরে আপনার বিন্দুর মধ্য দিয়ে উত্স থেকে রেখার দিকে নির্দেশ করার জন্য নির্ধারণ করুন, তারপরে আপনার ট্রায়াক্সগুলি সেই লাইনের সাথে আবার উত্সে পরিবহন করুন)। আর কি চাই, যেহেতু কোয়ার্টেরিয়ানের গুণগুলি ঘূর্ণনের সংমিশ্রণের সাথে সম্পর্কিত, আপনার বর্ণিত প্রতিটি ক্রিয়াকলাপ যথাযথ-নির্বাচিত চৌম্বকটি দ্বারা আপনার 'বর্তমান ওরিয়েন্টেশন'কে গুণিত করে প্রতিনিধিত্ব করা যেতে পারে: বিশেষত, (ইউনিট) কোয়ার্টেরিয়ন (কিউএক্স, কিউ, কিউজ, কিউডাব্লু) থেকে এর অর্থ 'আরকিওস (কিউডাব্লু) দ্বারা (কিউএক্স, কিউ, কিউজেড) অক্ষ সম্পর্কে ঘোরান', তারপরে (আপনার সমন্বিত সিস্টেমের নির্দিষ্ট পছন্দের উপর নির্ভর করে এবং সি_একে কোস (আলফা) এবং এস_একে পাপ (আলফা) হিসাবে দুটি দেওয়া হবে তিনটি চৌম্বক এম_এক্স = (এস_এ, 0, 0, সি_এ), এম_ই = (0, এস_এ, 0, সি_এ), এবং এম_জে = (0, 0, এস_এ, সি_এ) I দিকের দিকে 'ঘোরানো (অর্থাত্ সরানো) উপস্থাপন করবে 'বর্তমানে আমি আলফার মুখোমুখি' এবং 'আমি বর্তমানে আল্ফার মুখোমুখি হয়েছি এমন একটি দিকের অরথোগোনাল ঘোরান'। (এই চৌকোটিগুলির মধ্যে তৃতীয়টি 'তার নিজের অক্ষ সম্পর্কে আমার চরিত্রটি ঘোরান' উপস্থাপন করবে)Cur_q = M_x * Cur_qযদি প্লেয়ার টিপতে থাকে Cur_q = M_y * Cur_qবা প্লেয়ারটি ডানদিক চাপ দেয় (বা সম্ভবত Cur_q = M_yinv * Cur_qপ্লেয়ারটি বাম টিপে রাখার মতো কিছু , যেখানে এম_আইএনভ এম-ওয়াই কোয়ার্টেরিয়নের 'বিপরীত', অন্যভাবে একটি ঘূর্ণন উপস্থাপন করে)। নোট করুন যে আপনি আগে থেকে বা উত্তর বহুগুণে কিনা ঘূর্ণনটি কোন দিকে 'প্রয়োগ করেন' সে সম্পর্কে আপনাকে সতর্ক থাকতে হবে; স্পষ্ট করে বলতে গেলে, এটি বিচার-এবং-ত্রুটির সাথে সমাধান করা সবচেয়ে সহজ হতে পারে, উভয় গুণকে চেষ্টা করে এবং কোনটি কাজ করে তা দেখে।

আপনার আপডেট হওয়া চৌম্বক থেকে গোলকের একটি বিন্দুতে (এবং আপনার চরিত্রের একটি দিকনির্দেশ) দিকে যাওয়া তুলনামূলকভাবে সহজও: শেষ অনুচ্ছেদের চিঠিপত্রের মাধ্যমে, আপনাকে যা করতে হবে তা ভিত্তিক ভেক্টরগুলিতে আপনার চৌম্বকটি ব্যবহার করতে হবে (1, 0,0), (0,1,0) এবং (0,0,1) আপনার ফ্রেমের 'কোয়ার্টারিয়ন বাই ভেক্টর ঘোরান' অপারেশন ভি → কিউকিউ -1 এর মাধ্যমে (যেখানে এখানে গুণাগুণগুলি কোয়ার্টেরিয়ান গুণ রয়েছে এবং আমরা ভেক্টর ভি = (x, y, z) 'ডিজেনরেট কোয়ার্টারিয়ন' (x, y, z, 0)) দিয়ে। উদাহরণস্বরূপ, ইউনিট গোলকের অবস্থানটি কেবল z ভেক্টরকে রূপান্তরিত করে অর্জন করেছে: পজ = (কিউএক্স, কিউ, কিউজেড, কিউডাব্লু) * (0, 0, 1, 0) * (-কিউএক্স, -কিউ,-কিউজেড, qw) = (কিউএক্স, কিউ, কিউজেড, কিউডাব্লু) * (কিউই, -কিউএক্স, কিউডাব্লু, কিউজেড) = (২ (কিউই * কিউডব্লিউ + কিউজ * কিউএক্স), ২ (কিউজেড * কিউ-কিউউ * কিউএক্স), (কিউজেড) 2 + কিউডাব্লু ^ 2) - (কিউএক্স ^ 2 + কিউই ^ 2), 0), তাই(2(qy*qw+qz*qx), 2(qz*qy-qw*qx), (qz^2+qw^2)-(qx^2+qy^2))ইউনিট গোলকের 'রূপান্তরিত' ব্যবহারকারীর স্থানাঙ্ক হবে (এবং একটি স্বেচ্ছাসেবী ক্ষেত্রের মধ্যে স্থানাঙ্কগুলি পেতে, অবশ্যই আপনি গোলকের ব্যাসার্ধের দ্বারা কেবল এটিগুলি বহুগুণ করতে পারবেন); অনুরূপ গণনা অন্যান্য অক্ষের জন্য যেমন ব্যবহারকারীর মুখের দিকনির্দেশনা নির্ধারণ করতে কাজ করে।


অবশ্যই আমি যা অর্জন করতে চাই। ওরিয়েন্টেশন কোয়ার্টেরিয়েন থেকে বেরিয়ে আসার সঠিক উপায় সম্পর্কে আমি কেবল ভাবতে পারি নি। আপনি যা সরবরাহ করেছেন তা ব্যবহার করে, আমি Move()পদ্ধতিটি লিখতে পারি , তবে স্বাভাবিক অক্ষটি (যেমন আমার অবস্থান) পেতে, আমি কি কেবল গ্রহণ করব (sin(qx),sin(qy),sin(qw)) * r?
Azz

@ যথাযথভাবে নয় - আমি আমার পোস্টটি বিশদ সহ আপডেট করব, তবে সংক্ষিপ্ত সংস্করণটি হ'ল আপনি আপনার ইউনিট ভেক্টর, যেমন (0,0,1) রূপান্তর করতে আপনার কোয়ার্টারিয়নটি ব্যবহার করেন, সাধারণ ভি -> কিউভিউ <sup> -1 </sup> অপারেশন; আপনি একটি সাধারণ ভেক্টরকে রূপান্তর করছেন তার অর্থ এই যে (প্রাকৃতিকভাবে) এখানে একটি শর্ট কাট রয়েছে তবে চূড়ান্ত স্থানাঙ্কগুলি আপনার চৌম্বকটির মানগুলিতে রৈখিক নয়, চতুর্ভুজযুক্ত।
স্টিভেন স্টাডনিকি

1

আমি মনে করি আপনি এই http://www.youtube.com/watch?v=L2YRZbRSD1k এর অনুরূপ কিছু চান

আমি এটি 48 ঘন্টা গেমজমের জন্য বিকাশ করেছি ... আপনি কোডটি এখানে ডনলোড করতে পারেন ... http://archive.globalgamejam.org/2011/evil-god

আমি 3D কোডগুলি পাওয়ার জন্য আপনার কোডের অনুরূপ কিছু ব্যবহার করেছি ... তবে আমি গ্রহটি ঘোরালাম এবং প্লেয়ারটি একই পোস্টে ছিল, আমার মনে হয় আপনি জীবের চলাচলে আগ্রহী, এটি কি:

    // To add movement
    protected override void LocalUpdate(float seconds)
    {
        Creature.Alfa += Direction.X * seconds * Speed;
        Creature.Beta += Direction.Y * seconds * Speed;            
    }


    // To calculate position
       World.Planet.GetCartesian(Alfa, Beta, out Position); // as you do
       Matrix PositionMatrix = Matrix.CreateTranslation(Position) * World.Planet.RotationMatrix;           
       LastPositionAbsolute = PositionAbsolute;
       Vector3 Up = PositionAbsolute = Vector3.Transform(Vector3.Zero, PositionMatrix);           
       Up.Normalize();
       // This is to add and offset to the creature model position
       PositionAbsolute += Up * 8;  
      // calculate new forward vector if needed

       if ((PositionAbsolute - LastPositionAbsolute).Length() > 0.1f) {
           Forward = PositionAbsolute - LastPositionAbsolute;
           Forward.Normalize();
       }

       // Calculate the world transform with position, forward vector and up vector
       Matrix LocalWorld = Matrix.CreateWorld(PositionAbsolute, Forward, Up); 

       Transform = Matrix.CreateScale(Scale * ScaleFactor) * LocalWorld;
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.