xgqfrms™, xgqfrms® : xgqfrms's offical website of cnblogs! xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!

3D 模型压缩工具 Draco All In One

3D 模型压缩工具 Draco All In One

Draco 是一个用于压缩和解压缩 3D 几何网格和点云的库。它旨在改进 3D 图形的存储传输

Draco 的设计宗旨是压缩效率和速度,该代码支持压缩点、连接信息、纹理坐标、颜色信息、法线以及与几何图形关联的任何其他通用属性。Draco 作为 C++ 源代码发布,可用于压缩 3D 图形以及用于编码数据的 C++ 和 JavaScript 解码器。

image

https://google.github.io/draco/

https://github.com/google/draco

使用场景

  1. 压缩大型 3D 模型,优化传输和存储效率

...

demos

Draco compress big 3D models

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

$ cd draco

# 建议创建 build 目录的位置是 Draco 根目录下的一个目录。
$ mkdir build

$ cd build

# 注意:您无法在 Draco 根目录之外运行 cmake。
$ cmake ../

$ make
# draco_encoder 会读取 OBJ 或 PLY 文件作为输入,并输出 Draco 编码的文件。
$ ./draco_encoder -i ../testdata/bun_zipper.ply -o bunny.drc

# 原始文件为 2.9 MB,压缩文件约为 46 kB。大小缩减了 60 倍以上。

⚠️ 需要手动移动输出文件的 ./draco/build/bunny.drc 文件路径

# ✅ fix: 输出文件 bunny.drc 的路径
$ ./draco_encoder -i ../testdata/bun_zipper.ply -o ../../fix-bunny.drc

使用 WASM 解码 Draco 文件
在浏览器中解码 Draco 文件, DracoDecode.html

<!DOCTYPE html>
<html>
<head>
  <title>Codelab - Draco Decoder</title>
  <!-- 加载 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>
  <script>
  // 创建一个 Draco 解码器模块
  '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);
  }
  // 解码 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);
  }
  // 下载 Draco 编码网格
  // 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);
  }
  // 先调用“createDracoDecoderModule”函数来创建 Draco 解码器模块,该模块将调用“downloadEncodedMesh”函数下载已编码的 Draco 文件,该文件将调用“decodeMesh”函数解码已编码的 Draco 网格。
  createDracoDecoderModule();
  </script>
</head>
<body>
</body>
</html>

# 启动 Python Web 服务器。在终端类型中:
$ python -m SimpleHTTPServer

http://localhost:8000/DracoDecode.html

使用 three.js 渲染 Draco 文件
Web 3D 查看器 - three.js

<!DOCTYPE html>
<html>
<head>
  <title>Codelab - Draco three.js Render</title>
  <!-- 加载 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>
   <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.
    // 设置 Draco 解码器路径
    dracoLoader.setDecoderPath('https://www.gstatic.com/draco/versioned/decoders/1.4.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 );
    }

    // 添加了 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 );
      } );
    }
    // 启动 three.js 渲染循环并加载 Draco 网格
    window.onload = function() {
      initThreejs();
      animate();
      loadDracoMesh('bunny.drc');
    }
  </script>
</head>
<body>
  <div id="container"></div>
</body>
</html>

http://localhost:8000/ThreeJSWeb3DViewer.html

尝试不同的编码参数

Draco 编码器允许使用许多不同的参数,这些参数会影响压缩文件的大小和代码的视觉质量

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

# 使用 12 位(默认为 11)位量化模型的位置。
# 使用更多量化位会`增加`压缩文件的大小。
$ ./draco_encoder -i ../testdata/bun_zipper.ply -o out12.drc -qp 12

# 使用 6 位量化模型的位置。
# 使用较少的量化位可以`减小`压缩文件的大小。
$ ./draco_encoder -i ../testdata/bun_zipper.ply -o out6.drc -qp 6

# ⚠️ 使用太少的位数进行量化时,不仅会产生令人印象深刻的压缩比,而且可能会严重降低模型的质量。如果您渲染 out6.drc,会发现视觉效果与原始图片大不相同。

模型的压缩级别。使用 cl 标记,可以将压缩率调整为从 1(最低)到 10(最高)。

# 模型的压缩级别, 最低 1
$ ./draco_encoder -i ../testdata/bun_zipper.ply -o outLow.drc -cl 1


# 模型的压缩级别, 最高 10
$ ./draco_encoder -i ../testdata/bun_zipper.ply -o outHigh.drc -cl 10

与节省的位数相比,在最高压缩级别进行压缩所需的时间是有利的。应用的正确参数取决于编码时的时间大小要求。

(🐞 反爬虫测试!打击盗版⚠️)如果你看到这个信息, 说明这是一篇剽窃的文章,请访问 https://www.cnblogs.com/xgqfrms/ 查看原创文章!

CMake

CMake: A Powerful Software Build System

CMake is the de-facto standard for building C++ code, with over 2 million downloads a month. It’s a powerful, comprehensive solution for managing the software build process.

image

https://cmake.org/

$ cmake --version

