浏览代码

Removed old UTF8 format things.

Doing this in multiple steps not to confuse git.
alteredq 13 年之前
父节点
当前提交
dd33a5e665

+ 0 - 328
examples/js/loaders/UTF8Loader.js

@@ -1,328 +0,0 @@
-/**
- * Loader for UTF8 encoded models generated by:
- *	http://code.google.com/p/webgl-loader/
- *
- * Limitations:
- *  - number of vertices < 65536 (this is after optimizations in compressor, input OBJ may have even less)
- *	- models must have normals and texture coordinates
- *  - texture coordinates must be only from <0,1>
- *  - no materials support yet
- *  - models are scaled and offset (copy numbers from compressor and use them as parameters in UTF8Loader.load() )
- *
- * @author alteredq / http://alteredqualia.com/
- * @author won3d / http://twitter.com/won3d
- */
-
-THREE.UTF8Loader = function () {};
-
-THREE.UTF8Loader.prototype.load = function ( url, callback, metadata ) {
-
-	var xhr = new XMLHttpRequest();
-	var callbackProgress = null;
-	var length = 0;
-
-	xhr.onreadystatechange = function() {
-
-		if ( xhr.readyState == 4 ) {
-
-			if ( xhr.status == 200 || xhr.status == 0 ) {
-
-				var geometry = THREE.UTF8Loader.prototype.parse( xhr.responseText, metadata );
-				callback( geometry );
-
-			} else {
-
-				console.error( "THREE.UTF8Loader: Couldn't load [" + url + "] [" + xhr.status + "]" );
-
-			}
-
-		} else if ( xhr.readyState == 3 ) {
-
-			if ( callbackProgress ) {
-
-				if ( length == 0 ) {
-
-					length = xhr.getResponseHeader( "Content-Length" );
-
-				}
-
-				callbackProgress( { total: length, loaded: xhr.responseText.length } );
-
-			}
-
-		} else if ( xhr.readyState == 2 ) {
-
-			length = xhr.getResponseHeader( "Content-Length" );
-
-		}
-
-	}
-
-	xhr.open( "GET", url, true );
-	xhr.send( null );
-
-};
-
-// UTF-8 decoder from webgl-loader
-// http://code.google.com/p/webgl-loader/
-
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License"); you
-// may not use this file except in compliance with the License. You
-// may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-// implied. See the License for the specific language governing
-// permissions and limitations under the License.
-
-THREE.UTF8Loader.prototype.decompressMesh = function ( str ) {
-
-	var num_verts = str.charCodeAt( 0 );
-
-	if ( num_verts >= 0xE000 ) {
-
-		num_verts -= 0x0800;
-
-	}
-
-	num_verts ++;
-
-	var attribs_out = new Float32Array( 8 * num_verts );
-
-	var offset = 1;
-
-	for ( var i = 0; i < 8; i ++ ) {
-
-		var prev_attrib = 0;
-
-		for ( var j = 0; j < num_verts; ++ j ) {
-
-			var code = str.charCodeAt( j + offset );
-
-			prev_attrib += ( code >> 1 ) ^ ( - ( code & 1 ) );
-
-			attribs_out[ 8 * j + i ] = prev_attrib;
-
-		}
-
-		offset += num_verts;
-
-	}
-
-	var num_indices = str.length - offset;
-
-	var indices_out = new Uint16Array( num_indices );
-
-	var index_high_water_mark = 0;
-
-	for ( var i = 0; i < num_indices; i ++ ) {
-
-		var code = str.charCodeAt( i + offset );
-
-		indices_out[ i ] = index_high_water_mark - code;
-
-		if ( code == 0 ) {
-
-			index_high_water_mark ++;
-
-		}
-
-	}
-
-	return [ attribs_out, indices_out ];
-
-};
-
-THREE.UTF8Loader.prototype.parse = function ( data, metadata ) {
-
-	if ( metadata === undefined ) metadata = {};
-
-	var scale = metadata.scale !== undefined ? metadata.scale : 1;
-	var offsetX = metadata.offsetX !== undefined ? metadata.offsetX : 0;
-	var offsetY = metadata.offsetY !== undefined ? metadata.offsetY : 0;
-	var offsetZ = metadata.offsetZ !== undefined ? metadata.offsetZ : 0;
-
-	var Model = function ( texture_path ) {
-
-		//var s = (new Date).getTime();
-
-		var scope = this;
-
-		scope.materials = [];
-
-		THREE.Geometry.call( this );
-
-		var buffers = THREE.UTF8Loader.prototype.decompressMesh( data );
-
-		var normals = [],
-			uvs = [];
-
-		init_vertices( buffers[ 0 ], 8, 0 );
-		init_uvs( buffers[ 0 ], 8, 3 );
-		init_normals( buffers[ 0 ], 8, 5 );
-
-		init_faces( buffers[ 1 ] );
-
-		this.computeCentroids();
-		this.computeFaceNormals();
-		//this.computeTangents();
-
-		//var e = (new Date).getTime();
-
-		//console.log( "utf8 data parse time: " + (e-s) + " ms" );
-
-		function init_vertices( data, stride, offset ) {
-
-			var i, x, y, z,
-				end = data.length;
-
-			for( i = offset; i < end; i += stride ) {
-
-				x = data[ i ];
-				y = data[ i + 1 ];
-				z = data[ i + 2 ];
-
-				// fix scale and offsets
-
-				x = ( x / 16383 ) * scale;
-				y = ( y / 16383 ) * scale;
-				z = ( z / 16383 ) * scale;
-
-				x += offsetX;
-				y += offsetY;
-				z += offsetZ;
-
-				vertex( scope, x, y, z );
-
-			}
-
-		};
-
-		function init_normals( data, stride, offset ) {
-
-			var i, x, y, z,
-				end = data.length;
-
-			for( i = offset; i < end; i += stride ) {
-
-				x = data[ i ];
-				y = data[ i + 1 ];
-				z = data[ i + 2 ];
-
-				// normalize to <-1,1>
-
-				x = ( x - 512 ) / 511;
-				y = ( y - 512 ) / 511;
-				z = ( z - 512 ) / 511;
-
-				normals.push( x, y, z );
-
-			}
-
-		};
-
-		function init_uvs( data, stride, offset ) {
-
-			var i, u, v,
-				end = data.length;
-
-			for( i = offset; i < end; i += stride ) {
-
-				u = data[ i ];
-				v = data[ i + 1 ];
-
-				// normalize to <0,1>
-
-				u /= 1023;
-				v /= 1023;
-
-				uvs.push( u, v );
-
-			}
-
-		};
-
-		function init_faces( indices ) {
-
-			var i,
-				a, b, c,
-				u1, v1, u2, v2, u3, v3,
-				m,
-				end = indices.length;
-
-			m = 0; // all faces defaulting to material 0
-
-			for( i = 0; i < end; i += 3 ) {
-
-				a = indices[ i ];
-				b = indices[ i + 1 ];
-				c = indices[ i + 2 ];
-
-				f3n( scope, normals, a, b, c, m, a, b, c );
-
-				u1 = uvs[ a * 2 ];
-				v1 = uvs[ a * 2 + 1 ];
-
-				u2 = uvs[ b * 2 ];
-				v2 = uvs[ b * 2 + 1 ];
-
-				u3 = uvs[ c * 2 ];
-				v3 = uvs[ c * 2 + 1 ];
-
-				uv3( scope.faceVertexUvs[ 0 ], u1, v1, u2, v2, u3, v3 );
-
-			}
-
-
-		}
-
-	};
-
-	function vertex ( scope, x, y, z ) {
-
-		scope.vertices.push( new THREE.Vector3( x, y, z ) );
-
-	};
-
-	function f3n ( scope, normals, a, b, c, mi, nai, nbi, nci ) {
-
-		var nax = normals[ nai * 3     ],
-			nay = normals[ nai * 3 + 1 ],
-			naz = normals[ nai * 3 + 2 ],
-
-			nbx = normals[ nbi * 3     ],
-			nby = normals[ nbi * 3 + 1 ],
-			nbz = normals[ nbi * 3 + 2 ],
-
-			ncx = normals[ nci * 3     ],
-			ncy = normals[ nci * 3 + 1 ],
-			ncz = normals[ nci * 3 + 2 ];
-
-		var na = new THREE.Vector3( nax, nay, naz ),
-			nb = new THREE.Vector3( nbx, nby, nbz ),
-			nc = new THREE.Vector3( ncx, ncy, ncz );
-
-		scope.faces.push( new THREE.Face3( a, b, c, [ na, nb, nc ], null, mi ) );
-
-	};
-
-	function uv3 ( where, u1, v1, u2, v2, u3, v3 ) {
-
-		var uv = [];
-		uv.push( new THREE.UV( u1, v1 ) );
-		uv.push( new THREE.UV( u2, v2 ) );
-		uv.push( new THREE.UV( u3, v3 ) );
-		where.push( uv );
-
-	};
-
-	Model.prototype = Object.create( THREE.Geometry.prototype );
-
-	return new Model();
-
-};

