গ্রিডের কোন কোষ প্রদত্ত ত্রিভুজটির সাথে ছেদ করে তা কীভাবে নির্ধারণ করবেন?


10

আমি বর্তমানে একটি 2 ডি এআই সিমুলেশন লিখছি, তবে কোনও এজেন্টের অবস্থান অন্যের দেখার ক্ষেত্রের মধ্যে রয়েছে কিনা তা কীভাবে পরীক্ষা করব তা আমি পুরোপুরি নিশ্চিত নই।

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

এই ছবির মতো: এখানে চিত্র বর্ণনা লিখুন

লাল অঞ্চলগুলি সেই কক্ষগুলি যা আমি গণনা করতে চাই, ত্রিভুজটি সেই কোষগুলি ছেদ করে কিনা তা পরীক্ষা করে।

আগাম ধন্যবাদ.

সম্পাদনা করুন:

শুধু বিভ্রান্তিতে যুক্ত করতে (বা সম্ভবত এটি আরও সহজ করে তুলুন)। প্রতিটি ঘরে একটি ন্যূনতম এবং সর্বাধিক ভেক্টর থাকে যেখানে মিনিট নীচে বাম কোণে থাকে এবং সর্বাধিকটি ডানদিকে থাকে।


আপনি কি কোষগুলিকে ত্রিভুজগুলিতে বিভক্ত করতে এবং ত্রিভুজ-ত্রিভুজ পরীক্ষা করতে পারবেন না?
কম্যুনিস্ট হাঁস

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

এখানে কোনও উত্তর পছন্দ করবেন না; যাইহোক, এই প্রশ্নের কিছু সত্যই ভাল উত্তর রয়েছে: গেমদেব.স্ট্যাকেক্সেঞ্জ
অ্যান্ড্রু

উত্তর:


6

আপনার ফোভ ত্রিভুজের তিনটি কোণ গণনা করুন, সঠিক পথে এবং এরকম মুখোমুখি হতে তাদের ঘোরান এবং তারপরে একটি করুন:

1) সমস্ত সম্ভাব্য লক্ষ্যগুলির জন্য একটি পয়েন্ট-ইন-ত্রিভুজ পরীক্ষা করুন

২) এই ত্রিভুজের সীমানা বাক্স গণনা করুন, এবং এই সীমানা বাক্সের কোষের সমস্ত সম্ভাব্য লক্ষ্যগুলির জন্য একটি পয়েন্ট-ইন-ট্রায়াঙ্গেল পরীক্ষা করুন - এটি ডিবাগ করার জন্য খুব সোজা কোড হবে

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

3) এই ত্রিভুজটি 'রাস্টেরাইজ' করুন এবং এটি যেগুলি আঁকেন সেগুলি কোষগুলি পরীক্ষা করে - সম্ভবত এটি সবচেয়ে কার্যকর কোড, তবে সম্ভবত কেবলমাত্র প্রান্তিকভাবেই আমি অনুমান করতে পারি যে এটির সমস্ত ক্যাশে মিস টাইম দ্বারা প্রভাবিত এবং আপনার কোষগুলি কতটা জটিল এবং কীভাবে দখল করা হয়েছে তার উপর নির্ভর করে তারা হয়।

একটি বিকল্প পন্থা হ'ল একটি অফ-স্ক্রিন বিটম্যাপে FOV রেন্ডার এবং তারপরে আপনার প্রতিটি বস্তুর জন্য পিক্সেল মান পড়া; আপনি 'আনমিক্স পেইন্ট' করতে পারবেন না তবে সীমিত সংখ্যক অবজেক্টের সাথে এবং সাবধানে আপনার পেইন্টটি নির্বাচন করে কে কে দেখেছেন তা অনুমান করতে পারেন। এই পদ্ধতির সাথে ব্যবহারকারীরা যা ক্লিক করেছে তার কতগুলি গেমস কার্যকর হয় - হিট অঞ্চলের জন্য দৃ colors় রঙ ব্যবহার করে তারা দৃশ্যটি স্ক্রিনটি আঁকেন। ত্রিভুজ পূরণে GPU গুলি খুব দ্রুত ...


এর জন্য +1 ধন্যবাদ, আমি উপযুক্ত কোষগুলি দ্রুত নির্বাচন করতে ত্রিভুজটির জন্য একটি বাউন্ডিং বাক্স ব্যবহার করেছি এবং সেই ক্ষেত্রগুলির মধ্যে কোন সদস্যের ক্ষেত্রের মধ্যে রয়েছে তা নির্ধারণ করতে একটি পয়েন্ট-ইন-ট্রায়াঙ্গেল পরীক্ষা ব্যবহার করেছি :)
রায় দে

3

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

