মেকিং অফ দ্য ওয়ার্ল্ড ওয়ান্ডারস 3D গ্লোব

Ilmari Heikkinen

ওয়ার্ল্ড ওয়ান্ডারস 3D গ্লোবের সাথে পরিচিতি

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

আপনাকে একটি দ্রুত ওভারভিউ দেওয়ার জন্য, ওয়ার্ল্ড ওয়ান্ডার্স গ্লোব হল Google ডেটা আর্টস টিম দ্বারা ওয়েবজিএল গ্লোবের একটি ভারী টুইক করা সংস্করণ৷ আমরা আসল গ্লোব নিয়েছি, বার গ্রাফ বিটগুলি ছিনিয়ে নিয়েছি, শেডারগুলি পরিবর্তন করেছি, Mozilla-এর GlobeTweeter ডেমো থেকে অভিনব ক্লিকযোগ্য HTML মার্কার এবং প্রাকৃতিক আর্থ মহাদেশের জ্যামিতি যোগ করেছি (সেড্রিক পিনসনকে অনেক ধন্যবাদ!) সমস্ত সাইটটির সাথে মেলে একটি সুন্দর অ্যানিমেটেড গ্লোব তৈরি করার জন্য রঙের স্কিম এবং সাইটে পরিশীলিততার একটি অতিরিক্ত স্তর যোগ করে।

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

WebGL গ্লোব সেট আপ করা হচ্ছে

গ্লোব উইজেট তৈরির প্রথম ধাপ ছিল WebGL Globe ডাউনলোড করা এবং এটি চালু করা। WebGL Globe Google Code- এ অনলাইন রয়েছে এবং এটি ডাউনলোড এবং চালানো সহজ। এটিতে জিপ , সিডি ডাউনলোড এবং এক্সট্রাক্ট করুন এবং একটি মৌলিক ওয়েব সার্ভার চালান: python -m SimpleHTTPServer । (মনে রাখবেন, এটিতে ডিফল্টরূপে UTF-8 নেই; আপনি এটি ব্যবহার করতে পারেন ।) এখন আপনি যদি http://localhost:8000/globe/globe.html এ নেভিগেট করেন তবে আপনাকে WebGL গ্লোব দেখতে হবে।

WebGL Globe আপ এবং চালু হওয়ার সাথে সাথে সমস্ত অপ্রয়োজনীয় অংশগুলি কেটে ফেলার সময় এসেছে৷ আমি UI বিটগুলি এক্সাইজ করার জন্য HTML এডিট করেছি এবং গ্লোব ইনিশিয়ালাইজেশন ফাংশন থেকে গ্লোব বার গ্রাফ সেটআপ স্টাফ সরিয়ে দিয়েছি। সেই প্রক্রিয়ার শেষে, আমার স্ক্রিনে একটি খুব বেয়ারবোন ওয়েবজিএল গ্লোব ছিল। আপনি এটির চারপাশে ঘুরতে পারেন এবং এটি দুর্দান্ত দেখায়, তবে এটি সম্পর্কে।

অপ্রয়োজনীয় জিনিস কাটার জন্য, আমি গ্লোবের index.html থেকে সমস্ত UI উপাদান মুছে ফেলেছি এবং এর মতো দেখতে শুরু করার স্ক্রিপ্টটি সম্পাদনা করেছি:

if(!Detector.webgl){
  Detector.addGetWebGLMessage();
} else {
  var container = document.getElementById('container');
  var globe = new DAT.Globe(container);
  globe.animate();
}

মহাদেশের জ্যামিতি যোগ করা হচ্ছে

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

ল্যান্ডমাস জ্যামিতির জন্য, আমি ওপেন সোর্স GlobeTweeter ডেমোতে ফিরেছিলাম এবং এতে 3D মডেলটি Three.js-এ লোড করেছি। মডেল লোড এবং রেন্ডারিং এর সাথে, এটি বিশ্বের জন্য চেহারা পালিশ শুরু করার সময় ছিল. প্রথম সমস্যা ছিল যে গ্লোব ল্যান্ডমাস মডেলটি ওয়েবজিএল গ্লোবের সাথে ফ্লাশ করার জন্য যথেষ্ট গোলাকার ছিল না, তাই আমি একটি দ্রুত মেশ স্প্লিটিং অ্যালগরিদম লিখে শেষ করেছি যা ল্যান্ডমাস মডেলটিকে আরও গোলাকার করে তুলেছে।

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

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

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

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