二进制
examples/models/utf8/ben.utf8


二进制
examples/models/utf8/hand.utf8


+ 0 - 2
examples/webgl_loader_scene.html

@@ -152,7 +152,6 @@
 		<script src="js/loaders/ctm/lzma.js"></script>
 		<script src="js/loaders/ctm/ctm.js"></script>
 		<script src="js/loaders/ctm/CTMLoader.js"></script>
-		<script src="js/loaders/UTF8Loader.js"></script>
 
 		<script src="js/Detector.js"></script>
 		<script src="js/Stats.js"></script>
@@ -334,7 +333,6 @@
 				var loader = new THREE.SceneLoader();
 
 				loader.addGeometryHandler( "ctm", THREE.CTMLoader );
-				loader.addGeometryHandler( "utf8", THREE.UTF8Loader );
 
 				loader.callbackSync = callbackSync;
 				loader.callbackProgress = callbackProgress;

+ 0 - 197
examples/webgl_loader_utf8.html

@@ -1,197 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-	<head>
-		<title>three.js webgl - io - UTF8 loader</title>
-		<meta charset="utf-8">
-		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
-		<style>
-			body {
-				font-family: Monospace;
-				background-color: #000;
-				color: #fff;
-				margin: 0px;
-				overflow: hidden;
-			}
-			#info {
-				color: #fff;
-				position: absolute;
-				top: 10px;
-				width: 100%;
-				text-align: center;
-				z-index: 100;
-				display:block;
-			}
-			#info a, .button { color: #f00; font-weight: bold; text-decoration: underline; cursor: pointer }
-		</style>
-	</head>
-
-	<body>
-		<div id="info">
-		<a href="http://github.com/mrdoob/three.js" target="_blank">three.js</a> -
-		<a href="http://code.google.com/p/webgl-loader/" target="_blank">UTF8 format</a> loader test -
-		models from <a href="http://www.sci.utah.edu/~wald/animrep/" target="_blank">The Utah 3D Animation Repository</a>
-		</div>
-
-		<script src="../build/three.min.js"></script>
-		<script src="js/loaders/UTF8Loader.js"></script>
-
-		<script src="js/Detector.js"></script>
-		<script src="js/Stats.js"></script>
-
-		<script>
-
-			var SCREEN_WIDTH = window.innerWidth;
-			var SCREEN_HEIGHT = window.innerHeight;
-
-			var FLOOR = -150;
-
-			var container, stats;
-
-			var camera, scene, renderer;
-
-			var mesh, zmesh, geometry;
-
-			var mouseX = 0, mouseY = 0;
-
-			var windowHalfX = window.innerWidth / 2;
-			var windowHalfY = window.innerHeight / 2;
-
-			document.addEventListener('mousemove', onDocumentMouseMove, false);
-
-			init();
-			animate();
-
-
-			function init() {
-
-				container = document.createElement( 'div' );
-				document.body.appendChild( container );
-
-				camera = new THREE.PerspectiveCamera( 20, SCREEN_WIDTH / SCREEN_HEIGHT, 1, 2000 );
-				camera.position.z = 800;
-
-				scene = new THREE.Scene();
-				scene.fog = new THREE.Fog( 0x000000, 800, 2000 );
-
-				var path = "textures/cube/SwedishRoyalCastle/";
-				var format = '.jpg';
-				var urls = [
-					path + 'px' + format, path + 'nx' + format,
-					path + 'py' + format, path + 'ny' + format,
-					path + 'pz' + format, path + 'nz' + format
-				];
-
-				reflectionCube = THREE.ImageUtils.loadTextureCube( urls );
-
-				// LIGHTS
-
-				var ambient = new THREE.AmbientLight( 0x221100 );
-				scene.add( ambient );
-
-				var directionalLight = new THREE.DirectionalLight( 0xffeedd );
-				directionalLight.position.set( 0, 0, 1 ).normalize();
-				scene.add( directionalLight );
-
-				// RENDERER
-
-				renderer = new THREE.WebGLRenderer();
-				renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
-
-				renderer.setClearColor( scene.fog.color, 1 );
-
-				renderer.domElement.style.position = "relative";
-				container.appendChild( renderer.domElement );
-
-				// STATS
-
-				stats = new Stats();
-				stats.domElement.style.position = 'absolute';
-				stats.domElement.style.top = '0px';
-				stats.domElement.style.zIndex = 100;
-				container.appendChild( stats.domElement );
-
-				var loader = new THREE.UTF8Loader();
-
-				loader.load( "models/utf8/hand.utf8", function ( geometry ) {
-
-					callbackModel( geometry, 400, 0xffffff, 125, FLOOR, 0 );
-
-				}, { scale: 0.815141, offsetX: -0.371823, offsetY: -0.011920, offsetZ: -0.416061 } );
-
-				loader.load( "models/utf8/ben.utf8", function ( geometry ) {
-
-					callbackModel( geometry, 400, 0xffaa00, -125, FLOOR, 0 );
-
-				}, { scale: 0.707192, offsetX: -0.109362, offsetY: -0.006435, offsetZ: -0.268751 } );
-
-				//
-
-				window.addEventListener( 'resize', onWindowResize, false );
-
-			}
-
-			function onWindowResize() {
-
-				windowHalfX = window.innerWidth / 2;
-				windowHalfY = window.innerHeight / 2;
-
-				camera.aspect = window.innerWidth / window.innerHeight;
-				camera.updateProjectionMatrix();
-
-				renderer.setSize( window.innerWidth, window.innerHeight );
-
-			}
-
-			function callbackModel( geometry, s, color, x, y, z ) {
-
-				var material = new THREE.MeshLambertMaterial( {
-					color: color,
-					map: THREE.ImageUtils.loadTexture( "textures/ash_uvgrid01.jpg" ),
-					envMap: reflectionCube,
-					combine: THREE.MixOperation,
-					reflectivity: 0.3
-				} );
-				//material.shading =  THREE.FlatShading;
-
-				var mesh = new THREE.Mesh( geometry, material );
-
-				mesh.position.set( x, y, z );
-				mesh.scale.set( s, s, s );
-
-				scene.add( mesh );
-
-			}
-
-			function onDocumentMouseMove( event ) {
-
-				mouseX = ( event.clientX - windowHalfX );
-				mouseY = ( event.clientY - windowHalfY );
-
-			}
-
-			//
-
-			function animate() {
-
-				requestAnimationFrame( animate );
-
-				render();
-				stats.update();
-
-			}
-
-			function render() {
-
-				camera.position.x += ( mouseX - camera.position.x ) * .05;
-				camera.position.y += ( - mouseY - camera.position.y ) * .05;
-
-				camera.lookAt( scene.position );
-
-				renderer.render( scene, camera );
-
-			}
-
-		</script>
-
-	</body>
-</html>