আমি প্রচুর উপর চকচকে করছি বিবরণে তবে এটি মূল ধারণা। যদি আপনি "সফ্টওয়্যার রেন্ডার" এবং "ত্রিভুজ রাস্টারাইজেশন" এর সন্ধান করেন তবে আপনি সম্ভবত আরও কিছু বিশদ পাবেন। এটি একটি সলভ সমস্যা। আপনার গ্রাফিক্স কার্ডটি ফ্রেমে কয়েক মিলিয়ন বার করছে।

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


1
এটি বেশ দুর্দান্ত পদ্ধতির।
নোটবেন

2

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

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


2

ত্রিভুজটিতে থাকা প্রতিটি সারির কলামের একটি পরিসর বজায় রাখার বিষয়ে কীভাবে? আপনি যা করতে পারেন তা প্রতিটি পয়েন্টের জন্য সর্বনিম্ন এবং সর্বাধিক কলামটি সেট করা হয় যেখানে প্রতিটি পয়েন্ট থাকে এবং যেখানে প্রতিটি ত্রিভুজ লাইন একটি অনুভূমিক সারি বিভাজক রেখাটি অতিক্রম করে।

public class Point
{
    public float X;
    public float Y;
    public Point(float x, float y) { this.X = x; this.Y = y; }
}

public class Line
{
    float ROW_SIZE = 100f;
    float COL_SIZE = 100f;

    public Point P1, P2; // P1 has the lowest Y
    public float Slope, Intercept; // set in constructor
    public bool IsVertical;

    public Line(Point p1, Point p2)
    {
        if (p1.Y > p2.Y) { P1 = p2; P2 = p1; } // p1 has lowest Y
        else { P1 = p1; P2 = p2; }
        IsVertical = (p1.X == p2.X);
        if (!IsVertical) { Slope = (p2.Y - p1.Y) / (p2.X - p1.X); Intercept = p1.Y - Slope * p1.X; }
    }

    public void ExpandRanges(int[] minCol, int[] maxCol)
    {
        // start out at row, col where P1 is, which has lowest Y
        int row = (int)(P1.Y / ROW_SIZE);
        int col = (int)(P1.X / COL_SIZE);
        int lastRow = (int)(P2.Y / ROW_SIZE);
        int lastCol = (int)(P2.X / COL_SIZE);

        // expand row to include P1
        minCol[row] = Math.Min(col, minCol[row]); maxCol[row] = Math.Max(col, maxCol[row]);

        // now we find where our line intercepts each horizontal line up to P2
        float currY = P1.Y;
        float currX = P1.X;
        while (row < lastRow)
        {
            row = row + 1;
            float rowY = row * ROW_SIZE;
            float diffY = rowY - currY;
            float diffX = IsVertical ? 0f : diffY / Slope;
            currY = currY + diffY;
            currX = currX + diffX;
            col = (int)(currX / COL_SIZE);

            // expand rows above and below dividing line to include point
            minCol[row - 1] = Math.Min(col, minCol[row - 1]);
            maxCol[row - 1] = Math.Max(col, maxCol[row - 1]);
            minCol[row] = Math.Min(col, minCol[row]);
            maxCol[row] = Math.Max(col, maxCol[row]);
        }

        // expand last row to include P2
        minCol[lastRow] = Math.Min(lastCol, minCol[lastRow]);
        maxCol[lastRow] = Math.Max(lastCol, maxCol[lastRow]);
    }

    public static void Test()
    {
        Point p1 = new Point(160, 250);
        Point p2 = new Point(340, 250);
        Point p3 = new Point(250, 40);
        Line l1 = new Line(p1, p2);
        Line l2 = new Line(p2, p3);
        Line l3 = new Line(p3, p1);

        Line[] lines = { l1, l2, l3 };

        int rowCount = 4;
        int[] minCol = new int[rowCount];
        int[] maxCol = new int[rowCount];
        for (int i = 0; i < rowCount; i++)
        {
            minCol[i] = int.MaxValue;
            maxCol[i] = int.MinValue;
        }

        for (int i = 0; i < lines.Length; i++)
            lines[i].ExpandRanges(minCol, maxCol);

        for (int i = 0; i < rowCount; i++)
            Console.WriteLine("Row {0}:  {1} - {2}", i, minCol[i], maxCol[i]);
    }
}

আউটপুট:

Row 0:  2 - 2
Row 1:  1 - 3
Row 2:  1 - 3
Row 3:  2147483647 - -2147483648

1

রোগুলেক সম্প্রদায়টিতে কিছু আলগোরিদিম কাজ হয়েছে যা একটি টাইল-ভিত্তিক বিশ্বে FOV / LOS / আলো সরবরাহ করে।

সম্ভবত আপনি এই পৃষ্ঠায় এমন কিছু সন্ধান করতে পারেন যা আপনার সমস্যা সমাধানে সহায়তা করতে ব্যবহার করা যেতে পারে: http://roguebasin.roguelikedevelopment.org/index.php?title=Field_of_Vision

বিশেষত "Permissive FOV" আপনার অবস্থার জন্য সর্বাধিক প্রযোজ্য হতে পারে।

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