npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@lijuhong1981/modelto3dtiles

v2.1.1

Published

将obj/fbx/gltf/glb精细模型转换为3D Tiles的命令行工具,面向Cesium加载,支持空间切分、纹理图集、Draco压缩与构件级拾取

Readme

modelTo3DTiles

npm version license

将普通精细模型转换为 3D Tiles 的命令行工具,可在 Cesium 或 threejs 中加载,支持 .obj、.fbx、.gltf、.glb 格式。

特性

  • 多格式输入:obj(含 mtl/贴图)、fbx(自动读取文件声明的 UpAxis)、gltf/glb(含 Draco 压缩输入)
  • 坐标自动归一化:向上轴自动转换为 glTF 规范的 Y-up,锚点自动修正至模型包围盒中心,支持经纬度定位与自动贴地
  • 空间切分:瓦片按空间递归切分聚集,视锥剔除按瓦片生效
  • 纹理图集:可合并材质的贴图合成 2 的幂图集页并重映射 UV,显著减少 draw call
  • 贴图外置去重:瓦片间共享贴图文件(按内容哈希),避免重复下载与显存占用
  • Draco 几何压缩:瓦片几何体积压缩约 90%,加载端由 Cesium 自动解码
  • 实例化保留:glTF 输入中共享几何的实例构件(如族实例)以 EXT_mesh_gpu_instancing + EXT_instance_features 输出,只存一份几何 + 每实例矩阵表,体积与转换内存大幅下降,逐构件拾取/显隐不受影响(需 CesiumJS ≥ 1.107)
  • BIM 语义属性:配合 revitToGltf 插件导出的 .metadata sidecar(--md),构件的名称/元素ID/类别/族/类型/楼层/参数集写入 EXT_structural_metadata 多列属性表,支持按构件查询与按楼层/类别过滤
  • 构件级拾取:输出附带 EXT_mesh_features / EXT_structural_metadata 扩展,Cesium 中可按构件(如单个座椅)拾取、查询、显隐、着色;同一构件的多个图元归并为单一 featureId
  • b3dm / glb 双格式:默认 b3dm(3D Tiles 经典格式),可切换 glb 瓦片(3D Tiles 1.1)

安装

npm 安装(需 Node.js ≥ 18):

# 全局安装后使用 modelTo3DTiles 命令
npm install -g @lijuhong1981/modelto3dtiles

# 或免安装直接运行
npx @lijuhong1981/modelto3dtiles -i ./model.obj

exe 免安装(Windows):从 Releases 下载 modelTo3DTiles.exe。

从源码运行:

git clone https://github.com/lijuhong1981/modelTo3DTiles.git
cd modelTo3DTiles
npm install
npm run build:esbuild

使用

npm 全局安装或 exe 方式下,直接使用 modelTo3DTiles 命令:

# 基本转换(obj/fbx/gltf/glb 均可),默认已启用纹理图集与Draco压缩
modelTo3DTiles -i ./model.obj

# BIM模型:连同revitToGltf导出的.metadata一起转换,构件属性随瓦片写入属性表
modelTo3DTiles -i ./station.glb --md ./station.metadata

# 指定输出目录与经纬度(默认 116.4074,39.9042)
modelTo3DTiles -i ./model.fbx -o ./output --lla 106.55,29.56,0

# 追求最高画质、加载端零解码开销:关闭Draco压缩与纹理图集
modelTo3DTiles -i ./model.gltf -o ./output --no-draco --no-ta

从源码运行时,将命令换为 node main.js,参数完全相同:

node main.js -i ./model.obj

输入模型向上坐标轴自动识别与转换:obj 默认按 Z-up 处理(可用 --inputUpAxis 指定),fbx 读取文件 GlobalSettings 声明的 UpAxis,gltf/glb 按规范固定 Y-up。

命令参数

