Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

vtk-three-parser

yourusername0MIT2.0.0TypeScript support: included

Parse VTK/VTP 3D model files and convert them to Three.js objects - Browser UMD version

vtk, vtp, three.js, 3d, parser, converter, umd, browser, standalone

readme

vtk-three-parser

npm version License: MIT

一个强大的VTK/VTP 3D模型文件解析器,可以将VTK格式文件转换为Three.js对象,支持丰富的颜色信息和材质处理。

✨ 特性

  • 🎯 简单易用: 一行代码完成VTK/VTP文件解析
  • 🌐 浏览器友好: 支持UMD格式,可直接在浏览器中使用
  • 🎨 丰富颜色支持: 自动识别并处理顶点颜色、材质颜色
  • 🔧 智能解析策略: 多重回退机制确保最佳兼容性
  • 高性能: 基于@kitware/vtk.js构建,支持二进制格式
  • 🛠️ TypeScript支持: 完整的类型定义
  • 📦 零配置: 开箱即用,无需复杂设置

📦 安装与使用

Node.js环境

npm install vtk-three-parser

浏览器环境

  1. 下载并安装包

    npm install vtk-three-parser
  2. 复制UMD文件到项目

    # 复制UMD文件到你的项目目录
    cp node_modules/vtk-three-parser/dist/vtk-three-parser.umd.js ./libs/vtk-three-parser.js
  3. 在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、标量映射
  • 多种几何类型 - 三角形、四边形、复杂多边形

🌐 浏览器环境特性

智能回退机制

  1. 优先使用VTK.js - 如果页面中包含VTK.js,优先使用其强大的解析能力
  2. 自动回退到Three.js - 如果VTK.js不可用,自动使用Three.js VTKLoader
  3. 错误处理 - 提供详细的错误信息和解决建议

可选的VTK.js增强

如果需要更强大的VTK解析能力,可以下载并引入VTK.js:

  1. 下载VTK.js

    # 下载VTK.js到本地
    npm install @kitware/vtk.js
    cp node_modules/@kitware/vtk.js/dist/vtk.js ./libs/vtk.js
  2. 在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>

文件获取指南

  1. Three.js: 从Three.js官网下载,或从项目的node_modules中复制
  2. VTK Three Parser: 安装本包后从node_modules/vtk-three-parser/dist/vtk-three-parser.umd.js复制
  3. VTK.js (可选): 从node_modules/@kitware/vtk.js/dist/vtk.js复制

全局变量

浏览器环境中提供以下全局函数:

  • parseVTKModel() - 主要解析函数
  • parseVTKModelWithInfo() - 带详细信息的解析函数
  • createVTKModelMaterial() - 材质创建函数
  • VTKThreeParser - 完整的API对象

🔧 高级特性

智能解析策略

本库采用多重回退机制确保最佳兼容性:

  1. 改进的VTK.js加载器 - 支持丰富的颜色处理
  2. 标准VTK.js加载器 - 处理复杂二进制格式
  3. 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 文件

🙏 致谢


如果这个项目对您有帮助,请给我们一个⭐!