সি ++ এ ভক্সেল ইঞ্জিনের জন্য ভক্সেল সংরক্ষণ করা


9

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

আমি অষ্টা গাছগুলি সম্পর্কে পড়েছি এবং যা আমি বুঝতে পারি এটি থেকে 1 টি কিউব দিয়ে শুরু হয়, এবং সেই ঘনকটিতে আরও 8 টি কিউব হতে পারে, এবং এই 8 টি কিউবগুলিতে আরও 8 টি কিউব হতে পারে But তবে আমি মনে করি না এটি আমার ভক্সেল ইঞ্জিনের সাথে খাপ খায় কারণ আমার ভক্সেল কিউবস / আইটেমগুলি হুবহু একই আকার হবে।

সুতরাং অন্য বিকল্পটি হ'ল ১ 16 * ১ * * ১ of আকারের একটি অ্যারে তৈরি করা এবং এটি একটি অংশ হতে হবে এবং আপনি এটি আইটেম দিয়ে পূরণ করুন। এবং যে অংশগুলিতে কোনও আইটেম নেই সেখানে মান হিসাবে 0 (বায়ু) হবে। তবে আমি আশঙ্কা করছি এটি প্রচুর স্মৃতি নষ্ট করবে এবং খুব দ্রুত হবে না।

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

সুতরাং আমি সত্যিই একটি ভাল সমাধান খুঁজে পাচ্ছি না, এবং আমি আশা করছি যে কেউ এটির সাথে আমাকে সহায়তা করতে পারে। তাহলে আপনি কী ব্যবহার করবেন এবং কেন?

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

ধন্যবাদ!


1
আপনার কিউবগুলি রেন্ডার করার জন্য আপনার ইনস্ট্যান্সিং ব্যবহার করা উচিত। আপনি এখানে একটি টিউটোরিয়াল সন্ধান করতে পারেন learnopengl.com/Advanced-OpenGL/Instancing । কিউবগুলি সংরক্ষণ করার জন্য: আপনার কি হার্ডওয়ারে শক্তিশালী মেমরির সীমাবদ্ধতা রয়েছে? 16 ^ 3 কিউব খুব বেশি স্মৃতি মনে হয় না।
টার্মস

@ টিউমারস আপনার মন্তব্যের জন্য ধন্যবাদ! আমার শক্তিশালী স্মৃতিশক্তি নেই, এটি কেবলমাত্র একটি নিয়মিত পিসি। তবে আমি ভেবেছিলাম, প্রতিটি শীর্ষস্থানীয় অংশ যদি 50% বায়ু হয় এবং পৃথিবীটি খুব বড় হয় তবে অবশ্যই কিছুটা নষ্ট স্মৃতি থাকতে হবে। তবে এটি সম্ভবত আপনি বলার মতো নয়। তাহলে আমি কি স্থির পরিমাণে ব্লকগুলির সাথে 16 * 16 * 16 টি অংশে যাব? এবং এছাড়াও, আপনি বলেছিলেন আমার তাত্ক্ষণিক ব্যবহার করা উচিত, এটি কি সত্যই প্রয়োজন? আমার ধারণাটি ছিল প্রতিটি অংশের জন্য জাল তৈরি করা, কারণ এইভাবে আমি সমস্ত অদৃশ্য ত্রিভুজগুলি ছেড়ে দিতে পারি।

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

সেরা ভক্সেল ইঞ্জিন নির্বাচন করা একটি চ্যালেঞ্জ হতে পারে। নিজেকে জিজ্ঞাসা করতে বড় প্রশ্ন হ'ল "আমার ভক্সেলগুলিতে আমার কী অপারেশন করা উচিত?" এটি অপারেশনগুলিকে গাইড করে। উদাহরণস্বরূপ, অষ্ট-গাছের মধ্যে কোন ভক্সেলটি কোথায় রয়েছে তা নির্ধারণ করা আপনার পক্ষে কতটা কঠিন তা সম্পর্কে আপনি উদ্বিগ্ন। অক্টোবর-গাছের অ্যালগোরিদমগুলি সমস্যার জন্য দুর্দান্ত যা গাছটি চলার সাথে সাথে এই তথ্যটি প্রয়োজনীয় হিসাবে তৈরি করতে পারে (প্রায়শই পুনরাবৃত্ত পদ্ধতিতে)। আপনার যদি নির্দিষ্ট সমস্যা হয় যেখানে এটি খুব ব্যয়বহুল, তবে আপনি অন্যান্য বিকল্পগুলি দেখতে পারেন at
কর্ট

আরও একটি বড় প্রশ্ন হ'ল কতক্ষণ ভক্সেল আপডেট করা হয়। কিছু অ্যালগরিদম দুর্দান্ত হয় যদি তারা দক্ষতার সাথে ডেটা সংরক্ষণের জন্য প্রাক-প্রক্রিয়া করতে পারে তবে ডেটাটি কনটসেটলি আপডেট করা হয় তবে কম দক্ষ (ডেটা হিসাবে কণা ভিত্তিক তরল সিমুলেশন হতে পারে)
কর্ট

