بهینه سازی داده های سه بعدی با فشرده سازی هندسه دراکو

۱. مرور کلی

گرافیک سه‌بعدی بخش اساسی بسیاری از برنامه‌ها، از جمله بازی، طراحی و تجسم داده‌ها است. با پیشرفت مداوم پردازنده‌های گرافیکی و ابزارهای خلق، مدل‌های سه‌بعدی بزرگ‌تر و پیچیده‌تر رایج می‌شوند و به تقویت برنامه‌های جدید در واقعیت مجازی فراگیر (VR) و واقعیت افزوده (AR) کمک می‌کنند. به دلیل این افزایش پیچیدگی مدل، نیازهای ذخیره‌سازی و پهنای باند مجبورند با انفجار داده‌های سه‌بعدی همگام شوند.

با Draco، برنامه‌هایی که از گرافیک سه‌بعدی استفاده می‌کنند می‌توانند بدون افت کیفیت بصری، به‌طور قابل‌توجهی کوچک‌تر شوند. برای کاربران، این بدان معناست که اکنون برنامه‌ها می‌توانند سریع‌تر دانلود شوند، گرافیک سه‌بعدی در مرورگر سریع‌تر بارگذاری شود و صحنه‌های VR و AR اکنون می‌توانند با کسری از پهنای باند منتقل شوند، به‌سرعت رندر شوند و فوق‌العاده به نظر برسند.

دراکو چیست؟

Draco کتابخانه‌ای برای فشرده‌سازی و خارج کردن مش‌های هندسی سه‌بعدی و ابرهای نقطه‌ای است. این کتابخانه برای بهبود ذخیره‌سازی و انتقال گرافیک‌های سه‌بعدی در نظر گرفته شده است.

دراکو برای فشرده‌سازی با کارایی و سرعت بالا طراحی و ساخته شده است. این کد از نقاط فشرده‌سازی، اطلاعات اتصال، مختصات بافت، اطلاعات رنگ، نرمال‌ها و سایر ویژگی‌های عمومی مرتبط با هندسه پشتیبانی می‌کند. دراکو به عنوان کد منبع C++ منتشر شده است که می‌تواند برای فشرده‌سازی گرافیک‌های سه‌بعدی و همچنین رمزگشاهای C++ و جاوا اسکریپت برای داده‌های رمزگذاری شده استفاده شود.

آنچه یاد خواهید گرفت

  • نحوه استفاده از Draco برای فشرده سازی مدل سه بعدی
  • نحوه استفاده از مدل‌های فشرده‌سازی مختلف و تأثیر آنها بر کیفیت و اندازه مدل
  • نحوه مشاهده مدل سه بعدی در وب

آنچه نیاز دارید

۲. راه‌اندازی

مخزن گیت‌هاب را با استفاده از این خط فرمان کلون کنید:

git clone https://github.com/google/draco

به دایرکتوری ریشه Draco بروید.

cd draco

۳. ساخت انکودر

برای شروع رمزگذاری و رمزگشایی دراکو، ابتدا با ساخت برنامه‌ها شروع می‌کنیم.

ساخت انکودر

  • cmake را از دایرکتوری که می‌خواهید فایل‌های ساخت در آن ایجاد شوند، اجرا کنید و مسیر مخزن Draco خود را به آن بدهید.
mkdir build

cd build

cmake ../

make

۴. اولین فایل سه‌بعدی خود را رمزگذاری کنید

draco_encoder فایل‌های OBJ یا PLY را به عنوان ورودی می‌خواند و فایل‌های کدگذاری شده با Draco را به عنوان خروجی ارائه می‌دهد. ما مش خرگوش استنفورد را برای آزمایش اضافه کرده‌ایم. خط فرمان اولیه به این شکل است:

./draco_encoder -i ../testdata/bun_zipper.ply -o bunny.drc

اکنون می‌توانید حجم فایل خروجی را مشاهده کرده و آن را با فایل اصلی .ply مقایسه کنید. فایل فشرده باید بسیار کوچکتر از حجم فایل اصلی باشد.

توجه: اندازه فشرده شده می‌تواند بسته به گزینه‌های فشرده‌سازی متفاوت باشد.