|参数名称|别名|描述|类型|默认值|是否必须| |:---:|:---:|:---:|:---:|:---:|:---:| |--help|-h|显示帮助|Boolean||否| |--version|-v|显示版本号|Boolean||否| |--input|-i|输入模型路径|String||是| |--output|-o|模型输出目录,不填则在模型文件目录下自动创建一个3dtiles目录。|String||否| |--metadata|--md|输入BIM语义sidecar(.metadata),将构件的BIM属性(名称/元素ID/类别/族/类型/楼层/参数集)写入瓦片内EXT_structural_metadata多列属性表,支持加载端按构件查询与按楼层/类别过滤。.metadata由revitToGltf插件导出,其Elements数组的Key字段与glTF节点extras.uniqueId一一对应。|String||否| |--inputUpAxis|--iua|设置输入模型的向上坐标轴,[可选值:X,Y,Z,-X,-Y,-Z]obj默认按Z-up处理并自动转换,fbx默认读取文件GlobalSettings声明的UpAxis,gltf/glb按规范固定为Y-up。|String|见描述|否| |--rotation|-r|手动设置模型旋转角度,格式为[x,y,z],单位为度。坐标轴朝向已自动归一化,仅当模型存在轴向以外的偏转(如偏离正北)时才需要设置。|String||否| |--lngLatAlt|--lla|设置模型经度、纬度、海拔高度,格式为[longitude,latitude,altitude],高度单位为米。|String|116.4074,39.9042,0|否| |--correctCenter|--cc|自动修正模型锚点至模型包围盒中心点,修正后经纬度对应包围盒中心。|Boolean|true|否| |--b3dm||以b3dm容器输出瓦片,3D Tiles经典格式,兼容传统前端;关闭则输出glTF瓦片(3D Tiles 1.1)。|Boolean|true|否| |--split|-s|设置瓦片拆分方式,[可选值:spatial,material]material按材质顺序装填(默认,适合单精度精细模型,draw call恒为材质数、体积最小、加载最快);spatial按空间递归切分并生成LOD层级瓦片,远景渲染粗层、近景refine细层,适合大体量场景的漫游剔除,体积约为material的4倍,同精度模型下收益有限。|String|material|否| |--textureAtlas|--ta|启用纹理图集优化:将可合并材质的贴图按尺寸分桶合成2的幂网格图集页并重映射UV,减少材质数与draw call;非2的幂贴图重采样至最近2的幂。仅baseColor贴图、UV在[0,1]内的材质参与合并。|Boolean|true|否| |--resampleTextures|-rst|将非2的幂贴图重采样至最近2的幂(含全部贴图槽位),避免Cesium将NPOT纹理放大到下一2次幂导致显存膨胀;启用textureAtlas时无需单独开启。|Boolean|true|否| |--draco|-d|启用Draco几何压缩(KHR_draco_mesh_compression),瓦片体积大幅下降,加载端由Cesium自动解码;含featureId属性,与构件拾取兼容。|Boolean|true|否| |--mergePrimitive|-mp|设置是否合并材质相同的网格图元。|Boolean|true|否| |--instancing||保留glTF输入的实例化网格(EXT_mesh_gpu_instancing+EXT_instance_features):同几何多构件(如族实例)只存一份几何+每实例矩阵表,体积与转换内存大幅下降,构件拾取/显隐不受影响;仅material拆分模式生效,spatial自动回退为展开。需Cesium 1.107+加载。|Boolean|true|否| |--tileSize|-ts|设置期望的单个瓦片存储容量,单位mb。|Number|10|否| |--clampToGround|--ctg|设置模型是否自动贴地,为true时altitude属性失效。|Boolean|true|否| |--noneTransform|--nt|是否不设置模型变换矩阵,为true时lngLatAlt、clampToGround等属性失效。|Boolean|false|否|

另有面向 obj 材质转换的高级参数(透传自 obj2gltf,一般无需设置):--checkTransparency、--packOcclusion、--metallicRoughness、--specularGlossiness、--unlit,详见 modelTo3DTiles -h。

调参建议

瓦片策略(--split)的选择取决于模型精度结构与浏览方式:

| 场景 | 推荐配置 | 原因 | |---|---|---| | 单精度精细模型(默认情况) | -s material(默认) | draw call 恒为材质数(理论下限),体积最小、加载最快、行为可预期 | | 大体量场景 + 漫游剔除 | -s spatial | 生成LOD层级瓦片:远景渲染粗层(根瓦片图元数等于材质切分下限),镜头推进逐分支refine近景细层 |

