From b481eec05b7a10af9a05449fbde62894b0bd0fb7 Mon Sep 17 00:00:00 2001 From: Mugen87 Date: Mon, 21 Mar 2016 17:19:22 +0100 Subject: [PATCH] OBJExporter: Use BufferGeometry instead of Geometry This commit changes OBJExporter so it handles BufferGeometry directly. --- examples/js/exporters/OBJExporter.js | 266 +++++++++++++++------------ examples/webgl_exporter_obj.html | 153 ++++++++------- 2 files changed, 235 insertions(+), 184 deletions(-) diff --git a/examples/js/exporters/OBJExporter.js b/examples/js/exporters/OBJExporter.js index 308c8ce6c8..2870feba58 100644 --- a/examples/js/exporters/OBJExporter.js +++ b/examples/js/exporters/OBJExporter.js @@ -2,224 +2,250 @@ * @author mrdoob / http://mrdoob.com/ */ -THREE.OBJExporter = function () {}; + THREE.OBJExporter = function () {}; -THREE.OBJExporter.prototype = { + THREE.OBJExporter.prototype = { - constructor: THREE.OBJExporter, + constructor: THREE.OBJExporter, - parse: function ( object ) { + parse: function ( object ) { - var output = ''; + var output = ''; - var indexVertex = 0; - var indexVertexUvs = 0; - var indexNormals = 0; + var indexVertex = 0; + var indexVertexUvs = 0; + var indexNormals = 0; - var faceVertexKeys = [ "a", "b", "c" ]; + var vertex = new THREE.Vector3(); + var normal = new THREE.Vector3(); + var uv = new THREE.Vector2(); - var parseMesh = function ( mesh ) { + var i, j, m, face = []; - var nbVertex = 0; - var nbVertexUvs = 0; - var nbNormals = 0; + var parseMesh = function ( mesh ) { - var geometry = mesh.geometry; + var nbVertex = 0; + var nbNormals = 0; + var nbVertexUvs = 0; - if ( geometry instanceof THREE.BufferGeometry ) { + var geometry = mesh.geometry; - geometry = new THREE.Geometry().fromBufferGeometry( geometry ); + var normalMatrixWorld = new THREE.Matrix3(); - } + if ( geometry instanceof THREE.Geometry ) { - if ( geometry instanceof THREE.Geometry ) { + geometry = new THREE.BufferGeometry().setFromObject( mesh ); - output += 'o ' + mesh.name + '\n'; + } - var vertices = geometry.vertices; + if ( geometry instanceof THREE.BufferGeometry ) { - for ( var i = 0, l = vertices.length; i < l; i ++ ) { + // shortcuts + var vertices = geometry.getAttribute( 'position' ); + var normals = geometry.getAttribute( 'normal' ); + var uvs = geometry.getAttribute( 'uv' ); + var indices = geometry.getIndex(); - var vertex = vertices[ i ].clone(); - vertex.applyMatrix4( mesh.matrixWorld ); + // name of the mesh object + output += 'o ' + mesh.name + '\n'; - output += 'v ' + vertex.x + ' ' + vertex.y + ' ' + vertex.z + '\n'; + // vertices - nbVertex ++; + if( vertices !== undefined ) { - } + for ( i = 0; i < vertices.count ; i ++, nbVertex++ ) { - // uvs + vertex.x = vertices.getX( i ); + vertex.y = vertices.getY( i ); + vertex.z = vertices.getZ( i ); - var faces = geometry.faces; - var faceVertexUvs = geometry.faceVertexUvs[ 0 ]; - var hasVertexUvs = faces.length === faceVertexUvs.length; + // transfrom the vertex to world space + vertex.applyMatrix4( mesh.matrixWorld ); - if ( hasVertexUvs ) { + // transform the vertex to export format + output += 'v ' + vertex.x + ' ' + vertex.y + ' ' + vertex.z + '\n'; - for ( var i = 0, l = faceVertexUvs.length; i < l; i ++ ) { + } - var vertexUvs = faceVertexUvs[ i ]; + } - for ( var j = 0, jl = vertexUvs.length; j < jl; j ++ ) { + // uvs - var uv = vertexUvs[ j ]; + if( uvs !== undefined ) { - output += 'vt ' + uv.x + ' ' + uv.y + '\n'; + for ( i = 0; i < uvs.count ; i ++, nbVertexUvs++ ) { - nbVertexUvs ++; + uv.x = uvs.getX( i ); + uv.y = uvs.getY( i ); - } + // transform the uv to export format + output += 'vt ' + uv.x + ' ' + uv.y + '\n'; - } + } - } + } - // normals + // normals - var normalMatrixWorld = new THREE.Matrix3(); - normalMatrixWorld.getNormalMatrix( mesh.matrixWorld ); + if( normals !== undefined ) { - for ( var i = 0, l = faces.length; i < l; i ++ ) { + normalMatrixWorld.getNormalMatrix( mesh.matrixWorld ); - var face = faces[ i ]; - var vertexNormals = face.vertexNormals; + for ( i = 0; i < normals.count ; i ++, nbNormals++ ) { - if ( vertexNormals.length === 3 ) { + normal.x = normals.getX( i ); + normal.y = normals.getY( i ); + normal.z = normals.getZ( i ); - for ( var j = 0, jl = vertexNormals.length; j < jl; j ++ ) { + // transfrom the normal to world space + normal.applyMatrix3( normalMatrixWorld ); - var normal = vertexNormals[ j ].clone(); - normal.applyMatrix3( normalMatrixWorld ); + // transform the normal to export format + output += 'vn ' + normal.x + ' ' + normal.y + ' ' + normal.z + '\n'; - output += 'vn ' + normal.x + ' ' + normal.y + ' ' + normal.z + '\n'; + } - nbNormals ++; + } - } + // faces - } else { + if( indices !== null ) { - var normal = face.normal.clone(); - normal.applyMatrix3( normalMatrixWorld ); + for ( i = 0; i < indices.count ; i += 3 ) { - for ( var j = 0; j < 3; j ++ ) { + for( m = 0; m < 3; m ++ ){ - output += 'vn ' + normal.x + ' ' + normal.y + ' ' + normal.z + '\n'; + j = indices.getX( i + m ) + 1; - nbNormals ++; + face[ m ] = ( indexVertex + j ) + '/' + ( uvs ? ( indexVertexUvs + j ) : '' ) + '/' + ( indexNormals + j ); - } + } - } + // transform the face to export format + output += 'f ' + face.join( ' ' ) + "\n"; - } + } - // faces - var indices = []; + } else { - for ( var i = 0, j = 1, l = faces.length; i < l; i ++, j += 3 ) { + for ( i = 0; i < vertices.count ; i += 3 ) { - var face = faces[ i ]; + for( m = 0; m < 3; m ++ ){ - for ( var m = 0; m < 3; m ++ ) { + j = i + m + 1; - indices[ m ] = ( indexVertex + face[ faceVertexKeys[ m ] ] + 1 ) + '/' + ( hasVertexUvs ? ( indexVertexUvs + j + m + 1 ) : '' ) + '/' + ( indexNormals + j + m + 1 ); + face[ m ] = ( indexVertex + j ) + '/' + ( uvs ? ( indexVertexUvs + j ) : '' ) + '/' + ( indexNormals + j ); - } + } - output += 'f ' + indices.join( ' ' ) + "\n"; + // transform the face to export format + output += 'f ' + face.join( ' ' ) + "\n"; - } + } - } else { + } - console.warn( 'THREE.OBJExporter.parseMesh(): geometry type unsupported', mesh ); + } else { - } + console.warn( 'THREE.OBJExporter.parseMesh(): geometry type unsupported', geometry ); - // update index - indexVertex += nbVertex; - indexVertexUvs += nbVertexUvs; - indexNormals += nbNormals; + } - }; + // update index + indexVertex += nbVertex; + indexVertexUvs += nbVertexUvs; + indexNormals += nbNormals; - var parseLine = function( line ) { + }; - var geometry = line.geometry; - var type = line.type; + var parseLine = function( line ) { - if ( geometry instanceof THREE.BufferGeometry ) { + var geometry = line.geometry; + var type = line.type; - geometry = new THREE.Geometry().fromBufferGeometry( geometry ); + if ( geometry instanceof THREE.Geometry ) { - } + geometry = new THREE.BufferGeometry().setFromObject( line ); - if ( geometry instanceof THREE.Geometry ) { + } - output += 'o ' + line.name + '\n'; + if ( geometry instanceof THREE.BufferGeometry ) { - var vertices = geometry.vertices; + // shortcuts + var vertices = geometry.getAttribute( 'position' ); + var indices = geometry.getIndex(); - for ( var i = 0, l = vertices.length; i < l; i++ ) { + // name of the line object + output += 'o ' + line.name + '\n'; - var vertex = vertices[ i ].clone(); - vertex.applyMatrix4( line.matrixWorld ); + if( vertices !== undefined ) { - output += 'v ' + vertex.x + ' ' + vertex.y + ' ' + vertex.z + '\n'; + for ( i = 0; i < vertices.count ; i ++ ) { - } + vertex.x = vertices.getX( i ); + vertex.y = vertices.getY( i ); + vertex.z = vertices.getZ( i ); - if ( type === 'Line' ) { + // transfrom the vertex to world space + vertex.applyMatrix4( line.matrixWorld ); - output += 'l '; + // transform the vertex to export format + output += 'v ' + vertex.x + ' ' + vertex.y + ' ' + vertex.z + '\n'; - for ( var j = 1, m = vertices.length; j <= m; j++ ) { + } - output += j + ' '; + } - } + if ( type === 'Line' ) { - output += '\n'; + output += 'l '; - } + for ( j = 1; j <= vertices.count; j++ ) { - if ( type === 'LineSegments' ) { + output += j + ' '; - for ( var j = 1, k = j + 1, m = vertices.length; j < m; j += 2, k = j + 1 ) { + } - output += 'l ' + j + ' ' + k + '\n'; + output += '\n'; - } + } - } + if ( type === 'LineSegments' ) { - } else { + for ( j = 1, k = j + 1; j < vertices.count; j += 2, k = j + 1 ) { - console.warn('THREE.OBJExporter.parseLine(): geometry type unsupported', line); + output += 'l ' + j + ' ' + k + '\n'; - } - }; + } - object.traverse( function ( child ) { + } - if ( child instanceof THREE.Mesh ) { + } else { - parseMesh( child ); + console.warn('THREE.OBJExporter.parseLine(): geometry type unsupported', geometry ); - } + } - if ( child instanceof THREE.Line ) { + }; - parseLine( child ); + object.traverse( function ( child ) { - } + if ( child instanceof THREE.Mesh ) { - } ); + parseMesh( child ); - return output; + } - } + if ( child instanceof THREE.Line ) { -}; + parseLine( child ); + + } + + } ); + + return output; + + } + + }; diff --git a/examples/webgl_exporter_obj.html b/examples/webgl_exporter_obj.html index 241d7e33dc..cc7f3194f1 100644 --- a/examples/webgl_exporter_obj.html +++ b/examples/webgl_exporter_obj.html @@ -70,77 +70,93 @@ var exportButton, floatingDiv; var mouseX = 0, mouseY = 0; - function exportToObj () - { - var exporter = new THREE.OBJExporter (); - var result = exporter.parse (scene); + function exportToObj() { + + var exporter = new THREE.OBJExporter(); + var result = exporter.parse( scene ); floatingDiv.style.display = 'block'; - floatingDiv.innerHTML = result.split ('\n').join ('
'); + floatingDiv.innerHTML = result.split( '\n' ).join ( '
' ); + } - function addGeometry (type) - { - for (var i = 0; i < scene.children.length; i++) { - var current = scene.children[i]; - if (current instanceof THREE.Mesh) { - current.geometry.dispose (); - scene.remove (current); + function addGeometry( type ) { + + for( var i = 0; i < scene.children.length; i++ ) { + + var current = scene.children[ i ]; + + if( current instanceof THREE.Mesh ) { + + current.geometry.dispose(); + scene.remove( current ); i--; + } + } - console.log (renderer.info); - - if (type == 1) { - var material = new THREE.MeshLambertMaterial ( { color : 0x00cc00 } ); - var geometry = new THREE.Geometry (); - geometry.vertices.push (new THREE.Vector3 (-50, -50, 0)); - geometry.vertices.push (new THREE.Vector3 (50, -50, 0)); - geometry.vertices.push (new THREE.Vector3 (50, 50, 0)); - var face = new THREE.Face3 (0, 1, 2); - geometry.faces.push (face); - geometry.computeFaceNormals (); + if ( type === 1 ) { + + var material = new THREE.MeshLambertMaterial( { color : 0x00cc00 } ); + + var geometry = new THREE.Geometry(); + geometry.vertices.push( new THREE.Vector3( -50, -50, 0 ) ); + geometry.vertices.push( new THREE.Vector3( 50, -50, 0 ) ); + geometry.vertices.push( new THREE.Vector3( 50, 50, 0 ) ); + var face = new THREE.Face3( 0, 1, 2 ); + geometry.faces.push( face ); + geometry.computeFaceNormals(); + scene.add( new THREE.Mesh( geometry, material ) ); - } else if (type == 2) { - var material = new THREE.MeshLambertMaterial ( { color : 0x00cc00 } ); - var geometry = new THREE.BoxGeometry( 100, 100, 100 ); + + + } else if ( type === 2 ) { + + var material = new THREE.MeshLambertMaterial( { color : 0x00cc00 } ); + var geometry = new THREE.BoxBufferGeometry( 100, 100, 100 ); scene.add( new THREE.Mesh( geometry, material ) ); - } else if (type == 3) { - var material = new THREE.MeshLambertMaterial ( { color : 0x00cc00 } ); - var geometry = new THREE.CylinderGeometry( 50, 50, 100, 30, 1 ); + + } else if ( type === 3 ) { + + var material = new THREE.MeshLambertMaterial( { color : 0x00cc00 } ); + var geometry = new THREE.CylinderBufferGeometry( 50, 50, 100, 30, 1 ); scene.add( new THREE.Mesh( geometry, material ) ); - } else if (type == 4 || type == 5) { - var material = new THREE.MeshLambertMaterial ( { color : 0x00cc00 } ); - - var geometry = new THREE.Geometry (); - geometry.vertices.push (new THREE.Vector3 (-50, -50, 0)); - geometry.vertices.push (new THREE.Vector3 (50, -50, 0)); - geometry.vertices.push (new THREE.Vector3 (50, 50, 0)); - geometry.faces.push (new THREE.Face3 (0, 1, 2)); - geometry.computeFaceNormals (); + + } else if ( type === 4 || type === 5 ) { + + var material = new THREE.MeshLambertMaterial( { color : 0x00cc00 } ); + + var geometry = new THREE.Geometry(); + geometry.vertices.push( new THREE.Vector3( -50, -50, 0 ) ); + geometry.vertices.push( new THREE.Vector3( 50, -50, 0 ) ); + geometry.vertices.push( new THREE.Vector3( 50, 50, 0 ) ); + var face = new THREE.Face3( 0, 1, 2 ); + geometry.faces.push( face ); + geometry.computeFaceNormals(); + var mesh = new THREE.Mesh( geometry, material ); mesh.position.x = -200; - if (type == 5) { - mesh.rotation.y = Math.PI / 4.0; - } scene.add( mesh ); - var geometry2 = new THREE.BoxGeometry( 100, 100, 100 ); + var geometry2 = new THREE.BoxBufferGeometry( 100, 100, 100 ); var mesh2 = new THREE.Mesh( geometry2, material ); - if (type == 5) { - mesh2.rotation.y = Math.PI / 4.0; - } scene.add( mesh2 ); - var geometry3 = new THREE.CylinderGeometry( 50, 50, 100, 30, 1 ); + var geometry3 = new THREE.CylinderBufferGeometry( 50, 50, 100, 30, 1 ); var mesh3 = new THREE.Mesh( geometry3, material ); - if (type == 5) { + mesh3.position.x = 200; + scene.add( mesh3 ); + + if ( type === 5 ) { + + mesh.rotation.y = Math.PI / 4.0; + mesh2.rotation.y = Math.PI / 4.0; mesh3.rotation.y = Math.PI / 4.0; + } - mesh3.position.x = 200; - scene.add( mesh3 ); } + } function init() { @@ -151,48 +167,57 @@ document.body.appendChild( renderer.domElement ); camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 ); - camera.position.set (0, 0, 400); + camera.position.set( 0, 0, 400 ); scene = new THREE.Scene(); light = new THREE.DirectionalLight( 0xffffff ); scene.add( light ); - addGeometry (1); + addGeometry( 1 ); window.addEventListener( 'click', onWindowClick, false ); window.addEventListener( 'resize', onWindowResize, false ); document.addEventListener( 'mousemove', onDocumentMouseMove, false ); document.addEventListener( 'mouseover', onDocumentMouseMove, false ); - document.getElementById( 'triangle' ).addEventListener( 'click', function() { addGeometry (1); }); - document.getElementById( 'cube' ).addEventListener( 'click', function() { addGeometry (2); }); - document.getElementById( 'cylinder' ).addEventListener( 'click', function() { addGeometry (3); }); - document.getElementById( 'both' ).addEventListener( 'click', function() { addGeometry (4); }); - document.getElementById( 'transformed' ).addEventListener( 'click', function() { addGeometry (5); }); + document.getElementById( 'triangle' ).addEventListener( 'click', function() { addGeometry( 1 ); } ); + document.getElementById( 'cube' ).addEventListener( 'click', function() { addGeometry( 2 ); } ); + document.getElementById( 'cylinder' ).addEventListener( 'click', function() { addGeometry( 3 ); } ); + document.getElementById( 'both' ).addEventListener( 'click', function() { addGeometry( 4 ); } ); + document.getElementById( 'transformed' ).addEventListener( 'click', function() { addGeometry( 5 ); } ); exportButton = document.getElementById( 'export' ); - exportButton.addEventListener( 'click', function() { exportToObj (); }); + exportButton.addEventListener( 'click', function() { exportToObj(); }); - floatingDiv = document.createElement ('div'); + floatingDiv = document.createElement( 'div' ); floatingDiv.className = 'floating'; - document.body.appendChild (floatingDiv); + document.body.appendChild( floatingDiv ); + } - function onWindowClick(event) { + function onWindowClick( event ) { var needToClose = true; var target = event.target; - while (target !== null) { - if (target === floatingDiv || target == exportButton) { + + while( target !== null ) { + + if ( target === floatingDiv || target === exportButton ) { + needToClose = false; break; + } + target = target.parentElement; + } - if (needToClose) { + if ( needToClose ) { + floatingDiv.style.display = 'none'; + } } @@ -223,7 +248,7 @@ camera.position.y += ( -mouseY - camera.position.y ) * .05; camera.lookAt( scene.position ); - light.position.set( camera.position.x, camera.position.y, camera.position.z ).normalize (); + light.position.set( camera.position.x, camera.position.y, camera.position.z ).normalize(); renderer.render( scene, camera ); } -- GitLab