news 2026/4/10 17:31:06

JSAPIThree 加载单体三维模型学习笔记:SimpleModel 简易加载方式

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
JSAPIThree 加载单体三维模型学习笔记:SimpleModel 简易加载方式

在三维场景中加载模型是最常见的需求之一。虽然可以直接使用 Three.js 的 GLTFLoader,但在不同投影方式下需要手动处理坐标转换,比较麻烦。今天就来学习 mapvthree 提供的 SimpleModel 类,看看它是如何简化这个过程的。

了解 SimpleModel

SimpleModel 是 mapvthree 对 Three.js 模型加载的封装,主要解决了以下问题:

原生 Three.js 加载方式的问题

如果直接使用 Three.js 的 GLTFLoader 加载模型:

/* by 01022.hk - online tools website : 01022.hk/zh/pagecode.html */ import * as THREE from 'three'; import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'; const loader = new GLTFLoader(); loader.load('assets/models/tree/tree18.glb', gltf => { const model = gltf.scene; model.position.set(x, y, z); model.rotateX(Math.PI / 2); model.scale.setScalar(10); engine.add(model); });

问题:这种方式只适用于平面投影(EPSG:3857),在 ECEF 等其他投影上,需要额外进行投影旋转,非常麻烦。

SimpleModel 的优势

SimpleModel 是对 Three.js 的封装,具有以下优势:

  • 自动投影转换:自动根据当前投影进行坐标旋转,无需手动处理
  • 简化接口:统一的配置参数,更易使用
  • 多种加载方式:支持从 URL 加载,也支持传入已有的 Object3D 实例
  • 格式兼容:支持所有 Three.js 支持的模型格式(glb、gltf 等)
  • 坐标系转换:自动处理 Y-Up 到 Z-Up 的坐标系转换
  • 事件监听:提供加载完成事件,方便后续处理

我的理解:SimpleModel 本质上是对 Three.js 的 GLTFLoader 和 Object3D 的封装,让我们不需要关心底层的投影转换细节,专注于业务逻辑。

第一步:基本使用 - 从 URL 加载模型

最简单的方式是从 URL 加载模型文件。

基本示例

/* by 01022.hk - online tools website : 01022.hk/zh/pagecode.html */ import * as mapvthree from '@baidumap/mapv-three'; const container = document.getElementById('container'); const engine = new mapvthree.Engine(container, { map: { center: [120.628, 27.786, 0], range: 1000, pitch: 80, projection: 'EPSG:3857', provider: null, }, }); // 加载单体模型 const model = engine.add(new mapvthree.SimpleModel({ name: '树木模型', object: 'assets/models/tree/tree18.glb', point: [120.628, 27.786, 0], scale: [10, 10, 10], rotation: [Math.PI / 2, 0, 0], }));

我的发现:只需要提供模型路径和位置,引擎会自动处理加载和投影转换。

我的理解

  • object参数:模型文件的 URL 路径,支持 glb/gltf 格式(以及所有 Three.js 支持的格式)
  • point参数:模型在地图上的位置,格式为[经度, 纬度, 高度]
  • scale参数:模型缩放比例,格式为[x缩放, y缩放, z缩放]
  • rotation参数:模型旋转角度,格式为[roll, pitch, heading],单位为弧度

第二步:设置模型位置

模型位置使用地理坐标[经度, 纬度, 高度]来表示。

构造时设置位置

