为什么在 worker 中要重新生成一些 Vector3、Matrix3等数据
这是由于数据传递过程中会将一些特殊的对象转换成普通的对象,导致这些特殊对象原型上面的方法丢失导致很多问题,因此现在的策略就是将导出 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)
}