প্রচুর কিউব নিয়ে কাজ করা। পারফরম্যান্স উন্নত?


12

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

আমি এমন একটি প্রকল্পে কাজ করছি যেখানে একটি বিশ্ব প্রচুর পরিমাণে কিউব নিয়ে গঠিত (আমি আপনাকে একটি সংখ্যা দেব, তবে এটি ব্যবহারকারী সংজ্ঞায়িত ওয়ার্ল্ডস)। আমার পরীক্ষার প্রথমটি প্রায় (48 x 32 x 48) ব্লক।

মূলত এই ব্লকগুলি নিজেদের মধ্যে কিছু করে না। তারা শুধু সেখানে বসে।

খেলোয়াড়ের মিথস্ক্রিয়ায় এগুলি ব্যবহার করা শুরু করে।

ব্যবহারকারী মাউস কি কিউব (মাউস ওভার, ক্লিক করা ইত্যাদি) সাথে কি কিউবসের সাথে যোগাযোগ করে তা পরীক্ষা করা দরকার এবং প্লেয়ারের চলার সাথে সাথে সংঘর্ষের জন্য সনাক্ত করতে হবে।

এখন আমার প্রথমে প্রচুর পরিমাণে পিছিয়ে পড়েছিল, প্রতিটি ব্লকেই লুপ করে।

আমি সমস্ত ব্লকটি লুপ করে এবং কোন ব্লকগুলি চরিত্রের একটি নির্দিষ্ট পরিসরের মধ্যে রয়েছে তা খুঁজে বের করে এবং তারপরে কেবল সংঘর্ষ সনাক্তকরণের জন্য blocks ব্লকগুলির মধ্যে লুপিং করে আমি এই ল্যাগটি হ্রাস করতে সক্ষম হয়েছি etc.

যাইহোক, আমি এখনও একটি হতাশাজনক 2fps এ যাচ্ছি।

আমি কীভাবে এই ল্যাগটি হ্রাস করতে পারি সে সম্পর্কে কারও কি অন্য কোনও ধারণা রয়েছে?