https://cmake.org/cmake/help/latest/guide/tutorial/index.html

CMake 配置文件 CMakeLists.txt

https://github.com/google/draco/blob/main/CMakeLists.txt

.cmake files

image

https://github.com/google/draco/blob/main/cmake/draco_install.cmake


# Copyright 2021 The Draco Authors
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.

if(DRACO_CMAKE_DRACO_INSTALL_CMAKE_)
  return()
endif() # DRACO_CMAKE_DRACO_INSTALL_CMAKE_
set(DRACO_CMAKE_DRACO_INSTALL_CMAKE_ 1)

include(CMakePackageConfigHelpers)
include(GNUInstallDirs)

# Sets up the draco install targets. Must be called after the static library
# target is created.
macro(draco_setup_install_target)
  if(DRACO_INSTALL)
    set(bin_path "${CMAKE_INSTALL_BINDIR}")
    set(data_path "${CMAKE_INSTALL_DATAROOTDIR}")
    set(includes_path "${CMAKE_INSTALL_INCLUDEDIR}")
    set(libs_path "${CMAKE_INSTALL_LIBDIR}")

    foreach(file ${draco_sources})
      if(file MATCHES "h$")
        list(APPEND draco_api_includes ${file})
      endif()
    endforeach()

    list(REMOVE_DUPLICATES draco_api_includes)

    # Strip $draco_src_root from the file paths: we need to install relative to
    # $include_directory.
    list(TRANSFORM draco_api_includes REPLACE "${draco_src_root}/" "")

    foreach(draco_api_include ${draco_api_includes})
      get_filename_component(file_directory ${draco_api_include} DIRECTORY)
      set(target_directory "${includes_path}/draco/${file_directory}")
      install(FILES ${draco_src_root}/${draco_api_include}
              DESTINATION "${target_directory}")
    endforeach()

    install(FILES "${draco_build}/draco/draco_features.h"
            DESTINATION "${includes_path}/draco/")

    if(DRACO_BUILD_EXECUTABLES)
      install(TARGETS draco_decoder DESTINATION "${bin_path}")
      install(TARGETS draco_encoder DESTINATION "${bin_path}")

      if(DRACO_TRANSCODER_SUPPORTED)
        install(TARGETS draco_transcoder DESTINATION "${bin_path}")
      endif()
    endif()

    if(MSVC)
      install(
        TARGETS draco
        EXPORT dracoExport
        RUNTIME DESTINATION "${bin_path}"
        ARCHIVE DESTINATION "${libs_path}"
        LIBRARY DESTINATION "${libs_path}")
    else()
      install(
        TARGETS draco_static
        EXPORT dracoExport
        DESTINATION "${libs_path}")

      if(BUILD_SHARED_LIBS)
        install(
          TARGETS draco_shared
          EXPORT dracoExport
          RUNTIME DESTINATION "${bin_path}"
          ARCHIVE DESTINATION "${libs_path}"
          LIBRARY DESTINATION "${libs_path}")
      endif()
    endif()

    if(DRACO_UNITY_PLUGIN)
      install(TARGETS dracodec_unity DESTINATION "${libs_path}")
    endif()

    if(DRACO_MAYA_PLUGIN)
      install(TARGETS draco_maya_wrapper DESTINATION "${libs_path}")
    endif()

    # pkg-config: draco.pc
    configure_file("${draco_root}/cmake/draco.pc.template"
                  "${draco_build}/draco.pc" @ONLY NEWLINE_STYLE UNIX)
    install(FILES "${draco_build}/draco.pc" DESTINATION "${libs_path}/pkgconfig")

    # CMake config: draco-config.cmake
    configure_package_config_file(
      "${draco_root}/cmake/draco-config.cmake.template"
      "${draco_build}/draco-config.cmake"
      INSTALL_DESTINATION "${data_path}/cmake/draco")

    write_basic_package_version_file(
      "${draco_build}/draco-config-version.cmake"
      VERSION ${DRACO_VERSION}
      COMPATIBILITY AnyNewerVersion)

    export(
      EXPORT dracoExport
      NAMESPACE draco::
      FILE "${draco_build}/draco-targets.cmake")

    install(
      EXPORT dracoExport
      NAMESPACE draco::
      FILE draco-targets.cmake
      DESTINATION "${data_path}/cmake/draco")

    install(FILES "${draco_build}/draco-config.cmake"
                  "${draco_build}/draco-config-version.cmake"
            DESTINATION "${data_path}/cmake/draco")
  endif(DRACO_INSTALL)
endmacro()

https://github.com/google/draco/tree/main/cmake

refs

https://codelabs.developers.google.com/codelabs/draco-3d?hl=zh-cn#0



©xgqfrms 2012-2021

www.cnblogs.com/xgqfrms 发布文章使用:只允许注册用户才可以访问!

原创文章,版权所有©️xgqfrms, 禁止转载 🈲️,侵权必究⚠️!


posted @ 2026-02-26 22:03  xgqfrms  阅读(77)  评论(4)    收藏  举报