Optymalizacja danych 3D przy użyciu narzędzia Draco Geometry Compression

Optymalizacja danych 3D przy użyciu narzędzia Draco Geometry Compression

Informacje o tym ćwiczeniu (w Codelabs)

subjectOstatnia aktualizacja: mar 11, 2024
account_circleDokument stworzony przez pracownika Google

1. Omówienie

Grafika 3D jest podstawowym elementem wielu aplikacji, w tym gier, projektowania i wizualizacji danych. W miarę ulepszania procesorów graficznych i narzędzi do tworzenia większe i bardziej złożone modele 3D staną się powszechnymi i pomogą napędzać nowe aplikacje w rzeczywistości wirtualnej (VR) i rozszerzonej (AR). Większa złożoność modelu powoduje, że wymagania związane z miejscem na dane i przepustowością są zmuszone nadążać za ogromną ilością danych 3D.

Dzięki Draco aplikacje korzystające z grafiki 3D mogą być znacznie mniejsze bez obniżania jakości obrazu. Z punktu widzenia użytkowników oznacza to, że aplikacje można pobierać szybciej, grafika 3D w przeglądarce wczytuje się szybciej, a sceny VR i AR mogą być przesyłane za pomocą ułamka przepustowości, szybko renderowane i wyglądać fantastycznie.

Co to jest Draco?

Draco to biblioteka do kompresowania i dekompresji geometrycznych pazur i chmur punktów 3D. Ma na celu poprawę przechowywania i przesyłania grafiki 3D.

Zaprojektowano i opracowano Draco z myślą o wydajności i szybkości kompresji. Kod obsługuje punkty kompresji, informacje o połączeniach, współrzędne tekstury, informacje o kolorze, normalne i wszystkie inne atrybuty ogólne związane z geometrią. Draco jest wydawane jako kod źródłowy C++, którego można używać do kompresowania grafiki 3D, a także dekoderów C++ i JavaScript do kodowania danych.

Czego się nauczysz

  • Jak za pomocą Draco skompresować model 3D
  • Jak używać różnych modeli kompresji i ich wpływ na jakość i rozmiar modelu
  • Jak wyświetlić model 3D w internecie

Czego potrzebujesz

2. Przygotowanie

Skopiuj repozytorium GitHub za pomocą tego wiersza poleceń:

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

Przejdź do katalogu głównego Draco.

cd draco

3. Stworzenie kodera

Zacznijmy od kodowania i dekodowania Draco, więc najpierw stwórzmy aplikacje.

Utwórz koder

  • Uruchom cmake z katalogu, w którym chcesz wygenerować pliki kompilacji, i przekaż ścieżkę do swojego repozytorium Draco.
mkdir build

cd build

cmake
../

make

4. Kodowanie pierwszego zasobu 3D

Narzędzie draco_encoder odczytuje pliki OBJ i PLY jako dane wejściowe i wysyła pliki zakodowane w formacie Draco. Do testowania dodaliśmy siatkę królików Stanforda. Podstawowy wiersz poleceń wygląda tak:

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

Teraz możesz sprawdzić rozmiar pliku wyjściowego i porównać go z oryginalnym plikiem .ply. Skompresowany plik powinien być znacznie mniejszy niż oryginalny.

Uwaga: rozmiar skompresowanego pliku może się różnić w zależności od opcji kompresji.

5. Dekodowanie pliku Draco w przeglądarce

W tym momencie zaczniemy od podstawowej strony internetowej do dekodowania plików Draco. Zaczniemy od skopiowania i wklejenia poniższych sekcji kodu do edytora tekstu.

  1. Zacznij od podstawowego pliku HTML.
<!DOCTYPE html>
<html>
<head>
 
<title>Codelab - Draco Decoder</title>
  1. Ten fragment kodu spowoduje wczytanie dekodera WASM Draco.
  <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. Następnie dodaj tę funkcję, aby utworzyć moduł dekodera Draco. Tworzenie modułu dekodera jest asynchroniczne, więc aby z niego skorzystać, musisz poczekać na wywołanie zwrotne.
  <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. Dodaj funkcję, aby zdekodować siatkę zakodowaną w 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. Skoro mamy już funkcję dekodowania Draco, dodaj funkcję pobierania siatki zakodowanej w Draco. Funkcja „downloadEncodedMesh” akceptuje parametr pliku Draco, który ma zostać załadowany. W tym przypadku będzie to „bunny.drc”. od poprzedniego etapu.
    // 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. Wywołaj „createDracoDecoderModule” do utworzenia modułu dekodera Draco, który wywoła funkcję „downloadEncodedMesh” która pobiera zakodowany plik Draco, który wywołuje funkcję „decodeMesh” do zdekodowania zakodowanej siatki Draco.
    // Create the Draco decoder module.
    createDracoDecoderModule