+ 0 - 37
utils/exporters/utf8/README

@@ -1,37 +0,0 @@
--------------------------
----- three.js README ----
--------------------------
-
-Slightly modified "mesh.h" so that compressor:
-
-- compiles with latest MinGW on Windows 64-bit
-  (had to replace %z size_t formatting option)
-
-- dumps to stderr scaling and offset parameters
-
-
-Also for convenience added pre-build executable for Windows.
-
-Latest version of compressor can be downloaded at webgl-loader repository:
-
-http://code.google.com/p/webgl-loader/
-
---------------------------------------------
----- Original README from webgl-loader -----
---------------------------------------------
-
-Usage: ./objcompress in.obj [out.utf8]
-
-        If 'out' is specified, then attempt to write out a compressed,
-        UTF-8 version to 'out.'
-
-        If not, write a JSON version to STDOUT.
-
-
-Building:
-
-Since there are no external dependences outside of the C/C++ standard
-libraries, you can pretty much build this however you please. I've
-included a cheeky way to do this on POSIX-like systems by including a
-build shell script at the top of the file itself. You can build by
-making the .cc file executable, and running it on the command line.

+ 0 - 1
utils/exporters/utf8/build.bat

@@ -1 +0,0 @@
-g++ objcompress.cc -O2 -Wall -o objcompress

+ 0 - 787
utils/exporters/utf8/mesh.h

