আমি কীভাবে ক্যামেরার পিছনে একটি পয়েন্টটি সঠিকভাবে প্রজেক্ট করব?


10

আমি একটি 3D গেম তৈরি করছি যা আমি আগ্রহের পয়েন্টের উপরে একটি বিস্ময়বোধক চিহ্নিতকারী রেখেছি।

2D স্ক্রিনে আমার চিহ্নিতকারীটি কোথায় রাখা উচিত তা জানতে, আমি ম্যানুয়ালি 3 ডি পয়েন্টটি প্রবর্তন করছি যেখানে চিহ্নিতকারীটি হওয়া উচিত।

দেখে মনে হচ্ছে:

চিহ্নিতকারীরা দুর্দান্ত দেখাচ্ছে

দেখতে বেশ ভাল লাগছে। যখন চিহ্নিতকারী পর্দার বাইরে থাকে তখন আমি কেবল স্থানাঙ্কগুলি ক্লিপ করি যাতে তারা স্ক্রিনে ফিট হয়। দেখে মনে হচ্ছে:

চিহ্নিতকারীরা আরও দুর্দান্ত দেখছেন

এখনও পর্যন্ত ধারণাটি বেশ ভাল চলছে। যাইহোক, যখন আগ্রহের বিষয়গুলি ক্যামেরার পিছনে থাকে, ফলস্বরূপ এক্স, ওয়াই স্থানাঙ্কগুলি উল্টানো হয় (ধনাত্মক / নেতিবাচক হিসাবে), এবং আমি স্ক্রিনের বিপরীত কোণে এই চিহ্নটি উপস্থিত করতে পাই:

চিহ্নিতকারীরা এত ভয়ঙ্কর নয়

