提交 b481eec0 编写于 作者: M Mugen87

OBJExporter: Use BufferGeometry instead of Geometry

This commit changes OBJExporter so it handles BufferGeometry directly.
上级 8121b976
...@@ -2,224 +2,250 @@ ...@@ -2,224 +2,250 @@
* @author mrdoob / http://mrdoob.com/ * @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 indexVertex = 0;
var indexVertexUvs = 0; var indexVertexUvs = 0;
var indexNormals = 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 parseMesh = function ( mesh ) {
var nbVertexUvs = 0;
var nbNormals = 0;
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(); // name of the mesh object
vertex.applyMatrix4( mesh.matrixWorld ); 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; // transfrom the vertex to world space
var faceVertexUvs = geometry.faceVertexUvs[ 0 ]; vertex.applyMatrix4( mesh.matrixWorld );
var hasVertexUvs = faces.length === faceVertexUvs.length;
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(); if( normals !== undefined ) {
normalMatrixWorld.getNormalMatrix( mesh.matrixWorld );
for ( var i = 0, l = faces.length; i < l; i ++ ) { normalMatrixWorld.getNormalMatrix( mesh.matrixWorld );
var face = faces[ i ]; for ( i = 0; i < normals.count ; i ++, nbNormals++ ) {
var vertexNormals = face.vertexNormals;
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(); // transform the normal to export format
normal.applyMatrix3( normalMatrixWorld ); 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(); for ( i = 0; i < indices.count ; i += 3 ) {
normal.applyMatrix3( normalMatrixWorld );
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 } else {
var indices = [];
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 parseLine = function( line ) {
var type = line.type;
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(); if( vertices !== undefined ) {
vertex.applyMatrix4( line.matrixWorld );
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;
}
};
...@@ -70,77 +70,93 @@ ...@@ -70,77 +70,93 @@
var exportButton, floatingDiv; var exportButton, floatingDiv;
var mouseX = 0, mouseY = 0; var mouseX = 0, mouseY = 0;
function exportToObj () function exportToObj() {
{
var exporter = new THREE.OBJExporter (); var exporter = new THREE.OBJExporter();
var result = exporter.parse (scene); var result = exporter.parse( scene );
floatingDiv.style.display = 'block'; floatingDiv.style.display = 'block';
floatingDiv.innerHTML = result.split ('\n').join ('<br />'); floatingDiv.innerHTML = result.split( '\n' ).join ( '<br />' );
} }
function addGeometry (type) function addGeometry( type ) {
{
for (var i = 0; i < scene.children.length; i++) { for( var i = 0; i < scene.children.length; i++ ) {
var current = scene.children[i];
if (current instanceof THREE.Mesh) { var current = scene.children[ i ];
current.geometry.dispose ();
scene.remove (current); if( current instanceof THREE.Mesh ) {
current.geometry.dispose();
scene.remove( current );
i--; i--;
} }
} }
console.log (renderer.info); if ( type === 1 ) {
if (type == 1) { var material = new THREE.MeshLambertMaterial( { color : 0x00cc00 } );
var material = new THREE.MeshLambertMaterial ( { color : 0x00cc00 } );
var geometry = new THREE.Geometry (); 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.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); var face = new THREE.Face3( 0, 1, 2 );
geometry.faces.push (face); geometry.faces.push( face );
geometry.computeFaceNormals (); geometry.computeFaceNormals();
scene.add( new THREE.Mesh( geometry, material ) ); 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 ) ); scene.add( new THREE.Mesh( geometry, material ) );
} else if (type == 3) {
var material = new THREE.MeshLambertMaterial ( { color : 0x00cc00 } ); } else if ( type === 3 ) {
var geometry = new THREE.CylinderGeometry( 50, 50, 100, 30, 1 );
var material = new THREE.MeshLambertMaterial( { color : 0x00cc00 } );
var geometry = new THREE.CylinderBufferGeometry( 50, 50, 100, 30, 1 );
scene.add( new THREE.Mesh( geometry, material ) ); scene.add( new THREE.Mesh( geometry, material ) );
} else if (type == 4 || type == 5) {
var material = new THREE.MeshLambertMaterial ( { color : 0x00cc00 } ); } else if ( type === 4 || type === 5 ) {
var geometry = new THREE.Geometry (); var material = new THREE.MeshLambertMaterial( { color : 0x00cc00 } );
geometry.vertices.push (new THREE.Vector3 (-50, -50, 0));
geometry.vertices.push (new THREE.Vector3 (50, -50, 0)); var geometry = new THREE.Geometry();
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.vertices.push( new THREE.Vector3( 50, -50, 0 ) );
geometry.computeFaceNormals (); 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 ); var mesh = new THREE.Mesh( geometry, material );
mesh.position.x = -200; mesh.position.x = -200;
if (type == 5) {
mesh.rotation.y = Math.PI / 4.0;
}
scene.add( mesh ); 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 ); var mesh2 = new THREE.Mesh( geometry2, material );
if (type == 5) {
mesh2.rotation.y = Math.PI / 4.0;
}
scene.add( mesh2 ); 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 ); 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.rotation.y = Math.PI / 4.0;
} }
mesh3.position.x = 200;
scene.add( mesh3 );
} }
} }
function init() { function init() {
...@@ -151,48 +167,57 @@ ...@@ -151,48 +167,57 @@
document.body.appendChild( renderer.domElement ); document.body.appendChild( renderer.domElement );
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 ); 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(); scene = new THREE.Scene();
light = new THREE.DirectionalLight( 0xffffff ); light = new THREE.DirectionalLight( 0xffffff );
scene.add( light ); scene.add( light );
addGeometry (1); addGeometry( 1 );
window.addEventListener( 'click', onWindowClick, false ); window.addEventListener( 'click', onWindowClick, false );
window.addEventListener( 'resize', onWindowResize, false ); window.addEventListener( 'resize', onWindowResize, false );
document.addEventListener( 'mousemove', onDocumentMouseMove, false ); document.addEventListener( 'mousemove', onDocumentMouseMove, false );
document.addEventListener( 'mouseover', onDocumentMouseMove, false ); document.addEventListener( 'mouseover', onDocumentMouseMove, false );
document.getElementById( 'triangle' ).addEventListener( 'click', function() { addGeometry (1); }); document.getElementById( 'triangle' ).addEventListener( 'click', function() { addGeometry( 1 ); } );
document.getElementById( 'cube' ).addEventListener( 'click', function() { addGeometry (2); }); document.getElementById( 'cube' ).addEventListener( 'click', function() { addGeometry( 2 ); } );
document.getElementById( 'cylinder' ).addEventListener( 'click', function() { addGeometry (3); }); document.getElementById( 'cylinder' ).addEventListener( 'click', function() { addGeometry( 3 ); } );
document.getElementById( 'both' ).addEventListener( 'click', function() { addGeometry (4); }); document.getElementById( 'both' ).addEventListener( 'click', function() { addGeometry( 4 ); } );
document.getElementById( 'transformed' ).addEventListener( 'click', function() { addGeometry (5); }); document.getElementById( 'transformed' ).addEventListener( 'click', function() { addGeometry( 5 ); } );
exportButton = document.getElementById( 'export' ); 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'; floatingDiv.className = 'floating';
document.body.appendChild (floatingDiv); document.body.appendChild( floatingDiv );
} }
function onWindowClick(event) { function onWindowClick( event ) {
var needToClose = true; var needToClose = true;
var target = event.target; var target = event.target;
while (target !== null) {
if (target === floatingDiv || target == exportButton) { while( target !== null ) {
if ( target === floatingDiv || target === exportButton ) {
needToClose = false; needToClose = false;
break; break;
} }
target = target.parentElement; target = target.parentElement;
} }
if (needToClose) { if ( needToClose ) {
floatingDiv.style.display = 'none'; floatingDiv.style.display = 'none';
} }
} }
...@@ -223,7 +248,7 @@ ...@@ -223,7 +248,7 @@
camera.position.y += ( -mouseY - camera.position.y ) * .05; camera.position.y += ( -mouseY - camera.position.y ) * .05;
camera.lookAt( scene.position ); 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 ); renderer.render( scene, camera );
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册