কীভাবে ওপেনজিএলে একটি ট্র্যাকবল প্রয়োগ করবেন?


15

রূপান্তরগুলি সম্পর্কে এত বেশি পড়ার পরে আমার অ্যাপ্লিকেশনটির জন্য একটি ট্র্যাকবল প্রয়োগ করার সময় এসেছে। আমি বুঝতে পেরেছি যে উত্স থেকে মাউসটি ক্লিক করা হয়েছে সেখানে এবং তারপরে উত্স থেকে অন্যটি যেখানে মাউস প্রকাশিত হবে সেখানে আমাকে একটি ভেক্টর তৈরি করতে হবে।

আমার প্রশ্নটি হ'ল, আমাকে কি (x, y) পিক্সেল যৌগগুলি বিশ্ব-কোর্ডে স্থানান্তর করতে হবে বা আমার কেবলমাত্র চিত্রের জায়গাগুলিতে সমস্ত কিছু করা উচিত (চিত্রের স্থান বিবেচনা করে পিক্সেলের সাথে পরিমাপ করা দৃশ্যের 2D প্রক্ষেপণ)?

সম্পাদনা

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

আমার আবেদন আমি একটি আছে SimplePerspectiveCameraবর্গ যে পায় positionক্যামেরার, position of the targetআমরা এ খুঁজছি হয় upভেক্টর, fovy, aspectRatio, nearএবং farদূরত্বের।

তাদের সাথে আমি আমার ভিউ এবং প্রজেকশন ম্যাট্রিকগুলি তৈরি করি। এখন, আমি যদি জুম / আউট করতে চাই তবে আমি দেখার ক্ষেত্রটি আপডেট করি এবং আমার প্রজেকশন ম্যাট্রিক্স আপডেট করি update যদি আমি প্যান করতে চাই তবে আমি ক্যামেরার অবস্থানটি সরিয়ে নিয়ে যাচ্ছি এবং মাউস যে ডেল্টাটি তৈরি করে তা দেখুন।

পরিশেষে, আবর্তনের জন্য আমি কোণ-অক্ষ ট্রান্সফর্মেশন বা কোয়ার্টার্নান ব্যবহার করতে পারি। এর জন্য, আমি পিক্সেল-কর্ডগুলি সংরক্ষণ করি যেখানে মাউস টিপানো হয়েছিল এবং তারপরে যখন মাউসটি সরানো হয় আমি পিক্সেল-কর্ডগুলিও সংরক্ষণ করি।

Coords প্রতিটি জোড়া জন্য আমি জেড-মান গনা করতে একটি গোলক জন্য সূত্র দেওয়া অর্থাত, বর্গমূল (1-X ^ 2-Y ^ 2), তারপর ভেক্টর থেকে যেতে গনা targetকরতে PointMousePressedএবং থেকে targetথেকে PointMouseMoved, ক্রস পণ্যের না আবর্তনের অক্ষ পেতে এবং নতুন ক্যামেরার অবস্থান গণনা করতে যে কোনও পদ্ধতি ব্যবহার করুন।

যাইহোক, আমার সবচেয়ে বড় সন্দেহ হ'ল (x, y, z) মানগুলি পিক্সেল-সমন্বয়গুলিতে দেওয়া হয়, এবং যখন ভেক্টরগুলি গণনা করি যখন আমি ব্যবহার করি targetযা বিশ্ব-সমন্বয়ের একটি বিন্দু। এই স্থানাঙ্ক ব্যবস্থার মিশ্রণটি আমি ঘুরানোর ফলাফলকে প্রভাবিত করছি না?


1
"ট্র্যাকবল" এর অর্থ কি এমন একটি ক্যামেরা যা 3 ডি মডেলিং অ্যাপসের মতো কোনও বস্তুর চারদিকে প্রদক্ষিণ করে? যদি তা হয়, তবে আমি মনে করি এটি সাধারণত 2D মাউস স্থানাঙ্কের উপর নজর রাখার মাধ্যমে এবং ক্যামেরা ঘোরার জন্য x = ইয়া, y = পিচ ম্যাপিংয়ের মাধ্যমে সম্পন্ন হয়েছে।
নাথান রিড

1
@ নাথানরেইড অন্য অপশনটি অক্ষ-কোণ ভিত্তিক , আপনি একটি মাউন্ট পয়েন্ট 2 (ভার্চুয়াল) গোলকের উপর প্রজেক্ট করেন এবং তারপরে একটি থেকে অন্যটিতে ঘূর্ণনটি সন্ধান করেন ।
ratchet freak

@ নাথানরিদ হ্যাঁ ট্র্যাকবল বলতে যা বোঝাতে চেয়েছি, আমি ভেবেছিলাম এটি সিজি সম্প্রদায়ের একটি সাধারণ নাম।
BRabbit27