বিটিডব্লিউ, আমি এক্সএনএ (সি #) ব্যবহার করছি এবং হ্যাঁ, এটি 3 ডি।


তুমি কি মাইনক্রাফ্টের মতো? অর্থাৎ ভোকাসেল?
কম্যুনিস্ট হাঁস

4
আপনি কি অষ্টমীতে গিয়েছেন? en.wikipedia.org/wiki/Octree
bummzack

1
আপনি কি আপনার গেমটি প্রোফাইল করার চেষ্টা করেছেন? এটি এমন কিছু মূল অঞ্চল দেখাতে পারে যেখানে সর্বাধিক সময় ব্যয় করা হচ্ছে। আপনি যা ভাবেন এটি তা নাও হতে পারে।
ডিসলেরেটকাভিয়ার

2
প্রতিটি ঘনক্ষেত্রের সমস্ত 6 টি মুখ আঁকার চেয়ে আপনি কেবল এমন মুখগুলি আঁকতে পারেন যা কোনও কিছুর সংস্পর্শে নেই
ডেভিড আশমোর

1
@ ডেভিড: হ্যাঁ, বা তিনি প্রথমে প্রতি ঘন প্রতি একক ড্র কল করা বন্ধ করতে পারেন এবং তারপরে স্বতন্ত্র বহুভুজ সম্পর্কে পরে চিন্তিত হতে পারেন।
ওলহভস্কি

উত্তর:


20

মনে হচ্ছে আপনি গাছ সম্পর্কে শিখছেন!

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

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

এখন এই অঞ্চলটি নির্ধারণ করার জন্য, আমাদের প্লেয়ারের স্থানাঙ্কের স্থানটি কিউব মানচিত্রের স্থানাঙ্ক স্থানে ম্যাপ করতে হবে; তা হল, আমাদের খেলোয়াড়ের ভাসমান পয়েন্টের অবস্থানটি কিউবার বহুমাত্রিক অ্যারের একটি বিচ্ছিন্ন সূচকতে মানচিত্রের প্রয়োজন (উদাহরণস্বরূপ স্বরলিপিটি হতে পারে world[31][31][31], অর্থাত্ একটি *৪ * *৪ * 64৪ বহুমাত্রিক অ্যারের জন্য সঠিক মাঝারি)।

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

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

প্রশ্নটি: আমরা কীভাবে এটি বাস্তবায়ন করব?

*৪ * 64৪ * 64৪ বিশ্বের জন্য, এটি 8 * 8 * 8 জোনে ভাঙার কল্পনা করুন । এর অর্থ হ'ল আপনার বিশ্বে আপনার প্রতি অক্ষে 8 টি জোন (এক্স, ওয়াই, জেড) থাকবে। এই প্রতিটি জোনে 8 টি কিউব থাকবে যা এই নতুন সরলিকৃত সূচক দ্বারা সহজেই পুনরুদ্ধারযোগ্য।

আপনার বিশ্বের প্রতিটি কিউবটি পুনরাবৃত্ত করার পরিবর্তে আপনার যদি কাছের কিউবসের একটি সেটে কোনও ক্রিয়াকলাপ করা প্রয়োজন, তবে আপনি কেবলমাত্র এই অঞ্চলগুলিতে পুনরাবৃত্তি করতে পারবেন, আসল *৪ * 64৪ * (৪ (262144) থেকে সর্বোচ্চ পুনরাবৃত্তির সংখ্যাটি ভেঙে মাত্র 520 (8 * 8 * 8 + 8)।

এখন এই জোনগুলির জগত থেকে জুম আউট করুন, এবং অঞ্চলগুলি আরও বড় সুপার জোনে রাখুন ; যার মধ্যে প্রতিটি সুপার-জোনটিতে 2 * 2 * 2 নিয়মিত অঞ্চল থাকে । আপনার বিশ্বের বর্তমানে রয়েছে হিসাবে 512 (8 * 8 * 8) অঞ্চল , আমরা 8 * 8 * 8 ভাঙ্গতে পারে জোন 64 (4 * 4 * 4) মধ্যে সুপার-অঞ্চল 8 ভাগ অঞ্চল 2 দ্বারা অঞ্চল প্রতি সুপার-জোন । উপরে থেকে একই যুক্তি প্রয়োগ করা, এটি সুপার জোনটি সন্ধান করতে 512 থেকে 8 পর্যন্ত সর্বাধিক পুনরাবৃত্তিগুলি ভেঙে দেবে ; এবং তারপরে অগ্রণী অঞ্চলটি সর্বাধিক 64 সন্ধান করুন(মোট সর্বোচ্চ 72)! আপনি দেখতে পাচ্ছেন কীভাবে এটি ইতিমধ্যে আপনাকে প্রচুর পুনরাবৃত্তি সাশ্রয় করছে (262144: 72)।

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

নীচের চিত্রটি আপনাকে ধারণাটি কল্পনা করতে সহায়তা করবে। ( উইকিপিডিয়া: অক্টোবর থেকে চিত্র ): Octree

দাবি পরিত্যাগী:

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


আমি বলব আমি পেয়েছি, তবে দুর্ভাগ্যক্রমে আমি তা পাই না। ব্লকগুলির সংঘর্ষের বাক্সগুলি চলমান নয়, কেবল প্লেয়ারের সংঘর্ষের বাক্স। এবং আমার এখন একটি পদ্ধতি রয়েছে যা (সমস্ত ব্লকের মধ্য দিয়ে লুপিং ছাড়াই) প্লেয়ারের 5 টি ব্লক ব্যাসার্ধের মধ্যে থাকা সমস্ত ব্লককে ফিরিয়ে দেয়। ঝামেলার জন্য দুঃখিত, তবে কোনও ব্যাখ্যা? যাইহোক, এটিকে আরও সহজ করে তুলতে আপনি কি পৃথিবীটি x৪ x 64৪ x ass৪?
জোয়েল

এবং আমি এখনও 5fps কাছাকাছি পাচ্ছি :(
জোয়েল

আমি আমার উত্তরটি আবার লিখেছি, এটি সাহায্য করেছে কিনা তা আমাকে জানান।
ডিসলেরেটকাভিয়ার

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

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

13

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

আপনার গতির গতি উল্লেখযোগ্যভাবে বাড়ানোর জন্য আপনাকে আপনার কোড প্রোফাইল করতে হবে। বাধা কোথায় তা চিহ্নিত করুন, এটি আপনাকে সর্বাধিক উন্নতি করতে দেবে।

আপনার কোডটি প্রোফাইল করার জন্য প্রচুর উপায় রয়েছে, আপনি নিজের পারফরম্যান্স বিশ্লেষণ ক্লাসটি রোল করতে পারেন (যা স্টপওয়াচ ক্লাস (এমএসডিএন) ব্যবহার করতে পারে), বা সিপিইউ / জিপিইউ কতটা ব্যস্ত তা সম্পর্কে সাধারণ ধারণা পেতে আপনি পিক্স ব্যবহার করতে পারেন ।

আপনি আপনার কোডগুলিতে পিআইএক্স ইভেন্টের চিহ্নিতকারীগুলিও রাখতে পারেন , যা পিআইএক্সের রিডআউটগুলিতে রঙিন অঞ্চল হিসাবে প্রদর্শিত হবে। এই ক্রিয়াকলাপগুলিতে কোনও অফিসিয়াল সি # ইন্টারফেস নেই, তবে এই থ্রেডটি দেখায় যে আপনি কীভাবে নিজে একটি সি # ইন্টারফেস বানাতে পারেন।


2
+1, সম্পূর্ণ সম্মত। আপনি অ্যালগরিদমগুলিতে সন্ধান করা উচিত নয়, আপনার কোডটি প্রোফাইল করা উচিত। আমার অনুমান যে আপনি যেগুলি ব্লকগুলি দিয়ে পুনরাবৃত্তি করছেন (এটি এতগুলি নয়), এটি প্রতিটি ব্লকের সাথে আপনি যা করছেন তার সাথে কিছুই করার নেই My শেষ পর্যন্ত হ্যাঁ আপনার কাছে ব্রুর ফোর্সের চেয়ে আরও ভাল পদ্ধতি থাকা দরকার তবে আপনি যদি 48x32x48 কিউবে একটি সাধারণ পুনরাবৃত্তি পরিচালনা করতে না পারেন তবে প্রতিটি ঘনক দিয়ে আপনি কী করছেন তা পুনর্বিবেচনা করা দরকার, কীভাবে আপনি লুপ করছেন।
টিম হল্ট

4
@ টিম: যদি না তার প্লেয়ার 48x32x48 এর জায়গা দখল করতে যথেষ্ট বড় না হয়, তবে তার অনেক ঘনক্ষেত্রের কাছাকাছি কোথাও ঘুরতে হবে না। যদি তিনি প্রতি ফ্রেমে 000৩০০০ কিউবসের মাধ্যমে পুনরাবৃত্তি করছেন, তবে আমি আপনাকে কোনও প্রোফাইলিং না করেই বলতে পারি যে, এটি কয়েক হাজার গুণ বেশি পুনরাবৃত্তি না করা কীভাবে শিখতে হবে তা ছাড়া যদি অন্য কোনও কারণে না হয় তবে তা ঠিক করা তার পক্ষে উপযুক্ত it's প্রয়োজনীয়। এটি আমি মাইক্রো বা অকাল অপ্টিমাইজেশন কল করব না।
ওলহোভস্কি

আমার প্লেয়ারটি 1 কিউবের আকারের চেয়ে কম, যদিও এটি কোনও পর্যায়ে বড় হতে পারে (তবে খুব বেশি নয়)
জোয়েল

র্যান্ডমম্যান 159: তারপরে সংঘর্ষের জন্য আপনাকে কেবল তার আশপাশের 27 কিউবের বিরুদ্ধে পরীক্ষা করতে হবে। আমার উত্তর দেখুন।
ওলহভস্কি

6

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

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

যেহেতু আপনার প্লেয়ারটি 1 কিউব থেকে ছোট, সুতরাং আপনার কেবলমাত্র প্রতিবেশী 27 কিউবের বিরুদ্ধে সংঘর্ষের জন্য পরীক্ষা করা দরকার।

এটি ধরে নিয়েছে যে আপনি প্রতিটি কিউবের জন্য অ্যারেতে একটি স্লট সহ একটি অ্যারেতে কিউবগুলি সঞ্চয় করেন।

অন্যরা যেমন উল্লেখ করেছে, আসলে আপনাকে কী ধীর করে দিচ্ছে তা দেখার জন্য আপনার কোডটি প্রোফাইল করা দরকার।

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


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

ব্যক্তিগতভাবে, আমি আমার জন্য 000৩০০০ কিউব এর বিপরীতে পরীক্ষা করতে কোনও পদার্থবিজ্ঞানের ইঞ্জিনের ব্রডপেজের উপর নির্ভর করতে চাই না, যখন আমি কেবলমাত্র আমার জন্য সংঘর্ষের জন্য দক্ষতার সাথে পরীক্ষা করার জন্য দুই ডজন বা তার বেশি কোডের লাইন লিখতে পারি। এছাড়াও, এই মুহুর্তে সম্ভবত তার জন্য কোনও পদার্থবিজ্ঞানের ইঞ্জিন নেই।
ওলোভস্কি

1

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

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


-1

আমার ভক্সেল ইঞ্জিন নিয়ে আমার এই সমস্যাটি ছিল।

সমাধান: (অক্ট্রিগুলির তুলনায় অনেক সহজ) সমস্ত ব্লকের মধ্য দিয়ে লুপিংয়ের পরিবর্তে ব্লক অ্যারেতে ব্লকের অবস্থান নির্ধারণের জন্য কেবল একটি সমীকরণ ব্যবহার করুন।

BlockIndex = (x * WorldWidth * WorldHeight) + (z * WorldHeight) + y;

তারপরে যদি আপনি দেখতে চান যে কোনও ব্লক রয়েছে কিনা:

Blocks[BlockIndex].Type > -1;

অথবা তবে আপনি নির্ধারণ করুন যে ব্লকটি বিদ্যমান কিনা।


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