تحسين البيانات ثلاثية الأبعاد باستخدام برنامج Draco Geometry محرك

1. نظرة عامة

تعد الرسومات الثلاثية الأبعاد جزءًا أساسيًا من العديد من التطبيقات، بما في ذلك الألعاب والتصميم ومؤثرات عرض البيانات. مع استمرار تحسين معالجات الرسومات وأدوات الإنشاء، ستصبح النماذج الثلاثية الأبعاد الأكبر حجمًا والأكثر تعقيدًا شائعة، وستساعد في استخدام تطبيقات جديدة في الواقع الافتراضي (VR) والواقع المعزّز (AR). وبسبب تعقيد النموذج المتزايد، اضطررت متطلبات التخزين ومعدل نقل البيانات إلى مواكبة الانتشار الكبير للبيانات الثلاثية الأبعاد.

باستخدام Draco، يمكن أن تكون التطبيقات التي تستخدم الرسومات ثلاثية الأبعاد أصغر بكثير بدون المساس بالدقة البصرية. ويعني هذا أنّه يمكن للمستخدمين تنزيل التطبيقات بشكل أسرع، كما يمكن تحميل الرسومات الثلاثية الأبعاد في المتصفّح بشكل أسرع، ويمكن الآن نقل مَشاهد الواقع الافتراضي والواقع المعزّز مع جزء من النطاق الترددي لعرضها بسرعة وتبدو رائعة.

ما هو Draco؟

Draco هي مكتبة لضغط وفك ضغط الشبكات الهندسية الثلاثية الأبعاد والسحب النقطية. والغرض منه تحسين تخزين ونقل الرسومات الثلاثية الأبعاد.

تم تصميم Draco وتصميمه بما يتوافق مع كفاءة الضغط وسرعته. تتيح التعليمة البرمجية نقاط الضغط ومعلومات الاتصال وإحداثيات الهيئة ومعلومات الألوان والقيم العادية وأي سمات عامة أخرى مرتبطة بالهندسة. تم إطلاق Draco كرمز مصدر بلغة C++ يمكن استخدامه لضغط الرسومات الثلاثية الأبعاد بالإضافة إلى برامج فك ترميز C++ وJavaScript للبيانات المشفّرة.

ما سوف تتعلمه

  • كيفية استخدام Draco لضغط نموذج ثلاثي الأبعاد
  • كيفية استخدام نماذج الضغط المختلفة وتأثيرها في جودة النموذج وحجمه
  • كيفية عرض تصميم ثلاثي الأبعاد على الويب

المتطلبات

2. بدء الإعداد

استنساخ مستودع جيت هب باستخدام سطر الأوامر هذا:

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

انتقِل إلى الدليل الجذري لـ Draco.

cd draco

3- إنشاء برنامج الترميز

للبدء بترميز Draco وفكه، لنبدأ أولًا بإنشاء التطبيقات.

إصدار برنامج ترميز

  • قم بتشغيل cmake من دليل تريد إنشاء ملفات تصميم فيه، وتمريره في المسار إلى مستودع Draco.
mkdir build

cd build

cmake ../

make

4. ترميز أول مادة عرض ثلاثية الأبعاد

سيقوم draco_encoder بقراءة ملفات OBJ أو PLY كمدخلات وإخراج ملفات بترميز Draco. لقد قمنا بتضمين شبكة الأرنب الخاصة بستانفورد للاختبار. يبدو سطر الأوامر الأساسي على النحو التالي:

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

يمكنك الآن إلقاء نظرة على حجم ملف الإخراج ومقارنته بملف .ply الأصلي. يجب أن يكون حجم الملف المضغوط أصغر بكثير من حجم الملف الأصلي.

ملاحظة: يمكن أن يختلف الحجم المضغوط حسب خيارات الضغط.

5- فك ترميز ملف 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. في نوع الوحدة الطرفية:
python -m SimpleHTTPServer

  1. افتح localhost:8000/DracoDecode.html في Chrome. من المفترض أن يؤدي ذلك إلى عرض مربع رسالة تنبيه يحتوي على عدد النقاط (عدد النقاط = 34834) التي تم فك ترميزها من النموذج.

6- عرض ملف 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.
  <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.
  <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. أضِف 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. أضِف الرمز لتحميل الملف.
    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 في Chrome. من المفترض أن يظهر الآن ملف 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. تهانينا

لقد انتهيت من التمرين المعملي لترميز شبكة Draco المتداخلة ونجحت في استكشاف العديد من الميزات الأساسية لـ Draco!

نأمل أن يكون واضحًا لك كيف يمكن أن يساعد تطبيق Draco في تصغير حجم مواد العرض الثلاثية الأبعاد وجعلها أكثر كفاءة في نقلها عبر الويب. يمكنك معرفة المزيد عن Draco والحصول على أحدث مكتبة من github.