@ratchetfreak হ্যাঁ আমার পদ্ধতিটি অক্ষ-কোণ ভিত্তিক ঘূর্ণন বিবেচনা করে। আমার সন্দেহ হ'ল এটি যদি 2-ডি মাউস জালিকাগুলির সাথে বিশ্ব-কোর্ডার মানচিত্রের প্রয়োজন হয় বা না। আমি জানি যে আমি zব্যাসার্ধের গোলকের মান গণনা করতে (x, y) ব্যবহার করতে পারি r, তবে আমি নিশ্চিত নই যে সেই ক্ষেত্রটি বিশ্ব-স্থান বা চিত্র-স্পেসে বাস করে এবং এর অর্থ কী। সম্ভবত আমি সমস্যাটিকে ওভারথিংক করছি।
BRabbit27

2
আপনার সম্পাদনায়: হ্যাঁ ভিউ ম্যাট্রিক্স ব্যবহার করে আপনার নিজের (x, y, z) মানকে বিশ্ব স্পেসে রূপান্তর করতে হবে।
রিচিস্যামস

উত্তর:


16

ধরে নিচ্ছি আপনার বোঝা এমন একটি ক্যামেরা যা মাউস আন্দোলনের উপর ভিত্তি করে ঘুরবে:

এটিকে বাস্তবায়নের একটি উপায় হ'ল ক্যামেরার অবস্থান এবং স্থানটিতে এর ঘূর্ণনের ট্র্যাক রাখা। গোলাকার স্থানাঙ্কগুলি এর জন্য সুবিধাজনক বলে মনে হয়, যেহেতু আপনি সরাসরি কোণগুলি উপস্থাপন করতে পারেন।

গোলাকার সমন্বয়মূলক চিত্র

float m_theta;
float m_phi;
float m_radius;

float3 m_target;

ক্যামেরাটি পি তে অবস্থিত যা m_theta, m_phi এবং m_radius দ্বারা সংজ্ঞায়িত। এই তিনটি মান পরিবর্তন করে আমরা যেখানেই খুশি ঘোরাফেরা করতে এবং সরিয়ে নিতে পারি। যাইহোক, আমরা সবসময় এম_টারেজকে দেখি এবং চারদিকে ঘোরান। m_target হল গোলকের স্থানীয় উত্স। তবে আমরা বিশ্বের মহাকাশে যেখানেই চাই এই উত্সটিকে স্থানান্তর করতে স্বাধীন।

তিনটি প্রধান ক্যামেরা ফাংশন রয়েছে:

void Rotate(float dTheta, float dPhi);
void Zoom(float distance);
void Pan(float dx, float dy);

তাদের সহজতম ফর্মগুলিতে, ঘোরানো () এবং জুম () তুচ্ছ। যথাক্রমে কেবলমাত্র_পরিচালনা, এম_ফাই এবং এম_রাডিয়াস:

void Camera::Rotate(float dTheta, float dPhi) {
    m_theta += dTheta;
    m_phi += dPhi;
}

void Camera::Zoom(float distance) {
    m_radius -= distance;
}

প্যানিং কিছুটা জটিল। একটি ক্যামেরা প্যানটিকে ক্যামেরাটি বাম / ডানদিকে এবং / অথবা উপরে / ডাউন বর্তমান ক্যামেরা দেখার সাথে সম্পর্কিত হিসাবে সংজ্ঞায়িত করা হয়েছে। আমরা এটি সম্পাদন করার সবচেয়ে সহজ উপায়টি হল আমাদের বর্তমান ক্যামেরা ভিউটিকে গোলাকার স্থানাঙ্ক থেকে কার্তেসিয়ান স্থানাঙ্কে রূপান্তর করা। এটি আমাদের একটি আপ এবং ডান ভেক্টর দেবে।

void Camera::Pan(float dx, float dy) {
    float3 look = normalize(ToCartesian());
    float3 worldUp = float3(0.0f, 1.0f, 0.0f, 0.0f);

    float3 right = cross(look, worldUp);
    float3 up = cross(look, right);

    m_target = m_target + (right * dx) + (up * dy);
}

inline float3 ToCartesian() {
    float x = m_radius * sinf(m_phi) * sinf(m_theta);
    float y = m_radius * cosf(m_phi);
    float z = m_radius * sinf(m_phi) * cosf(m_theta);
    float w = 1.0f;

    return float3(x, y, z, w);
}

সুতরাং, প্রথম, আমরা আমাদের গোলাকার তুল্য সিস্টেম কার্টিজিয়ান আমাদের পেতে রূপান্তর বর্ণন ভেক্টর। এরপরে, আমরা সঠিক ভেক্টর পাওয়ার জন্য আমরা বিশ্বের আপ ভেক্টরের সাথে ভেক্টর ক্রস পণ্যটি করি । এটি এমন একটি ভেক্টর যা ক্যামেরা দৃশ্যের সরাসরি ডানদিকে নির্দেশ করে। শেষ অবধি , আমরা ক্যামেরা আপ ভেক্টর পেতে অন্য ভেক্টর ক্রস পণ্য করি ।

