vtk-three-parser
一个强大的VTK/VTP 3D模型文件解析器,可以将VTK格式文件转换为Three.js对象,支持丰富的颜色信息和材质处理。
✨ 特性
- 🎯 简单易用: 一行代码完成VTK/VTP文件解析
- 🌐 浏览器友好: 支持UMD格式,可直接在浏览器中使用
- 🎨 丰富颜色支持: 自动识别并处理顶点颜色、材质颜色
- 🔧 智能解析策略: 多重回退机制确保最佳兼容性
- ⚡ 高性能: 基于@kitware/vtk.js构建,支持二进制格式
- 🛠️ TypeScript支持: 完整的类型定义
- 📦 零配置: 开箱即用,无需复杂设置
📦 安装与使用
Node.js环境
npm install vtk-three-parser
浏览器环境
下载并安装包:
npm install vtk-three-parser
复制UMD文件到项目:
# 复制UMD文件到你的项目目录 cp node_modules/vtk-three-parser/dist/vtk-three-parser.umd.js ./libs/vtk-three-parser.js
在HTML中引入:
<!DOCTYPE html> <html> <head> <script src="./libs/three.min.js"></script> <script src="./libs/vtk-three-parser.js"></script> </head> <body> <script> // 直接使用全局函数 async function loadModel(arrayBuffer) { const object = await parseVTKModel(arrayBuffer, 'vtp'); scene.add(object); } </script> </body> </html>
🚀 快速开始
Node.js环境使用
import { parseVTKModel } from 'vtk-three-parser';
import * as THREE from 'three';
// 创建场景
const scene = new THREE.Scene();
// 解析VTK/VTP文件
async function loadModel(arrayBuffer: ArrayBuffer) {
try {
// 一行代码完成解析
const object = await parseVTKModel(arrayBuffer, 'vtp');
// 直接添加到场景
scene.add(object);
console.log('模型加载成功!');
} catch (error) {
console.error('模型加载失败:', error);
}
}
浏览器环境使用
完整示例项目结构:
your-project/
├── libs/
│ ├── three.min.js # Three.js库文件
│ └── vtk-three-parser.js # 从node_modules复制的UMD文件
├── models/ # 存放VTK模型文件
│ ├── example.vtk
│ └── example.vtp
└── index.html # 主页面
index.html 完整示例:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>VTK Three Parser Browser Example</title>
<style>
body { margin: 0; overflow: hidden; background: #f0f0f0; }
canvas { display: block; }
.controls {
position: absolute;
top: 10px;
left: 10px;
background: rgba(255,255,255,0.9);
padding: 15px;
border-radius: 5px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.file-input {
margin: 10px 0;
padding: 5px;
}
</style>
</head>
<body>
<!-- 引入本地Three.js文件 -->
<script src="./libs/three.min.js"></script>
<!-- 引入本地VTK Three Parser文件 -->
<script src="./libs/vtk-three-parser.js"></script>
<div class="controls">
<h3>VTK/VTP 模型加载器</h3>
<input type="file" id="fileInput" accept=".vtk,.vtp" class="file-input">
<div id="info">请选择VTK或VTP文件</div>
</div>
<script>
// 初始化Three.js场景
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0xf0f0f0);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
document.body.appendChild(renderer.domElement);
// 添加光源
const ambientLight = new THREE.AmbientLight(0x404040, 0.4);
scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(10, 10, 5);
directionalLight.castShadow = true;
scene.add(directionalLight);
// 添加地面
const groundGeometry = new THREE.PlaneGeometry(20, 20);
const groundMaterial = new THREE.MeshLambertMaterial({ color: 0xffffff });
const ground = new THREE.Mesh(groundGeometry, groundMaterial);
ground.rotation.x = -Math.PI / 2;
ground.receiveShadow = true;
scene.add(ground);
// 轨道控制器(如果有引入)
let controls;
if (typeof THREE.OrbitControls !== 'undefined') {
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
}
// 信息显示元素
const infoDiv = document.getElementById('info');
// 文件上传处理
document.getElementById('fileInput').addEventListener('change', async (event) => {
const file = event.target.files[0];
if (!file) return;
infoDiv.textContent = '正在加载模型...';
try {
const arrayBuffer = await file.arrayBuffer();
const extension = file.name.split('.').pop().toLowerCase();
// 使用全局函数解析VTK文件
const result = await parseVTKModelWithInfo(arrayBuffer, extension, {
enableVertexColors: true,
wireframe: false
});
// 清除之前的模型
const objectsToRemove = [];
scene.traverse(child => {
if (child.isMesh && child !== ground) {
objectsToRemove.push(child);
}
});
objectsToRemove.forEach(obj => scene.remove(obj));
// 添加新模型
scene.add(result.object);
// 调整相机位置
const box = new THREE.Box3().setFromObject(result.object);
const center = box.getCenter(new THREE.Vector3());
const size = box.getSize(new THREE.Vector3());
const maxDim = Math.max(size.x, size.y, size.z);
const distance = maxDim * 2;
camera.position.copy(center);
camera.position.add(new THREE.Vector3(distance, distance, distance));
camera.lookAt(center);
if (controls) {
controls.target.copy(center);
controls.update();
}
// 显示模型信息
infoDiv.innerHTML = `
<strong>模型加载成功!</strong><br>
顶点数: ${result.info.vertices.toLocaleString()}<br>
面数: ${result.info.faces.toLocaleString()}<br>
包含颜色: ${result.hasColors ? '是' : '否'}
`;
console.log('模型加载成功!', result.info);
} catch (error) {
console.error('模型加载失败:', error);
infoDiv.innerHTML = `<span style="color: red;">加载失败: ${error.message}</span>`;
}
});
// 渲染循环
function animate() {
requestAnimationFrame(animate);
if (controls) {
controls.update();
}
renderer.render(scene, camera);
}
animate();
// 窗口大小调整
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
// 设置初始相机位置
camera.position.set(5, 5, 5);
camera.lookAt(0, 0, 0);
</script>
</body>
</html>
高级配置
import { parseVTKModel, VTKParseOptions } from 'vtk-three-parser';
const options: VTKParseOptions = {
enableVertexColors: true, // 启用顶点颜色
wireframe: false, // 线框模式
materialColor: 0xFF0000, // 材质颜色(红色)
opacity: 0.8, // 透明度
transparent: true, // 透明材质
shininess: 100 // 光泽度
};
const object = await parseVTKModel(arrayBuffer, 'vtk', options);
scene.add(object);
获取详细信息
import { parseVTKModelWithInfo } from 'vtk-three-parser';
const result = await parseVTKModelWithInfo(arrayBuffer, 'vtp');
console.log('模型信息:', {
vertices: result.info.vertices, // 顶点数
faces: result.info.faces, // 面数
hasColors: result.hasColors, // 是否包含颜色
hasMaterials: result.info.hasMaterials // 是否包含材质
});
scene.add(result.object);
📚 API文档
parseVTKModel(data, fileExtension, options?)
主要的解析函数,将VTK/VTP文件转换为Three.js对象。
参数:
data: ArrayBuffer
- 模型文件的二进制数据fileExtension: 'vtk' | 'vtp'
- 文件扩展名options?: VTKParseOptions
- 可选配置
返回:
Promise<THREE.Object3D>
- 可直接添加到场景的Three.js对象
浏览器环境:
<script>
// 全局函数,直接调用
const object = await parseVTKModel(arrayBuffer, 'vtp', {
enableVertexColors: true,
materialColor: 0xFF0000
});
</script>
Node.js环境:
import { parseVTKModel } from 'vtk-three-parser';
const object = await parseVTKModel(arrayBuffer, 'vtp');
VTKParseOptions
解析配置选项接口:
interface VTKParseOptions {
enableVertexColors?: boolean; // 启用顶点颜色,默认true
wireframe?: boolean; // 线框模式,默认false
materialColor?: number; // 材质颜色,默认0xAAAAAA
autoComputeNormals?: boolean; // 自动计算法向量,默认true
opacity?: number; // 透明度,默认1.0
transparent?: boolean; // 透明材质,默认false
specular?: number; // 镜面反射,默认0x111111
shininess?: number; // 光泽度,默认200
}
parseVTKModelWithInfo(data, fileExtension, options?)
获取详细解析信息的函数。
返回:
interface VTKParseResult {
object: THREE.Object3D; // Three.js对象
hasColors: boolean; // 是否包含颜色
info: {
vertices: number; // 顶点数
faces: number; // 面数
hasMaterials: boolean; // 是否包含材质
};
}
🎨 支持的格式
- VTK Legacy格式 (.vtk) - ASCII和Binary
- VTK XML格式 (.vtp) - ASCII、Binary和Appended
- 自动颜色识别 - RGB、RGBA、标量映射
- 多种几何类型 - 三角形、四边形、复杂多边形
🌐 浏览器环境特性
智能回退机制
- 优先使用VTK.js - 如果页面中包含VTK.js,优先使用其强大的解析能力
- 自动回退到Three.js - 如果VTK.js不可用,自动使用Three.js VTKLoader
- 错误处理 - 提供详细的错误信息和解决建议
可选的VTK.js增强
如果需要更强大的VTK解析能力,可以下载并引入VTK.js:
下载VTK.js:
# 下载VTK.js到本地 npm install @kitware/vtk.js cp node_modules/@kitware/vtk.js/dist/vtk.js ./libs/vtk.js
在HTML中引入:
<!-- 可选:引入VTK.js以获得更好的解析能力 --> <script src="./libs/vtk.js"></script> <!-- 引入Three.js --> <script src="./libs/three.min.js"></script> <!-- 引入VTK Three Parser --> <script src="./libs/vtk-three-parser.js"></script>
文件获取指南
- Three.js: 从Three.js官网下载,或从项目的node_modules中复制
- VTK Three Parser: 安装本包后从
node_modules/vtk-three-parser/dist/vtk-three-parser.umd.js
复制 - VTK.js (可选): 从
node_modules/@kitware/vtk.js/dist/vtk.js
复制
全局变量
浏览器环境中提供以下全局函数:
parseVTKModel()
- 主要解析函数parseVTKModelWithInfo()
- 带详细信息的解析函数createVTKModelMaterial()
- 材质创建函数VTKThreeParser
- 完整的API对象
🔧 高级特性
智能解析策略
本库采用多重回退机制确保最佳兼容性:
- 改进的VTK.js加载器 - 支持丰富的颜色处理
- 标准VTK.js加载器 - 处理复杂二进制格式
- Three.js VTKLoader - 基础格式支持
颜色处理
- 自动识别RGB/RGBA颜色数据
- 标量数据映射为伪彩色
- Cell Data插值到顶点
- 支持材质ID离散颜色映射
性能优化
- 智能几何体三角化
- 自动法向量计算
- 内存效率优化
- 错误处理和日志记录
📋 使用示例
文件上传处理
import { parseVTKModel } from 'vtk-three-parser';
function handleFileUpload(event: Event) {
const input = event.target as HTMLInputElement;
const file = input.files?.[0];
if (file) {
const reader = new FileReader();
reader.onload = async (e) => {
const arrayBuffer = e.target?.result as ArrayBuffer;
const extension = file.name.split('.').pop()?.toLowerCase() as 'vtk' | 'vtp';
try {
const object = await parseVTKModel(arrayBuffer, extension);
scene.add(object);
} catch (error) {
console.error('加载失败:', error);
}
};
reader.readAsArrayBuffer(file);
}
}
批量处理
async function loadMultipleModels(files: { data: ArrayBuffer, ext: 'vtk' | 'vtp' }[]) {
const objects = await Promise.all(
files.map(file => parseVTKModel(file.data, file.ext))
);
objects.forEach(object => scene.add(object));
}
🤝 贡献
欢迎提交Issue和Pull Request来改进这个项目!
📄 许可证
MIT License - 详见 LICENSE 文件
🙏 致谢
- @kitware/vtk.js - 强大的VTK处理库
- Three.js - 优秀的3D图形库
如果这个项目对您有帮助,请给我们一个⭐!