Skip to content
扫码开始移动端阅读

首先看一下效果

🔍 滚轮可以放大,

🔄 左右拖动可以旋转视角

🛰️ Ctrl+拖动 移动视角

制作一个模型

首先要在appStore 下载一个软件,名字叫 3d Scanner App.

其次最好你的手机支持3d雷达。所有的iphone都是有面部的雷达,但是只有iphone 12 pro 以上的手机是有后面的雷达。同样,ipad Pro 也是有雷达的。

接着。你就可以扫描一个模型了。这个App比较傻瓜式。这里就不详细说明了。

导出模型

这个软件可以导出很多格式。

OBJ(Wavefront Object)

  • 描述: OBJ是一种简单的文本格式,用于描述三维模型的几何形状和材质信息。
  • 特点: 可以包含顶点、法线、纹理坐标等信息,但不支持动画和复杂的材质属性。
  • 应用: 主要用于静态模型的导入和导出。

GLTF(GL Transmission Format)

  • 描述: GLTF是一种基于JSON的文件格式,用于有效地传输和加载三维模型,支持材质、动画和其他属性。
  • 特点: 支持PBR材质、动画、节点层次结构等高级特性,适合Web和移动应用。
  • 应用: 被广泛应用于虚拟现实、增强现实和游戏开发领域。

GLB

  • 描述: GLB是GLTF的二进制版本,将所有模型数据打包在一个文件中,提高加载效率。
  • 特点: 包含模型的几何、材质、动画等数据,适合网络传输和实时加载。
  • 应用: 在需要快速加载和高性能的场景中使用。

STL(Stereolithography)

  • 描述: STL是一种用于表示三维表面几何的文件格式,通常用于3D打印。
  • 特点: 简单且易于解析,适合描述几何形状的表面。
  • 应用: 主要用于3D打印和CAD软件之间的数据交换。

Point Cloud

  • 描述: Point Cloud是一组点的集合,用于表示物体的表面或场景的形状。
  • 特点: 可以描述真实世界中的场景,但需要大量的点数据。
  • 应用: 用于激光扫描、三维重建和虚拟现实等领域。

DAE(Digital Asset Exchange)

  • 描述: DAE是一种基于XML的文件格式,用于交换数字资产,包括三维模型、动画和材质。
  • 特点: 支持多种属性和节点信息,适合复杂的三维场景描述。
  • 应用: 在建模软件和游戏引擎之间进行数据交换和共享。

FBX

  • 描述: FBX是Autodesk开发的一种通用的三维文件格式,支持多种三维软件之间的数据交换。
  • 特点: 包含几何、材质、动画、节点层次结构等多种数据,适用于复杂的三维场景。
  • 应用: 在不同的三维软件之间进行数据交换和合作。

TIP

当然,我们今天选择的是GLB。本来从通用性考虑,STL是最好的选择,但是STL是没有色彩信息的,

显示模型

代码比较简单,毕竟是第一次玩,写的不好轻喷。

vue
<template>
  <!-- 定义一个容器用于渲染3D场景 -->
  <div ref="container" class="mt-2 cursor-move" style="height: 500px"></div>
</template>

<script setup>
import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import { onMounted, ref, defineProps } from 'vue';

// 定义props,接收外部传入的模型路径
const props = defineProps({
  src: {
    type: String,
    required: true,
  },
});

// 创建一个ref用于引用容器元素
const container = ref(null);

// 在组件挂载后执行的操作
onMounted(() => {
  // 创建一个场景
  const scene = new THREE.Scene();

  // 获取容器的宽度和高度
  const width = container.value.clientWidth;
  const height = container.value.clientHeight;

  // 创建透视相机
  const camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 1000);

  // 创建WebGL渲染器
  const renderer = new THREE.WebGLRenderer({ alpha: true });
  renderer.setSize(width, height);

  // 将渲染器的dom元素添加到容器中
  container.value.appendChild(renderer.domElement);

  // 加载模型的函数
  const loadModel = (modelPath) => {
    const loader = new GLTFLoader();
    loader.load(modelPath, (gltf) => {
      const model = gltf.scene;

      // 计算模型包围盒中心
      const box = new THREE.Box3().setFromObject(model);
      const center = box.getCenter(new THREE.Vector3());

      // 将模型居中
      model.position.sub(center);
      scene.add(model);
    });
  };

  // 创建控制器
  const controls = new OrbitControls(camera, renderer.domElement);

  // 窗口大小改变时的处理函数
  const resize = () => {
    const width = container.value.clientWidth;
    const height = container.value.clientHeight;

    // 更新相机的长宽比例和投影矩阵
    camera.aspect = width / height;
    camera.updateProjectionMatrix();
    renderer.setSize(width, height);
  };

  // 监听窗口大小改变事件
  window.addEventListener('resize', resize);

  // 设置相机位置
  camera.position.set(0, 0, 10);
  camera.position.z = 5;

  // 动画函数
  const animate = () => {
    requestAnimationFrame(animate);
    controls.update();
    renderer.render(scene, camera);
  };

  // 加载模型并开始动画
  loadModel(props.src);
  animate();
});
</script>

优化

增加Loading

因为有些模型比较大,所以要加载很久,最好增加一个loading框.

页面

html
<div ref="container" class="mt-2 cursor-move" style="height: 500px">
  <div class="w-full h-full flex items-center justify-center" v-if="isLoading">
<span class="loading loading-lg text-primary"></span>
  </div>

</div>

脚本

js
const isLoading = ref(true); 
const loadModel = (modelPath) => {
  const loader = new GLTFLoader();
  loader.load(modelPath, (gltf) => {
    const model = gltf.scene;
    // 计算模型包围盒中心
    const box = new THREE.Box3().setFromObject(model);
    const center = box.getCenter(new THREE.Vector3());
    // 将模型居中
    model.position.sub(center);
    scene.add(model);
    isLoading.value = false; 
  });
};

总结

OrbitControls 真的很好用,完全不用手动实现镜头的控制了。具体感兴趣的可以看看文档OrbitControls
THREE.js 也是真的好玩,希望以后能有机会再深度玩玩。