【问题标题】:Export a three js textured model to a .OBJ with .MTL file使用 .MTL 文件将三个 js 纹理模型导出到 .OBJ
【发布时间】:2016-05-06 08:00:53
【问题描述】:

我希望能够像本例中一样导出 obj 文件 http://threejs.org/examples/#webgl_exporter_obj

但是,我想在 .mtl 纹理文件中导出带有相应纹理的 .obj 文件(我见过带有“usemtl someTextureNameFromMTL”的 obj 文件)

我见过this question,但出口商似乎只出口网格。我也找到了this question,但只讨论了进口商。

我想要实现的是制作一个可以导出纹理/颜色的 3d 可打印编辑器,因为已经有一个用于 3d 打印的 .stl 网格导出器。但是,我没有发现三个 js 的网格+颜色/纹理导出器 :(

【问题讨论】:

  • Brakebein 的解决方案很棒。关于纹理的纯色之一问题,是因为图像已在多边形的表面上重复出现。我尝试使用-clamp on 关闭重复模式,但没有成功。

标签: 3d three.js textures webgl .obj


【解决方案1】:

我稍微扩展了 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
	}

	}

};

【讨论】:

  • 哇!太酷了!当我测试这个时,我会告诉你它是怎么回事
  • 此代码引用了此行中不存在的全局 id 变量 materials[id] = material; 导致程序崩溃
  • 谢谢。该行应为materials[material.id] = material;
  • 只是为了让您知道,导出很顺利,只有一些小错误。不过,我必须进行一些自定义调整,因为我导出的不是纹理模型,而是纯色模型。从来没有,这是一个巨大的帮助作为起点
  • 这似乎正是我正在寻找的,但它如何处理纹理?我无法让它与它一起工作。
【解决方案2】:

以下是使用文件保护程序和 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 加载模型时,只会出现我使用三个.js 函数创建的内容。

【讨论】:

    猜你喜欢
    • 2017-01-24
    • 2020-07-05
    • 2015-01-07
    • 1970-01-01
    • 2021-07-20
    • 2018-10-18
    • 2020-11-11
    • 2020-10-05
    • 1970-01-01
    相关资源
    最近更新 更多