(প্রজেক্টড-এরপরে-ক্ল্যাম্পড পয়েন্ট হ'ল চিহ্নিতকারীটির টিপ the চিহ্নিতকারীকে ঘোরানোর বিষয়ে কিছু মনে করবেন না)

এটি বোঝা যায়, যেহেতু হতাশার পিছনে স্থানাঙ্কগুলি এক্স এবং ওয়াইতে উল্টানো হয় So যাইহোক, স্থানাঙ্কগুলি উল্টানো উচিত ঠিক তখনকার অবস্থাটি আমি এখনও জানি না।

এটি বর্তমানে আমার প্রজেকশন কোডটির মতো দেখাচ্ছে (শার্পডএক্সের সাথে সি # তে):

    public override PointF ProjectPosition(float viewportWidth, float viewportHeight, float y)
    {
        var projectionMatrix = Matrix.PerspectiveFovRH(GetCalibratedFOV(Camera.FOV, viewportWidth, viewportHeight), viewportWidth / viewportHeight, Camera.Near, Camera.Far);
        var viewMatrix = Matrix.LookAtRH(new Vector3(Camera.PositionX, Camera.PositionY, Camera.PositionZ), new Vector3(Camera.LookAtX, Camera.LookAtY, Camera.LookAtZ), Vector3.UnitY);
        var worldMatrix = Matrix.RotationY(Rotation) * Matrix.Scaling(Scaling) * Matrix.Translation(PositionX, PositionY, PositionZ);
        var worldViewProjectionMatrix = worldMatrix * viewMatrix * projectionMatrix;

        Vector4 targetVector = new Vector4(0, y, 0, 1);
        Vector4 projectedVector = Vector4.Transform(targetVector, worldViewProjectionMatrix);

        float screenX = (((projectedVector.X / projectedVector.W) + 1.0f) / 2.0f) * viewportWidth;
        float screenY = ((1.0f - (projectedVector.Y / projectedVector.W)) / 2.0f) * viewportHeight;
        float screenZ = projectedVector.Z / projectedVector.W;

        // Invert X and Y when behind the camera
        if (projectedVector.Z < 0 ||
            projectedVector.W < 0)
        {
            screenX = -screenX;
            screenY = -screenY;
        }

        return new PointF(screenX, screenY);
    }

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

অর্ধেক দুর্দান্ত!

আমি যখন উল্টানোর চেষ্টা করেছি:

  • Z নেতিবাচক (এটাই আমার কাছে সবচেয়ে বেশি বোঝায়)
  • W নেতিবাচক (আমি নেতিবাচক ডাব্লু মানের অর্থ বুঝতে পারি না)
  • হয় হয় Zবা Wনেতিবাচক (বর্তমানে বেশিরভাগ সময় কী কাজ করছে)
  • Zএবং Wবিভিন্ন চিহ্নের, হ'ল ওরফে: Z / W < 0(আমার কাছে বোধ হয়। যদিও কাজ করে না)

তবে এখনও আমার একটি সামঞ্জস্যপূর্ণ উপায় খুঁজে পাওয়া যায় নি যার সাথে আমার সমস্ত পয়েন্ট সঠিকভাবে অনুমান করা হয়েছে।

কোন ধারনা?

উত্তর:


2

কীভাবে এটি কিছুটা আলাদাভাবে করা যায়?

যথারীতি শুরু করুন এবং ভিউপোর্টের মধ্যে সমস্ত মার্কার রেন্ডার করুন। যদি কোনও মার্কার ভিউপোর্টের বাইরে থাকে - এগিয়ে যান:

  1. চিহ্নিতকারীর অবস্থানগুলি পান A
  2. ক্যামেরার অবস্থান পান B(সম্ভবত এর সামান্য দিকে)
  3. ABএই দুটিয়ের মধ্যে 3 ডি ভেক্টর গণনা করুন
  4. সেই ভেক্টরকে 2 ডি স্ক্রিনের সীমানায় রূপান্তর এবং স্বাভাবিক করুন ( Aদর্শন কেন্দ্রে থাকবে এবং Bএকটি দর্শন সীমানায় আঘাত করবে)

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

রঙের লাইনগুলি ABভেক্টর হয়। পাতলা কালো লাইনগুলি অক্ষরের উচ্চতা। ডানদিকে 2D স্ক্রিন রয়েছে

  1. সম্ভবত একটি নিয়ম যুক্ত করুন, ক্যামেরার পিছনে সমস্ত কিছু সর্বদা নীচের দিকে চলে যায়
  2. চিহ্নিতকারীগুলির আকার এবং ওভারল্যাপের ক্ষেত্রে স্ক্রিন স্পেসে চিহ্নিতকারীটি আঁকুন

ভিউপোর্টটি বন্ধ রেখে অবস্থানকারীদের মধ্যে অবস্থান করছে কিনা তা দেখার জন্য আপনাকে এটি চেষ্টা করার প্রয়োজন হতে পারে। যদি এটি হয় তবে আপনি যখন ভিউপোর্টের সীমানার কাছে পৌঁছান তখন অবস্থানটি ফাঁকে দেওয়ার চেষ্টা করতে পারেন।


4 ধাপটি ঠিক কীভাবে কাজ করবে?
পান্ডা পাইজামা 14'15

@ পান্ডপাজামা: উত্তরে আমি কিছুটা যুক্ত করেছি। এটা কি এখন আরও পরিষ্কার?
ক্রোমস্টার 14'15

আসলে তা না. আপনি কীভাবে ভেক্টরকে "রূপান্তর ও স্বাভাবিককরণ" করছেন? যদি এটি কোনও প্রোজেকশন ম্যাট্রিক্স প্রয়োগ করে হয় তবে আপনি যা করছেন আমি একই জিনিস করছি
পান্ডা পাজামা

@ পান্ডপাজামা: আমি যতদূর বুঝতে পেরেছি আপনি এটি ক্যামেরা-স্পেসে করছেন (যার ফলে নেতিবাচক জেডডাব্লু সমস্যা)। আমি এটি বিশ্ব স্পেসে করার পরামর্শ দিই এবং কেবলমাত্র তখনই স্ক্রিন-স্পেসে রূপান্তর করব।
ক্রোমস্টার

তবে, গণনা করে AB, আমি কি বিশ্ব স্থানাঙ্ক থেকে লক্ষ্য অবস্থানটি ক্যামেরা স্থানাঙ্কে রূপান্তর করছি না?
পান্ডা পাইজামা

1

তিনটি ভেক্টর দেওয়া [camera position], [camera direction]এবং [object position]। এর ডট পণ্যের গণনা [camera direction]এবং [object position]-[camera position]। ফলাফলটি নেতিবাচক হলে অবজেক্টটি ক্যামেরার পিছনে থাকে।

আমি আপনার কোডটি ঠিক বুঝতে পেরেছি তা হ'ল:

if((PositionX - Camera.PositionX) * Camera.LookAtX
    + (PositionY - Camera.PositionY) * Camera.LookAtY
    + (PositionZ - Camera.PositionZ) * Camera.LookAtZ
    < 0)

Yহয় PositionY + (y * Scaling)। আজ রাত্রে একবার চেষ্টা করে দেখব
পান্ডা পাজামা

এর সাথে আমি প্রকৃতপক্ষে জানতে পারি কখন ক্যামেরার পিছনে রয়েছে is যাইহোক, এটি Z = 0 এ এককথায় পৌঁছাতে প্রক্ষেপণটিকে আটকাবে না।
পান্ডা পাইজামা

@ পান্ডপাজামা এটি কি বাস্তব সমস্যা? Zহুবহু হবার সম্ভাবনা 0খুব কম হওয়া উচিত, বেশিরভাগ খেলোয়াড় কখনই এটি অনুভব করতে পারবেন না এবং প্রত্যাশিত কয়েকটি ক্ষেত্রে গেমপ্লে প্রভাবটি একটি উপেক্ষিত একক ফ্রেমের ভিজ্যুয়াল গ্লাচ। আমি বলব আপনার সময়টি অন্য কোথাও ভাল সময় কাটাতে হবে।
aaaaaaaaaaaa

0

কেবল পরীক্ষা (প্রজেক্টড। ডাব্লু <0), জেড <0 || ডাব্লু <0) নয়।

কিছু ক্লিপ স্পেস ফর্মুলেশনে ( কাশি ওপেনজিএল কাশি ), দৃশ্যমান পরিসরে ধনাত্মক এবং নেতিবাচক জেড মান অন্তর্ভুক্ত থাকে, যেখানে ডাব্লু সবসময় ক্যামেরার সামনে ইতিবাচক থাকে এবং পিছনে নেতিবাচক থাকে।


আমি কেবল ডাব্লু <0 দিয়ে চেষ্টা করেছি, তবে এখনও এমন জায়গা রয়েছে যেখানে এটি ভুলভাবে অনুমান করা হয়েছে।
পান্ডা পাইজামা

0
float screenX = (((projectedVector.X / abs(projectedVector.W)) + 1.0f) / 2.0f) * viewportWidth;
float screenY = ((1.0f - (projectedVector.Y / abs(projectedVector.W))) / 2.0f) * viewportHeight;

এবং এই অংশটি সরান

// Invert X and Y when behind the camera
if (projectedVector.Z < 0 || projectedVector.W < 0)
{
    screenX = -screenX;
    screenY = -screenY;
}

-2

একটি বিলবোর্ড চেষ্টা করুন, যা পিকটি স্বয়ংক্রিয়ভাবে ক্যামেরার মুখোমুখি হবে এবং স্বয়ংক্রিয়ভাবে যথাযথ স্থানে পিকটি স্ক্রিনে আঁকবে


3
প্রশ্ন পড়েছেন?
ক্রোমস্টার

দুঃখিত, আমাকে ব্যাখ্যা করতে দাও - কোনও বিলবোর্ডের আউটপুট নেওয়া, স্কেলিং থেকে মুক্তি পাওয়া সম্ভব (তাই এটি 2 ডি তবে 3 ডি অবস্থান অনুসরণ করে), এবং তারপরে কিছু ম্যাট্রিক্স গণিত ব্যবহার করে এটি পর্দার সীমানায় রাখুন।
মাইকেল ল্যাংফোর্ড

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