প্রক্রিয়াগতভাবে উত্পন্ন বিশ্বের একটি অংশকে অন্য বিশ্বের এক অংশের সাথে মেলে


18

আপনি কি রোজার জেলাজনির দ্বারা ক্রনিকলস অফ অ্যাম্বার পড়েছেন?

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

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

এবং এই জ্ঞানের সাথে আপনি উপরের লিখিত মত কিছু করতে পারেন সে সম্পর্কে আমার কোনও ধারণা নেই। আমার মনে যে ধারণা আসে তা কিছু তাত্ত্বিক সমস্যার মুখোমুখি হয়। আমি ভাবতে পারি এমন কিছু ধারণা এখানে রইল:

1) ইনপুট হিসাবে একটি বীজ সংখ্যা এবং কিছু সম্পূর্ণরূপে বর্ণনাকারী- a-हिस्सा-সংখ্যার সাথে "রিভার্সিবল" বিশ্ব-প্রজন্ম

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

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

2) খণ্ডগুলি সম্পূর্ণরূপে এলোমেলোভাবে তৈরি করা এবং তাদের মধ্যে একটি রূপান্তর করা।

যেমন আরাকথর পরামর্শ দিয়েছেন। এই পদ্ধতির সুবিধাগুলি হ'ল এটি সম্ভব এবং এটিতে কোনও যাদু ফিকশন প্রয়োজন হয় না :)

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

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

যাইহোক, আমি বিশ্বাস করি আপনি সাধারণ ধারণা পেয়ে গেছেন। আপনি এটি কিভাবে হত?


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

আপনার কাছে যোগ করার মতো কিছু থাকলে @ অ্যালেক্সটিল দয়া করে করুন। আমি কোনও ধারণা এবং পরামর্শ শুনে খুশি হব।
নেটাহोलিক

উত্তর:


23

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

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

আপনি যদি ইতিমধ্যে 3 ডি শব্দ ব্যবহার করেন তবে 4D থেকে নমুনা ব্যবহার করা হলে এই ধারণাটিও কাজ করে। এছাড়াও, সিম্প্লেক্স গোলমালটি একবার দেখুন। এটি পার্লিন শব্দের উন্নত সংস্করণ এবং আরও মাত্রার জন্য আরও ভাল কাজ করে।


2
এটা মজার. আমি কি সঠিকভাবে বুঝতে পেরেছি যে আপনি 3 ডি শব্দ উত্পন্ন করার পরামর্শ দিয়েছেন, এর নির্দিষ্ট জেডে উচ্চতা ম্যাপ হিসাবে একটি জাই-স্লাইস ব্যবহার করুন এবং জেড পরিবর্তন করে অন্য স্লাইসে মসৃণ স্থানান্তর করুন - প্লেয়ারের দূরত্ব বাড়ার সাথে সাথে সমন্বয় করুন?
নেটাহোলিক

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

1
এই একটি উজ্জ্বল ধারণা। মূলত, আপনার ভূখণ্ডের মানচিত্রটি 3 ডি ভলিউমের মাধ্যমে প্যারাবলিক (বা অন্যান্য বক্ররেখা) হবে।
ভুয়া নাম

এটি সত্যই চালাক ধারণা is
ব্যবহারকারী 253751

5

বিশ্বের বিভিন্ন অংশে বিভক্ত করার আপনার ধারণাটি খারাপ নয়। এটা ঠিক অসম্পূর্ণ।

সমস্যা শুধুমাত্র অংশগুলির মধ্যে জংশন। উদাহরণস্বরূপ, যদি আপনি স্বস্তি তৈরি করতে পার্লিন শব্দ এবং প্রতিটি অংশের জন্য আলাদা একটি বীজ ব্যবহার করেন এবং এটি হওয়ার ঝুঁকি থাকে:

খণ্ড ত্রাণ বাগ

এর সমাধান হ'ল কেবল পার্লিনের শব্দের বীজ থেকে নয়, পাশাপাশি এর আশেপাশের অন্যান্য খণ্ডগুলি থেকেও খণ্ড ত্রাণ তৈরি করা হবে।

পার্লিন অ্যালগরিদম এগুলিকে "মসৃণ" করতে তাদের চারপাশে এলোমেলো মানচিত্রের মান ব্যবহার করে। যদি তারা একটি সাধারণ মানচিত্র ব্যবহার করে তবে সেখানে একসাথে মসৃণ হবে।

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

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

হালনাগাদ:

যদি আপনার বিশ্বের প্রতিটি অংশ আলাদা আলাদা রকমের হয় তবে সমস্যাটি বড় হয়। এটি কেবল ত্রাণ নিয়ে নয়। একটি ব্যয়বহুল সমাধান নিম্নলিখিত হবে:

খণ্ড কাটা

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

এবং আপনি যেমন এই ছবিতে দেখতে পাচ্ছেন, নরকের ভাগের অংশটি কোণের কোণায় ছোট ছোট স্কোয়ার হবে: তাদের 4 টি অংশের মধ্যে একটি লিঙ্ক তৈরি করতে হবে, সম্ভাব্য বিভিন্ন স্বভাবের।

সুতরাং এই জটিলতা স্তরের জন্য, আমি মনে করি পার্লিন 2 ডি এর মতো ক্লাসিক 2 ডি-ওয়ার্ল্ড প্রজন্ম কেবল ব্যবহার করা যায় না । আমি আপনাকে এটির জন্য @ দঞ্জির উত্তরে উল্লেখ করি।


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

@ নেটাহোলিক এটি আরও বড় নয়, তবে এক ধরণের হবে। আমি এটিতে একটি অনুচ্ছেদ যুক্ত করেছি।
আরাকথর

আমি আমার প্রশ্ন আপডেট করেছি। আমার কিছু ধারণাগুলি বর্ণনা করার চেষ্টা করা হয়েছে
নেটাহोलিক

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

0

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

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

ধারণাটি মূলত একই রকম। তবে উচ্চতর মাত্রিক গোলমালের নমুনা না দিয়ে আপনি বিভিন্ন পুনরাবৃত্ত স্তরগুলিতে মানগুলি পুনরাবৃত্তি করতে পারেন।

সুতরাং আপনি পূর্বে অনুরোধকৃত মানগুলি এখনও সঞ্চয় করে রাখুন এবং সেগুলি ক্যাশে করুন (এই স্কিমটি ইতিমধ্যে একটি সুপার-ফাস্ট অ্যালগরিদমের গতি বাড়ানোর জন্য স্বাধীনভাবে ব্যবহৃত হতে পারে)। এবং যখন নতুন অঞ্চলটি অনুরোধ করা হয়, তখন এটি একটি নতুন y মান দিয়ে তৈরি করা হয়। এবং সেই অনুরোধে অনুরোধ করা কোনও অঞ্চল সরিয়ে ফেলা হবে।

সুতরাং অতিরিক্ত মাত্রায় বিভিন্ন স্থানের চেয়ে স্কোপিংয়ের চেয়ে। আমরা বিভিন্নগুলিতে মিশ্রিত করতে একগুঁয়ে ডেটা অতিরিক্ত বিট সংরক্ষণ করি (বিভিন্ন স্তরে ক্রমান্বয়ে বৃহত্তর পরিমাণে)।

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

সুতরাং আমরা যদি প্রতিটি পুনরাবৃত্তিকে 100x100 মানগুলি সংরক্ষণ করি। তারপরে প্লেয়ার থেকে 100x100 এ কিছুই পরিবর্তন করতে পারে নি। তবে, 200x200 এ 1 টি ব্লক পরিবর্তন হতে পারে। 400x400 এ জিনিসগুলি 2 টি ব্লক দ্বারা পরিবর্তন হতে পারে। 800x800 দূরে জিনিসগুলি 4 টি ব্লক দ্বারা পরিবর্তন করতে সক্ষম হবে। সুতরাং জিনিসগুলি পরিবর্তন হবে এবং আপনি আরও এগিয়ে যাবেন এবং এগুলি আরও বেশি পরিবর্তন হবে। আপনি যদি ফিরে যান তবে এগুলি পৃথক হবে, আপনি যদি খুব বেশি দূরে যান তবে সেগুলি সম্পূর্ণরূপে পরিবর্তিত হবে এবং সমস্ত বীজ পরিত্যাগ করা হবে বলে সম্পূর্ণরূপে হারিয়ে যাবে।

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

https://jsfiddle.net/rkdzau7o/

var SCALE_FACTOR = 2;
//The scale factor is kind of arbitrary, but the code is only consistent for 2 currently. Gives noise for other scale but not location proper.
var BLUR_EDGE = 2; //extra pixels are needed for the blur (3 - 1).
var buildbuffer = BLUR_EDGE + SCALE_FACTOR;

canvas = document.getElementById('canvas');
ctx = canvas.getContext("2d");
var stride = canvas.width + buildbuffer;
var colorvalues = new Array(stride * (canvas.height + buildbuffer));
var iterations = 7;
var xpos = 0;
var ypos = 0;
var singlecolor = true;