@@ -1,787 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License"); you
-// may not use this file except in compliance with the License. You
-// may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-// implied. See the License for the specific language governing
-// permissions and limitations under the License.
-
-#ifndef WEBGL_LOADER_MESH_H_
-#define WEBGL_LOADER_MESH_H_
-
-#include <float.h>
-#include <math.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <map>
-#include <string>
-#include <utility>
-#include <vector>
-
-typedef unsigned short uint16;
-typedef short int16;
-
-typedef std::vector<float> AttribList;
-typedef std::vector<int> IndexList;
-typedef std::vector<uint16> QuantizedAttribList;
-
-struct DrawMesh {
-  // Interleaved vertex format:
-  //  3-D Position
-  //  3-D Normal
-  //  2-D TexCoord
-  // Note that these
-  AttribList interleaved_attribs;
-  // Indices are 0-indexed.
-  IndexList triangle_indices;
-};
-
-void DumpJsonFromQuantizedAttribs(const QuantizedAttribList& attribs) {
-  puts("var attribs = new Uint16Array([");
-  for (size_t i = 0; i < attribs.size(); i += 8) {
-    printf("%u,%hu,%hu,%hu,%hu,%hu,%hu,%hu,\n",
-           attribs[i + 0], attribs[i + 1], attribs[i + 2], attribs[i + 3],
-           attribs[i + 4], attribs[i + 5], attribs[i + 6], attribs[i + 7]);
-  }
-  puts("]);");
-}
-
-void DumpJsonFromInterleavedAttribs(const AttribList& attribs) {
-  puts("var attribs = new Float32Array([");
-  for (size_t i = 0; i < attribs.size(); i += 8) {
-    printf("%f,%f,%f,%f,%f,%f,%f,%f,\n",
-           attribs[i + 0], attribs[i + 1], attribs[i + 2], attribs[i + 3],
-           attribs[i + 4], attribs[i + 5], attribs[i + 6], attribs[i + 7]);
-  }
-  puts("]);");
-}
-
-void DumpJsonFromIndices(const IndexList& indices) {
-  puts("var indices = new Uint16Array([");
-  for (size_t i = 0; i < indices.size(); i += 3) {
-    printf("%d,%d,%d,\n", indices[i + 0], indices[i + 1], indices[i + 2]);
-  }
-  puts("]);");
-}
-
-// A short list of floats, useful for parsing a single vector
-// attribute.
-class ShortFloatList {
- public:
-  static const size_t kMaxNumFloats = 4;
-  ShortFloatList()
-      : size_(0) { }
-
-  // Parse up to kMaxNumFloats from C string.
-  size_t ParseLine(const char* line) {
-    for (size_ = 0; size_ != kMaxNumFloats; ++size_) {
-      char* endptr = NULL;
-      a_[size_] = strtof(line, &endptr);
-      if (endptr == NULL || line == endptr) break;
-      line = endptr;
-    }
-    return size_;
-  }
-
-  void AppendTo(AttribList* attribs) const {
-    attribs->insert(attribs->end(), a_, a_ + size_);
-  }
-
-  bool empty() const { return size_ == 0; }
-
-  size_t size() const { return size_; }
- private:
-  float a_[kMaxNumFloats];
-  size_t size_;
-};
-
-class IndexFlattener {
- public:
-  explicit IndexFlattener(size_t num_positions)
-      : count_(0),
-        table_(num_positions) {
-  }
-
-  int count() const { return count_; }
-
-  // Returns a pair of: < flattened index, newly inserted >.
-  std::pair<int, bool> GetFlattenedIndex(int position_index,
-                                         int texcoord_index,
-                                         int normal_index) {
-    // First, optimistically look up position_index in the table.
-    IndexType& index = table_[position_index];
-    if (index.position_or_flat == kIndexUnknown) {
-      // This is the first time we've seen this position in the table,
-      // so fill it. Since the table is indexed by position, we can
-      // use the position_or_flat_index field to store the flat index.
-      const int flat_index = count_++;
-      index.position_or_flat = flat_index;
-      index.texcoord = texcoord_index;
-      index.normal = normal_index;
-      return std::make_pair(flat_index, true);
-    } else if (index.position_or_flat == kIndexNotInTable) {
-      // There are multiple flattened indices at this position index,
-      // so resort to the map.
-      return GetFlattenedIndexFromMap(position_index,
-                                      texcoord_index,
-                                      normal_index);
-    } else if (index.texcoord == texcoord_index &&
-               index.normal == normal_index) {
-      // The other indices match, so we can use the value cached in
-      // the table.
-      return std::make_pair(index.position_or_flat, false);
-    }
-    // The other indices don't match, so we mark this table entry,
-    // and insert both the old and new indices into the map.
-    const IndexType old_index(position_index, index.texcoord, index.normal);
-    map_.insert(std::make_pair(old_index, index.position_or_flat));
-    index.position_or_flat = kIndexNotInTable;
-    const IndexType new_index(position_index, texcoord_index, normal_index);
-    const int flat_index = count_++;
-    map_.insert(std::make_pair(new_index, flat_index));
-    return std::make_pair(flat_index, true);
-  }
- private:
-  std::pair<int, bool> GetFlattenedIndexFromMap(int position_index,
-                                                int texcoord_index,
-                                                int normal_index) {
-    IndexType index(position_index, texcoord_index, normal_index);
-    MapType::iterator iter = map_.lower_bound(index);
-    if (iter == map_.end() || iter->first != index) {
-      const int flat_index = count_++;
-      map_.insert(iter, std::make_pair(index, flat_index));
-      return std::make_pair(flat_index, true);
-    } else {
-      return std::make_pair(iter->second, false);
-    }
-  }
-
-  static const int kIndexUnknown = -1;
-  static const int kIndexNotInTable = -2;
-
-  struct IndexType {
-    IndexType()
-        : position_or_flat(kIndexUnknown),
-          texcoord(kIndexUnknown),
-          normal(kIndexUnknown)
-    { }
-
-    IndexType(int position_index, int texcoord_index, int normal_index)
-        : position_or_flat(position_index),
-          texcoord(texcoord_index),
-          normal(normal_index)
-    { }
-
-    // I'm being tricky/lazy here. The table_ stores the flattened
-    // index in the first field, since it is indexed by position. The
-    // map_ stores position and uses this struct as a key to lookup the
-    // flattened index.
-    int position_or_flat;
-    int texcoord;
-    int normal;
-
-    // An ordering for std::map.
-    bool operator<(const IndexType& that) const {
-      if (position_or_flat == that.position_or_flat) {
-        if (texcoord == that.texcoord) {
-          return normal < that.normal;
-        } else {
-          return texcoord < that.texcoord;
-        }
-      } else {
-        return position_or_flat < that.position_or_flat;
-      }
-    }
-
-    bool operator==(const IndexType& that) const {
-      return position_or_flat == that.position_or_flat &&
-          texcoord == that.texcoord && normal == that.normal;
-    }
-
-    bool operator!=(const IndexType& that) const {
-      return !operator==(that);
-    }
-  };
-  typedef std::map<IndexType, int> MapType;
-
-  int count_;
-  std::vector<IndexType> table_;
-  MapType map_;
-};
-
-// TODO: consider splitting this into a low-level parser and a high-level
-// object.
-class WavefrontObjFile {
- public:
-  struct Group {
-    std::string name;
-    size_t start, end;
-  };
-
-  typedef std::vector<Group> GroupList;
-
-  explicit WavefrontObjFile(FILE* fp) {
-    ParseFile(fp);
-  };
-
-  const GroupList& groups() const { return groups_; }
-
-  // Populate draw_meshes.
-  void CreateDrawMeshes(std::vector<DrawMesh>* draw_meshes) {
-    draw_meshes->push_back(DrawMesh());
-    DrawMesh& draw_mesh = draw_meshes->back();
-    IndexFlattener flattener(positions_.size() / positionDim());
-    for (size_t i = 0; i < faces_.size(); i += 3) {
-      // .OBJ files use 1-based indexing.
-      const int position_index = faces_[i + 0] - 1;
-      const int texcoord_index = faces_[i + 1] - 1;
-      const int normal_index = faces_[i + 2] - 1;
-      const std::pair<int, bool> flattened = flattener.GetFlattenedIndex(
-          position_index, texcoord_index, normal_index);
-      draw_mesh.triangle_indices.push_back(flattened.first);
-      if (flattened.second) {
-        for (size_t i = 0; i < positionDim(); ++i) {
-          draw_mesh.interleaved_attribs.push_back(
-              positions_[positionDim() * position_index + i]);
-        }
-        for (size_t i = 0; i < texcoordDim(); ++i) {
-          draw_mesh.interleaved_attribs.push_back(
-              texcoords_[texcoordDim() * texcoord_index + i]);
-        }
-        for (size_t i = 0; i < normalDim(); ++i) {
-          draw_mesh.interleaved_attribs.push_back(
-              normals_[normalDim() * normal_index + i]);
-        }
-      }
-    }
-  }
-
-  /*
-  // %z formatting chokes MinGW compiler on Windows :/
-  // using instead unsigned long
-
-  void DumpDebug() const {
-    printf("positions size: %zu\ntexcoords size: %zu\nnormals size: %zu"
-           "\nfaces size: %zu\n", positions_.size(), texcoords_.size(),
-           normals_.size(), faces_.size());
-  }
-  */
-
-  void DumpDebug() const {
-    printf("positions size: %lu\ntexcoords size: %lu\nnormals size: %lu"
-           "\nfaces size: %lu\n", (unsigned long)positions_.size(), (unsigned long)texcoords_.size(),
-           (unsigned long)normals_.size(), (unsigned long)faces_.size());
-  }
-
- private:
-  void ParseFile(FILE* fp) {
-    // TODO: don't use a fixed-size buffer.
-    const size_t kLineBufferSize = 256;
-    char buffer[kLineBufferSize];
-    unsigned int line_num = 1;
-    while (fgets(buffer, kLineBufferSize, fp) != NULL) {
-      const char* stripped = buffer;
-      while (isspace(*stripped)) {
-        ++stripped;
-      }
-      ParseLine(stripped, line_num++);
-    }
-  }
-
-  void ParseLine(const char* line, unsigned int line_num) {
-    switch (*line) {
-      case 'v':
-        ParseAttrib(line + 1, line_num);
-        break;
-      case 'f':
-        ParseFace(line + 1, line_num);
-        break;
-      case 'g':
-        ParseGroup(line + 1, line_num);
-        break;
-      case '\0':
-      case '#':
-        break;  // Do nothing for comments or blank lines.
-      case 'p':
-        WarnLine("point unsupported", line_num);
-        break;
-      case 'l':
-        WarnLine("line unsupported", line_num);
-        break;
-      case 'u':
-        WarnLine("usemtl (?) unsupported", line_num);
-        break;
-      case 'm':
-        WarnLine("mtllib (?) unsupported", line_num);
-        break;
-      case 's':
-        WarnLine("s unsupported", line_num);
-        break;
-      default:
-        WarnLine("unknown keyword", line_num);
-        break;
-    }
-  }
-
-  void ParseAttrib(const char* line, unsigned int line_num) {
-    ShortFloatList floats;
-    floats.ParseLine(line + 1);
-    if (isspace(*line)) {
-      ParsePosition(floats, line_num);
-    } else if (*line == 't') {
-      ParseTexCoord(floats, line_num);
-    } else if (*line == 'n') {
-      ParseNormal(floats, line_num);
-    } else {
-      WarnLine("unknown attribute format", line_num);
-    }
-  }
-
-  void ParsePosition(const ShortFloatList& floats, unsigned int line_num) {
-    if (floats.size() != positionDim()) {
-      ErrorLine("bad position", line_num);
-    }
-    floats.AppendTo(&positions_);
-  }
-
-  void ParseTexCoord(const ShortFloatList& floats, unsigned int line_num) {
-    if (floats.size() != texcoordDim()) {
-      ErrorLine("bad texcoord", line_num);
-    }
-    floats.AppendTo(&texcoords_);
-  }
-
-  void ParseNormal(const ShortFloatList& floats, unsigned int line_num) {
-    if (floats.size() != normalDim()) {
-      ErrorLine("bad normal", line_num);
-    }
-    floats.AppendTo(&normals_);
-  }
-
-  // Parses faces and converts to triangle fans. This is not a
-  // particularly good tesselation in general case, but it is really
-  // simple, and is perfectly fine for triangles and quads.
-  void ParseFace(const char* line, unsigned int line_num) {
-    // Also handle face outlines as faces.
-    if (*line == 'o') ++line;
-
-    // TODO: instead of storing these indices as-is, it might make
-    // sense to flatten them right away. This can reduce memory
-    // consumption and improve access locality, especially since .OBJ
-    // face indices are so needlessly large.
-    int indices[9] = { 0 };
-    // The first index acts as the pivot for the triangle fan.
-    line = ParseIndices(line, line_num, indices + 0, indices + 1, indices + 2);
-    if (line == NULL) {
-      ErrorLine("bad first index", line_num);
-    }
-    line = ParseIndices(line, line_num, indices + 3, indices + 4, indices + 5);
-    if (line == NULL) {
-      ErrorLine("bad second index", line_num);
-    }
-    // After the first two indices, each index introduces a new
-    // triangle to the fan.
-    while ((line = ParseIndices(line, line_num,
-                                indices + 6, indices + 7, indices + 8))) {
-      faces_.insert(faces_.end(), indices, indices + 9);
-      // The most recent vertex is reused for the next triangle.
-      indices[3] = indices[6];
-      indices[4] = indices[7];
-      indices[5] = indices[8];
-      indices[6] = indices[7] = indices[8] = 0;
-    }
-  }
-
-  // Parse a single group of indices, separated by slashes ('/').
-  // TODO: convert negative indices (that is, relative to the end of
-  // the current vertex positions) to more conventional positive
-  // indices.
-  const char* ParseIndices(const char* line, unsigned int line_num,
-                           int* position_index, int* texcoord_index,
-                           int* normal_index) {
-    int bytes_consumed = 0;
-    int indices_parsed = sscanf(line, "%d/%d/%d%n",
-                                position_index, texcoord_index, normal_index,
-                                &bytes_consumed);
-    if (indices_parsed != 3) {
-      return NULL;
-    }
-
-    if (*position_index <= 0 || *texcoord_index <= 0 || *normal_index <= 0 ) {
-      ErrorLine("bad index format", line_num);
-    }
-
-    return line + bytes_consumed;
-  }
-
-  void ParseGroup(const char* line, unsigned int line_num) {
-    WarnLine("group unsupported", line_num);
-  }
-
-  void WarnLine(const char* why, unsigned int line_num) {
-    fprintf(stderr, "WARNING: %s at line %u\n", why, line_num);
-  }
-
-  void ErrorLine(const char* why, unsigned int line_num) {
-    fprintf(stderr, "ERROR: %s at line %u\n", why, line_num);
-    exit(-1);
-  }
-
-  static size_t positionDim() { return 3; }
-  static size_t texcoordDim() { return 2; }
-  static size_t normalDim() { return 3; }
-
-  AttribList positions_;
-  AttribList texcoords_;
-  AttribList normals_;
-  // Indices are 1-indexed, and per-attrib.
-  IndexList faces_;
-  GroupList groups_;
-};
-
-// Axis-aligned bounding box
-struct AABB {
-  float mins[3];
-  float maxes[3];
-};
-
-void DumpJsonFromAABB(const AABB& aabb) {
-  printf("var aabb = { mins: [%f, %f, %f], maxes: [%f, %f, %f] };\n",
-         aabb.mins[0], aabb.mins[1], aabb.mins[2],
-         aabb.maxes[0], aabb.maxes[1], aabb.maxes[2]);
-}
-
-float UniformScaleFromAABB(const AABB& aabb) {
-  const float x = aabb.maxes[0] - aabb.mins[0];
-  const float y = aabb.maxes[1] - aabb.mins[1];
-  const float z = aabb.maxes[2] - aabb.mins[2];
-  return (x > y)
-      ? ((x > z) ? x : z)
-      : ((y > z) ? y : z);
-}
-
-void AABBToCenter(const AABB& aabb, float center[3]) {
-  for (size_t i = 0; i < 3; ++i) {
-    center[i] = 0.5*(aabb.mins[i] + aabb.maxes[i]);
-  }
-}
-
-AABB AABBFromAttribs(const AttribList& interleaved_attribs) {
-  AABB aabb;
-  for (size_t i = 0; i < 3; ++i) {
-    aabb.mins[i] = FLT_MAX;
-    aabb.maxes[i] = -FLT_MAX;
-  }
-  for (size_t i = 0; i < interleaved_attribs.size(); i += 8) {
-    for (size_t j = 0; j < 3; ++j) {
-      const float attrib = interleaved_attribs[i + j];
-      if (aabb.mins[j] > attrib) {
-        aabb.mins[j] = attrib;
-      }
-      if (aabb.maxes[j] < attrib) {
-        aabb.maxes[j] = attrib;
-      }
-    }
-  }
-  return aabb;
-}
-
-uint16 Quantize(float f, float offset, float range, int bits) {
-  const float f_offset = f + offset;
-  // Losslessly multiply a float by 1 << bits;
-  const float f_scaled = ldexpf(f_offset, bits);
-  // static_cast rounds towards zero (i.e. truncates).
-  return static_cast<uint16>(f_scaled / range - 0.5f);
-}
-
-void AttribsToQuantizedAttribs(const AttribList& interleaved_attribs,
-                               QuantizedAttribList* quantized_attribs) {
-  const AABB aabb = AABBFromAttribs(interleaved_attribs);
-  const float scale = UniformScaleFromAABB(aabb);
-  quantized_attribs->resize(interleaved_attribs.size());
-  const float offsets[8] = { -aabb.mins[0], -aabb.mins[1], -aabb.mins[2],
-                             0.0f, 0.0f, 1.f, 1.f, 1.f };
-  const float scales[8] = { scale, scale, scale, 1.f, 1.f, 2.f, 2.f, 2.f };
-  const int bits[8] = { 14, 14, 14, 10, 10, 10, 10, 10 };
-  for (size_t i = 0; i < interleaved_attribs.size(); i += 8) {
-    for (size_t j = 0; j < 8; ++j) {
-      quantized_attribs->at(i + j) = Quantize(interleaved_attribs[i + j],
-                                              offsets[j], scales[j], bits[j]);
-    }
-  }
-
-  // dump for reconstruction of real dimensions in JavaScript
-  // (probably should be embedded as a part of the UTF8 file)
-  fprintf(stderr, "scale: %f, offsetX: %f, offsetY: %f, offsetZ: %f\n", scale, aabb.mins[0], aabb.mins[1], aabb.mins[2] );
-}
-
-// Based on:
-// http://home.comcast.net/~tom_forsyth/papers/fast_vert_cache_opt.html
-class VertexOptimizer {
- public:
-  // TODO: this could easily work with non-quantized attribute lists.
-  VertexOptimizer(const QuantizedAttribList& attribs, const IndexList& indices)
-      : attribs_(attribs),
-        indices_(indices),
-        per_vertex_data_(attribs_.size() / 8) {
-    // The cache has an extra slot allocated to simplify the logic in
-    // InsertIndexToCache.
-    for (unsigned int i = 0; i <= kCacheSize; ++i) {
-      cache_[i] = kUnknownIndex;
-    }
-
-    // Loop through the indices, incrementing active triangle counts.
-    for (size_t i = 0; i < indices_.size(); ++i) {
-      per_vertex_data_[indices_[i]].active_tris++;
-    }
-
-    // Compute initial vertex scores.
-    for (size_t i = 0; i < per_vertex_data_.size(); ++i) {
-      per_vertex_data_[i].UpdateScore();
-    }
-  }
-
-  void GetOptimizedMesh(QuantizedAttribList* attribs, IndexList* indices) {
-    attribs->resize(attribs_.size());
-    indices->resize(indices_.size());
-
-    uint16* attribs_out = &attribs->at(0);
-    int* indices_out = &indices->at(0);
-    int next_unused_index = 0;
-    // Consume indices_, one triangle at a time. When a triangle is consumed from
-    // the middle of indices_, the last one is copied in to replace it so that we
-    // can shrink indices_ from the end.
-    while (!indices_.empty()) {
-      const size_t best_triangle = FindBestTriangle();
-      const size_t last_triangle = indices_.size() - 3;
-      // Go through the indices of the best triangle.
-      for (size_t i = 0; i < 3; ++i) {
-        const int index = indices_[best_triangle + i];
-        // After consuming this vertex, copy the corresponding index
-        // from the last triangle into this slot.
-        indices_[best_triangle + i] = indices_[last_triangle + i];
-        per_vertex_data_[index].active_tris--;
-        InsertIndexToCache(index);
-        const int cached_output_index = per_vertex_data_[index].output_index;
-        // Have we seen this index before?
-        if (cached_output_index != kUnknownIndex) {
-          *indices_out++ = cached_output_index;
-          continue;
-        }
-        // The first time we see an index, not only do we increment
-        // next_index counter, but we must also copy the corresponding
-        // attributes.
-        per_vertex_data_[index].output_index = next_unused_index;
-        for (size_t j = 0; j < 8; ++j) {
-          *attribs_out++ = attribs_[8*index + j];
-        }
-        *indices_out++ = next_unused_index++;
-      }
-      // Remove the last triangle.
-      indices_.resize(last_triangle);
-    }
-  }
- private:
-  static const int kUnknownIndex = -1;
-  static const uint16 kCacheSize = 32;
-
-  struct VertexData {
-    VertexData()
-        : active_tris(0),
-          cache_tag(kCacheSize),
-          output_index(kUnknownIndex),
-          score(-1.f)
-    { }
-
-    void UpdateScore() {
-      if (active_tris <= 0) {
-        score = -1.f;
-        return;
-      }
-      // TODO: build initial score table.
-      if (cache_tag < 3) {
-        // The most recent triangle should has a fixed score to
-        // discourage generating nothing but really long strips. If we
-        // want strips, we should use a different optimizer.
-        const float kLastTriScore = 0.75f;
-        score = kLastTriScore;
-      } else if (cache_tag < kCacheSize) {
-        // Points for being recently used.
-        const float kScale = 1.f / (kCacheSize - 3);
-        const float kCacheDecayPower = 1.5f;
-        score = powf(1.f - kScale * (cache_tag - 3), kCacheDecayPower);
-      } else {
-        // Not in cache.
-        score = 0.f;
-      }
-
-      // Bonus points for having a low number of tris still to use the
-      // vert, so we get rid of lone verts quickly.
-      const float kValenceBoostScale = 2.0f;
-      const float kValenceBoostPower = 0.5f;
-      const float valence_boost = powf(active_tris, -kValenceBoostPower);  // rsqrt?
-      score += valence_boost * kValenceBoostScale;
-    };
-
-    int active_tris;
-    unsigned int cache_tag;  // == kCacheSize means not in cache.
-    int output_index;  // For output remapping.
-    float score;
-  };
-
-  // This also updates the vertex scores!
-  void InsertIndexToCache(int index) {
-    // Find how recently the vertex was used.
-    const unsigned int cache_tag = per_vertex_data_[index].cache_tag;
-
-    // Don't do anything if the vertex is already at the head of the
-    // LRU list.
-    if (cache_tag == 0) return;
-
-    // Loop through the cache, inserting the index at the front, and
-    // bubbling down to where the index was originally found. If the
-    // index was not originally in the cache, then it claims to be at
-    // the (kCacheSize + 1)th entry, and we use an extra slot to make
-    // that case simpler.
-    int to_insert = index;
-    for (unsigned int i = 0; i <= cache_tag; ++i) {
-      const int current_index = cache_[i];
-
-      // Update cross references between the entry of the cache and
-      // the per-vertex data.
-      cache_[i] = to_insert;
-      per_vertex_data_[to_insert].cache_tag = i;
-      per_vertex_data_[to_insert].UpdateScore();
-
-      // No need to continue if we find an empty entry.
-      if (current_index == kUnknownIndex) {
-        break;
-      }
-
-      to_insert = current_index;
-    }
-  }
-
-  size_t FindBestTriangle() {
-    float best_score = -FLT_MAX;
-    size_t best_triangle = 0;
-    // TODO: without a boundary structure, this performs a linear
-    // scan, which makes Tom Forsyth's linear algorithm run in
-    // quadratic time!
-    for (size_t i = 0; i < indices_.size(); i += 3) {
-      const float score =
-          per_vertex_data_[indices_[i + 0]].score +
-          per_vertex_data_[indices_[i + 1]].score +
-          per_vertex_data_[indices_[i + 2]].score;
-      if (score > best_score) {
-        best_score = score;
-        best_triangle = i;
-      }
-    }
-    return best_triangle;
-  }
-
-  const QuantizedAttribList& attribs_;
-  IndexList indices_;
-  std::vector<VertexData> per_vertex_data_;
-  int cache_[kCacheSize + 1];
-};
-
-uint16 ZigZag(int16 word) {
-  return (word >> 15) ^ (word << 1);
-}
-
-#define CHECK(PRED) if (!(PRED)) {                              \
-    fprintf(stderr, "%d: CHECK failed: " #PRED "\n", __LINE__); \
-    exit(-1); } else
-
-bool Uint16ToUtf8(uint16 word, std::vector<char>* utf8) {
-  const char kMoreBytesPrefix = static_cast<char>(0x80);
-  const uint16 kMoreBytesMask = 0x3F;
-  if (word < 0x80) {
-    utf8->push_back(static_cast<char>(word));
-  } else if (word < 0x800) {
-    const char kTwoBytePrefix = static_cast<char>(0xC0);
-    utf8->push_back(kTwoBytePrefix + static_cast<char>(word >> 6));
-    utf8->push_back(kMoreBytesPrefix +
-                    static_cast<char>(word & kMoreBytesMask));
-  } else if (word < 0xF800) {
-    const char kThreeBytePrefix = static_cast<char>(0xE0);
-    // We can only encode 65535 - 2048 values because of illegal UTF-8
-    // characters, such as surrogate pairs in [0xD800, 0xDFFF].
-    //TODO: what about other characters, like reversed-BOM 0xFFFE?
-    if (word >= 0xD800) {
-      // Shift the result to avoid the surrogate pair range.
-      word += 0x0800;
-    }
-    utf8->push_back(kThreeBytePrefix + static_cast<char>(word >> 12));
-    utf8->push_back(kMoreBytesPrefix +
-                    static_cast<char>((word >> 6) & kMoreBytesMask));
-    utf8->push_back(kMoreBytesPrefix +
-                    static_cast<char>(word & kMoreBytesMask));
-  } else {
-    return false;
-  }
-  return true;
-}
-
-void CompressIndicesToUtf8(const IndexList& list, std::vector<char>* utf8) {
-  // For indices, we don't do delta from the most recent index, but
-  // from the high water mark. The assumption is that the high water
-  // mark only ever moves by one at a time. Foruntately, the vertex
-  // optimizer does that for us, to optimize for per-transform vertex
-  // fetch order.
-  uint16 index_high_water_mark = 0;
-  for (size_t i = 0; i < list.size(); ++i) {
-    const int index = list[i];
-    CHECK(index >= 0);
-    CHECK(index <= index_high_water_mark);
-    CHECK(Uint16ToUtf8(index_high_water_mark - index, utf8));
-    if (index == index_high_water_mark) {
-      ++index_high_water_mark;
-    }
-  }
-}
-
-void CompressQuantizedAttribsToUtf8(const QuantizedAttribList& attribs,
-                                    std::vector<char>* utf8) {
-  for (size_t i = 0; i < 8; ++i) {
-    // Use a transposed representation, and delta compression.
-    uint16 prev = 0;
-    for (size_t j = i; j < attribs.size(); j += 8) {
-      const uint16 word = attribs[j];
-      const uint16 za = ZigZag(static_cast<int16>(word - prev));
-      prev = word;
-      CHECK(Uint16ToUtf8(za, utf8));
-    }
-  }
-}
-
-void CompressMeshToFile(const QuantizedAttribList& attribs,
-                        const IndexList& indices,
-                        const char* fn) {
-  CHECK((attribs.size() & 7) == 0);
-  const size_t num_verts = attribs.size() / 8;
-
-  fprintf(stderr, "num_verts: %lu", (unsigned long)num_verts);
-
-  CHECK(num_verts > 0);
-  CHECK(num_verts < 65536);
-  std::vector<char> utf8;
-  CHECK(Uint16ToUtf8(static_cast<uint16>(num_verts - 1), &utf8));
-  CompressQuantizedAttribsToUtf8(attribs, &utf8);
-  CompressIndicesToUtf8(indices, &utf8);
-
-  FILE* fp = fopen(fn, "wb");
-  fwrite(&utf8[0], 1, utf8.size(), fp);
-  fclose(fp);
-}
-
-#endif  // WEBGL_LOADER_MESH_H_

