Draco Geometri Sıkıştırma ile 3D verileri optimize etme

1. Genel Bakış

3D grafikler; oyun, tasarım ve veri görselleştirme gibi birçok uygulamanın temel bir parçasıdır. Grafik işlemciler ve içerik oluşturma araçları gelişmeye devam ettikçe daha büyük ve daha karmaşık 3D modeller yaygınlaşacak ve sürükleyici sanal gerçeklik (VR) ile artırılmış gerçeklik (AR) alanlarında yeni uygulamaların geliştirilmesine yardımcı olacak. Modelin karmaşıklığı arttığı için depolama ve bant genişliği gereksinimleri, 3D verilerdeki artışa ayak uydurmak zorunda kalıyor.

Draco sayesinde, 3D grafik kullanan uygulamalar görsel doğruluktan ödün vermeden önemli ölçüde küçültülebilir. Bu sayede kullanıcılar uygulamaları daha hızlı indirebilir, tarayıcıdaki 3D grafikler daha hızlı yüklenebilir, VR ve AR sahneleri daha az bant genişliğiyle aktarılabilir, hızlıca oluşturulabilir ve harika görünebilir.

Draco nedir?

Draco, 3D geometrik örgüleri ve nokta bulutlarını sıkıştırmak ve açmak için kullanılan bir kitaplıktır. Amacı, 3D grafiklerin depolanmasını ve iletilmesini iyileştirmektir.

Draco, sıkıştırma verimliliği ve hız için tasarlanıp geliştirilmiştir. Kod; noktaların, bağlantı bilgilerinin, doku koordinatlarının, renk bilgilerinin, normal vektörlerin ve geometriyle ilişkili diğer genel özelliklerin sıkıştırılmasını destekler. Draco, 3D grafiklerin yanı sıra kodlanmış veriler için C++ ve JavaScript kod çözücülerini sıkıştırmak üzere kullanılabilecek C++ kaynak kodu olarak yayınlanır.

Öğrenecekleriniz

  • 3D modeli sıkıştırmak için Draco'yu kullanma
  • Farklı sıkıştırma modelleri nasıl kullanılır ve bu modeller, model kalitesini ve boyutunu nasıl etkiler?
  • Web'de 3D model görüntüleme

İhtiyacınız olanlar

2. Hazırlanma

Şu komut satırını kullanarak GitHub deposunu klonlayın:

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

Draco kök dizinine gidin.

cd draco

3. Kodlayıcıyı oluşturma

Draco kodlama ve kod çözme işlemlerine başlamak için önce uygulamaları oluşturarak başlayalım.

Build Encoder

  • Derleme dosyalarını oluşturmak istediğiniz bir dizinden cmake'i çalıştırın ve Draco deponuzun yolunu iletin.
mkdir build

cd build

cmake ../

make

4. İlk 3D öğenizi kodlama

draco_encoder, OBJ veya PLY dosyalarını giriş olarak okur ve Draco kodlu dosyalar oluşturur. Test için Stanford'un Bunny mesh'ini ekledik. Temel komut satırı şu şekilde görünür:

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

Artık çıkış dosyasının boyutuna bakabilir ve bunu orijinal .ply dosyasıyla karşılaştırabilirsiniz. Sıkıştırılmış dosya, orijinal dosya boyutundan çok daha küçük olmalıdır.

Not: Sıkıştırılmış boyut, sıkıştırma seçeneklerine göre değişebilir.

5. Tarayıcıda Draco dosyasının kodunu çözme

Bu noktada, Draco dosyalarının kodunu çözmek için temel bir web sayfasıyla başlayacağız. Aşağıdaki kod bölümlerini kopyalayıp metin düzenleyiciye yapıştırarak başlayacağız.

  1. Temel HTML dosyasıyla başlayın.
<!DOCTYPE html>
<html>
<head>
  <title>Codelab - Draco Decoder</title>
  1. Aşağıdaki kod snippet'i Draco WASM kod çözücüsünü yükler.
  <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. Ardından, Draco kod çözücü modülü oluşturacak bu işlevi ekleyin. Kod çözücü modülünün oluşturulması eşzamansızdır. Bu nedenle, modülü kullanabilmek için geri çağırma işlemi yapılana kadar beklemeniz gerekir.
  <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 kodlu bir ağı kod çözmek için işlevi ekleyin.
    // 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 kod çözme işlevini eklediğimize göre, şimdi de Draco kodlu bir ağı indirmek için bir işlev ekleyin. "downloadEncodedMesh" işlevi, yüklenecek Draco dosyası için bir parametre kabul eder. Bu durumda, önceki aşamadan "bunny.drc" olacaktır.
    // 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. Draco kod çözücü modülünü oluşturmak için "createDracoDecoderModule" işlevini çağırın. Bu işlev, kodlanmış Draco dosyasını indirmek için "downloadEncodedMesh" işlevini çağırır. Bu işlev de kodlanmış Draco ağını çözmek için "decodeMesh" işlevini çağırır.
    // Create the Draco decoder module.
    createDracoDecoderModule();
  </script>