۵. رمزگشایی فایل Draco در مرورگر

در این مرحله، ما با یک صفحه وب ساده برای رمزگشایی فایل‌های Draco شروع خواهیم کرد. ما با کپی کردن و چسباندن بخش‌های کد زیر در ویرایشگر متن شروع خواهیم کرد.

  1. با یک فایل HTML ساده شروع کنید.
<!DOCTYPE html>
<html>
<head>
  <title>Codelab - Draco Decoder</title>
  1. قطعه کد زیر، رمزگشای Draco WASM را بارگذاری می‌کند.
  <script src="https://www.gstatic.com/draco/versioned/decoders/1.4.1/draco_wasm_wrapper.js">
    // It is recommended to always pull your Draco JavaScript and WASM decoders
    // from the above URL. Users will benefit from having the Draco decoder in
    // cache as more sites start using the static URL.
  </script>
  1. سپس این تابع را اضافه کنید که یک ماژول دیکدر Draco ایجاد می‌کند. ایجاد ماژول دیکدر ناهمزمان است، بنابراین باید منتظر بمانید تا تابع فراخوانی شود و سپس بتوانید از ماژول استفاده کنید.
  <script>
    'use strict';

    // The global Draco decoder module.
    let decoderModule = null;

    // Creates the Draco decoder module.
    function createDracoDecoderModule() {
      let dracoDecoderType = {};

      // Callback when the Draco decoder module is fully instantiated. The
      // module parameter is the created Draco decoder module.
      dracoDecoderType['onModuleLoaded'] = function(module) {
        decoderModule = module;

        // Download the Draco encoded file and decode.
        downloadEncodedMesh('bunny.drc');
      };
      DracoDecoderModule(dracoDecoderType);
    }
  1. تابعی را برای رمزگشایی مش کدگذاری شده Draco اضافه کنید.
    // Decode an encoded Draco mesh. byteArray is the encoded mesh as
    // an Uint8Array.
    function decodeMesh(byteArray) {
      // Create the Draco decoder.
      const decoder = new decoderModule.Decoder();

      // Create a buffer to hold the encoded data.
      const buffer = new decoderModule.DecoderBuffer();
      buffer.Init(byteArray, byteArray.length);

      // Decode the encoded geometry.
      let outputGeometry = new decoderModule.Mesh();
      let decodingStatus = decoder.DecodeBufferToMesh(buffer, outputGeometry);

      alert('Num points = ' + outputGeometry.num_points());

      // You must explicitly delete objects created from the DracoModule
      // or Decoder.
      decoderModule.destroy(outputGeometry);
      decoderModule.destroy(decoder);
      decoderModule.destroy(buffer);
    }
  1. حالا که تابع رمزگشایی Draco را داریم، یک تابع برای دانلود مش کدگذاری شده Draco اضافه می‌کنیم. تابع 'downloadEncodedMesh' یک پارامتر به فایل Draco که قرار است بارگذاری شود، می‌پذیرد. در این حالت، این پارامتر 'bunny.drc' از مرحله قبل خواهد بود.
    // Download and decode the Draco encoded geometry.
    function downloadEncodedMesh(filename) {
      // Download the encoded file.
      const xhr = new XMLHttpRequest();
      xhr.open("GET", filename, true);
      xhr.responseType = "arraybuffer";
      xhr.onload = function(event) {
        const arrayBuffer = xhr.response;
        if (arrayBuffer) {
          const byteArray = new Uint8Array(arrayBuffer);
          decodeMesh(byteArray);
        }
      };
      xhr.send(null);
    }
  1. تابع 'createDracoDecoderModule' را برای ایجاد ماژول رمزگشای Draco فراخوانی کنید، که تابع 'downloadEncodedMesh' را برای دانلود فایل رمزگذاری شده Draco فراخوانی می‌کند، که تابع 'decodeMesh' را برای رمزگشایی مش رمزگذاری شده Draco فراخوانی می‌کند.
    // Create the Draco decoder module.
    createDracoDecoderModule();
  </script>