উত্তর:


23

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

অক্ট্রিগুলি প্রকৃতপক্ষে ভক্সেল ভিত্তিক গেমগুলির জন্য দুর্দান্ত, যেহেতু তারা বৃহত্তর বৈশিষ্ট্যগুলি (যেমন একই ব্লকের প্যাচগুলি) সহ ডেটা সংরক্ষণে বিশেষজ্ঞ। এটি চিত্রিত করার জন্য, আমি একটি চতুর্ভুজ (মূলত 2 ডি-তে অক্ট্রি) ব্যবহার করেছি:

এটি 32x32 টাইলযুক্ত আমার শুরু সেট যা 1024 মানের সমান হবে: এখানে চিত্র বর্ণনা লিখুন

এটিকে 1024 পৃথক মান হিসাবে সংরক্ষণ করা অদক্ষ মনে হয় না, তবে একবার টেরেরিয়ার মতো গেমের মতো মানচিত্রের আকারে পৌঁছে গেলে লোডিং স্ক্রিনগুলি একাধিক সেকেন্ড সময় নিতে পারে। এবং যদি আপনি এটি তৃতীয় মাত্রায় বৃদ্ধি করেন তবে এটি সিস্টেমের সমস্ত স্থান ব্যবহার শুরু করে।

কোয়াডট্রি (বা 3 ডি-তে অক্ট্রি) পরিস্থিতি সাহায্য করতে পারে। একটি তৈরি করতে, আপনি হয় টাইলগুলি থেকে যেতে পারেন এবং তাদের একসাথে গোষ্ঠী করতে পারেন, বা একটি বিশাল কক্ষ থেকে যেতে পারেন এবং আপনি টাইলগুলিতে পৌঁছা পর্যন্ত আপনি এটি ভাগ করে নিতে পারেন। আমি প্রথম পদ্ধতির ব্যবহার করব, কারণ এটি কল্পনা করা সহজ।

সুতরাং, প্রথম পুনরাবৃত্তিতে আপনি সবকিছুকে 2x2 কোষে বিভক্ত করেন এবং কোনও ঘরে যদি একই ধরণের টাইল থাকে তবে আপনি টাইলগুলি ফেলে দিন এবং কেবল টাইপটি সংরক্ষণ করুন। এক পুনরাবৃত্তির পরে, আমাদের মানচিত্রটি এর মতো দেখাবে:

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

লাল রেখাগুলি চিহ্নিত করে যা আমরা সংরক্ষণ করি। প্রতিটি বর্গক্ষেত্রের মূল্য মাত্র 1। এটি আকারটি 1024 মান থেকে 439 এ নামিয়ে আনল, এটি হ'ল 57% হ্রাস।

তবে আপনি মন্ত্রটি জানেন । আসুন আরও এক ধাপ এগিয়ে যান এবং এগুলি সেলগুলিতে গ্রুপ করুন:

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

এটি সঞ্চিত মানগুলির পরিমাণ হ্রাস করেছে 367 That's এটি মূল আকারের মাত্র 36%।

আপনার অবশ্যই স্পষ্টতই এই বিভাগটি করা দরকার যতক্ষণ না প্রতিটি অংশের মধ্যে প্রতিটি 4 সংলগ্ন সেল (3 ডি তে 8 টি সংলগ্ন ব্লক) একটি কোষের ভিতরে সংরক্ষণ করা হয়, একটি অংশটিকে মূলত একটি বড় কক্ষে রূপান্তরিত করে।

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


