স্থির অক্ষের চারপাশে বস্তুটি ঘোরান


12

আমি আমার অ্যাপ্লিকেশনটির ব্যবহারকারীকে স্ক্রিনে তাদের আঙুলটি টেনে স্ক্রিনের মাঝে আঁকানো একটি 3 ডি অবজেক্টটি ঘোরানোর চেষ্টা করছি। স্ক্রিনে একটি অনুভূমিক চলন অর্থ একটি স্থির Y অক্ষের চারপাশে ঘূর্ণন এবং একটি উল্লম্ব আন্দোলন মানে এক্স অক্ষের চারপাশে ঘূর্ণন। আমার যে সমস্যাটি হচ্ছে তা হ'ল আমি যদি কেবলমাত্র একটি অক্ষের চারপাশে ঘোরানোর অনুমতি দিই তবে বস্তুটি সূক্ষ্মভাবে ঘোরে, তবে আমি দ্বিতীয় ঘূর্ণনটি প্রবর্তন করার সাথে সাথে প্রত্যাশা অনুযায়ী বস্তুটি ঘোরবে না।

এখানে যা ঘটছে তার একটি চিত্র:

এখানে চিত্র বর্ণনা লিখুন

নীল অক্ষগুলি আমার স্থির অক্ষকে উপস্থাপন করে। এই স্থির নীল অক্ষটিযুক্ত পর্দার চিত্র দিন। এটিই আমি চাই যা সম্পর্কিতটির সাথে সম্পর্কিত হোক। যা হচ্ছে তা লালচে।

আমি যা জানি তা এখানে:

  1. Y এর চারপাশে প্রথম ঘূর্ণন (0, 1, 0) মডেলটিকে নীল স্থান থেকে (এই স্পেস এটিকে কল করুন) অন্য একটি স্পেসে স্থানান্তরিত করে (এই স্পেস বিটিকে কল করুন)
  2. ভেক্টর (1, 0, 0) ব্যবহার করে আবার ঘোরানোর চেষ্টা করা হচ্ছে স্থান A তে নয় বরং স্থান B এ x অক্ষের চারদিকে ঘোরে।

আমি যা চেষ্টা করেছি তা এখানে দেওয়া হয়েছে (আমি মনে করি) যা আমি জানি (ব্রিভটির জন্য ডাব্লু কোর্ড ছেড়ে):

  1. কোয়ার্টারিয়ন ব্যবহার করে প্রথমে Y (0, 1, 0) এর চারদিকে ঘোরান।
  2. ঘূর্ণন Y কোয়ার্টেরিয়নকে একটি ম্যাট্রিক্সে রূপান্তর করুন।
  3. নতুন স্থানের সাথে এক্স অক্ষ পেতে আমার স্থির অক্ষ x ভেক্টর (1, 0, 0) দ্বারা Y রোটেশন ম্যাট্রিক্সকে গুণ করুন।
  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 অক্ষের চারপাশে ঘোরে বলে মনে হচ্ছে।

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

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
আমার উত্তর এখানে গেমদেব.স্ট্যাকেক্সচেঞ্জ / সেকশনস / 199 9 / / / you আপনাকে সাহায্য করতে পারে ..
ধারণা

আমি আপনার উত্তরের পিছনে ধারণাটি বুঝতে পারি, তবে কীভাবে বাস্তবায়ন করতে হয় তা আমার থেকে দূরে যায়।
ক্রিস্টোফার পেরি

আপনি যদি অন্য উত্তরগুলি পরীক্ষা করে থাকেন তবে সিনট্যাক উত্তরটি আমার ব্যাখ্যা করা ধারণাটি কার্যকর করে।
ধারণার

না এটি হয় না, এটি বিভিন্ন অক্ষ সম্পর্কে একাধিক আবর্তন করছে। আপনি একক ঘোরানোর পরামর্শ দিচ্ছেন।
ক্রিস্টোফার পেরি

উত্তর:


3

আপনার সমস্যাটি হ'ল গিম্বল লক । আমি তোমার করতে বলা হয় খুঁজছেন কি মনে করেন arcball ঘূর্ণন । আরকবলের জন্য গণিতটি জটিল জটিল হতে পারে।

এটি করার একটি সহজ উপায় হ'ল স্ক্রিনে 2 ডি সোয়াইপের একটি 2 ডি ভেক্টর লম্ব খুঁজে পেয়ে।

ভেক্টরটি নিয়ে যান এবং বিশ্বের মহাকাশে 3 ডি ভেক্টর পেতে বিমানের কাছাকাছি ক্যামেরাটিতে প্রজেক্ট করুন। স্ক্রিন স্পেস ওয়ার্ল্ড স্পেসে

তারপরে এই ভেক্টরটির সাহায্যে একটি চৌম্বক তৈরি করুন এবং এটিকে গেমোবজেক্টে গুণ করুন। সম্ভবত কিছু স্লার্প বা এলআরপি স্থানান্তর সহ।

সম্পাদনা:

