3d - Exporte un modelo texturizado de tres js a un archivo.OBJ con.MTL
three.js textures (1)
Me gustaría poder exportar un archivo obj como en este ejemplo http://threejs.org/examples/#webgl_exporter_obj
Sin embargo, me gustaría exportar el archivo .obj con las texturas correspondientes en el archivo de textura .mtl (he visto archivos obj con "usemtl someTextureNameFromMTL")
He visto esta pregunta, pero el exportador parece estar exportando solo malla. También encontré esta pregunta, pero eso solo se refiere al importador.
Lo que quería implementar es hacer un editor imprimible en 3D que también exporte texturas / colores, ya que ya hay un exportador de malla .stl para impresión en 3D. sin embargo, no he encontrado ningún exportador de mesh + color / texture para tres js :(
He extendido un poco el OBJExporter. Devolverá un objeto que contiene la parte .obj y la parte .mtl. Lo escribí sin pruebas, por lo que probablemente haya errores, pero espero que sea algo para empezar.
No he buscado todos los valores de mtl, solo utilicé algunos valores de estándares aparte de la información de color y textura. Quizás lo mejore más adelante. También debe tener en cuenta el nombre de archivo mtl. Actualmente, estoy escribiendo un nombre estático para la parte obj. Cuando guarde los archivos, el archivo mtl debe ser del mismo nombre que en el archivo obj declarado. De lo contrario 3ds max etc. no lo leerá.
/**
* @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
}
}
};