</head>
<body>
</body>
</html>
  1. Bu dosyayı "DracoDecode.html" olarak kaydedin.
  2. Python web sunucusunu başlatın. Terminalde şunu yazın:
python -m SimpleHTTPServer

  1. Chrome'da localhost:8000/DracoDecode.html adresini açın. Bu işlem, modelden çözülen puan sayısını (Num points = 34834) içeren bir uyarı mesajı kutusu göstermelidir.

6. three.js ile Draco dosyası oluşturma

WASM kullanarak bir Draco dosyasının nasıl kodunun çözüleceğini öğrendiğimize göre artık popüler bir web 3D görüntüleyici olan three.js'yi kullanabiliriz. Önceki örnekte olduğu gibi, aşağıdaki kod bölümlerini kopyalayıp metin düzenleyiciye yapıştırarak başlayacağız.

  1. Temel HTML dosyasıyla başlayın
<!DOCTYPE html>
<html>
<head>
  <title>Codelab - Draco three.js Render</title>
  1. three.js ve Draco three.js yükleyicisini yüklemek için kod ekleyin.
  <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. Draco kod çözücü yolunu ayarlayın.
  <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 oluşturma kodu ekleyin.
    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. Draco yükleme ve kod çözme kodu ekleyin.
    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. Dosyayı yüklemek için kod ekleyin.
    window.onload = function() {
      initThreejs();
      animate();
      loadDracoMesh('bunny.drc');
    }
  </script>
</head>
<body>
  <div id="container"></div>
</body>
</html>
  1. Bu dosyayı "DracoRender.html" olarak kaydedin.
  2. Gerekirse web sunucusunu yeniden başlatın.
python -m SimpleHTTPServer

  1. Chrome'da localhost:8000/DracoRender.html adresini açın. Draco dosyanız artık tarayıcıda oluşturulmuş olarak görünmelidir.

7. Farklı kodlama parametrelerini deneyin

Draco kodlayıcı, sıkıştırılmış dosyanın boyutunu ve kodun görsel kalitesini etkileyen birçok farklı parametreye izin verir. Komut satırında sonraki birkaç komutu çalıştırıp sonuçları görmeyi deneyin.

  1. Aşağıdaki komut, modelin konumlarını 12 bit kullanarak nicelendirir (varsayılan değer 11'dir).
./draco_encoder -i ../testdata/bun_zipper.ply -o out12.drc -qp 12

  1. Bir önceki bölümdeki bunny.drc dosyasına kıyasla out12.drc dosyasının boyutuna dikkat edin. Daha fazla nicemleme biti kullanmak, sıkıştırılmış dosyanın boyutunu artırabilir.

3.Aşağıdaki komut, modelin konumlarını 6 bit kullanarak nicelendirir.

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

  1. Bir önceki bölümdeki bunny.drc dosyasıyla karşılaştırıldığında out6.drc dosyasının boyutunu not edin. Daha az nicemleme biti kullanmak, sıkıştırılmış dosyanın boyutunu küçültebilir.
  1. Aşağıdaki parametreler, modelin sıkıştırma düzeylerini etkiler. cl işaretini kullanarak sıkıştırmanızı 1 (en düşük sıkıştırma oranı) ile 10 (en yüksek sıkıştırma oranı) arasında ayarlayabilirsiniz.
./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 kodlayıcının çıktısını not edin. En yüksek sıkıştırma düzeylerinde sıkıştırma için gereken süre ile bit tasarrufu arasında bir denge olduğunu görebilirsiniz. Uygulamanız için doğru parametre, kodlama sırasındaki zamanlama ve boyut şartlarına bağlıdır.

8. Tebrikler

Draco mesh sıkıştırma kod laboratuvarını tamamladınız ve Draco'nun birçok temel özelliğini başarıyla keşfettiniz.

Draco'nun 3D öğelerinizi küçültmenize ve web üzerinden daha verimli bir şekilde iletmenize nasıl yardımcı olabileceğini anladığınızı umuyoruz. Draco hakkında daha fazla bilgi edinebilir ve en son kitaplığı GitHub'dan indirebilirsiniz.