二进制
utils/exporters/utf8/objcompress


+ 0 - 61
utils/exporters/utf8/objcompress.cc

@@ -1,61 +0,0 @@
-#if 0  // A cute trick to making this .cc self-building from shell.
-g++ $0 -O2 -Wall -Werror -o `basename $0 .cc`;
-exit;
-#endif
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License"); you
-// may not use this file except in compliance with the License. You
-// may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-// implied. See the License for the specific language governing
-// permissions and limitations under the License.
-
-#include "mesh.h"
-
-const bool kQuantize = true;
-const bool kOptimize = true;
-
-int main(int argc, char* argv[]) {
-  if (argc < 2 || argc > 3) {
-    fprintf(stderr, "Usage: %s in.obj [out.utf8]\n\n"
-            "\tIf 'out' is specified, then attempt to write out a compressed,\n"
-            "\tUTF-8 version to 'out.'\n\n"
-            "\tIf not, write a JSON version to STDOUT.\n\n",
-            argv[0]);
-    return -1;
-  }
-  FILE* fp = fopen(argv[1], "r");
-  WavefrontObjFile obj(fp);
-  fclose(fp);
-  std::vector<DrawMesh> meshes;
-  obj.CreateDrawMeshes(&meshes);
-  if (kQuantize) {
-    QuantizedAttribList attribs;
-    AttribsToQuantizedAttribs(meshes[0].interleaved_attribs, &attribs);
-    if (kOptimize) {
-      QuantizedAttribList optimized_attribs;
-      IndexList optimized_indices;
-      VertexOptimizer vertex_optimizer(attribs, meshes[0].triangle_indices);
-      vertex_optimizer.GetOptimizedMesh(&optimized_attribs, &optimized_indices);
-      if (argc == 3) {
-        CompressMeshToFile(optimized_attribs, optimized_indices, argv[2]);
-      } else {
-        DumpJsonFromQuantizedAttribs(optimized_attribs);
-        DumpJsonFromIndices(optimized_indices);
-      }
-      return 0;
-    } else {
-      DumpJsonFromQuantizedAttribs(attribs);
-    }
-  } else {
-    DumpJsonFromInterleavedAttribs(meshes[0].interleaved_attribs);
-  }
-  DumpJsonFromIndices(meshes[0].triangle_indices);
-  return 0;
-}

二进制
utils/exporters/utf8/objcompress.exe