Ityক্যের উদাহরণ: theক্যের উদাহরণে, গেমোবজিকস রোটেশনের অভ্যন্তরীণ অবস্থাটি একটি ম্যাট্রিক্স নয়, একটি চৌম্বক ion ট্রান্সফর্ম.ট্রোটেশন পদ্ধতি ভেক্টর এবং প্রদত্ত কোণের উপর ভিত্তি করে একটি চৌম্বক উত্পন্ন করে এবং গেমোবজেক্টস রোটেশন কোয়ার্টেরিয়নের সাথে সেই কোয়ার্টেরিয়ানকে বহুগুণ করে। এটি কেবল পরবর্তী সময়ে রেন্ডারিং বা পদার্থবিজ্ঞানের জন্য রোটেশন ম্যাট্রিক্স উত্পন্ন করে। Quaternions অ্যাডিটিভ এবং গিম্বল লক এড়ানো।

আপনার কোডটি এর মতো দেখতে হবে:

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. 
  }

আর্কবাল রোটেশন ওপেনগল টিউটোরিয়াল


আমি গিম্বল লক পাচ্ছি না, প্রথম রোটেশনটি অক্ষটি সরায় তাই দ্বিতীয় রোটেশনটি সরানো অক্ষের উপর নির্ভরশীল। আমি যে ছবিটি দিয়েছি তা দয়া করে দ্বিতীয়বার দেখুন।
ক্রিস্টোফার পেরি

আমি আশা করি আপনি এটি বুঝতে পেরেছেন। সংক্ষেপে. ঘূর্ণন প্রয়োগ করার জন্য কোয়ার্টার্নগুলি একসাথে গুণ করা যায়। সমস্ত ঘূর্ণন গণনার শেষে আপনার কেবল ম্যাট্রিক্স তৈরি করা উচিত। এছাড়াও xQ * yQ yQ * xQ এর সমান নয়। ক্রিস্টোফার পেরি যেমন বলেছিল, চতুষ্কোণগুলি অচলনীয় নয়।
অ্যান্টনি রাইমনডো

আমি আমার সমস্ত কোড এখানে রেখেছি । আমার মনে হচ্ছে আমি সব চেষ্টা করেছি। সম্ভবত এই কারও কারও চোখ আমার ভুলটি ধরবে।
ক্রিস্টোফার পেরি

আমি এটি গ্রহণ করি নি, স্ট্যাক এক্সচেঞ্জগুলি অ্যালগরিদম অটো আপনাকে পয়েন্টগুলি বরাদ্দ করেছে। : /
ক্রিস্টোফার পেরি 23

আমি এই অন্যায়ের জন্য দুঃখিত।
অ্যান্থনি রাইমন্ডো

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 রোটেশনের সাথে এক্স অক্ষটি ঘোরানোর সাথে সাথে আপনি স্থানীয় এক্স অক্ষটি পাবেন, যখন আপনি তারপরে বস্তুটি ঘোরান যখন আপনি নিজের চিত্রটিতে প্রদর্শিত ফলাফল পাবেন। কোনও ব্যবহারকারী দৃষ্টিকোণ থেকে ঘূর্ণন যৌক্তিক হতে আপনি তার পরিবর্তে বিশ্ব সমন্বয় অক্ষ ব্যবহার করে বস্তুটি ঘোরান।

আপনি যদি চান যে আপনার ব্যবহারকারীর আপনার বস্তুটি বহুবার স্পিন করতে সক্ষম হবে তবে আপনার ঘূর্ণনটি ম্যাট্রিক্সের পরিবর্তে একটি চৌম্বকীয় স্থানে সংরক্ষণ করা বোধগম্য হবে, সময়ের সাথে সাথে একাধিক স্পিন (এবং ভাসমান পয়েন্টের ভুলগুলি) ম্যাট্রিক্সকে কম দেখায় এবং কম দেখায় একটি ঘূর্ণন ম্যাট্রিক্স, অবশ্যই একটি চতুর্থাংশে ঘটে, তবে কেবল চতুর্মুখীকরণকে স্বাভাবিককরণ এটিকে আবার একটি ভাল আবর্তনে ফিরিয়ে আনে।

কেবলমাত্র প্রাথমিক মান হিসাবে পরিচয় কোয়ার্টারিয়নটি ব্যবহার করুন এবং প্রতিবার ব্যবহারকারী Quaternion.fromAxisAngle(yAxis, -angleX)কোডের সাহায্যে আপনার চৌম্বকটি ঘোরান স্ক্রিনটি সোয়াইপ করে । সর্বদা এক্স ঘূর্ণনের জন্য (1,0,0,1) এবং y ঘূর্ণনের জন্য (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();
}

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


আমি ঠিক একই আচরণ এটি করছি।
ক্রিস্টোফার পেরি

1
@ ক্রিস্টোফেরপেরি ঘোরার ক্রমটি উল্টানোর চেষ্টা করুন: myRotation = rotationX.rotate(rotationY).rotate(myRotation).normalize()এগুলি পরিবর্তনীয় নয় তাই আপনি যে আদেশটি করেন তা গণনা করা হয়। আপনার কাঠামো / ভাষার সাথে অন্য মন্তব্য যুক্ত করুন যদি এটি কাজ না করে এবং Ill এ আরও কিছুটা খনন করে।
ড্যানিয়েল কার্লসন

এটিও কাজ করে না, আমি একই আচরণ পেয়েছি।
ক্রিস্টোফার পেরি

আমি আমার সমস্ত কোড এখানে
ক্রিস্টোফার পেরি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.