PRTLoader

157 阅读1分钟
import { BufferGeometry, Float32BufferAttribute, Uint32BufferAttribute } from 'three';

class PRTLoader {
  constructor() {}

  load(url, onLoad, onProgress, onError) {
    const loader = new FileLoader();
    loader.setResponseType('arraybuffer');
    loader.load(url, (data) => {
      const geometry = this.parse(data);
      onLoad(geometry);
    }, onProgress, onError);
  }

  parse(data) {
    const view = new DataView(data); // 使用 DataView 处理二进制数据
    let offset = 0;

    // 解析文件版本(4字节)
    const version = view.getUint32(offset, true);
    offset += 4;
    console.log(`PRT File Version: ${version}`);

    // 解析顶点数量(4字节)
    const vertexCount = view.getUint32(offset, true);
    offset += 4;
    console.log(`Vertex Count: ${vertexCount}`);

    // 解析面数量(4字节)
    const faceCount = view.getUint32(offset, true);
    offset += 4;
    console.log(`Face Count: ${faceCount}`);

    // 解析顶点数据
    const vertices = new Float32Array(vertexCount * 3); // 每个顶点 3 个浮点数
    for (let i = 0; i < vertexCount; i++) {
      const x = view.getFloat32(offset, true); // 读取 x 坐标
      offset += 4;
      const y = view.getFloat32(offset, true); // 读取 y 坐标
      offset += 4;
      const z = view.getFloat32(offset, true); // 读取 z 坐标
      offset += 4;
      vertices[i * 3] = x;
      vertices[i * 3 + 1] = y;
      vertices[i * 3 + 2] = z;
    }
    console.log(`Vertices Parsed: ${vertices}`);

    // 解析面数据
    const indices = new Uint32Array(faceCount * 3); // 每个面 3 个顶点索引
    for (let i = 0; i < faceCount; i++) {
      const a = view.getUint32(offset, true); // 读取第一个顶点索引
      offset += 4;
      const b = view.getUint32(offset, true); // 读取第二个顶点索引
      offset += 4;
      const c = view.getUint32(offset, true); // 读取第三个顶点索引
      offset += 4;
      indices[i * 3] = a;
      indices[i * 3 + 1] = b;
      indices[i * 3 + 2] = c;
    }
    console.log(`Faces Parsed: ${indices}`);

    // 构建 three.js 的几何体
    const geometry = new BufferGeometry();
    geometry.setAttribute('position', new Float32BufferAttribute(vertices, 3)); // 设置顶点属性
    geometry.setIndex(new Uint32BufferAttribute(indices, 1)); // 设置面索引
    geometry.computeVertexNormals(); // 计算法线

    return geometry;
  }
}

export { PRTLoader };