ব্ল্যাক গ্লোবের জন্য সাগরের শেডার কেমন দেখায় তা এখানে। খুব বেসিক ভার্টেক্স শেডার এবং একটি হ্যাকি "ওহ যেটি দেখতে কিছুটা ঝরঝরে টুইক টুইক " ফ্র্যাগমেন্ট শেডার।

    'ocean' : {
      uniforms: {
        'texture': { type: 't', value: 0, texture: null }
      },
      vertexShader: [
        'varying vec3 vNormal;',
        'varying vec2 vUv;',
        'void main() {',
          'gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );',
          'vNormal = normalize( normalMatrix * normal );',
          'vUv = uv;',
        '}'
      ].join('\n'),
      fragmentShader: [
        'uniform sampler2D texture;',
        'varying vec3 vNormal;',
        'varying vec2 vUv;',
        'void main() {',
          'vec3 diffuse = texture2D( texture, vUv ).xyz;',
          'float intensity = pow(1.05 - dot( vNormal, vec3( 0.0, 0.0, 1.0 ) ), 4.0);',
          'float i = 0.8-pow(clamp(dot( vNormal, vec3( 0, 0, 1.0 )), 0.0, 1.0), 1.5);',
          'vec3 atmosphere = vec3( 1.0, 1.0, 1.0 ) * intensity;',
          'float d = clamp(pow(max(0.0,(diffuse.r-0.062)*10.0), 2.0)*5.0, 0.0, 1.0);',
          'gl_FragColor = vec4( (d*vec3(i)) + ((1.0-d)*diffuse) + atmosphere, 1.0 );',
        '}'
      ].join('\n')
    }

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

সিএসএস দিয়ে মার্কার তৈরি করা

মার্কারের কথা বলতে গেলে, গ্লোব এবং ল্যান্ডমাস কাজ করার সাথে সাথে, আমি প্লেসমার্কারগুলিতে কাজ শুরু করেছি। আমি মার্কারগুলির জন্য CSS-স্টাইলের HTML উপাদানগুলির সাথে যাওয়ার সিদ্ধান্ত নিয়েছি, মার্কারগুলিকে সহজে তৈরি করা এবং স্টাইল করা এবং সম্ভাব্যভাবে 2D মানচিত্রে মার্কারগুলিকে পুনরায় ব্যবহার করার জন্য দলটি কাজ করছে৷ সেই সময়ে আমি ওয়েবজিএল মার্কারগুলিকে ক্লিকযোগ্য করার সহজ উপায় সম্পর্কেও জানতাম না এবং মার্কার মডেলগুলি লোড করার / তৈরি করার জন্য অতিরিক্ত কোড লিখতে চাইনি। অদূরদর্শীতে, CSS মার্কারগুলি ভাল কাজ করেছিল কিন্তু ব্রাউজার কম্পোজিটর এবং রেন্ডারারগুলি প্রবাহের সময়কালে মাঝে মাঝে পারফরম্যান্সের সমস্যায় পড়ার প্রবণতা ছিল। পারফরম্যান্সের দৃষ্টিকোণ থেকে, WebGL-এ মার্কারগুলি করা একটি ভাল বিকল্প হবে। তারপরে আবার, CSS মার্কারগুলি ডেভের সময় একটি ভাল চুক্তি সাশ্রয় করেছে।

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

মার্কারগুলি যেভাবে 3D দৃশ্যের সাথে সিঙ্ক্রোনাইজ করা হয় তা খুব জটিল নয়। প্রতিটি মার্কারের Three.js দৃশ্যে একটি সংশ্লিষ্ট অবজেক্ট3D আছে, যা মার্কার ট্র্যাক করতে ব্যবহৃত হয়। স্ক্রীন স্পেস কোঅর্ডিনেট পেতে, আমি গ্লোব এবং মার্কারের জন্য Three.js ম্যাট্রিক্স গ্রহণ করি এবং সেগুলির সাথে একটি শূন্য ভেক্টরকে গুণ করি। তা থেকে আমি মার্কার দৃশ্যের অবস্থান পাই। মার্কারের স্ক্রিনের অবস্থান পেতে, আমি ক্যামেরার মাধ্যমে দৃশ্যের অবস্থানটি প্রজেক্ট করি। ফলস্বরূপ প্রক্ষিপ্ত ভেক্টরে মার্কারের জন্য স্ক্রীন স্পেস স্থানাঙ্ক রয়েছে, যা CSS-এ ব্যবহারের জন্য প্রস্তুত।

var mat = new THREE.Matrix4();
var v = new THREE.Vector3();

for (var i=0; i<locations.length; i++) {
  mat.copy(scene.matrix);
  mat.multiplySelf(locations[i].point.matrix);
  v.set(0,0,0);
  mat.multiplyVector3(v);
  projector.projectVector(v, camera);
  var x = w * (v.x + 1) / 2; // Screen coords are between -1 .. 1, so we transform them to pixels.
  var y = h - h * (v.y + 1) / 2; // The y coordinate is flipped in WebGL.
  var z = v.z;
}

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

আপনি যখন একটি মার্কারে ক্লিক করেন তখন এটি ক্লিকযোগ্য স্থানের নামের তালিকায় প্রসারিত হয়। এটি সব সাধারণ HTML DOM স্টাফ, তাই এটি লিখতে খুব সহজ ছিল। সমস্ত লিঙ্ক এবং পাঠ্য রেন্ডারিং আমাদের পক্ষ থেকে কোন অতিরিক্ত কাজ ছাড়াই কাজ করে।