</head>
<body>
</body>
</html>
  1. این فایل را با نام "DracoDecode.html" ذخیره کنید.
  2. وب سرور پایتون را اجرا کنید. در ترمینال دستور زیر را تایپ کنید:
python -m SimpleHTTPServer

  1. فایل localhost:8000/DracoDecode.html را در کروم باز کنید. این باید یک کادر پیام هشدار با تعداد نقاط (تعداد نقاط = ۳۴۸۳۴) که از مدل رمزگشایی شده‌اند را نمایش دهد.

۶. رندر کردن یک فایل Draco با three.js

حالا که می‌دانیم چگونه یک فایل Draco را با استفاده از WASM رمزگشایی کنیم، از یک نمایشگر سه‌بعدی محبوب وب - three.js - استفاده خواهیم کرد. مانند مثال قبلی، با کپی کردن و چسباندن بخش‌های کد زیر در ویرایشگر متن شروع می‌کنیم.

  1. با یک فایل HTML پایه شروع کنید
<!DOCTYPE html>
<html>
<head>
  <title>Codelab - Draco three.js Render</title>
  1. کدی برای بارگذاری three.js و Draco three.js loader اضافه کنید.
  <script type="importmap">
          {
            "imports": {
              "three": "https://unpkg.com/three@v0.162.0/build/three.module.js",
              "three/addons/": "https://unpkg.com/three@v0.162.0/examples/jsm/"
            }
          }
  </script>
  1. مسیر رمزگشای دراکو را تنظیم کنید.
  <script type="module">
    // import three.js and DRACOLoader.
    import * as THREE from 'three';
    import {DRACOLoader} from 'three/addons/loaders/DRACOLoader.js'

    // three.js globals.
    var camera, scene, renderer;

    // Create the Draco loader.
    var dracoLoader = new DRACOLoader();

    // Specify path to a folder containing WASM/JS decoding libraries.
    // It is recommended to always pull your Draco JavaScript and WASM decoders
    // from the below URL. Users will benefit from having the Draco decoder in
    // cache as more sites start using the static URL.
    dracoLoader.setDecoderPath('https://www.gstatic.com/draco/versioned/decoders/1.4.1/');
  1. کد رندر three.js را اضافه کنید.
    function initThreejs() {
      camera = new THREE.PerspectiveCamera( 35, window.innerWidth / window.innerHeight, 0.1, 15 );
      camera.position.set( 3, 0.25, 3 );

      scene = new THREE.Scene();
      scene.background = new THREE.Color( 0x443333 );
      scene.fog = new THREE.Fog( 0x443333, 1, 4 );

      // Ground
      var plane = new THREE.Mesh(
        new THREE.PlaneGeometry( 8, 8 ),
        new THREE.MeshPhongMaterial( { color: 0x999999, specular: 0x101010 } )
      );
      plane.rotation.x = - Math.PI / 2;
      plane.position.y = 0.03;
      plane.receiveShadow = true;
      scene.add(plane);

      // Lights
      var light = new THREE.HemisphereLight( 0x443333, 0x111122 );
      scene.add( light );

      var light = new THREE.SpotLight();
      light.angle = Math.PI / 16;
      light.penumbra = 0.5;
      light.castShadow = true;
      light.position.set( - 1, 1, 1 );
      scene.add( light );

      // renderer
      renderer = new THREE.WebGLRenderer( { antialias: true } );
      renderer.setPixelRatio( window.devicePixelRatio );
      renderer.setSize( window.innerWidth, window.innerHeight );
      renderer.shadowMap.enabled = true;

      const container = document.getElementById('container');
      container.appendChild( renderer.domElement );

      window.addEventListener( 'resize', onWindowResize, false );
    }

    function onWindowResize() {
      camera.aspect = window.innerWidth / window.innerHeight;
      camera.updateProjectionMatrix();

      renderer.setSize( window.innerWidth, window.innerHeight );
    }

    function animate() {
      render();
      requestAnimationFrame( animate );
    }

    function render() {
      var timer = Date.now() * 0.0003;

      camera.position.x = Math.sin( timer ) * 0.5;
      camera.position.z = Math.cos( timer ) * 0.5;
      camera.lookAt( new THREE.Vector3( 0, 0.1, 0 ) );

      renderer.render( scene, camera );
    }
  1. کد بارگذاری و رمزگشایی دراکو را اضافه کنید.
    function loadDracoMesh(dracoFile) {
      dracoLoader.load(dracoFile, function ( geometry ) {
        geometry.computeVertexNormals();

        var material = new THREE.MeshStandardMaterial( { vertexColors: THREE.VertexColors } );
        var mesh = new THREE.Mesh( geometry, material );
        mesh.castShadow = true;
        mesh.receiveShadow = true;
        scene.add( mesh );
      } );
    }

  1. کدی برای بارگذاری فایل اضافه کنید.
    window.onload = function() {
      initThreejs();
      animate();
      loadDracoMesh('bunny.drc');
    }
  </script>
