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

1. بررسی اجمالی

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

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

دراکو چیست؟

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

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

آنچه خواهید آموخت

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

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

2. راه اندازی

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

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

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

cd draco

3. رمزگذار را بسازید

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

ساخت رمزگذار

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

cd build

cmake ../

make

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

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

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

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

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

5. یک فایل دراکو را در مرورگر رمزگشایی کنید

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

  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. تابع را برای رمزگشایی مش رمزگذاری شده دراکو اضافه کنید.
    // 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 را داریم، یک تابع برای دانلود مش رمزگذاری شده دراکو اضافه کنید. تابع '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' را برای رمزگشایی مش دراکو کدگذاری شده فراخوانی می کند.
    // Create the Draco decoder module.
    createDracoDecoderModule();
  </script>
</head>
<body>
</body>
</html>
  1. این فایل را به عنوان "DracoDecode.html" ذخیره کنید
  2. وب سرور پایتون را راه اندازی کنید. در نوع ترمینال:
python -m SimpleHTTPServer

  1. localhost:8000/DracoDecode.html را در کروم باز کنید. این باید یک جعبه پیام هشدار با تعداد نقاط (Num points = 34834) که از مدل رمزگشایی شده است را نمایش دهد.

6. یک فایل دراکو را با 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 خود را در مرورگر مشاهده کنید.

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

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

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

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

3. دستور زیر موقعیت های مدل را با استفاده از 6 بیت کوانتیزه می کند.

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

  1. به اندازه فایل out6.drc در مقایسه با فایل bunny.drc در بخش قبل توجه کنید. استفاده از بیت های کوانتیزاسیون کمتر می تواند حجم فایل فشرده را کاهش دهد.
  1. پارامترهای زیر بر سطوح فشرده سازی مدل تأثیر می گذارد. با استفاده از پرچم cl، می توانید فشرده سازی خود را از 1 (کمترین نسبت فشرده سازی) به 10 (بالاترین) تنظیم کنید.
./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 توجه کنید. می بینید که در زمان مورد نیاز برای فشرده سازی در بالاترین سطوح فشرده سازی در مقایسه با صرفه جویی در بیت ها، یک معاوضه وجود دارد. پارامتر صحیح برای برنامه شما به زمان بندی و اندازه مورد نیاز در زمان رمزگذاری بستگی دارد.

8. تبریک می گویم

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

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