আপনার উত্তর দেওয়ার জন্য ধন্যবাদ! মনে হচ্ছে অষ্টমুখে যাওয়ার পথ ((যেহেতু আমার ভক্সেল ইঞ্জিনটি থ্রিডি হবে) আমার একটি ঘন ঘন প্রশ্ন রয়েছে তবে আমি জিজ্ঞাসা করতে চাই: আপনার শেষ ছবিতে কালো অংশগুলি আরও বড় স্কোয়ারের জন্য দেখানো হয়েছে, যেহেতু আমার মতো একটি মাইনক্রাফ্ট করার ইচ্ছা আছে ইঞ্জিন যেখানে আপনি ভক্সেল ভূখণ্ডকে সংশোধন করতে পারবেন, আমি ব্লকযুক্ত সমস্ত কিছুকে একই আকারে রাখতে পছন্দ করব, কারণ অন্যথায় এটি জিনিসগুলিকে খুব জটিল করে তুলবে, এটাই সম্ভব? "দ্বিতীয় আমি খালি / এয়ার স্লটগুলি অবশ্যই সহজ করব Second দ্বিতীয় , কীভাবে একটি অষ্টমীর প্রোগ্রাম করবে এমন কোনও ধরণের টিউটোরিয়াল আছে? ধন্যবাদ!

7
@ appmaker1358 এটি কোনও সমস্যা নয়। যদি প্লেয়ারটি একটি বৃহত ব্লককে সংশোধন করার চেষ্টা করে, তবে আপনি সেই মুহুর্তে এটিকে ছোট ব্লকে বিভক্ত করুন । "শিলা" এর 16x16x16 মান সংরক্ষণ করার দরকার নেই যখন আপনি পরিবর্তে বলতে পারবেন "এই পুরো খণ্ডটি শক্ত শিলা" যতক্ষণ না এটি আর সত্য না থাকে।
ডিএমগ্রিগরি

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

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

অक्ट্রি অগত্যা সেরা পছন্দ নয়। এখানে একটি আকর্ষণীয় পঠন করা হয়েছে: 0fps.net/2012/01/14/an-analysis-of-minecraft- Like
engines

7

আপনি বর্ণিত ঠিক সেই সমস্যার সমাধান করতে অক্টোবর উপস্থিত রয়েছে, বড় অনুসন্ধানের সময় ব্যতীত স্পার্স ডেটার ঘন স্টোরেজকে অনুমতি দেয়।

আপনার ভক্সেলগুলি একই আকারের অর্থ এই যে আপনার অষ্টমীর একটি নির্দিষ্ট গভীরতা রয়েছে। যেমন। 16x16x16 খণ্ডের জন্য আপনার গাছের সর্বাধিক 5 স্তরের প্রয়োজন:

  • খণ্ডমূল (16x16x16)
    • প্রথম স্তরের অক্ট্যান্ট (8x8x8)
      • দ্বিতীয় স্তরের অক্ট্যান্ট (4x4x4)
        • তৃতীয় স্তরের অক্ট্যান্ট (2x2x2)
          • একক ভক্সেল (1x1x1)

এর অর্থ হ'ল খণ্ডে কোনও নির্দিষ্ট অবস্থানে ভোক্সেল রয়েছে কিনা তা জানতে আপনার সর্বাধিক 5 টি পদক্ষেপ রয়েছে:

  • খণ্ড মূল: পুরো খণ্ডটি একই মান (যেমন সমস্ত বায়ু)? যদি তা হয় তবে আমরা শেষ করেছি। যদি না...
    • প্রথম স্তর: এই পজিশনটি সমস্ত একই মানযুক্ত অক্টেন্ট কি একই মান? যদি না...
      • দ্বিতীয় স্তর...
        • তৃতীয় স্তর ...
          • এখন আমরা একটি একক ভক্সেলকে সম্বোধন করছি, এবং এর মানটি ফিরিয়ে দিতে পারি।

4096 ভক্সেল পর্যন্ত অ্যারে দিয়ে স্ক্যান করার চেয়েও অনেক ছোট!

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


কিছু অংশের বাচ্চাদের সম্বোধন করার জন্য, আমরা সাধারণত মর্টন ক্রমে এগিয়ে যাব , এরকম কিছু:

  1. এক্স- ওয়াই- জেড-
  2. এক্স- ওয়াই- জেড +
  3. এক্স- ওয়াই + জেড-
  4. এক্স- ওয়াই + জেড +
  5. এক্স + ওয়াই- জেড-
  6. এক্স + ওয়াই- জেড +
  7. এক্স + ওয়াই + জেড-
  8. এক্স + ওয়াই + জেড +

সুতরাং, আমাদের অক্ট্রি নোড নেভিগেশন এই জাতীয় কিছু দেখতে পারে:

GetOctreeValue(OctreeNode node, int depth, int3 nodeOrigin, int3 queryPoint) {
    if(node.IsAllOneValue)
        return node.Value;

    int childIndex =  0;
    childIndex += (queryPoint.x > nodeOrigin.x) ? 4 : 0;
    childIndex += (queryPoint.y > nodeOrigin.y) ? 2 : 0;
    childIndex += (queryPoint.z > nodeOrigin.z) ? 1 : 0;

    OctreeNode child = node.GetChild(childIndex);

    return GetOctreeValue(
                child, 
                depth + 1,
                nodeOrigin + childOffset[depth, childIndex],
                queryPoint
    );
}

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

হ্যাঁ, আপনি ইতিমধ্যে আপনার প্রশ্নে 16x16x16 ভক্সেলের একটি বিস্তৃত অ্যারের কেসটি আবৃত করেছেন এবং দেখে মনে হয়েছে অতিরিক্ত পরিমাণ হিসাবে প্রতিটি কন্ড মেমরির পদচিহ্নগুলি (প্রতিটি ভোক্সেল আইডি একটি বাইট হিসাবে ধরে নেওয়া) প্রত্যাখ্যান করে। আপনি উল্লিখিত অনুসন্ধানটি এমন একটি অবস্থানের সাথে ভক্সেলের একটি তালিকা সংরক্ষণ করার সময় আসে যখন আপনি আপনার লক্ষ্য স্থানে ভক্সেল সন্ধানের জন্য তালিকার মাধ্যমে স্ক্যান করতে বাধ্য করেন। 4096 এখানে তালিকার দৈর্ঘ্যের উপরের সীমাটি রয়েছে - সাধারণত এটি এর চেয়ে ছোট হবে তবে সাধারণত এটি আজও সম্পর্কিত অষ্ট্রি অনুসন্ধানের চেয়ে আরও গভীর।
ডিএমগ্রিগরি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.