我希望能够导出一个obj文件,就像在这个示例http://threejs.org/examples/#webgl_exporter_obj
中一样但是,我想在.mtl纹理文件中导出带有相应纹理的.obj文件(我已经看过obj文件" usemtl someTextureNameFromMTL")
我见过this question,但导出器似乎只导出网格物体。我还找到了this question,但仅讨论了导入器。
我想要实现的是制作一个3d打印的编辑器,它也可以导出纹理/颜色,因为已经存在用于3d打印的.stl网格导出器。但是,我发现三个js没有网格+颜色/纹理导出器:(
答案 0 :(得分:7)
我已经扩展了OBJExporter一点点。它将返回包含.obj部分和.mtl部分的对象。我只是在没有测试的情况下将其写下来,所以可能存在错误,但我希望它能够开始。
我没有查找所有的mtl值,我只使用了一些标准值,除了颜色和纹理信息。也许我会在以后改进它。您还需要知道mtl文件名。目前,我正在为obj部分写一个静态名称。保存文件时,mtl文件需要与声明的obj文件中的名称相同。否则3ds max等将无法读取它。
/**
* @author mrdoob / http://mrdoob.com/
*/
THREE.OBJExporter = function () {};
THREE.OBJExporter.prototype = {
constructor: THREE.OBJExporter,
parse: function ( object ) {
var output = '';
var materials = {};
var indexVertex = 0;
var indexVertexUvs = 0;
var indexNormals = 0;
var mtlFileName = 'objmaterial'; // maybe this value can be passed as parameter
output += 'mtllib ' + mtlFileName + '.mtl\n';
var parseMesh = function ( mesh ) {
var nbVertex = 0;
var nbVertexUvs = 0;
var nbNormals = 0;
var geometry = mesh.geometry;
var material = mesh.material;
if ( geometry instanceof THREE.Geometry ) {
output += 'o ' + mesh.name + '\n';
var vertices = geometry.vertices;
for ( var i = 0, l = vertices.length; i < l; i ++ ) {
var vertex = vertices[ i ].clone();
vertex.applyMatrix4( mesh.matrixWorld );
output += 'v ' + vertex.x + ' ' + vertex.y + ' ' + vertex.z + '\n';
nbVertex ++;
}
// uvs
var faces = geometry.faces;
var faceVertexUvs = geometry.faceVertexUvs[ 0 ];
var hasVertexUvs = faces.length === faceVertexUvs.length;
if ( hasVertexUvs ) {
for ( var i = 0, l = faceVertexUvs.length; i < l; i ++ ) {
var vertexUvs = faceVertexUvs[ i ];
for ( var j = 0, jl = vertexUvs.length; j < jl; j ++ ) {
var uv = vertexUvs[ j ];
output += 'vt ' + uv.x + ' ' + uv.y + '\n';
nbVertexUvs ++;
}
}
}
// normals
var normalMatrixWorld = new THREE.Matrix3();
normalMatrixWorld.getNormalMatrix( mesh.matrixWorld );
for ( var i = 0, l = faces.length; i < l; i ++ ) {
var face = faces[ i ];
var vertexNormals = face.vertexNormals;
if ( vertexNormals.length === 3 ) {
for ( var j = 0, jl = vertexNormals.length; j < jl; j ++ ) {
var normal = vertexNormals[ j ].clone();
normal.applyMatrix3( normalMatrixWorld );
output += 'vn ' + normal.x + ' ' + normal.y + ' ' + normal.z + '\n';
nbNormals ++;
}
} else {
var normal = face.normal.clone();
normal.applyMatrix3( normalMatrixWorld );
for ( var j = 0; j < 3; j ++ ) {
output += 'vn ' + normal.x + ' ' + normal.y + ' ' + normal.z + '\n';
nbNormals ++;
}
}
}
// material
if (material.name !== '')
output += 'usemtl ' + material.name + '\n';
else
output += 'usemtl material' + material.id + '\n';
materials[material.id] = material;
// faces
for ( var i = 0, j = 1, l = faces.length; i < l; i ++, j += 3 ) {
var face = faces[ i ];
output += 'f ';
output += ( indexVertex + face.a + 1 ) + '/' + ( hasVertexUvs ? ( indexVertexUvs + j ) : '' ) + '/' + ( indexNormals + j ) + ' ';
output += ( indexVertex + face.b + 1 ) + '/' + ( hasVertexUvs ? ( indexVertexUvs + j + 1 ) : '' ) + '/' + ( indexNormals + j + 1 ) + ' ';
output += ( indexVertex + face.c + 1 ) + '/' + ( hasVertexUvs ? ( indexVertexUvs + j + 2 ) : '' ) + '/' + ( indexNormals + j + 2 ) + '\n';
}
} else {
console.warn( 'THREE.OBJExporter.parseMesh(): geometry type unsupported', mesh );
// TODO: Support only BufferGeometry and use use setFromObject()
}
// update index
indexVertex += nbVertex;
indexVertexUvs += nbVertexUvs;
indexNormals += nbNormals;
};
object.traverse( function ( child ) {
if ( child instanceof THREE.Mesh ) parseMesh( child );
} );
// mtl output
var mtlOutput = '';
for (var key in materials) {
var mat = materials[key];
if (mat.name !== '')
mtlOutput += 'newmtl ' + mat.name + '\n';
else
mtlOutput += 'newmtl material' + mat.id + '\n';
mtlOutput += 'Ns 10.0000\n';
mtlOutput += 'Ni 1.5000\n';
mtlOutput += 'd 1.0000\n';
mtlOutput += 'Tr 0.0000\n';
mtlOutput += 'Tf 1.0000 1.0000 1.0000\n';
mtlOutput += 'illum 2\n';
mtlOutput += 'Ka ' + mat.color.r + ' ' + mat.color.g + ' ' + mat.color.b + ' ' + '\n';
mtlOutput += 'Kd ' + mat.color.r + ' ' + mat.color.g + ' ' + mat.color.b + ' ' + '\n';
mtlOutput += 'Ks 0.0000 0.0000 0.0000\n';
mtlOutput += 'Ke 0.0000 0.0000 0.0000\n';
if (mat.map && mat.map instanceof THREE.Texture) {
var file = mat.map.image.currentSrc.slice( mat.map.image.currentSrc.slice.lastIndexOf("/"), mat.map.image.currentSrc.length - 1 );
mtlOutput += 'map_Ka ' + file + '\n';
mtlOutput += 'map_Kd ' + file + '\n';
}
}
return {
obj: output,
mtl: mtlOutput
}
}
};
答案 1 :(得分:0)
这是使用filesaver和JSZip保存的方法
var oexporter = new THREE.OBJExporter();
var result = oexporter.parse(scene);
zip.file('mymodel.obj', result.obj);
zip.file('objmaterial.mtl', result.mtl);
var zz=zip.generate({ type: 'blob' });
saveAs(zz, 'mymodel.zip');
但是,我的问题是,我从文件中加载到场景中的3D模型没有被保存。当我用3DBuilder加载模型时,只有我用three.js函数创建的东西出现。