ফাইলের আকার চেপে ধরছি

ডেমোটি কাজ করে এবং বাকি ওয়ার্ল্ড ওয়ান্ডার্স সাইটের সাথে যুক্ত হওয়ার সাথে সাথে, সমাধান করার জন্য এখনও একটি বড় সমস্যা ছিল। গ্লোব ল্যান্ডমাসের জন্য JSON-ফর্ম্যাটের জালটি প্রায় 3 মেগা আকারের ছিল। শোকেস সাইটের প্রথম পৃষ্ঠার জন্য ভাল নয়। ভাল জিনিস ছিল যে জিজিপ দিয়ে জালটি কম্প্রেস করা এটিকে 350 kB এ নামিয়ে এনেছে। কিন্তু হেই, 350 kB এখনও একটু বড়। কিছু ইমেল পরে আমরা ওয়ান চুনকে নিয়োগ করতে পেরেছিলাম -- যিনি বিশাল Google বডি মেশগুলিকে সংকুচিত করার জন্য কাজ করেছিলেন -- আমাদের মেশকে সংকুচিত করতে সাহায্য করার জন্য৷ তিনি JSON স্থানাঙ্ক হিসাবে প্রদত্ত ত্রিভুজগুলির একটি বড় সমতল তালিকা থেকে সূচীকৃত ত্রিভুজ সহ সংকুচিত 11-বিট কোর্ডে জালটি চেপেছিলেন এবং ফাইলের আকার 95 kB জিজিপ করা হয়েছিল।

কম্প্রেসড মেশ ব্যবহার করলে শুধু ব্যান্ডউইথই সাশ্রয় হয় না, মেশগুলি পার্স করাও দ্রুত হয়। 3 মেগা স্ট্রিংকৃত সংখ্যাকে নেটিভ সংখ্যায় পরিণত করা বাইনারি ডেটার 100 kB পার্স করার চেয়ে অনেক বেশি কাজ করে। এবং ফলস্বরূপ পৃষ্ঠাটির জন্য 250 kB আকারের হ্রাস খুবই নিফটি এবং এটি একটি 2 Mbps সংযোগে এক সেকেন্ডের নিচে প্রাথমিক লোড সময় পায়। দ্রুত এবং ছোট, আশ্চর্যজনক সস!

একই সময়ে, আমি আসল ন্যাচারাল আর্থ শেপফাইলগুলি লোড করার সাথে ডুডলিং করছিলাম যেখান থেকে GlobeTweeter জালটি উদ্ভূত হয়েছে৷ আমি শেপফাইলগুলি লোড করতে পেরেছি কিন্তু ফ্ল্যাট ল্যান্ডমাসেস হিসাবে রেন্ডার করার জন্য তাদের ত্রিভুজাকার প্রয়োজন (লেকের জন্য গর্ত সহ, ন্যাচ।) আমি THREE.js ইউটিলস ব্যবহার করে আকারগুলি ত্রিভুজাকার পেয়েছি কিন্তু গর্ত নয়। এবং ফলস্বরূপ জালগুলির খুব দীর্ঘ প্রান্ত ছিল, যার জন্য জালটিকে ছোট ট্রিসে বিভক্ত করা প্রয়োজন। দীর্ঘ গল্প সংক্ষেপে, আমি এটিকে সময়মতো কাজ করতে পরিচালনা করতে পারিনি, তবে পরিষ্কার জিনিসটি ছিল যে আরও সংকুচিত শেপফাইল ফর্ম্যাটটি আপনাকে একটি 8 kB ল্যান্ডমাস মডেল পেত। ওহ ভাল, হয়তো পরবর্তী সময়।

ভবিষ্যতে কাজ

একটি জিনিস যা কিছুটা অতিরিক্ত কাজ ব্যবহার করতে পারে তা হল মার্কার অ্যানিমেশনগুলিকে আরও সুন্দর করে তুলছে। এখন যখন তারা দিগন্ত অতিক্রম করে, প্রভাবটি কিছুটা জটিল। উপরন্তু, মার্কার খোলার জন্য একটি দুর্দান্ত অ্যানিমেশন থাকা চমৎকার হবে।

পারফরম্যান্স অনুসারে দুটি জিনিসের অভাব হল জাল বিভাজন অ্যালগরিদমকে অপ্টিমাইজ করা এবং মার্কারগুলিকে দ্রুততর করা৷ তা ছাড়া, জিনিসগুলি ড্যান্ডি। হুররাহ!

সারসংক্ষেপ

এই নিবন্ধে আমি বর্ণনা করেছি কিভাবে আমরা Google World Wonders প্রকল্পের জন্য 3D গ্লোব তৈরি করেছি। আমি আশা করি আপনি উদাহরণগুলি উপভোগ করেছেন এবং আপনার নিজস্ব কাস্টম গ্লোব উইজেট তৈরি করার চেষ্টা করবেন।

তথ্যসূত্র