/**
 * Function adds all the required ints into the ints array.
 * Note that the scanline should not actually equal the width.
 * It should be larger as per the getRequiredDim function.
 *
 * @param iterations Number of iterations to perform.
 * @param ints       pixel array to be used to insert values. (Pass by reference)
 * @param stride     distance in the array to the next requestedY value.
 * @param x          requested X location.
 * @param y          requested Y location.
 * @param width      width of the image.
 * @param height     height of the image.
 */

function fieldOlsenNoise(iterations, ints, stride, x, y, width, height) {
  olsennoise(ints, stride, x, y, width, height, iterations); //Calls the main routine.
  //applyMask(ints, stride, width, height, 0xFF000000);
}

function applyMask(pixels, stride, width, height, mask) {
  var index;
  index = 0;
  for (var k = 0, n = height - 1; k <= n; k++, index += stride) {
    for (var j = 0, m = width - 1; j <= m; j++) {
      pixels[index + j] |= mask;
    }
  }
}

/**
 * Converts a dimension into the dimension required by the algorithm.
 * Due to the blurring, to get valid data the array must be slightly larger.
 * Due to the interpixel location at lowest levels it needs to be bigger by
 * the max value that can be. (SCALE_FACTOR)
 *
 * @param dim
 * @return
 */

function getRequiredDim(dim) {
  return dim + BLUR_EDGE + SCALE_FACTOR;
}

//Function inserts the values into the given ints array (pass by reference)
//The results will be within 0-255 assuming the requested iterations are 7.
function olsennoise(ints, stride, x_within_field, y_within_field, width, height, iteration) {
  if (iteration == 0) {
    //Base case. If we are at the bottom. Do not run the rest of the function. Return random values.
    clearValues(ints, stride, width, height); //base case needs zero, apply Noise will not eat garbage.
    applyNoise(ints, stride, x_within_field, y_within_field, width, height, iteration);
    return;
  }

  var x_remainder = x_within_field & 1; //Adjust the x_remainder so we know how much more into the pixel are.
  var y_remainder = y_within_field & 1; //Math.abs(y_within_field % SCALE_FACTOR) - Would be assumed for larger scalefactors.

  /*
  Pass the ints, and the stride for that set of ints.
  Recurse the call to the function moving the x_within_field forward if we actaully want half a pixel at the start.
  Same for the requestedY.
  The width should expanded by the x_remainder, and then half the size, with enough extra to store the extra ints from the blur.
  If the width is too long, it'll just run more stuff than it needs to.
  */

  olsennoise(ints, stride,
    (Math.floor((x_within_field + x_remainder) / SCALE_FACTOR)) - x_remainder,
    (Math.floor((y_within_field + y_remainder) / SCALE_FACTOR)) - y_remainder,
    (Math.floor((width + x_remainder) / SCALE_FACTOR)) + BLUR_EDGE,
    (Math.floor((height + y_remainder) / SCALE_FACTOR)) + BLUR_EDGE, iteration - 1);

  //This will scale the image from half the width and half the height. bounds.
  //The scale function assumes you have at least width/2 and height/2 good ints.
  //We requested those from olsennoise above, so we should have that.

  applyScaleShift(ints, stride, width + BLUR_EDGE, height + BLUR_EDGE, SCALE_FACTOR, x_remainder, y_remainder);

  //This applies the blur and uses the given bounds.
  //Since the blur loses two at the edge, this will result
  //in us having width requestedX height of good ints and required
  // width + blurEdge of good ints. height + blurEdge of good ints.
  applyBlur(ints, stride, width + BLUR_EDGE, height + BLUR_EDGE);

  //Applies noise to all the given ints. Does not require more or less than ints. Just offsets them all randomly.
  applyNoise(ints, stride, x_within_field, y_within_field, width, height, iteration);
}



function applyNoise(pixels, stride, x_within_field, y_within_field, width, height, iteration) {
  var bitmask = 0b00000001000000010000000100000001 << (7 - iteration);
  var index = 0;
  for (var k = 0, n = height - 1; k <= n; k++, index += stride) { //iterate the requestedY positions. Offsetting the index by stride each time.
    for (var j = 0, m = width - 1; j <= m; j++) { //iterate the requestedX positions through width.
      var current = index + j; // The current position of the pixel is the index which will have added stride each, requestedY iteration
      pixels[current] += hashrandom(j + x_within_field, k + y_within_field, iteration) & bitmask;
      //add on to this pixel the hash function with the set reduction.
      //It simply must scale down with the larger number of iterations.
    }
  }
}