</head>
<body>
  <div id="container"></div>
</body>
</html>
  1. این فایل را با نام "DracoRender.html" ذخیره کنید.
  2. در صورت نیاز، وب‌سرور را مجدداً راه‌اندازی کنید.
python -m SimpleHTTPServer

  1. فایل localhost:8000/DracoRender.html را در کروم باز کنید. اکنون باید فایل Draco خود را که در مرورگر رندر شده است، مشاهده کنید.

۷. پارامترهای کدگذاری مختلف را امتحان کنید

انکودر Draco پارامترهای مختلفی را که بر اندازه فایل فشرده و کیفیت بصری کد تأثیر می‌گذارند، در نظر می‌گیرد. چند دستور بعدی را در خط فرمان اجرا کنید و نتایج را ببینید.

  1. دستور زیر موقعیت‌های مدل را با استفاده از ۱۲ بیت (پیش‌فرض ۱۱ بیت است) کوانتیزه می‌کند.
./draco_encoder -i ../testdata/bun_zipper.ply -o out12.drc -qp 12

  1. به اندازه فایل out12.drc در مقایسه با فایل bunny.drc در بخش قبل توجه کنید. استفاده از بیت‌های کوانتیزاسیون بیشتر می‌تواند اندازه فایل فشرده را افزایش دهد.

۳. دستور زیر موقعیت‌های مدل را با استفاده از ۶ بیت کوانتیزه می‌کند.

./draco_encoder -i ../testdata/bun_zipper.ply -o out6.drc -qp 6

  1. به اندازه فایل out6.drc در مقایسه با فایل bunny.drc در بخش قبل توجه کنید. استفاده از بیت‌های کوانتیزاسیون کمتر می‌تواند اندازه فایل فشرده را کاهش دهد.
  1. پارامترهای زیر بر سطوح فشرده‌سازی مدل تأثیر می‌گذارند. با استفاده از پرچم cl، می‌توانید فشرده‌سازی خود را از ۱ (کمترین نسبت فشرده‌سازی) تا ۱۰ (بیشترین نسبت فشرده‌سازی) تنظیم کنید.
./draco_encoder -i ../testdata/bun_zipper.ply -o outLow.drc -cl 1

./draco_encoder -i ../testdata/bun_zipper.ply -o outHigh.drc -cl 10

به خروجی انکودر Draco توجه کنید. می‌توانید ببینید که بین زمان مورد نیاز برای فشرده‌سازی در بالاترین سطوح فشرده‌سازی و صرفه‌جویی در بیت‌ها، بده‌بستانی وجود دارد. پارامتر صحیح برای کاربرد شما به زمان‌بندی و الزامات اندازه در زمان انکود بستگی دارد.

۸. تبریک

شما آزمایشگاه کد فشرده‌سازی مش Draco را به پایان رسانده‌اید و با موفقیت بسیاری از ویژگی‌های کلیدی Draco را بررسی کرده‌اید!

امیدوارم برای شما روشن شده باشد که چگونه Draco می‌تواند به کوچک‌تر و کارآمدتر کردن فایل‌های سه‌بعدی شما برای انتقال از طریق وب کمک کند. می‌توانید اطلاعات بیشتری در مورد Draco کسب کنید و جدیدترین کتابخانه را از github دریافت کنید.