threejs 在 web worker 中导出带颜色的 obj 文件

为什么在 worker 中要重新生成一些 Vector3、Matrix3等数据

这是由于数据传递过程中会将一些特殊的对象转换成普通的对象,导致这些特殊对象原型上面的方法丢失导致很多问题,因此现在的策略就是将导出 obj 文件所需的数据逐个传递进来

为什么源代码中没有导出颜色

带颜色的 obj 文件

带颜色obj

不带颜色 obj 文件

在这里插入图片描述
从上面对比中很明显看出带颜色的 obj 文件明显多了三个数值,分别对应 r、g、b颜色值。但是源码中并没有遍历加上后面的颜色值

输入

this.worker = new Worker();
// this.mesh 表示要导出的 obj 对象
this.worker?.postMessage({
   position: this.mesh.geometry.attributes?.position.array,
   normals: this.mesh.geometry.attributes.normal?.array,
   uv: this.mesh.geometry.attributes.uv?.array,
   colors: this.mesh.geometry.attributes.color?.array,
   indices: this.mesh.geometry.getIndex(),
   name: this.mesh.name,
   matrixWorld: JSON.stringify(this.mesh.matrixWorld),
   })

worker 中的代码

self.onmessage = (event: any) => {
const data = event.data
const objStr = objWorkerExport(data)
// 这里将其导出为文件用于直接拿这个文件上传
const blob = new Blob([objStr], { type: 'text/plain' });
    const file = new File([blob], 'file.obj', { type: blob.type });
    self.postMessage({
      funType: typeFun.fileTransition,
      data: file
    })
}
// 用于生成导出 obj 文件所需的数据
const objWorkerExport = (data: any) => {
  let output = '';
  let indexVertex = 0;
  let indexVertexUvs = 0;
	let indexNormals = 0;
  const vertex = new THREE.Vector3();
  const uv = new THREE.Vector2();
  const normal = new THREE.Vector3();
  const face: any[] = [];
  function parseMesh() {
    let nbVertex = 0;
    let nbNormals = 0;
    let nbVertexUvs = 0;

    output += 'o ' + data.name + '\n';


    const normalMatrixWorld = new THREE.Matrix3();
    
    const vertices = getBufferAttributeData(data.position, 3)
    const normals = getBufferAttributeData(data.normals, 3)
    const uvs = getBufferAttributeData(data.uv, 3)
    const colors = getBufferAttributeData(data.colors, 3)
    const indices = data.indices
    // vertices
    const _color = new THREE.Color()
    const matrixWorld = getMatrix4Info(data.matrixWorld)
    if ( vertices !== undefined ) {
      for ( let i = 0, l = vertices.count; i < l; i ++, nbVertex ++ ) {
        vertex.fromBufferAttribute( vertices, i );
        _color.fromBufferAttribute( colors!, i ).convertLinearToSRGB();
        vertex.applyMatrix4( matrixWorld );
        output += 'v ' + vertex.x + ' ' + vertex.y + ' ' + vertex.z + ' ' + _color.r + ' ' + _color.g + ' ' + _color.b + '\n';
      }
    }
    // uvs
    if ( uvs !== undefined ) {
      for ( let i = 0, l = uvs.count; i < l; i ++, nbVertexUvs ++ ) {

        uv.fromBufferAttribute( uvs, i );

        // transform the uv to export format
        output += 'vt ' + uv.x + ' ' + uv.y + '\n';

      }
    }
    // normals
    if ( normals !== undefined ) {
      normalMatrixWorld.getNormalMatrix( matrixWorld );
      for ( let i = 0, l = normals.count; i < l; i ++, nbNormals ++ ) {

        normal.fromBufferAttribute( normals, i );

        // transform the normal to world space
        normal.applyMatrix3( normalMatrixWorld ).normalize();

        // transform the normal to export format
        output += 'vn ' + normal.x + ' ' + normal.y + ' ' + normal.z + '\n';

      }
    }
    // faces
    if ( indices !== null ) {
      for ( let i = 0, l = indices.count; i < l; i += 3 ) {

        for ( let m = 0; m < 3; m ++ ) {

          const j = indices.getX( i + m ) + 1;

          face[ m ] = ( indexVertex + j ) + ( normals || uvs ? '/' + ( uvs ? ( indexVertexUvs + j ) : '' ) + ( normals ? '/' + ( indexNormals + j ) : '' ) : '' );

        }

        // transform the face to export format
        output += 'f ' + face.join( ' ' ) + '\n';

      }
    } else {
      for ( let i = 0, l = vertices!.count; i < l; i += 3 ) {
        for ( let m = 0; m < 3; m ++ ) {

          const j = i + m + 1;

          face[ m ] = ( indexVertex + j ) + ( normals || uvs ? '/' + ( uvs ? ( indexVertexUvs + j ) : '' ) + ( normals ? '/' + ( indexNormals + j ) : '' ) : '' );

        }

        // transform the face to export format
        output += 'f ' + face.join( ' ' ) + '\n';
      }
    }
    // update index
		indexVertex += nbVertex;
		indexVertexUvs += nbVertexUvs;
		indexNormals += nbNormals;
  }
  parseMesh()
  return output;
}

输出

this.worker.onmessage = (res) => {
const data = res.data
console.log(data.data)
}
  • 11
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您可以使用d3-force模块webworker来并行计算力导向图。您需要创建一个新的JavaScript文件,用于运行webworker,并在d3.js调用它。您可以使用d3-force模块的以下代码: ``` javascript var simulation = d3.forceSimulation(nodes) .force("charge", d3.forceManyBody()) .force("link", d3.forceLink(links)) .force("x", d3.forceX()) .force("y", d3.forceY()) .alphaTarget(1) .on("tick", ticked); if (window.Worker) { // 创建新的webworker var worker = new Worker("worker.js"); // 发送数据给webworker worker.postMessage({nodes: nodes, links: links}); // 监听webworker的消息 worker.onmessage = function(event) { console.log("Received data from worker: ", event.data); // 更新节点和链接 simulation.nodes(event.data.nodes).links(event.data.links); }; } else { // 如果浏览器不支持webworker,则在主线程运行d3-force simulation.nodes(nodes).on("tick", ticked); } function ticked() { // 更新节点和链接的位置 } ``` 在上面的代码,我们检查是否支持webworker,如果支持,我们就创建一个新的webworker,并将节点和链接发送给它。webworker会计算新的位置,并将它们发送回主线程。如果不支持webworker,我们就在主线程运行d3-force。最后,在ticked()函数更新节点和链接的位置。 请注意,为了使此代码段保持简洁,它并不完全包含在d3.js的工作流程。如果您需要更详细的说明,请参阅d3-force模块的文档。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值