function applyScaleShift(pixels, stride, width, height, factor, shiftX, shiftY) {
  var index = (height - 1) * stride; //We must iteration backwards to scale so index starts at last Y position.
  for (var k = 0, n = height - 1; k <= n; n--, index -= stride) { // we iterate the requestedY, removing stride from index.
    for (var j = 0, m = width - 1; j <= m; m--) { // iterate the requestedX positions from width to 0.
      var pos = index + m; //current position is the index (position of that scanline of Y) plus our current iteration in scale.
      var lower = (Math.floor((n + shiftY) / factor) * stride) + Math.floor((m + shiftX) / factor); //We find the position that is half that size. From where we scale them out.
      pixels[pos] = pixels[lower]; // Set the outer position to the inner position. Applying the scale.
    }
  }
}

function clearValues(pixels, stride, width, height) {
  var index;
  index = 0;
  for (var k = 0, n = height - 1; k <= n; k++, index += stride) { //iterate the requestedY values.
    for (var j = 0, m = width - 1; j <= m; j++) { //iterate the requestedX values.
      pixels[index + j] = 0; //clears those values.
    }
  }
}

//Applies the blur.
//loopunrolled box blur 3x3 in each color.
function applyBlur(pixels, stride, width, height) {
  var index = 0;
  var v0;
  var v1;
  var v2;

  var r;
  var g;
  var b;

  for (var j = 0; j < height; j++, index += stride) {
    for (var k = 0; k < width; k++) {
      var pos = index + k;

      v0 = pixels[pos];
      v1 = pixels[pos + 1];
      v2 = pixels[pos + 2];

      r = ((v0 >> 16) & 0xFF) + ((v1 >> 16) & 0xFF) + ((v2 >> 16) & 0xFF);
      g = ((v0 >> 8) & 0xFF) + ((v1 >> 8) & 0xFF) + ((v2 >> 8) & 0xFF);
      b = ((v0) & 0xFF) + ((v1) & 0xFF) + ((v2) & 0xFF);
      r = Math.floor(r / 3);
      g = Math.floor(g / 3);
      b = Math.floor(b / 3);
      pixels[pos] = r << 16 | g << 8 | b;
    }
  }
  index = 0;
  for (var j = 0; j < height; j++, index += stride) {
    for (var k = 0; k < width; k++) {
      var pos = index + k;
      v0 = pixels[pos];
      v1 = pixels[pos + stride];
      v2 = pixels[pos + (stride << 1)];

      r = ((v0 >> 16) & 0xFF) + ((v1 >> 16) & 0xFF) + ((v2 >> 16) & 0xFF);
      g = ((v0 >> 8) & 0xFF) + ((v1 >> 8) & 0xFF) + ((v2 >> 8) & 0xFF);
      b = ((v0) & 0xFF) + ((v1) & 0xFF) + ((v2) & 0xFF);
      r = Math.floor(r / 3);
      g = Math.floor(g / 3);
      b = Math.floor(b / 3);
      pixels[pos] = r << 16 | g << 8 | b;
    }
  }
}


function hashrandom(v0, v1, v2) {
  var hash = 0;
  hash ^= v0;
  hash = hashsingle(hash);
  hash ^= v1;
  hash = hashsingle(hash);
  hash ^= v2;
  hash = hashsingle(hash);
  return hash;
}

function hashsingle(v) {
  var hash = v;
  var h = hash;

  switch (hash & 3) {
    case 3:
      hash += h;
      hash ^= hash << 32;
      hash ^= h << 36;
      hash += hash >> 22;
      break;
    case 2:
      hash += h;
      hash ^= hash << 22;
      hash += hash >> 34;
      break;
    case 1:
      hash += h;
      hash ^= hash << 20;
      hash += hash >> 2;
  }
  hash ^= hash << 6;
  hash += hash >> 10;
  hash ^= hash << 8;
  hash += hash >> 34;
  hash ^= hash << 50;
  hash += hash >> 12;
  return hash;
}


//END, OLSEN NOSE.



//Nuts and bolts code.

function MoveMap(dx, dy) {
  xpos -= dx;
  ypos -= dy;
  drawMap();
}

