123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309 |
- /**
- * @author Garrett Johnson / http://gkjohnson.github.io/
- * https://github.com/gkjohnson/ply-exporter-js
- *
- * Usage:
- * var exporter = new THREE.PLYExporter();
- *
- * // second argument is an array of attributes to
- * // explicitly exclude from the file:
- * // 'color', 'uv', 'normal', 'index'
- * var data = exporter.parse(mesh, [ 'color' ]);
- *
- * Format Definition:
- * http://paulbourke.net/dataformats/ply/
- */
- THREE.PLYExporter = function () {};
- THREE.PLYExporter.prototype = {
- constructor: THREE.PLYExporter,
- parse: function ( object, excludeProperties ) {
- if ( Array.isArray( excludeProperties ) !== true ) {
- excludeProperties = [];
- }
- var geomToBufferGeom = new WeakMap();
- var includeNormals = false;
- var includeColors = false;
- var includeUVs = false;
- var includeIndices = true;
- object.traverse( function ( child ) {
- if ( child instanceof THREE.Mesh ) {
- var mesh = child;
- var geometry = mesh.geometry;
- if ( geometry instanceof THREE.Geometry ) {
- var bufferGeometry = geomToBufferGeom.get( geometry ) || new THREE.BufferGeometry().setFromObject( mesh );
- geomToBufferGeom.set( geometry, bufferGeometry );
- geometry = bufferGeometry;
- }
- if ( geometry instanceof THREE.BufferGeometry ) {
- var vertices = geometry.getAttribute( 'position' );
- var normals = geometry.getAttribute( 'normal' );
- var uvs = geometry.getAttribute( 'uv' );
- var colors = geometry.getAttribute( 'color' );
- var indices = geometry.getIndex();
- if ( vertices == null ) {
- return;
- }
- if ( normals != null ) includeNormals = true;
- if ( uvs != null ) includeUVs = true;
- if ( colors != null ) includeColors = true;
- }
- }
- } );
- includeNormals = includeNormals && excludeProperties.indexOf( 'normal' ) === - 1;
- includeColors = includeColors && excludeProperties.indexOf( 'color' ) === - 1;
- includeUVs = includeUVs && excludeProperties.indexOf( 'uv' ) === - 1;
- includeIndices = includeIndices && excludeProperties.indexOf( 'index' ) === - 1;
- // count the number of vertices
- var vertexCount = 0;
- var faceCount = 0;
- var vertexList = '';
- var faceList = '';
- var vertex = new THREE.Vector3();
- var normalMatrixWorld = new THREE.Matrix3();
- object.traverse( function ( child ) {
- if ( child instanceof THREE.Mesh ) {
- var mesh = child;
- var geometry = mesh.geometry;
- if ( geometry instanceof THREE.Geometry ) {
- geometry = geomToBufferGeom.get( geometry );
- }
- if ( geometry instanceof THREE.BufferGeometry ) {
- var vertices = geometry.getAttribute( 'position' );
- var normals = geometry.getAttribute( 'normal' );
- var uvs = geometry.getAttribute( 'uv' );
- var colors = geometry.getAttribute( 'color' );
- var indices = geometry.getIndex();
- normalMatrixWorld.getNormalMatrix( mesh.matrixWorld );
- if ( vertices == null ) {
- return;
- }
- // form each line
- for ( var i = 0, l = vertices.count; i < l; i ++ ) {
- vertex.x = vertices.getX( i );
- vertex.y = vertices.getY( i );
- vertex.z = vertices.getZ( i );
- vertex.applyMatrix4( mesh.matrixWorld );
- // Position information
- var line =
- vertex.x + ' ' +
- vertex.y + ' ' +
- vertex.z;
- // Normal information
- if ( includeNormals === true ) {
- if ( normals != null ) {
- vertex.x = normals.getX( i );
- vertex.y = normals.getY( i );
- vertex.z = normals.getZ( i );
- vertex.applyMatrix3( normalMatrixWorld );
- line += ' ' +
- vertex.x + ' ' +
- vertex.y + ' ' +
- vertex.z;
- } else {
- line += ' 0 0 0';
- }
- }
- // UV information
- if ( includeUVs === true ) {
- if ( uvs != null ) {
- line += ' ' +
- uvs.getX( i ) + ' ' +
- uvs.getY( i );
- } else if ( includeUVs !== false ) {
- line += ' 0 0';
- }
- }
- // Color information
- if ( includeColors === true ) {
- if ( colors != null ) {
- line += ' ' +
- Math.floor( colors.getX( i ) * 255 ) + ' ' +
- Math.floor( colors.getY( i ) * 255 ) + ' ' +
- Math.floor( colors.getZ( i ) * 255 );
- } else {
- line += ' 255 255 255';
- }
- }
- vertexList += line + '\n';
- }
- // Create the face list
- if ( includeIndices === true ) {
- if ( indices !== null ) {
- for ( var i = 0, l = indices.count; i < l; i += 3 ) {
- faceList += `3 ${ indices.getX( i + 0 ) + vertexCount }`;
- faceList += ` ${ indices.getX( i + 1 ) + vertexCount }`;
- faceList += ` ${ indices.getX( i + 2 ) + vertexCount }\n`;
- }
- } else {
- for ( var i = 0, l = vertices.count; i < l; i += 3 ) {
- faceList += `3 ${ vertexCount + i } ${ vertexCount + i + 1 } ${ vertexCount + i + 2 }\n`;
- }
- }
- faceCount += indices ? indices.count / 3 : vertices.count / 3;
- }
- vertexCount += vertices.count;
- }
- }
- } );
- if ( includeIndices && faceCount !== Math.floor( faceCount ) ) {
- // point cloud meshes will not have an index array and may not have a
- // number of vertices that is divisble by 3 (and therefore representable
- // as triangles)
- console.error(
- 'PLYExporter: Failed to generate a valid PLY file with triangle indices because the ' +
- 'number of indices is not divisible by 3.'
- );
- return null;
- }
- var output =
- 'ply\n' +
- 'format ascii 1.0\n' +
- `element vertex ${vertexCount}\n` +
- // position
- 'property float x\n' +
- 'property float y\n' +
- 'property float z\n';
- if ( includeNormals === true ) {
- // normal
- output +=
- 'property float nx\n' +
- 'property float ny\n' +
- 'property float nz\n';
- }
- if ( includeUVs === true ) {
- // uvs
- output +=
- 'property float s\n' +
- 'property float t\n';
- }
- if ( includeColors === true ) {
- // colors
- output +=
- 'property uchar red\n' +
- 'property uchar green\n' +
- 'property uchar blue\n';
- }
- if ( includeIndices === true ) {
- // faces
- output +=
- `element face ${faceCount}\n` +
- 'property list uchar int vertex_index\n';
- }
- output +=
- 'end_header\n' +
- `${vertexList}\n` +
- ( includeIndices ? `${faceList}\n` : '' );
- return output;
- }
- };
|