const model = engine.add(new mapvthree.SimpleModel({ object: 'assets/models/tree/tree18.glb', point: [120.628, 27.786, 0], // 经度、纬度、高度 }));

动态修改位置

// 通过 point 属性修改 model.point = [120.629, 27.787, 50]; // 或通过 setTransform 方法 model.setTransform({ point: [120.629, 27.787, 50], });

我的发现:可以随时动态修改模型位置,引擎会自动更新模型的实际坐标。

我的理解

  • 高度(z 值)是相对于地面的高度
  • 引擎会自动将地理坐标转换为场景坐标
  • 不同投影方式下的转换逻辑由引擎自动处理

第三步:设置模型旋转和缩放

模型的旋转和缩放也非常简单。

设置旋转

const model = engine.add(new mapvthree.SimpleModel({ object: 'assets/models/tree/tree18.glb', point: [120.628, 27.786, 0], rotation: [Math.PI / 2, 0, 0], // [roll, pitch, heading] })); // 动态修改旋转 model.setTransform({ rotation: [0, Math.PI / 4, Math.PI / 2], });

我的理解

  • rotation[0](roll):绕 x 轴旋转
  • rotation[1](pitch):绕 y 轴旋转
  • rotation[2](heading):绕 z 轴旋转
  • 单位是弧度,不是角度(角度需要转换:角度 * Math.PI / 180

设置缩放

const model = engine.add(new mapvthree.SimpleModel({ object: 'assets/models/tree/tree18.glb', point: [120.628, 27.786, 0], scale: [10, 10, 10], // [x缩放, y缩放, z缩放] })); // 动态修改缩放 model.setTransform({ scale: [20, 20, 20], });

我的发现:可以对 x、y、z 三个方向分别设置缩放比例,实现非均匀缩放。

使用 Three.js 的 Vector3

import * as THREE from 'three'; // 也可以使用 Three.js 的 Vector3 model.setTransform({ point: new THREE.Vector3(120.628, 27.786, 50), scale: new THREE.Vector3(15, 15, 15), rotation: new THREE.Vector3(Math.PI / 2, 0, 0), });

我的理解:SimpleModel 兼容数组和 Vector3 两种格式,可以根据习惯选择。

第四步:监听加载完成事件

模型加载是异步的,可以通过事件监听器获取加载完成的通知。

监听 loaded 事件

const model = engine.add(new mapvthree.SimpleModel({ object: 'assets/models/tree/tree18.glb', point: [120.628, 27.786, 0], })); // 监听模型加载完成事件 model.addEventListener('loaded', e => { console.log('模型加载完成:', e.value); // 在加载完成后可以进行后续操作 // 例如:添加动画、修改材质等 });

我的发现:在loaded事件中,可以通过e.value获取加载的模型对象,进行进一步的自定义操作。

我的理解

  • 如果需要在加载完成后进行操作(如修改材质、添加动画),一定要使用loaded事件
  • 不要在构造函数返回后立即操作模型,因为此时模型可能还没加载完成

第五步:动态更新模型变换

使用setTransform方法可以灵活地更新模型的位置、旋转和缩放。

只更新部分参数

// 只更新位置 model.setTransform({ point: [120.629, 27.787, 50], }); // 只更新旋转 model.setTransform({ rotation: [0, Math.PI / 4, 0], }); // 只更新缩放 model.setTransform({ scale: [15, 15, 15], });

我的发现setTransform方法的参数都是可选的,可以只更新需要修改的参数。

同时更新多个参数

// 同时更新位置、旋转和缩放 model.setTransform({ point: [120.629, 27.787, 50], rotation: [Math.PI / 2, Math.PI / 4, 0], scale: [20, 20, 20], });

我的理解setTransform是更新模型变换的推荐方式,比直接修改positionrotationscale属性更安全。

第六步:理解 autoYUpToZUp 参数

很多三维模型(如从建模软件导出的模型)使用 Y 轴向上的坐标系,而地理场景通常使用 Z 轴向上。

autoYUpToZUp 的作用

const model = engine.add(new mapvthree.SimpleModel({ object: 'assets/models/tree/tree18.glb', point: [120.628, 27.786, 0], autoYUpToZUp: true, // 默认为 true }));

我的理解

  • autoYUpToZUp = true(默认):自动将 Y-Up 坐标系转换为 Z-Up,模型会自动旋转 90 度
  • autoYUpToZUp = false:不进行坐标系转换,保持模型原始方向
  • 这个参数仅对通过 URL 加载的模型有效,对直接传入的 Object3D 实例无效

什么时候需要关闭

// 如果模型本身就是 Z-Up,或者已经做了正确的旋转 const model = engine.add(new mapvthree.SimpleModel({ object: 'assets/models/building.glb', point: [120.628, 27.786, 0], autoYUpToZUp: false, // 不需要自动转换 }));

我的发现:如果发现加载的模型方向不对(如倒着的、躺着的),可能是autoYUpToZUp的设置问题。

第七步:直接传入 Object3D 实例

除了从 URL 加载,还可以直接传入已经加载好的 Three.js Object3D 实例。

传入已有的 Object3D

import * as THREE from 'three'; import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'; // 先用 Three.js 原生方式加载 const loader = new GLTFLoader(); loader.load('assets/models/tree/tree18.glb', gltf => { const mesh = gltf.scene; // 将加载好的模型传给 SimpleModel const model = engine.add(new mapvthree.SimpleModel({ name: '树木模型', object: mesh, // 传入 Object3D 实例 point: [120.628, 27.786, 0], scale: [10, 10, 10], })); });

我的理解

  • 这种方式适合需要对模型进行预处理的场景
  • 例如:修改材质、合并多个模型、自定义加载逻辑等
  • 传入 Object3D 时,autoYUpToZUp参数不生效

传入自定义创建的 Mesh

import * as THREE from 'three'; // 创建一个自定义的立方体 const geometry = new THREE.BoxGeometry(10, 10, 10); const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 }); const cube = new THREE.Mesh(geometry, material); // 将自定义 Mesh 传给 SimpleModel const model = engine.add(new mapvthree.SimpleModel({ name: '立方体', object: cube, point: [120.628, 27.786, 0], }));

我的发现:可以传入任何 Three.js 的 Object3D 对象,不仅限于从文件加载的模型。

我的理解:这展示了 SimpleModel 的灵活性,它本质上是一个位置和变换管理器,可以管理任何 Three.js 对象。

第八步:完整示例

我想写一个完整的示例,把学到的都用上:

import * as mapvthree from '@baidumap/mapv-three'; import * as THREE from 'three'; const container = document.getElementById('container'); const engine = new mapvthree.Engine(container, { map: { center: [120.628, 27.786, 0], range: 1000, pitch: 80, projection: 'EPSG:3857', provider: null, }, rendering: { enableAnimationLoop: true, }, }); // 加载单体模型 const model = engine.add(new mapvthree.SimpleModel({ name: '树木模型', object: 'assets/models/tree/tree18.glb', point: [120.628, 27.786, 0], scale: [10, 10, 10], rotation: [Math.PI / 2, 0, 0], autoYUpToZUp: true, // 自动坐标系转换 })); // 监听加载完成事件 model.addEventListener('loaded', e => { console.log('模型加载完成:', e.value); // 可以在这里进行后续操作 // 例如:修改材质、添加动画等 }); // 动态更新模型位置(例如:5秒后移动模型) setTimeout(() => { model.setTransform({ point: [120.629, 27.787, 50], rotation: [Math.PI / 2, Math.PI / 4, 0], scale: [15, 15, 15], }); }, 5000);

我的感受:掌握了 SimpleModel,加载单体模型变得非常简单,不需要关心投影转换的细节!

第九步:踩过的坑

作为一个初学者,我踩了不少坑,记录下来避免再犯:

坑 1:模型不显示

原因:模型路径错误,或者模型文件格式不支持。

解决

  1. 检查模型文件路径是否正确
  2. 确认模型文件格式是否为 glb/gltf(或其他 Three.js 支持的格式)
  3. 打开浏览器控制台查看是否有加载错误
  4. 检查模型位置是否在视野范围内

坑 2:模型方向不对

原因:坐标系转换问题,或者旋转设置不正确。

解决

  1. 尝试修改autoYUpToZUp参数(true/false)
  2. 调整rotation参数,尝试不同的旋转角度
  3. 在建模软件中检查模型的坐标系和方向

坑 3:模型太大或太小

原因:模型原始尺寸与场景比例不匹配。

解决

  1. 调整scale参数,尝试不同的缩放比例
  2. 如果模型太小看不见,尝试放大 10 倍、100 倍
  3. 如果模型太大,尝试缩小到 0.1、0.01

坑 4:动态修改不生效

原因:在模型加载完成前就进行了修改操作。

解决

  1. 使用loaded事件,确保在模型加载完成后再操作
  2. 使用setTransform方法而不是直接修改属性
  3. 检查是否启用了enableAnimationLoop(某些操作需要渲染循环)

坑 5:不同投影下模型位置不对

原因:没有正确理解 SimpleModel 的自动投影转换。

解决

  1. 确认传入的是地理坐标[经度, 纬度, 高度],而不是场景坐标
  2. 不要手动计算投影转换,SimpleModel 会自动处理
  3. 如果需要场景坐标,使用engine.map.projectArrayCoordinate()转换

坑 6:传入 Object3D 时 autoYUpToZUp 不生效

原因autoYUpToZUp只对通过 URL 加载的模型有效。

解决

  1. 如果传入 Object3D 实例,需要手动处理坐标系转换
  2. 或者使用rotation参数手动旋转
  3. 或者在加载时就处理好坐标系

我的学习总结

经过这一天的学习,我掌握了:

  1. SimpleModel 的本质:对 Three.js 加载方式的封装,自动处理投影转换
  2. 支持的格式:所有 Three.js 支持的模型格式(glb、gltf 等)
  3. 两种加载方式:从 URL 加载,或传入 Object3D 实例
  4. 位置设置:使用地理坐标[经度, 纬度, 高度]
  5. 旋转和缩放:使用数组或 Vector3 格式
  6. 动态更新:使用setTransform方法
  7. 坐标系转换:理解autoYUpToZUp的作用
  8. 事件监听:使用loaded事件处理加载完成后的逻辑

我的感受:SimpleModel 让加载单体模型变得非常简单,不需要关心底层的投影转换细节。它本质上是对 Three.js 的封装,所以如果熟悉 Three.js,上手会非常快!

下一步计划

  1. 学习如何加载和管理多个模型
  2. 学习 LODModel 实现性能优化
  3. 学习如何给模型添加动画

学习笔记就到这里啦!作为一个初学者,我觉得 SimpleModel 是一个非常实用的工具类,它简化了三维模型的加载和管理。关键是要理解它是对 Three.js 的封装,支持所有 Three.js 支持的模型格式,并能自动处理不同投影方式下的坐标转换。希望我的笔记能帮到其他初学者!大家一起加油!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/9 21:23:44

648678678

678687678

作者头像 李华
网站建设 2026/4/9 17:16:51

MCP概念和实践

MCP(模型上下文协议)是一种用于将 AI 应用程序连接到外部系统的开源标准。 使用 MCP,Claude 或 ChatGPT 等 AI 应用程序可以连接到数据源(例如本地文件、数据库)、工具(例如搜索引擎、计算器)和…

作者头像 李华
网站建设 2026/4/10 2:53:55

测试反馈的心理艺术:构建高效沟通的测试文化

在软件开发的生命周期中,测试反馈是连接开发与测试团队的关键纽带。2025年的今天,随着敏捷开发模式的普及和远程协作的常态化,测试人员面临的已不仅是技术挑战,更有沟通艺术的心理考验。一条有效的测试反馈不仅能准确描述问题&…

作者头像 李华
网站建设 2026/4/7 18:19:48

乐迪信息:人员违规识别新方案!AI摄像机+智慧煤矿,降本增效保安全

在众多技术创新中,基于AI视觉识别技术的智能监控系统,正逐步成为提升煤矿安全管理水平、实现降本增效的关键工具。人员违规识别作为安全生产管理中的重要一环,也因AI摄像机的引入而迎来新的解决方案。 一:煤矿安全 煤矿生产环境复…

作者头像 李华
网站建设 2026/4/5 5:59:58

Higress健康检查实战指南:构建微服务高可用性的核心技术

Higress健康检查实战指南:构建微服务高可用性的核心技术 【免费下载链接】higress Next-generation Cloud Native Gateway | 下一代云原生网关 项目地址: https://gitcode.com/GitHub_Trending/hi/higress 在云原生微服务架构中,服务实例的健康状…

作者头像 李华
网站建设 2026/4/1 5:03:57

结构化机器学习项目 第一周:机器学习策略(二)数据集设置

本周为第三课的第一周内容,本周的内容关于在实际项目进行中的一些基本策略,并不涉及技术性的知识。经过整个第一课和第二课后, 我们已经了解了足够支持我们构建一个完整的基础神经网络项目的知识和技术,本周便是在这些基础上的一个…

作者头像 李华