function drawMap() {
  //int iterations, int[] ints, int stride, int x, int y, int width, int height
  console.log("Here.");
  fieldOlsenNoise(iterations, colorvalues, stride, xpos, ypos, canvas.width, canvas.height);
  var img = ctx.createImageData(canvas.width, canvas.height);

  for (var y = 0, h = canvas.height; y < h; y++) {
    for (var x = 0, w = canvas.width; x < w; x++) {
      var standardShade = colorvalues[(y * stride) + x];
      var pData = ((y * w) + x) * 4;
      if (singlecolor) {
        img.data[pData] = standardShade & 0xFF;
        img.data[pData + 1] = standardShade & 0xFF;
        img.data[pData + 2] = standardShade & 0xFF;
      } else {
        img.data[pData] = standardShade & 0xFF;
        img.data[pData + 1] = (standardShade >> 8) & 0xFF;
        img.data[pData + 2] = (standardShade >> 16) & 0xFF;
      }
      img.data[pData + 3] = 255;
    }
  }
  ctx.putImageData(img, 0, 0);
}

$("#update").click(function(e) {
  iterations = parseInt($("iterations").val());
  drawMap();
})
$("#colors").click(function(e) {
  singlecolor = !singlecolor;
  drawMap();
})

var m = this;
m.map = document.getElementById("canvas");
m.width = canvas.width;
m.height = canvas.height;

m.hoverCursor = "auto";
m.dragCursor = "url(data:image/vnd.microsoft.icon;base64,AAACAAEAICACAAcABQAwAQAAFgAAACgAAAAgAAAAQAAAAAEAAQAAAAAAAAEAAAAAAAAAAAAAAgAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD8AAAA/AAAAfwAAAP+AAAH/gAAB/8AAAH/AAAB/wAAA/0AAANsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////////////////////////////////////////////////////////////////////////////////////gH///4B///8Af//+AD///AA///wAH//+AB///wAf//4AH//+AD///yT/////////////////////////////8=), default";
m.scrollTime = 300;

m.mousePosition = new Coordinate;
m.mouseLocations = [];
m.velocity = new Coordinate;
m.mouseDown = false;
m.timerId = -1;
m.timerCount = 0;

m.viewingBox = document.createElement("div");
m.viewingBox.style.cursor = m.hoverCursor;

m.map.parentNode.replaceChild(m.viewingBox, m.map);
m.viewingBox.appendChild(m.map);
m.viewingBox.style.overflow = "hidden";
m.viewingBox.style.width = m.width + "px";
m.viewingBox.style.height = m.height + "px";
m.viewingBox.style.position = "relative";
m.map.style.position = "absolute";

function AddListener(element, event, f) {
  if (element.attachEvent) {
    element["e" + event + f] = f;
    element[event + f] = function() {
      element["e" + event + f](window.event);
    };
    element.attachEvent("on" + event, element[event + f]);
  } else
    element.addEventListener(event, f, false);
}

function Coordinate(startX, startY) {
  this.x = startX;
  this.y = startY;
}

var MouseMove = function(b) {
  var e = b.clientX - m.mousePosition.x;
  var d = b.clientY - m.mousePosition.y;
  MoveMap(e, d);
  m.mousePosition.x = b.clientX;
  m.mousePosition.y = b.clientY;
};

/**
 * mousedown event handler
 */
AddListener(m.viewingBox, "mousedown", function(e) {
  m.viewingBox.style.cursor = m.dragCursor;

  // Save the current mouse position so we can later find how far the
  // mouse has moved in order to scroll that distance
  m.mousePosition.x = e.clientX;
  m.mousePosition.y = e.clientY;

  // Start paying attention to when the mouse moves
  AddListener(document, "mousemove", MouseMove);
  m.mouseDown = true;

  event.preventDefault ? event.preventDefault() : event.returnValue = false;
});

/**
 * mouseup event handler
 */
AddListener(document, "mouseup", function() {
  if (m.mouseDown) {
    var handler = MouseMove;
    if (document.detachEvent) {
      document.detachEvent("onmousemove", document["mousemove" + handler]);
      document["mousemove" + handler] = null;
    } else {
      document.removeEventListener("mousemove", handler, false);
    }

    m.mouseDown = false;

    if (m.mouseLocations.length > 0) {
      var clickCount = m.mouseLocations.length;
      m.velocity.x = (m.mouseLocations[clickCount - 1].x - m.mouseLocations[0].x) / clickCount;
      m.velocity.y = (m.mouseLocations[clickCount - 1].y - m.mouseLocations[0].y) / clickCount;
      m.mouseLocations.length = 0;
    }
  }

  m.viewingBox.style.cursor = m.hoverCursor;
});

drawMap();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="canvas" width="500" height="500">
</canvas>
<fieldset>
  <legend>Height Map Properties</legend>
  <input type="text" name="iterations" id="iterations">
  <label for="iterations">
    Iterations(7)
  </label>
  <label>
    <input type="checkbox" id="colors" />Rainbow</label>
</fieldset>

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