说明:当前粗层与细层为同一精度的几何(仅聚合粒度不同),spatial 模式体积约为 material 的 4 倍,近景 draw call 略高于 material——它的完整收益依赖多精度简化(粗层真减三角形),适合确认需要漫游剔除的大场景再启用;配合 --ts 2~4 调细叶子粒度可增强剔除敏感性。

输出结构

output/
├── tileset.json      # 3D Tiles 入口
├── Tile-0.b3dm       # 瓦片内容(b3dm或glb)
├── Tile-1.b3dm
└── textures/         # 外置共享贴图与图集页

注意:textures/ 目录与瓦片文件必须整体分发,不可只拷贝 .b3dm 文件。

Cesium 加载

const tileset = await Cesium.Cesium3DTileset.fromUrl('output/tileset.json');
viewer.scene.primitives.add(tileset);
viewer.zoomTo(tileset);

// 构件级拾取:点击查询构件名称、单独显隐/着色
const handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);
handler.setInputAction(movement => {
    const feature = viewer.scene.pick(movement.position);
    if (feature instanceof Cesium.Cesium3DTileFeature) {
        console.log(feature.getProperty('name'));  // 构件名称
        feature.color = Cesium.Color.RED;          // 单构件高亮
    }
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);

版本要求:CesiumJS ≥ 1.104(Cesium3DTileset.fromUrl API);构件级拾取(EXT_mesh_features)需 ≥ 1.97,实例化输出(EXT_mesh_gpu_instancing/EXT_instance_features)需 ≥ 1.107(实测 1.137 可用),建议直接使用最新版。

在 threejs 中使用

两种方式,按场景选择。

方式一:直接加载瓦片 GLB(简单场景,自行管理相机与剔除)

转换时用 --no-b3dm 输出 glTF 瓦片,遍历 tileset.json 逐个加载合成。输出为模型局部坐标系(米,Y-up),不含地理定位,需自行摆放:

import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
import { DRACOLoader } from 'three/addons/loaders/DRACOLoader.js';

// 默认开启的Draco压缩需要配置解码器
const dracoLoader = new DRACOLoader();
dracoLoader.setDecoderPath('https://www.gstatic.com/draco/versioned/decoders/1.5.7/');
const loader = new GLTFLoader();
loader.setDRACOLoader(dracoLoader);

const group = new THREE.Group();
const tileset = await (await fetch('output/tileset.json')).json();
for (const child of tileset.root.children) {
    const gltf = await loader.loadAsync('output/' + child.content.uri);
    group.add(gltf.scene);
}
scene.add(group);

方式二:经 3d-tiles-renderer 加载完整 tileset(需要瓦片调度、视锥剔除时)

import { TilesRenderer } from '3d-tiles-renderer';

const tiles = new TilesRenderer('output/tileset.json');
tiles.setCamera(camera);
tiles.setResolutionFromRenderer(renderer);
scene.add(tiles.group);

// 渲染循环中更新
tiles.update();

说明:

  • 启用 --draco 时务必配置 DRACOLoader(b3dm 容器需自行剥离 28 字节头再交由 GLTFLoader,建议直接用 --no-b3dm);
  • textures/ 目录需与瓦片同目录部署(外置贴图按相对路径解析);
  • 构件拾取:GLTFLoader 不识别 EXT_mesh_features/EXT_instance_features 扩展,但 _FEATURE_ID_0 属性会保留在几何体上——实例化构件(EXT_mesh_gpu_instancing)被渲染为 InstancedMesh,拾取用 intersection.instanceId 读实例属性 geometry.getAttribute('_FEATURE_ID_0')(loader 原样保留实例语义大小写);合并网格为逐顶点属性,但 loader 会把自定义顶点语义小写化为 _feature_id_0,拾取用 intersection.face.a 顶点索引。构件名称/属性可自行解码 GLB JSON 块中 EXT_structural_metadata 的属性表(stringOffsets 均为 BIN 块内偏移)。

从源码构建 exe

npm install
npm run build        # esbuild打包 + pkg封装为 node22-win-x64 可执行文件

产物约 210MB(内嵌 Node 运行时、Cesium 资源与 Draco/图像原生库),首次构建需从网络下载 Node 运行时。

License

MIT