();
 
</script>
</
head>
<body>
</body>
</
html>
  1. Zapisz ten plik jako „DracoDecode.html”
  2. Uruchom serwer WWW w Pythonie. Typ terminala:
python -m SimpleHTTPServer

  1. Otwórz plik localhost:8000/DracoDecode.html w Chrome. Powinno wyświetlić się pole z komunikatem alertu z liczbą punktów (Liczba punktów = 34834), które zostały odkodowane z modelu.

6. Renderowanie pliku Draco za pomocą pliku trzy.js

Wiesz już, jak zdekodować plik Draco za pomocą WASM, więc teraz użyjemy popularnej przeglądarki 3D – trzy.js. Tak jak w poprzednim przykładzie, zaczniemy od skopiowania poniższych sekcji kodu i wklejenia ich do edytora tekstu.

  1. Zacznij od podstawowego pliku HTML
<!DOCTYPE html>
<html>
<head>
 
<title>Codelab - Draco three.js Render</title>
  1. Dodaj kod, aby wczytać kod wczytujący trzy.js i 3.js Draco.
  <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. Skonfiguruj ścieżkę dekodera Draco.
  <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. Dodaj kod renderowania trzy.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. Dodaj wczytywanie i dekodowanie kodu Draco.
    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. Dodaj kod, aby wczytać plik.
    window.onload = function() {
      initThreejs
();
      animate
();
      loadDracoMesh
('bunny.drc');
   
}
 
</script>
</
head>
<body>
 
<div id="container"></div>
</body>
</
html>
  1. Zapisz ten plik jako „DracoRender.html”
  2. W razie potrzeby ponownie uruchom serwer WWW.
python -m SimpleHTTPServer

  1. Otwórz plik localhost:8000/DracoRender.html w Chrome. Plik Draco powinien być teraz wyrenderowany w przeglądarce.

7. Wypróbuj inne parametry kodowania

Koder Draco zezwala na wiele różnych parametrów, które wpływają na rozmiar skompresowanego pliku i jakość wizualnej kodu. Spróbuj uruchomić kilka kolejnych poleceń w wierszu poleceń i zobaczyć wyniki.

  1. To polecenie określa kwantyfikację pozycji modelu z użyciem 12 bitów (domyślnie jest to 11 bitów).
./draco_encoder -i ../testdata/bun_zipper.ply -o out12.drc -qp 12

  1. Zwróć uwagę na rozmiar pliku out12.drc w porównaniu z plikiem bunny.drc w poprzedniej sekcji. Użycie większej liczby bitów kwantyzacji może zwiększyć rozmiar skompresowanego pliku.

3.Poniższe polecenie tworzy kwantyfikację pozycji modelu za pomocą 6 bitów.

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

  1. Zwróć uwagę na rozmiar pliku out6.drc w porównaniu z plikiem bunny.drc w poprzedniej sekcji. Użycie mniejszej liczby bitów kwantyzacji może zmniejszyć rozmiar skompresowanego pliku.
  1. Poniższe parametry wpływają na poziomy kompresji modelu. Za pomocą flagi cl możesz dostosować stopień kompresji od 1 (najniższy współczynnik kompresji) do 10 (najwyższy).
./draco_encoder -i ../testdata/bun_zipper.ply -o outLow.drc -cl 1

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

Zwróć uwagę na dane wyjściowe kodera Draco. Widać, że czas potrzebny na kompresję przy najwyższym poziomie kompresji jest niższy niż oszczędność czasu w bitach. Prawidłowy parametr aplikacji będzie zależał od wymagań dotyczących czasu i rozmiaru podczas kodowania.

8. Gratulacje

Udało Ci się ukończyć moduł dotyczący kodu kompresji siatki Draco i poznać wiele kluczowych funkcji Draco.

Mamy nadzieję, że wiesz już, w jaki sposób Draco może pomóc w zmniejszaniu zasobów 3D w celu ich przesyłania przez sieć. Więcej informacji o Draco i najnowsze wersje biblioteki znajdziesz na github.