প্যানটি শেষ করতে, আমরা উপরের এবং ডান ভেক্টরগুলির সাথে মি_টারেজ সরিয়ে নিয়েছি ।

আপনি যে প্রশ্নটি জিজ্ঞাসা করতে পারেন তা হ'ল: কেন সর্বদা কার্টেসিয়ান এবং গোলাকৃতির মধ্যে রূপান্তর (ভিউ ম্যাট্রিক্স তৈরি করতে আপনাকে রূপান্তর করতে হবে)।

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

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

সুতরাং, শেষ পর্যন্ত, আমি গোলাকার স্থানাঙ্কের সাথে আটকে গেলাম। অতিরিক্ত গণনাগুলি মোকাবেলা করার জন্য, আমি ভিউ ম্যাট্রিক্সের ক্যাশে শেষ করেছিলাম এবং ক্যামেরাটি সরে গেলে কেবল এটি গণনা করি।

শেষ পদক্ষেপটি এই ক্যামেরা ক্লাসটি ব্যবহার করা । আপনার অ্যাপের মাউসডাউন / আপ / স্ক্রোল ফাংশনগুলির মধ্যে কেবল উপযুক্ত সদস্য ফাংশনটি কল করুন:

void MouseDown(WPARAM buttonState, int x, int y) {
    m_mouseLastPos.x = x;
    m_mouseLastPos.y = y;

    SetCapture(m_hwnd);
}

void MouseUp(WPARAM buttonState, int x, int y) {
    ReleaseCapture();
}

void MouseMove(WPARAM buttonState, int x, int y) {
    if ((buttonState & MK_LBUTTON) != 0) {
        if (GetKeyState(VK_MENU) & 0x8000) {
            // Calculate the new phi and theta based on mouse position relative to where the user clicked
            float dPhi = ((float)(m_mouseLastPos.y - y) / 300);
            float dTheta = ((float)(m_mouseLastPos.x - x) / 300);

            m_camera.Rotate(-dTheta, dPhi);
        }
    } else if ((buttonState & MK_MBUTTON) != 0) {
        if (GetKeyState(VK_MENU) & 0x8000) {
            float dx = ((float)(m_mouseLastPos.x - x));
            float dy = ((float)(m_mouseLastPos.y - y));

            m_camera.Pan(-dx * m_cameraPanFactor, dy * m_cameraPanFactor);
        }
    }

    m_mouseLastPos.x = x;
    m_mouseLastPos.y = y;
}

void MouseWheel(int zDelta) {
    // Make each wheel dedent correspond to a size based on the scene
    m_camera.Zoom((float)zDelta * m_cameraScrollFactor);
}

M_camera * ফ্যাক্টর ভেরিয়েবলগুলি কেবলমাত্র স্কেল ফ্যাক্টর যা আপনার ক্যামেরাটি কত দ্রুত / প্যান / স্ক্রোল ঘোরায় তা পরিবর্তন করে

: কোড আমি উপরের আছে ক্যামেরা সিস্টেম আমি একটি পার্শ্ব প্রকল্পের জন্য তৈরি একটি সরলীকৃত সিউডো-কোড সংস্করণ camera.h এবং camera.cpp । ক্যামেরাটি মায়া ক্যামেরা সিস্টেমটি অনুকরণ করার চেষ্টা করে। কোডটি নিখরচায় এবং মুক্ত উত্স, সুতরাং এটি আপনার নিজের প্রকল্পে বিনা দ্বিধায় অনুভব করুন।


1
আমি অনুমান করি যে 300 দ্বারা বিভাজনটি কি মাউসের স্থানচ্যুতি প্রদানে ঘূর্ণনের সংবেদনশীলতার জন্য কেবলমাত্র একটি পরামিতি?
BRabbit27

সঠিক। এই সময়ে আমার রেজোলিউশনটি দিয়ে ভালভাবে কাজ করার জন্য এটি ঘটেছে।
রিচিস্যামস

-2

আপনি যদি একটি প্রস্তুত সমাধান সন্ধান করতে চান তবে আমার কাছে সি ++ এবং সি # তে থ্রি.জেএস ট্র্যাকবাল নিয়ন্ত্রণগুলির একটি বন্দর রয়েছে


আমি মনে করি এটি এটি করে। ট্র্যাকবল কীভাবে কাজ করে তার ভিতরে কোড থেকে সে শিখতে পারে।
মাইকেল চতুর্থ

1
@ মিশেলআইভি তা সত্ত্বেও, অ্যালান ওল্ফের একটি বক্তব্য রয়েছে। আপনি নিজের উত্তরটি প্রাসঙ্গিক কোড অন্তর্ভুক্ত করে নিজেই এটির স্ব-অন্তর্নিহিত এবং কোনও দিন লিঙ্কটি মারা যাওয়ার বিরুদ্ধে ভবিষ্যত-প্রমাণ তৈরি করে ব্যাপক উন্নতি করতে পারেন।
মার্টিন ইন্ডার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.