소스 검색

Merge branch 'dev' of [email protected]:mrdoob/three.js into modernAnimationSystem

Conflicts:
	src/objects/MorphAnimMesh.js
Ben Houston 10 년 전
부모
커밋
fa92cf1511
100개의 변경된 파일2665개의 추가작업 그리고 5621개의 파일을 삭제
  1. 282 165
      build/three.js
  2. 264 271
      build/three.min.js
  3. 1 1
      docs/api/core/BufferAttribute.html
  4. 91 3
      docs/api/core/BufferGeometry.html
  5. 41 2
      docs/api/core/Geometry.html
  6. 4 2
      docs/api/extras/core/Path.html
  7. 6 3
      docs/api/extras/curves/EllipseCurve.html
  8. 10 63
      docs/api/lights/DirectionalLight.html
  9. 7 5
      docs/api/math/Color.html
  10. 6 4
      docs/api/math/Vector2.html
  11. 5 4
      docs/api/math/Vector3.html
  12. 5 6
      docs/api/math/Vector4.html
  13. 0 3
      docs/api/objects/SkinnedMesh.html
  14. 5 7
      docs/api/renderers/WebGLRenderer.html
  15. 0 1
      docs/scenes/bones-browser.html
  16. 2 0
      editor/index.html
  17. 4 1
      editor/js/Editor.js
  18. 81 0
      editor/js/History.js
  19. 20 0
      editor/js/Loader.js
  20. 29 1
      editor/js/Menubar.Edit.js
  21. 1 15
      editor/js/Sidebar.Geometry.Modifiers.js
  22. 23 0
      editor/js/Sidebar.Material.js
  23. 2 2
      editor/js/Sidebar.Object3D.js
  24. 29 1
      editor/js/Viewport.js
  25. 3 3
      editor/js/libs/app.js
  26. 1 1
      examples/canvas_geometry_cube.html
  27. 1 2
      examples/canvas_geometry_earth.html
  28. 2 4
      examples/canvas_geometry_terrain.html
  29. 1 1
      examples/canvas_interactive_voxelpainter.html
  30. 9 0
      examples/canvas_materials.html
  31. 0 345
      examples/canvas_particles_shapes.html
  32. 3 3
      examples/canvas_particles_sprites.html
  33. 1 1
      examples/css3d_molecules.html
  34. 5 4
      examples/index.html
  35. 515 0
      examples/js/GPUParticleSystem.js
  36. 1 1
      examples/js/Gyroscope.js
  37. 3 7
      examples/js/MD2Character.js
  38. 3 7
      examples/js/MD2CharacterComplex.js
  39. 15 15
      examples/js/MarchingCubes.js
  40. 4 4
      examples/js/Mirror.js
  41. 1 1
      examples/js/Ocean.js
  42. 0 981
      examples/js/Sparks.js
  43. 6 0
      examples/js/controls/DeviceOrientationControls.js
  44. 6 0
      examples/js/controls/DragControls.js
  45. 21 2
      examples/js/controls/EditorControls.js
  46. 26 8
      examples/js/controls/FirstPersonControls.js
  47. 27 7
      examples/js/controls/FlyControls.js
  48. 6 0
      examples/js/controls/MouseControls.js
  49. 26 5
      examples/js/controls/OrbitControls.js
  50. 23 3
      examples/js/controls/OrthographicTrackballControls.js
  51. 6 0
      examples/js/controls/PointerLockControls.js
  52. 22 3
      examples/js/controls/TrackballControls.js
  53. 6 0
      examples/js/controls/VRControls.js
  54. 1 1
      examples/js/effects/AnaglyphEffect.js
  55. 1 1
      examples/js/effects/ParallaxBarrierEffect.js
  56. 2 2
      examples/js/effects/StereoEffect.js
  57. 1 1
      examples/js/effects/VREffect.js
  58. 0 754
      examples/js/exporters/SceneExporter.js
  59. 8 18
      examples/js/loaders/AssimpJSONLoader.js
  60. 7 7
      examples/js/loaders/BinaryLoader.js
  61. 314 0
      examples/js/loaders/MD2Loader.js
  62. 42 18
      examples/js/loaders/VTKLoader.js
  63. 1 3
      examples/js/loaders/ctm/CTMLoader.js
  64. 1 1
      examples/js/loaders/gltf/glTFLoader.js
  65. 407 350
      examples/js/loaders/sea3d/SEA3DLoader.js
  66. 2 4
      examples/js/math/Lut.js
  67. 1 1
      examples/js/renderers/CSS2DRenderer.js
  68. 1 1
      examples/js/renderers/CSS3DRenderer.js
  69. 1 1
      examples/js/renderers/CSS3DStereoRenderer.js
  70. 6 5
      examples/js/renderers/Projector.js
  71. 1 1
      examples/js/renderers/RaytracingRenderer.js
  72. 191 12
      examples/js/renderers/SoftwareRenderer.js
  73. 1 1
      examples/misc_controls_deviceorientation.html
  74. 1 1
      examples/misc_controls_pointerlock.html
  75. 1 1
      examples/misc_lookat.html
  76. 13 10
      examples/misc_ubiquity_test.html
  77. 0 15
      examples/models/animated/ogro/ogro-light.js
  78. 0 72
      examples/models/animated/ogro/weapon-light.js
  79. 0 15
      examples/models/animated/ratamahatta/ratamahatta.js
  80. 0 73
      examples/models/animated/ratamahatta/ratamahatta.txt
  81. 0 2
      examples/models/animated/ratamahatta/readme.txt
  82. 0 193
      examples/models/animated/ratamahatta/w_bfg.js
  83. 0 224
      examples/models/animated/ratamahatta/w_blaster.js
  84. 0 224
      examples/models/animated/ratamahatta/w_chaingun.js
  85. 0 224
      examples/models/animated/ratamahatta/w_glauncher.js
  86. 0 224
      examples/models/animated/ratamahatta/w_hyperblaster.js
  87. 0 224
      examples/models/animated/ratamahatta/w_machinegun.js
  88. 0 215
      examples/models/animated/ratamahatta/w_railgun.js
  89. 0 80
      examples/models/animated/ratamahatta/w_rlauncher.js
  90. 0 224
      examples/models/animated/ratamahatta/w_shotgun.js
  91. 0 224
      examples/models/animated/ratamahatta/w_sshotgun.js
  92. 0 226
      examples/models/animated/ratamahatta/weapon.js
  93. 0 0
      examples/models/json/teapot-claraio.json
  94. 0 0
      examples/models/md2/ogro/Ogro.txt
  95. BIN
      examples/models/md2/ogro/ogro.md2
  96. 0 0
      examples/models/md2/ogro/skins/arboshak.png
  97. 0 0
      examples/models/md2/ogro/skins/ctf_b.png
  98. 0 0
      examples/models/md2/ogro/skins/ctf_r.png
  99. 0 0
      examples/models/md2/ogro/skins/darkam.png
  100. 0 0
      examples/models/md2/ogro/skins/freedom.png

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 282 - 165
build/three.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 264 - 271
build/three.min.js


+ 1 - 1
docs/api/core/BufferAttribute.html

@@ -17,7 +17,7 @@
 		<h2>Constructor</h2>
 		<h3>[name]([page:Array array], [page:Integer itemSize])</h3>
 		<div>
-		Instantiates this attibute with data from the associated buffer. The array can either be a regular Array or a Typed Array.
+		Instantiates this attribute with data from the associated buffer. The array can either be a regular Array or a Typed Array.
 		itemSize gives the number of values of the array that should be associated with a particular vertex.
 		</div>
 

+ 91 - 3
docs/api/core/BufferGeometry.html

@@ -129,7 +129,7 @@
 		When set, it holds certain buffers in memory to have faster updates for this object. When unset, it deletes those buffers and   saves memory.
 		</div> -->
 
-		<h3>[property:Array drawCalls] (previously [property:Array offsets])</h3>
+		<h3>[property:Array drawcalls] (previously [property:Array offsets])</h3>
 		<div>
 		For geometries that use indexed triangles, this Array can be used to split the object into multiple WebGL draw calls. Each draw call will draw some subset of the vertices in this geometry using the configured [page:Material shader]. This may be necessary if, for instance, you have more than 65535 vertices in your object.
 		Each element is an object of the form:
@@ -176,14 +176,67 @@
 
 		<h3>[method:null addDrawCall]( [page:Integer start], [page:Integer count], [page:Integer indexOffset] )</h3>
 		<div>
-		Adds a draw call to this geometry; see the drawcalls property for details.
+		Adds a draw call to this geometry; see the [page:BufferGeometry.drawcalls drawcalls] property for details.
+		</div>
+    
+		<h3>[method:null clearDrawCalls]( )</h3>
+		<div>
+		Clears all draw calls.
 		</div>
-
 
 		<h3>[method:null applyMatrix]( [page:Matrix4 matrix] )</h3>
 		<div>
 		Bakes matrix transform directly into vertex coordinates.
 		</div>
+    
+		<h3>[method:null center] ()</h3>
+		<div>
+		Center the geometry based on the bounding box.
+		</div>
+    
+		<h3>[method:BufferGeometry rotateX] ( [page:Float radians] )</h3>
+		<div>
+		Rotate the geometry about the X axis. This is typically done as a one time operation, and not during a loop
+    Use [page:Object3D.rotation] for typical real-time mesh rotation.
+		</div>
+
+		<h3>[method:BufferGeometry rotateY] ( [page:Float radians] )</h3>
+		<div>
+		Rotate the geometry about the Y axis. This is typically done as a one time operation, and not during a loop
+    Use [page:Object3D.rotation] for typical real-time mesh rotation.
+		</div>
+
+		<h3>[method:BufferGeometry rotateZ] ( [page:Float radians] )</h3>
+		<div>
+		Rotate the geometry about the Z axis. This is typically done as a one time operation, and not during a loop
+    Use [page:Object3D.rotation] for typical real-time mesh rotation.
+		</div>
+
+		<h3>[method:BufferGeometry translate] ( [page:Float x], [page:Float y], [page:Float z] )</h3>
+		<div>
+		Translate the geometry. This is typically done as a one time operation, and not during a loop
+    Use [page:Object3D.position] for typical real-time mesh translation.
+		</div>
+
+		<h3>[method:BufferGeometry scale] ( [page:Float x], [page:Float y], [page:Float z] )</h3>
+		<div>
+		Scale the geometry data. This is typically done as a one time operation, and not during a loop
+    Use [page:Object3D.scale] for typical real-time mesh scaling.
+		</div>
+
+		<h3>[method:BufferGeometry lookAt] ( [page:Vector3 vector] )</h3>
+		<div>
+		vector - A world vector to look at.<br />
+		</div>
+		<div>
+		Rotates the geometry to face point in space. This is typically done as a one time operation, and not during a loop
+    Use [page:Object3D.lookAt] for typical real-time mesh usage.
+		</div>
+
+		<h3>[method:BufferGeometry setFromObject] ( [page:Object3D object] )</h3>
+		<div>
+		Sets the attributes for this BufferGeometry from an [page:Object3D].
+		</div>
 
 		<h3>[method:null computeVertexNormals]()</h3>
 		<div>
@@ -209,6 +262,19 @@
 		Bounding spheres aren't computed by default. They need to be explicitly computed, otherwise they are *null*.
 		</div>
 
+		<h3>[method:null computeOffsets] ( [page:Integer size] )</h3>
+		<div>
+		Compute the draw offset for large models by chunking the index buffer into chunks of 65k addressable vertices.
+		This method will effectively rewrite the index buffer and remap all attributes to match the new indices.
+		WARNING: This method will also expand the vertex count to prevent sprawled triangles across draw offsets.
+		size - Defaults to 65535 or 4294967296 if extension OES_element_index_uint supported, but allows for larger or smaller chunks.
+		</div>
+
+		<h3>[method:null merge]( [page:BufferGeometry bufferGeometry], [page:Integer offset] )</h3>
+		<div>
+		Merge in another BufferGeometry with an optional offset of where to start merging in.
+		</div>
+
 		<h3>[method:null dispose]()</h3>
 		<div>
 		Disposes the object from memory. <br />
@@ -225,12 +291,34 @@
 		Returns the [page:BufferAttribute attribute] with the specified name.
 		</div>
 
+		<h3>[method:BufferAttribute removeAttribute]( [page:String name] )</h3>
+		<div>
+		Removes the [page:BufferAttribute attribute] with the specified name.
+		</div>
+
 		<h3>[method:null normalizeNormals]()</h3>
 		<div>
 		Every normal vector in a geometry will have a magnitude of 1.
 		This will correct lighting on the geometry surfaces.
 		</div>
 
+		<h3>[method:Object toJSON]()</h3>
+		<div>
+		Returns a raw object representation of the BufferGeometry.
+		</div>
+		
+		<h3>[method:BufferGeometry clone]()</h3>
+		<div>
+		Creates a clone of this BufferGeometry.
+		</div>
+		
+		<h3>[method:BufferGeometry copy]( [page:BufferGeometry bufferGeometry] )</h3>
+		<div>
+		Copies another BufferGeometry to this BufferGeometry.
+		</div>
+		
+		
+
 		<h2>Source</h2>
 
 		[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

+ 41 - 2
docs/api/core/Geometry.html

@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html lang="en">
 	<head>
-		<meta charset="utf-8" />
+		<meta charset="utf-8" />
 		<base href="../../" />
 		<script src="list.js"></script>
 		<script src="page.js"></script>
@@ -204,10 +204,49 @@
 		Bakes matrix transform directly into vertex coordinates.
 		</div>
 
-		<h3>[method:null center]()</h3>
+		<h3>[method:null center] ()</h3>
 		<div>
 		Center the geometry based on the bounding box.
 		</div>
+    
+		<h3>[method:Geometry rotateX] ( [page:Float radians] )</h3>
+		<div>
+		Rotate the geometry about the X axis. This is typically done as a one time operation, and not during a loop
+    Use [page:Object3D.rotation] for typical real-time mesh rotation.
+		</div>
+
+		<h3>[method:Geometry rotateY] ( [page:Float radians] )</h3>
+		<div>
+		Rotate the geometry about the Y axis. This is typically done as a one time operation, and not during a loop
+    Use [page:Object3D.rotation] for typical real-time mesh rotation.
+		</div>
+
+		<h3>[method:Geometry rotateZ] ( [page:Float radians] )</h3>
+		<div>
+		Rotate the geometry about the Z axis. This is typically done as a one time operation, and not during a loop
+    Use [page:Object3D.rotation] for typical real-time mesh rotation.
+		</div>
+
+		<h3>[method:Geometry translate] ( [page:Float x], [page:Float y], [page:Float z] )</h3>
+		<div>
+		Translate the geometry. This is typically done as a one time operation, and not during a loop
+    Use [page:Object3D.position] for typical real-time mesh translation.
+		</div>
+
+		<h3>[method:Geometry scale] ( [page:Float x], [page:Float y], [page:Float z] )</h3>
+		<div>
+		Scale the geometry data. This is typically done as a one time operation, and not during a loop
+    Use [page:Object3D.scale] for typical real-time mesh scaling.
+		</div>
+
+		<h3>[method:Geometry lookAt] ( [page:Vector3 vector] )</h3>
+		<div>
+		vector - A world vector to look at.<br />
+		</div>
+		<div>
+		Rotates the geometry to face point in space. This is typically done as a one time operation, and not during a loop
+    Use [page:Object3D.lookAt] for typical real-time mesh usage.
+		</div>
 
 		<h3>[method:null computeFaceNormals]()</h3>
 		<div>

+ 4 - 2
docs/api/extras/core/Path.html

@@ -81,7 +81,7 @@
 		</div>
 		<div>Draw an arc absolutely positioned</div>
 
-		<h3>[method:null ellipse]( [page:Float x], [page:Float y], [page:Float xRadius], [page:Float yRadius], [page:Float startAngle], [page:Float endAngle], [page:Float clockwise] )</h3>
+		<h3>[method:null ellipse]( [page:Float x], [page:Float y], [page:Float xRadius], [page:Float yRadius], [page:Float startAngle], [page:Float endAngle], [page:Float clockwise], [page:Float rotation] )</h3>
 		<div>
 		x, y -- The center of the ellipse offset from the last call
 		xRadius -- The radius of the ellipse in the x axis
@@ -89,10 +89,11 @@
 		startAngle -- The start angle in radians
 		endAngle -- The end angle in radians
 		clockwise -- Sweep the ellipse clockwise. Defaults to false
+		rotation -- The rotation angle of the ellipse in radians, counterclockwise from the positive X axis. Optional, defaults to 0
 		</div>
 		<div>Draw an ellipse offset from the last call</div>
 
-		<h3>[method:null absellipse]( [page:Float x], [page:Float y], [page:Float xRadius], [page:Float yRadius], [page:Float startAngle], [page:Float endAngle], [page:Float clockwise] )</h3>
+		<h3>[method:null absellipse]( [page:Float x], [page:Float y], [page:Float xRadius], [page:Float yRadius], [page:Float startAngle], [page:Float endAngle], [page:Float clockwise], [page:Float rotation] )</h3>
 		<div>
 		x, y -- The absolute center of the ellipse
 		xRadius -- The radius of the ellipse in the x axis
@@ -100,6 +101,7 @@
 		startAngle -- The start angle in radians
 		endAngle -- The end angle in radians
 		clockwise -- Sweep the ellipse clockwise. Defaults to false
+		rotation -- The rotation angle of the ellipse in radians, counterclockwise from the positive X axis. Optional, defaults to 0
 		</div>
 		<div>Draw an ellipse absolutely positioned</div>
 

+ 6 - 3
docs/api/extras/curves/EllipseCurve.html

@@ -21,7 +21,8 @@ var curve = new THREE.EllipseCurve(
 	0,  0,            // ax, aY
 	10, 10,           // xRadius, yRadius
 	0,  2 * Math.PI,  // aStartAngle, aEndAngle
-	false             // aClockwise
+	false,            // aClockwise
+	0                 // aRotation 
 );
 
 var path = new THREE.Path( curve.getPoints( 50 ) );
@@ -35,7 +36,7 @@ var ellipse = new THREE.Line( geometry, material );
 		<h2>Constructor</h2>
 
 
-		<h3>[name]( [page:Float aX], [page:Float aY], [page:Float xRadius], [page:Float yRadius], [page:Radians aStartAngle], [page:Radians aEndAngle], [page:Boolean aClockwise] )</h3>
+		<h3>[name]( [page:Float aX], [page:Float aY], [page:Float xRadius], [page:Float yRadius], [page:Radians aStartAngle], [page:Radians aEndAngle], [page:Boolean aClockwise], [page:Radians aRotation] )</h3>
 		<div>
 			aX – The X center of the ellipse<br/>
 			aY – The Y center of the ellipse<br/>
@@ -43,7 +44,8 @@ var ellipse = new THREE.Line( geometry, material );
 			yRadius – The radius of the ellipse in the y direction<br/>
 			aStartAngle – The start angle of the curve in radians starting from the middle right side<br/>
 			aEndAngle – The end angle of the curve in radians starting from the middle right side<br/>
-			aClockwise – Whether the ellipse is clockwise<br/><br/>
+			aClockwise – Whether the ellipse is clockwise<br/>
+			aRotation – The rotation angle of the ellipse in radians, counterclockwise from the positive X axis (optional)<br/><br/>
 
 			<strong>Note:</strong> When going clockwise it's best to set the start angle to (Math.PI * 2) and then work towards lower numbers.
 		</div>
@@ -58,6 +60,7 @@ var ellipse = new THREE.Line( geometry, material );
 		<h3>[property:Float aStartAngle]</h3>
 		<h3>[property:Float aEndAngle]</h3>
 		<h3>[property:Boolean aClockwise]</h3>
+		<h3>[property:Float aRotation]</h3>
 
 		<h2>Methods</h2>
 

+ 10 - 63
docs/api/lights/DirectionalLight.html

@@ -27,7 +27,7 @@
 		<div>[example:webgl_geometry_extrude_splines geometry / extrude / splines ]</div>
 		<div>[example:webgl_materials_bumpmap materials / bumpmap ]</div>
 		<div>[example:webgl_materials_cubemap_balls_reflection materials / cubemap / balls / reflection ]</div>
-		
+
 		<code>// White directional light at half intensity shining from the top.
 
 var directionalLight = new THREE.DirectionalLight( 0xffffff, 0.5 );
@@ -68,13 +68,13 @@ scene.add( directionalLight );</code>
 			If set to *true* light will only cast shadow but not contribute any lighting (as if *intensity* was 0 but cheaper to compute).<br />
 			Default — *false*.
 		</div>
-		
+
 		<h3>[property:Boolean castShadow]</h3>
 		<div>
 			If set to true light will cast dynamic shadows. Warning: This is expensive and requires tweaking to get shadows looking right.<br />
 			Default — *false*.
 		</div>
-		
+
 		<h3>[property:Float shadowCameraNear]</h3>
 		<div>
 			Orthographic shadow camera frustum parameter.<br />
@@ -141,90 +141,37 @@ scene.add( directionalLight );</code>
 			Default — *512*.
 		</div>
 
-		<h3>[property:Boolean shadowCascade]</h3>
-		<div>
-			**Experimental** If true, use a series of shadow maps in a cascade. This can give better z-depth resolution for a directional light. <br />
-			Default — *false*.
-		</div>
-
-		<h3>[property:Integer shadowCascadeCount]</h3>
-		<div>
-			Number of shadow maps to allocate in a cascade (one after another). <br />
-			Default — *2*.
-		</div>
-
-		<h3>[property:Vector3 shadowCascadeOffset]</h3>
-		<div>
-			A relative position to real camera where virtual shadow cameras are attached. A magic vector; scene and light orientation dependent. <br />
-			Default — *Three.Vector3( 0, 0, -1000 )*.
-		</div>
-
-		<h3>[property:Array shadowCascadeBias]</h3>
-		<div>
-			An array of shadowMapBias values for the corresponding shadow map in the cascade, near to far. <br />
-			Default — <strong>[ 0, 0, 0 ]</strong>.
-		</div>
-
-		<h3>[property:Array shadowCascadeWidth]</h3>
-		<div>
-			An array of shadowMapWidth values for the corresponding shadow map in the cascade, near to far. <br />
-			Default — <strong>[ 512, 512, 512 ]</strong>.
-		</div>
-
-		<h3>[property:Array shadowCascadeHeight]</h3>
-		<div>
-			An array of shadowMapHeight values for the corresponding shadow map in the cascade, near to far. <br />
-			Default — <strong>[ 512, 512, 512 ]</strong>.
-		</div>
-
-		<h3>[property:Array shadowCascadeNearZ]</h3>
-		<div>
-			An array of shadowMapNear values for the corresponding shadow map in the cascade, near to far. These typically start with -1.0 (near plane) and match with the previous shadowCascadeFarZ array value.<br />
-			Default — <strong>[ -1.000, 0.990, 0.998 ]</strong>.
-		</div>
-
-		<h3>[property:Array shadowCascadeFarZ]</h3>
-		<div>
-			An array of shadowMapFar values for the corresponding shadow map in the cascade, near to far. These typically match with the next shadowCascadeNearZ array value, ending in 1.0.<br />
-			Default — <strong>[ 0.990, 0.998, 1.000 ]</strong>.
-		</div>
-
-		<h3>[property:Array shadowCascadeArray]</h3>
-		<div>
-			Array of size shadowCascadeCount of [page:DirectionalLight THREE.DirectionalLight] objects. This holds the series of separate shadow maps in a cascade, near to far. Created internally.
-		</div>
-
 		<h3>[property:Vector2 shadowMapSize]</h3>
 		<div>
 			The shadowMapWidth and shadowMapHeight stored in a [page:Vector2 THREE.Vector2]. Set internally during rendering.
-		</div> 
+		</div>
 
 		<h3>[property:OrthographicCamera shadowCamera]</h3>
 		<div>
 			The shadow's view of the world. Computed internally during rendering from the shadowCamera* settings.
-		</div> 
+		</div>
 
 		<h3>[property:Matrix4 shadowMatrix]</h3>
 		<div>
 			Model to shadow camera space, to compute location and depth in shadow map. Computed internally during rendering.
-		</div> 
+		</div>
 
 		<h3>[property:WebGLRenderTarget shadowMap]</h3>
 		<div>
 		    The depth map generated using the shadowCamera; a location beyond a pixel's depth is in shadow. Computed internally during rendering.
-		</div> 
-		
+		</div>
+
 		<h2>Methods</h2>
 		<h3>[method:DirectionalLight clone]()</h3>
 		<div>
 		It returns a clone of DirectionalLight.
 		</div>
-		
+
 		<h3>[method:JSON toJSON]()</h3>
 		<div>
 		Return DirectionalLight data in JSON format.
 		</div>
-		
+
 		<h2>Source</h2>
 
 		[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

+ 7 - 5
docs/api/math/Color.html

@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html lang="en">
 	<head>
-		<meta charset="utf-8" />
+		<meta charset="utf-8" />
 		<base href="../../" />
 		<script src="list.js"></script>
 		<script src="page.js"></script>
@@ -18,7 +18,9 @@
 		<h2>Example</h2>
 		<code>var color = new THREE.Color();</code>
 		<code>var color = new THREE.Color( 0xff0000 );</code>
-		<code>var color = new THREE.Color("rgb(255,0,0)");</code>
+		<code>var color = new THREE.Color("rgb(255, 0, 0)");</code>
+		<code>var color = new THREE.Color("rgb(100%, 0%, 0%)");</code>
+		<code>var color = new THREE.Color("hsl(0, 100%, 50%)");</code>
 		<code>var color = new THREE.Color( 1, 0, 0 );</code>
 
 
@@ -27,7 +29,7 @@
 
 		<h3>[name]( value )</h3>
 		<div>
-		value — optional argument that sets initial color.  Can be a hexadecimal or a CSS-style string, for example, "rgb(250, 0,0)", "rgb(100%,0%,0%)", "#ff0000", "#f00", or "red", or three arguments that represent color channels.
+		value — optional argument that sets initial color.  Can be a hexadecimal or a CSS-style string, for example, "rgb(250, 0,0)", "rgb(100%,0%,0%)", "hsl(0, 100%, 50%)", "#ff0000", "#f00", or "red", or three arguments that represent color channels.
 		</div>
 
 		<h2>Properties</h2>
@@ -113,10 +115,10 @@
 
 		<h3>[method:Color setStyle]( [page:String style] ) [page:Color this]</h3>
 		<div>
-		style — color as a CSS-style string, for example, "rgb(250, 0,0)", "rgb(100%,0%,0%)", "#ff0000", "#f00", or "red"
+		style — color as a CSS-style string.
 		</div>
 		<div>
-		Sets this color	from a CSS-style string.
+		Sets this color from a CSS-style string. For example, "rgb(250, 0,0)", "rgb(100%, 0%, 0%)", "hsl(0, 100%, 50%)", "#ff0000", "#f00", or "red". Transluent colors such as "rgba(255, 0, 0, 0.5)" and "hsla(0, 100%, 50%, 0.5)" are also accepted, but the alpha-channel coordinate will be discarded.
 		</div>
 
 		<h3>[method:String getStyle]()</h3>

+ 6 - 4
docs/api/math/Vector2.html

@@ -152,7 +152,8 @@
 		max -- [page:Vector2] containing the max x and y values in the desired range
 		</div>
 		<div>
-		If this vector's x or y value is greater than the max vector's x or y value, it is replaced by the corresponding value. <br />	If this vector's x or y value is less than the min vector's x or y value, it is replace by the corresponding value.
+		If this vector's x or y value is greater than the max vector's x or y value, it is replaced by the corresponding value. <br /><br />
+		If this vector's x or y value is less than the min vector's x or y value, it is replaced by the corresponding value.
 		</div>
 
 		<h3>[method:Vector2 clampScalar]([page:Float min], [page:Float max]) [page:Vector2 this]</h3>
@@ -161,7 +162,8 @@
 		max -- [page:Float] the maximum value the components will be clamped to
 		</div>
 		<div>
-		If this vector's x or y values are greater than the max value, they are replaced by the max value. <br />  If this vector's x or y values are less than the min value, they are replace by the min value.
+		If this vector's x or y values are greater than the max value, they are replaced by the max value. <br /><br />
+		If this vector's x or y values are less than the min value, they are replaced by the min value.
 		</div>
 
 		<h3>[method:Vector2 floor]()</h3>
@@ -251,7 +253,7 @@
 		v -- [page:Vector2]
 		</div>
 		<div>
-		If this vector's x or y value is less than v's x or y value, replace that value with the corresponding min value.
+		If this vector's x or y value is greater than v's x or y value, replace that value with the corresponding min value.
 		</div>
 
 		<h3>[method:Vector2 max]([page:Vector2 v]) [page:Vector2 this]</h3>
@@ -259,7 +261,7 @@
 		v -- [page:Vector2]
 		</div>
 		<div>
-		If this vector's x or y value is greater than v's x or y value, replace that value with the corresponding max value.
+		If this vector's x or y value is less than v's x or y value, replace that value with the corresponding max value.
 		</div>
 
 		<h3>[method:Vector2 setX]([page:Float x]) [page:Vector2 this]</h3>

+ 5 - 4
docs/api/math/Vector3.html

@@ -193,7 +193,7 @@
 		</div>
 		<div>
 		If this vector's x, y or z value is greater than the max vector's x, y or z value, it is replaced by the corresponding value. <br /><br />
-		If this vector's x, y or z value is less than the min vector's x, y or z value, it is replace by the corresponding value.
+		If this vector's x, y or z value is less than the min vector's x, y or z value, it is replaced by the corresponding value.
 		</div>
 
 		<h3>[method:Vector3 clampScalar]([page:Float min], [page:Float max]) [page:Vector3 this]</h3>
@@ -202,7 +202,8 @@
 		max -- [page:Float] the maximum value the components will be clamped to
 		</div>
 		<div>
-		If this vector's x, y or z values are greater than the max value, they are replaced by the max value. <br />  If this vector's x, y or z values are less than the min value, they are replace by the min value.
+		If this vector's x, y or z values are greater than the max value, they are replaced by the max value. <br /><br />
+		If this vector's x, y or z values are less than the min value, they are replaced by the min value.
 		</div>
 
 		<h3>[method:Vector3 floor]()</h3>
@@ -278,7 +279,7 @@
 		v -- [page:Vector3]
 		</div>
 		<div>
-		If this vector's x, y, or z value is less than vector v's x, y, or z value, that value is replaced by the corresponding vector v value.
+		If this vector's x, y, or z value is greater than vector v's x, y, or z value, that value is replaced by the corresponding vector v value.
 		</div>
 
 		<h3>[method:Vector3 max]([page:Vector3 v]) [page:Vector3 this]</h3>
@@ -286,7 +287,7 @@
 		v -- [page:Vector3]
 		</div>
 		<div>
-		If this vector's x, y, or z value is greater than vector v's x, y, or z value, that value is replaced by the corresponding vector v value.
+		If this vector's x, y, or z value is less than vector v's x, y, or z value, that value is replaced by the corresponding vector v value.
 		</div>
 
 		<h3>[method:Vector3 setComponent]([page:Integer index], [page:Float value]) [page:Vector3 this]</h3>

+ 5 - 6
docs/api/math/Vector4.html

@@ -137,8 +137,7 @@
 		</div>
 		<div>
 		If this vector's x, y, z, or w value is greater than the max vector's x, y, z, or w value, it is replaced by the corresponding value.<br/><br/>
-
-		If this vector's x, y, z, or w value is less than the min vector's x, y, z, or w value, it is replace by the corresponding value.
+		If this vector's x, y, z, or w value is less than the min vector's x, y, z, or w value, it is replaced by the corresponding value.
 		</div>
 
 		<h3>[method:Vector4 clampScalar]([page:Float min], [page:Float max]) [page:Vector4 this]</h3>
@@ -147,8 +146,8 @@
 		max -- [page:Float] the maximum value the components will be clamped to
 		</div>
 		<div>
-		If this vector's x, y, z or w values are greater than the max value, they are replaced by the max value. <br />
-		If this vector's x, y, z or w values are less than the min value, they are replace by the min value.
+		If this vector's x, y, z or w values are greater than the max value, they are replaced by the max value. <br /><br />
+		If this vector's x, y, z or w values are less than the min value, they are replaced by the min value.
 		</div>
 
 		<h3>[method:Vector4 floor]()</h3>
@@ -184,7 +183,7 @@
 		v -- [page:Vector4]
 		</div>
 		<div>
-		If this vector's x, y, z, or w value is less than vector v's x, y, z, or w value, that value is replaced by the corresponding vector v value.
+		If this vector's x, y, z, or w value is greater than vector v's x, y, z, or w value, that value is replaced by the corresponding vector v value.
 		</div>
 
 		<h3>[method:Vector4 max]([page:Vector4 v]) [page:Vector4 this]</h3>
@@ -192,7 +191,7 @@
 		v -- [page:Vector4]
 		</div>
 		<div>
-		If this vector's x, y, z, or w value is greater than vector v's x, y, z, or w value, that value is replaced by the corresponding vector v value.
+		If this vector's x, y, z, or w value is less than vector v's x, y, z, or w value, that value is replaced by the corresponding vector v value.
 		</div>
 
 		<h3>[method:Vector4 addScalar]([page:Float s]) [page:Vector4 this]</h3>

+ 0 - 3
docs/api/objects/SkinnedMesh.html

@@ -43,9 +43,6 @@
 		// Bind the skeleton to the mesh
 		mesh.bind( armSkeleton );
 		
-		// Update the inverse matrices in the skeleton to reflect the newly bound skeleton
-		armSkeleton.calculateInverses();
-		
 		// Move the bones and manipulate the model
 		armSkeleton.bones[ 0 ].rotation.x = -0.1;
 		armSkeleton.bones[ 1 ].rotation.x = 0.2;

+ 5 - 7
docs/api/renderers/WebGLRenderer.html

@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html lang="en">
 	<head>
-		<meta charset="utf-8" />
+		<meta charset="utf-8" />
 		<base href="../../" />
 		<script src="list.js"></script>
 		<script src="page.js"></script>
@@ -23,13 +23,15 @@
 
 		<div>
 		canvas — A [page:Canvas] where the renderer draws its output.<br />
-		precision — shader precision. Can be *"highp"*, *"mediump"* or *"lowp"*.<br />
+		context — The [page:RenderingContext] context to use.<br />
+		precision — Shader precision. Can be *"highp"*, *"mediump"* or *"lowp"*. Defaults to *"highp"* if supported by the device.<br />
 		alpha — [page:Boolean], default is *false*.<br />
 		premultipliedAlpha — [page:Boolean], default is *true*.<br />
 		antialias — [page:Boolean], default is *false*.<br />
 		stencil — [page:Boolean], default is *true*.<br />
 		preserveDrawingBuffer — [page:Boolean], default is *false*.<br />
-		maxLights — [page:Integer], default is *4*.<br />
+		depth — [page:Boolean], default is *true*.<br />
+		logarithmicDepthBuffer — [page:Boolean], default is *false*.<br />
 		</div>
 
 		<h2>Properties</h2>
@@ -70,10 +72,6 @@
 		<div>Note: Sorting is used to attempt to properly render objects that have some degree of transparency.  By definition, sorting objects may not work in all cases.  Depending on the needs of application, it may be neccessary to turn off sorting and use other methods to deal with transparency rendering e.g. manually determining the object rendering order.</div>
 
 
-		<h3>[property:Boolean autoUpdateObjects]</h3>
-
-		<div>Defines whether the renderer should auto update objects. Default is true.</div>
-
 		<h3>[property:Boolean gammaInput]</h3>
 
 		<div>Default is false. If set, then it expects that all textures and colors are premultiplied gamma.</div>

+ 0 - 1
docs/scenes/bones-browser.html

@@ -159,7 +159,6 @@
 				mesh.add( bones[ 0 ] );
 	
 				mesh.bind( skeleton );
-				skeleton.calculateInverses();
 
 				skeletonHelper = new THREE.SkeletonHelper( mesh );
 				skeletonHelper.material.linewidth = 2;

+ 2 - 0
editor/index.html

@@ -17,6 +17,7 @@
 		<script src="../examples/js/loaders/AWDLoader.js"></script>
 		<script src="../examples/js/loaders/BabylonLoader.js"></script>
 		<script src="../examples/js/loaders/ColladaLoader.js"></script>
+		<script src="../examples/js/loaders/MD2Loader.js"></script>
 		<script src="../examples/js/loaders/OBJLoader.js"></script>
 		<script src="../examples/js/loaders/PLYLoader.js"></script>
 		<script src="../examples/js/loaders/STLLoader.js"></script>
@@ -83,6 +84,7 @@
 
 		<script src="js/Editor.js"></script>
 		<script src="js/Config.js"></script>
+		<script src="js/History.js"></script>
 		<script src="js/Loader.js"></script>
 		<script src="js/Menubar.js"></script>
 		<script src="js/Menubar.File.js"></script>

+ 4 - 1
editor/js/Editor.js

@@ -70,6 +70,7 @@ var Editor = function () {
 	};
 
 	this.config = new Config();
+	this.history = new History( this );
 	this.storage = new Storage();
 	this.loader = new Loader( this );
 
@@ -188,7 +189,7 @@ Editor.prototype = {
 
 	removeObject: function ( object ) {
 
-		if ( object.parent === undefined ) return; // avoid deleting the camera or scene
+		if ( object.parent === null ) return; // avoid deleting the camera or scene
 
 		var scope = this;
 
@@ -411,6 +412,8 @@ Editor.prototype = {
 
 	clear: function () {
 
+		this.history.clear();
+
 		this.camera.position.set( 500, 250, 500 );
 		this.camera.lookAt( new THREE.Vector3() );
 

+ 81 - 0
editor/js/History.js

@@ -0,0 +1,81 @@
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
+
+var History = function ( editor ) {
+
+	this.array = [];
+	this.arrayLength = -1;
+
+	this.current = -1;
+	this.isRecording = true;
+
+	//
+
+	var scope = this;
+	var signals = editor.signals;
+
+	signals.objectAdded.add( function ( object ) {
+
+		if ( scope.isRecording === false ) return;
+
+		scope.add(
+			function () {
+				editor.removeObject( object );
+				editor.select( null );
+			},
+			function () {
+				editor.addObject( object );
+				editor.select( object );
+			}
+		);
+
+	} );
+
+};
+
+History.prototype = {
+
+	add: function ( undo, redo ) {
+
+		this.current ++;
+
+		this.array[ this.current ] = { undo: undo, redo: redo };
+		this.arrayLength = this.current;
+
+	},
+
+	undo: function () {
+
+		if ( this.current < 0 ) return;
+
+		this.isRecording = false;
+
+		this.array[ this.current -- ].undo();
+
+		this.isRecording = true;
+
+	},
+
+	redo: function () {
+
+		if ( this.current === this.arrayLength ) return;
+
+		this.isRecording = false;
+
+		this.array[ ++ this.current ].redo();
+
+		this.isRecording = true;
+
+	},
+
+	clear: function () {
+
+		this.array = [];
+		this.arrayLength = -1;
+
+		this.current = -1;
+
+	}
+
+};

+ 20 - 0
editor/js/Loader.js

@@ -184,6 +184,26 @@ var Loader = function ( editor ) {
 
 				break;
 
+				case 'md2':
+
+					var reader = new FileReader();
+					reader.addEventListener( 'load', function ( event ) {
+
+						var contents = event.target.result;
+
+						var geometry = new THREE.MD2Loader().parse( contents );
+						geometry.name = filename;
+
+						var object = new THREE.Mesh( geometry, new THREE.MeshPhongMaterial() );
+
+						editor.addObject( object );
+						editor.select( object );
+
+					}, false );
+					reader.readAsArrayBuffer( file );
+
+					break;
+
 			case 'obj':
 
 				var reader = new FileReader();

+ 29 - 1
editor/js/Menubar.Edit.js

@@ -16,6 +16,34 @@ Menubar.Edit = function ( editor ) {
 	options.setClass( 'options' );
 	container.add( options );
 
+	// Undo
+
+	var option = new UI.Panel();
+	option.setClass( 'option' );
+	option.setTextContent( 'Undo' );
+	option.onClick( function () {
+
+		editor.history.undo();
+
+	} );
+	options.add( option );
+
+	// Redo
+
+	var option = new UI.Panel();
+	option.setClass( 'option' );
+	option.setTextContent( 'Redo' );
+	option.onClick( function () {
+
+		editor.history.redo();
+
+	} );
+	options.add( option );
+
+	// ---
+
+	options.add( new UI.HorizontalRule() );
+
 	// Clone
 
 	var option = new UI.Panel();
@@ -25,7 +53,7 @@ Menubar.Edit = function ( editor ) {
 
 		var object = editor.selected;
 
-		if ( object.parent === undefined ) return; // avoid cloning the camera or scene
+		if ( object.parent === null ) return; // avoid cloning the camera or scene
 
 		object = object.clone();
 

+ 1 - 15
editor/js/Sidebar.Geometry.Modifiers.js

@@ -35,21 +35,7 @@ Sidebar.Geometry.Modifiers = function ( signals, object ) {
 
 	var isBufferGeometry = geometry instanceof THREE.BufferGeometry;
 
-	if ( geometry instanceof THREE.BufferGeometry ) {
-
-		var button = new UI.Button( 'Convert to Geometry' );
-		button.onClick( function () {
-
-			if ( confirm( 'Are you sure?' ) === false ) return;
-
-			object.geometry = new THREE.Geometry().fromBufferGeometry( object.geometry );
-
-			signals.geometryChanged.dispatch( object );
-
-		} );
-		container.add( button );
-
-	} else {
+	if ( geometry instanceof THREE.Geometry ) {
 
 		var button = new UI.Button( 'Convert to BufferGeometry' );
 		button.onClick( function () {

+ 23 - 0
editor/js/Sidebar.Material.js

@@ -346,6 +346,16 @@ Sidebar.Material = function ( editor ) {
 
 	container.add( materialTransparentRow );
 
+	// alpha test
+
+	var materialAlphaTestRow = new UI.Panel();
+	var materialAlphaTest = new UI.Number().setWidth( '60px' ).setRange( 0, 1 ).onChange( update );
+
+	materialAlphaTestRow.add( new UI.Text( 'Alpha Test' ).setWidth( '90px' ) );
+	materialAlphaTestRow.add( materialAlphaTest );
+
+	container.add( materialAlphaTestRow );
+
 	// wireframe
 
 	var materialWireframeRow = new UI.Panel();
@@ -606,6 +616,12 @@ Sidebar.Material = function ( editor ) {
 
 			}
 
+			if ( material.alphaTest !== undefined ) {
+
+				material.alphaTest = materialAlphaTest.getValue();
+
+			}
+
 			if ( material.wireframe !== undefined ) {
 
 				material.wireframe = materialWireframe.getValue();
@@ -658,6 +674,7 @@ Sidebar.Material = function ( editor ) {
 			'blending': materialBlendingRow,
 			'opacity': materialOpacityRow,
 			'transparent': materialTransparentRow,
+			'alphaTest': materialAlphaTestRow,
 			'wireframe': materialWireframeRow
 		};
 
@@ -858,6 +875,12 @@ Sidebar.Material = function ( editor ) {
 
 		}
 
+		if ( material.alphaTest !== undefined ) {
+
+			materialAlphaTest.setValue( material.alphaTest );
+
+		}
+
 		if ( material.wireframe !== undefined ) {
 
 			materialWireframe.setValue( material.wireframe );

+ 2 - 2
editor/js/Sidebar.Object3D.js

@@ -342,7 +342,7 @@ Sidebar.Object3D = function ( editor ) {
 
 		if ( object !== null ) {
 
-			if ( object.parent !== undefined ) {
+			if ( object.parent !== null ) {
 
 				var newParentId = parseInt( objectParent.getValue() );
 
@@ -535,7 +535,7 @@ Sidebar.Object3D = function ( editor ) {
 		objectUUID.setValue( object.uuid );
 		objectName.setValue( object.name );
 
-		if ( object.parent !== undefined ) {
+		if ( object.parent !== null ) {
 
 			objectParent.setValue( object.parent.id );
 

+ 29 - 1
editor/js/Viewport.js

@@ -36,6 +36,8 @@ var Viewport = function ( editor ) {
 	selectionBox.visible = false;
 	sceneHelpers.add( selectionBox );
 
+	var matrix = new THREE.Matrix4();
+
 	var transformControls = new THREE.TransformControls( camera, container.dom );
 	transformControls.addEventListener( 'change', function () {
 
@@ -58,12 +60,37 @@ var Viewport = function ( editor ) {
 	} );
 	transformControls.addEventListener( 'mouseDown', function () {
 
+		var object = transformControls.object;
+
+		matrix.copy( object.matrix );
+
 		controls.enabled = false;
 
 	} );
 	transformControls.addEventListener( 'mouseUp', function () {
 
-		signals.objectChanged.dispatch( transformControls.object );
+		var object = transformControls.object;
+
+		if ( matrix.equals( object.matrix ) === false ) {
+
+			( function ( matrix1, matrix2 ) {
+
+				editor.history.add(
+					function () {
+						matrix1.decompose( object.position, object.quaternion, object.scale );
+						signals.objectChanged.dispatch( object );
+					},
+					function () {
+						matrix2.decompose( object.position, object.quaternion, object.scale );
+						signals.objectChanged.dispatch( object );
+					}
+				);
+
+			} )( matrix.clone(), object.matrix.clone() );
+
+		}
+
+		signals.objectChanged.dispatch( object );
 		controls.enabled = true;
 
 	} );
@@ -375,6 +402,7 @@ var Viewport = function ( editor ) {
 
 	signals.objectChanged.add( function ( object ) {
 
+		selectionBox.update( object );
 		transformControls.update();
 
 		if ( object instanceof THREE.PerspectiveCamera ) {

+ 3 - 3
editor/js/libs/app.js

@@ -101,7 +101,7 @@ var APP = {
 
 			if ( vr === true ) {
 
-				if ( camera.parent === undefined ) {
+				if ( camera.parent === null ) {
 
 					// camera needs to be in the scene so camera2 matrix updates
 
@@ -167,7 +167,7 @@ var APP = {
 
 				} catch (e) {
 
-					console.error(e.stack || e);
+					console.error( ( e.message || e ), ( e.stack || "" ) );
 
 				}
 
@@ -212,7 +212,7 @@ var APP = {
 			dispatch( events.start, arguments );
 
 			request = requestAnimationFrame( animate );
-			prevTime = performance.now();
+			prevTime = ( window.performance || Date ).now();
 		};
 
 		this.stop = function () {

+ 1 - 1
examples/canvas_geometry_cube.html

@@ -82,7 +82,7 @@
 				// Plane
 
 				var geometry = new THREE.PlaneBufferGeometry( 200, 200 );
-				geometry.applyMatrix( new THREE.Matrix4().makeRotationX( - Math.PI / 2 ) );
+				geometry.rotateX( - Math.PI / 2 );
 
 				var material = new THREE.MeshBasicMaterial( { color: 0xe0e0e0, overdraw: 0.5 } );
 

+ 1 - 2
examples/canvas_geometry_earth.html

@@ -100,8 +100,7 @@
 				context.fillStyle = gradient;
 				context.fillRect( 0, 0, canvas.width, canvas.height );
 
-				var texture = new THREE.Texture( canvas );
-				texture.needsUpdate = true;
+				var texture = new THREE.CanvasTexture( canvas );
 
 				var geometry = new THREE.PlaneBufferGeometry( 300, 300, 3, 3 );
 				var material = new THREE.MeshBasicMaterial( { map: texture, overdraw: 0.5 } );

+ 2 - 4
examples/canvas_geometry_terrain.html

@@ -69,15 +69,13 @@
 				scene = new THREE.Scene();
 
 				var data = generateHeight( 1024, 1024 );
-				var texture = new THREE.Texture( generateTexture( data, 1024, 1024 ) );
-				texture.needsUpdate = true;
-
+				var texture = new THREE.CanvasTexture( generateTexture( data, 1024, 1024 ) );
 				var material = new THREE.MeshBasicMaterial( { map: texture, overdraw: 0.5 } );
 
 				var quality = 16, step = 1024 / quality;
 
 				var geometry = new THREE.PlaneGeometry( 2000, 2000, quality - 1, quality - 1 );
-				geometry.applyMatrix( new THREE.Matrix4().makeRotationX( - Math.PI / 2 ) );
+				geometry.rotateX( - Math.PI / 2 );
 
 				for ( var i = 0, l = geometry.vertices.length; i < l; i ++ ) {
 

+ 1 - 1
examples/canvas_interactive_voxelpainter.html

@@ -82,7 +82,7 @@
 				mouse = new THREE.Vector2();
 
 				var geometry = new THREE.PlaneBufferGeometry( 1000, 1000 );
-				geometry.applyMatrix( new THREE.Matrix4().makeRotationX( - Math.PI / 2 ) );
+				geometry.rotateX( - Math.PI / 2 );
 
 				plane = new THREE.Mesh( geometry, new THREE.MeshBasicMaterial( { visible: false } ) );
 				scene.add( plane );

+ 9 - 0
examples/canvas_materials.html

@@ -80,6 +80,15 @@
 
 				];
 
+				for ( var i = 0, l = geometry.faces.length; i < l; i ++ ) {
+
+					var face = geometry.faces[ i ];
+					if ( Math.random() > 0.5 ) face.materialIndex = Math.floor( Math.random() * materials.length );
+
+				}
+
+				materials.push( new THREE.MeshFaceMaterial( materials ) );
+
 				objects = [];
 
 				for ( var i = 0, l = materials.length; i < l; i ++ ) {

+ 0 - 345
examples/canvas_particles_shapes.html

@@ -1,345 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-	<head>
-		<title>three.js canvas - particles with shapes</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: #f0f0f0;
-				margin: 0px;
-				overflow: hidden;
-			}
-		</style>
-	</head>
-	<body>
-
-
-		<script src="../build/three.min.js"></script>
-
-		<script src="js/renderers/Projector.js"></script>
-		<script src="js/renderers/CanvasRenderer.js"></script>
-
-		<script src="js/libs/stats.min.js"></script>
-		<script src="js/libs/tween.min.js"></script>
-		<script src="js/Sparks.js"></script>
-
-		<!-- load the font file from canvas-text -->
-
-		<script src="fonts/helvetiker_regular.typeface.js"></script>
-
-
-		<script>
-
-			var container, stats;
-
-			var camera, scene, renderer;
-
-			var group, text, plane;
-
-			var targetRotation = 0;
-			var targetRotationOnMouseDown = 0;
-
-			var mouseX = 0;
-			var mouseXOnMouseDown = 0;
-
-			var windowHalfX = window.innerWidth / 2;
-			var windowHalfY = window.innerHeight / 2;
-
-			var heartShape, particleCloud, sparksEmitter, emitterPos;
-			var _rotation = 0;
-			var timeOnShapePath = 0;
-
-			init();
-			animate();
-
-			function init() {
-
-				container = document.createElement( 'div' );
-				document.body.appendChild( container );
-
-				var info = document.createElement( 'div' );
-				info.style.position = 'absolute';
-				info.style.top = '10px';
-				info.style.width = '100%';
-				info.style.textAlign = 'center';
-				info.innerHTML = 'Three.js with Love. Simple Particle Systems with Shapes by <a href="http://www.lab4games.net/zz85/blog">zz85</a><br>Move your mouse.';
-				container.appendChild( info );
-
-				camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 1000 );
-				camera.position.set( 0, 150, 700 );
-
-				scene = new THREE.Scene();
-
-				group = new THREE.Group();
-				scene.add( group );
-
-				// Get text from hash
-
-				var string = "THREE.JS";
-				var hash = document.location.hash.substr( 1 );
-
-				if ( hash.length !== 0 ) {
-
-					string = hash;
-
-				}
-
-				var text3d = new THREE.TextGeometry( string, {
-
-					size: 80,
-					height: 20,
-					curveSegments: 2,
-					font: "helvetiker"
-
-				});
-
-				text3d.computeBoundingBox();
-				var centerOffset = -0.5 * ( text3d.boundingBox.max.x - text3d.boundingBox.min.x );
-
-				var textMaterial = new THREE.MeshBasicMaterial( { color: Math.random() * 0xffffff, overdraw: 0.5 } );
-
-				text = new THREE.Mesh( text3d, textMaterial );
-
-				// Potentially, we can extract the vertices or faces of the text to generate particles too.
-				// Geo > Vertices > Position
-
-				text.position.x = centerOffset;
-				text.position.y = 100;
-				text.position.z = 0;
-
-				text.rotation.x = 0;
-				text.rotation.y = Math.PI * 2;
-
-				group.add( text );
-
-
-				particleCloud = new THREE.Object3D(); // Just a group
-				particleCloud.y = 800;
-				group.add( particleCloud );
-
-				// Create Particle Systems
-
-				// Heart
-
-				var x = 0, y = 0;
-
-				heartShape = new THREE.Shape();
-
-				heartShape.moveTo( x + 25, y + 25 );
-				heartShape.bezierCurveTo( x + 25, y + 25, x + 20, y, x, y );
-				heartShape.bezierCurveTo( x - 30, y, x - 30, y + 35,x - 30,y + 35 );
-				heartShape.bezierCurveTo( x - 30, y + 55, x - 10, y + 77, x + 25, y + 95 );
-				heartShape.bezierCurveTo( x + 60, y + 77, x + 80, y + 55, x + 80, y + 35 );
-				heartShape.bezierCurveTo( x + 80, y + 35, x + 80, y, x + 50, y );
-				heartShape.bezierCurveTo( x + 35, y, x + 25, y + 25, x + 25, y + 25 );
-
-				var hue = 0;
-
-				var hearts = function ( context ) {
-
-					context.globalAlpha = 0.5;
-					var x = 0, y = 0;
-					context.scale(0.05, -0.05); // Scale so canvas render can redraw within bounds
-					context.beginPath();
-					 // From http://blog.burlock.org/html5/130-paths
-					context.bezierCurveTo( x + 2.5, y + 2.5, x + 2.0, y, x, y );
-					context.bezierCurveTo( x - 3.0, y, x - 3.0, y + 3.5,x - 3.0,y + 3.5 );
-					context.bezierCurveTo( x - 3.0, y + 5.5, x - 1.0, y + 7.7, x + 2.5, y + 9.5 );
-					context.bezierCurveTo( x + 6.0, y + 7.7, x + 8.0, y + 5.5, x + 8.0, y + 3.5 );
-					context.bezierCurveTo( x + 8.0, y + 3.5, x + 8.0, y, x + 5.0, y );
-					context.bezierCurveTo( x + 3.5, y, x + 2.5, y + 2.5, x + 2.5, y + 2.5 );
-					context.fill();
-					context.lineWidth = 0.5; //0.05
-					context.stroke();
-
-				};
-
-				var setTargetParticle = function() {
-
-					var material = new THREE.SpriteCanvasMaterial( {
-						program: hearts
-					} );
-
-					material.color.setHSL(hue, 1, 0.75);
-					hue += 0.001;
-					if (hue>1) hue-=1;
-
-					particle = new THREE.Sprite( material );
-
-					particle.scale.x = particle.scale.y = Math.random() * 40 + 40;
-					particleCloud.add( particle );
-
-					return particle;
-
-				};
-
-				var onParticleCreated = function( p ) {
-
-					p.target.position.copy( p.position );
-
-				};
-
-				var onParticleDead = function( particle ) {
-
-					particle.target.visible = false;
-					particleCloud.remove( particle.target );
-
-				};
-
-				sparksEmitter = new SPARKS.Emitter(new SPARKS.SteadyCounter(160));
-
-				emitterpos = new THREE.Vector3();
-
-				sparksEmitter.addInitializer(new SPARKS.Position( new SPARKS.PointZone( emitterpos ) ) );
-				sparksEmitter.addInitializer(new SPARKS.Lifetime(0,2));
-				sparksEmitter.addInitializer(new SPARKS.Target(null, setTargetParticle));
-
-				sparksEmitter.addInitializer(new SPARKS.Velocity(new SPARKS.PointZone(new THREE.Vector3(0,-50,10))));
-
-				// TOTRY Set velocity to move away from centroid
-
-				sparksEmitter.addAction(new SPARKS.Age());
-				//sparksEmitter.addAction(new SPARKS.Accelerate(0.2));
-				sparksEmitter.addAction(new SPARKS.Move());
-				sparksEmitter.addAction(new SPARKS.RandomDrift(50,50,2000));
-
-				sparksEmitter.addCallback("created", onParticleCreated);
-				sparksEmitter.addCallback("dead", onParticleDead);
-				sparksEmitter.addCallback("updated", function( particle ) {
-
-					particle.target.position.copy( particle.position );
-
-				});
-
-				sparksEmitter.start();
-
-				// End Particles
-
-
-				renderer = new THREE.CanvasRenderer();
-				renderer.setClearColor( 0xf0f0f0 );
-				renderer.setPixelRatio( window.devicePixelRatio );
-				renderer.setSize( window.innerWidth, window.innerHeight );
-				container.appendChild( renderer.domElement );
-
-				stats = new Stats();
-				stats.domElement.style.position = 'absolute';
-				stats.domElement.style.top = '0px';
-				container.appendChild( stats.domElement );
-
-				document.addEventListener( 'mousedown', onDocumentMouseDown, false );
-				document.addEventListener( 'touchstart', onDocumentTouchStart, false );
-				document.addEventListener( 'touchmove', onDocumentTouchMove, false );
-
-				//
-
-				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 );
-
-			}
-
-			//
-
-			document.addEventListener( 'mousemove', onDocumentMouseMove, false );
-
-			function onDocumentMouseDown( event ) {
-
-				event.preventDefault();
-
-				mouseXOnMouseDown = event.clientX - windowHalfX;
-				targetRotationOnMouseDown = targetRotation;
-
-				if ( sparksEmitter.isRunning() ) {
-
-					sparksEmitter.stop();
-
-				} else {
-
-					sparksEmitter.start();
-
-				}
-
-			}
-
-			function onDocumentMouseMove( event ) {
-
-				mouseX = event.clientX - windowHalfX;
-
-				targetRotation = targetRotationOnMouseDown + ( mouseX - mouseXOnMouseDown ) * 0.02;
-
-			}
-
-			function onDocumentTouchStart( event ) {
-
-				if ( event.touches.length == 1 ) {
-
-					event.preventDefault();
-
-					mouseXOnMouseDown = event.touches[ 0 ].pageX - windowHalfX;
-					targetRotationOnMouseDown = targetRotation;
-
-				}
-
-			}
-
-			function onDocumentTouchMove( event ) {
-
-				if ( event.touches.length == 1 ) {
-
-					event.preventDefault();
-
-					mouseX = event.touches[ 0 ].pageX - windowHalfX;
-					targetRotation = targetRotationOnMouseDown + ( mouseX - mouseXOnMouseDown ) * 0.05;
-
-				}
-
-			}
-
-			//
-
-			function animate() {
-
-				requestAnimationFrame( animate );
-
-				render();
-				stats.update();
-
-			}
-
-			function render() {
-
-				timeOnShapePath += 0.0337;
-
-				if (timeOnShapePath > 1) timeOnShapePath -= 1;
-
-				// TODO Create a PointOnShape Action/Zone in the particle engine
-				var pointOnShape = heartShape.getPointAt( timeOnShapePath );
-
-				emitterpos.x = pointOnShape.x * 5 - 100;
-				emitterpos.y = -pointOnShape.y * 5 + 400;
-
-				// Pretty cool effect if you enable this
-				// particleCloud.rotation.y += 0.05;
-
-				group.rotation.y += ( targetRotation - group.rotation.y ) * 0.05;
-				renderer.render( scene, camera );
-
-			}
-
-		</script>
-
-	</body>
-</html>

+ 3 - 3
examples/canvas_particles_sprites.html

@@ -12,7 +12,7 @@
 			}
 
 			a {
-				color:#0078ff;
+				color: #0078ff;
 			}
 		</style>
 	</head>
@@ -49,7 +49,7 @@
 				scene = new THREE.Scene();
 
 				var material = new THREE.SpriteMaterial( {
-					map: new THREE.Texture( generateSprite() ),
+					map: new THREE.CanvasTexture( generateSprite() ),
 					blending: THREE.AdditiveBlending
 				} );
 
@@ -136,7 +136,7 @@
 
 				new TWEEN.Tween( particle.scale )
 					.delay( delay )
-					.to( { x: 0, y: 0 }, 10000 )
+					.to( { x: 0.01, y: 0.01 }, 10000 )
 					.start();
 
 			}

+ 1 - 1
examples/css3d_molecules.html

@@ -347,7 +347,7 @@
 				loader.load( url, function ( geometry, geometryBonds ) {
 
 					var offset = geometry.center();
-					geometryBonds.applyMatrix( new THREE.Matrix4().makeTranslation( offset.x, offset.y, offset.z ) );
+					geometryBonds.translate( offset.x, offset.y, offset.z );
 
 					for ( var i = 0; i < geometry.vertices.length; i ++ ) {
 

+ 5 - 4
examples/index.html

@@ -225,6 +225,7 @@
 				"webgl_geometry_text",
 				"webgl_geometry_text2",
 				"webgl_gpgpu_birds",
+				"webgl_gpu_particle_system",
 				"webgl_hdr",
 				"webgl_helpers",
 				"webgl_interactive_buffergeometry",
@@ -257,7 +258,10 @@
 				"webgl_loader_ctm_materials",
 				"webgl_loader_gltf",
 				"webgl_loader_json_blender",
+				"webgl_loader_json_claraio",
 				"webgl_loader_json_objconverter",
+				"webgl_loader_md2",
+				"webgl_loader_md2_control",
 				"webgl_loader_msgpack",
 				"webgl_loader_obj",
 				"webgl_loader_obj_mtl",
@@ -266,6 +270,7 @@
 				"webgl_loader_sea3d",
 				"webgl_loader_sea3d_hierarchy",
 				"webgl_loader_sea3d_keyframe",
+				"webgl_loader_sea3d_morph",
 				"webgl_loader_sea3d_skinning",
 				"webgl_loader_sea3d_sound",
 				"webgl_loader_scene",
@@ -314,8 +319,6 @@
 				"webgl_morphtargets",
 				"webgl_morphtargets_horse",
 				"webgl_morphtargets_human",
-				"webgl_morphtargets_md2",
-				"webgl_morphtargets_md2_control",
 				"webgl_multiple_canvases_circle",
 				"webgl_multiple_canvases_complex",
 				"webgl_multiple_canvases_grid",
@@ -331,7 +334,6 @@
 				"webgl_particles_billboards_colors",
 				"webgl_particles_dynamic",
 				"webgl_particles_random",
-				"webgl_particles_shapes",
 				"webgl_particles_sprites",
 				"webgl_performance",
 				"webgl_performance_doublesided",
@@ -457,7 +459,6 @@
 				"canvas_morphtargets_horse",
 				"canvas_particles_floor",
 				"canvas_particles_random",
-				"canvas_particles_shapes",
 				"canvas_particles_sprites",
 				"canvas_particles_waves",
 				"canvas_performance",

+ 515 - 0
examples/js/GPUParticleSystem.js

@@ -0,0 +1,515 @@
+/*
+ * GPU Particle System
+ * @author flimshaw - Charlie Hoey - http://charliehoey.com
+ *
+ * A simple to use, general purpose GPU system.  Particles are spawn-and-forget with
+ * several options available, and do not require monitoring or cleanup after spawning.
+ * Because the paths of all particles are completely deterministic once spawned, the scale
+ * and direction of time is also variable.
+ *
+ * Currently uses a static wrapping perlin noise texture for turbulence, and a small png texture for
+ * particles, but adding support for a particle texture atlas or changing to a different type of turbulence
+ * would be a fairly light day's work.
+ *
+ * Shader and javascript packing code derrived from several Stack Overflow examples.
+ *
+ */
+
+THREE.GPUParticleSystem = function(options) {
+
+  var self = this;
+  var options = options || {};
+
+  // parse options and use defaults
+  self.PARTICLE_COUNT = options.maxParticles || 1000000;
+  self.PARTICLE_CONTAINERS = options.containerCount || 1;
+  self.PARTICLES_PER_CONTAINER = Math.ceil(self.PARTICLE_COUNT / self.PARTICLE_CONTAINERS);
+  self.PARTICLE_CURSOR = 0;
+  self.time = 0;
+
+
+  // Custom vertex and fragement shader
+  var GPUParticleShader = {
+
+    vertexShader: [
+
+      'precision highp float;',
+      'const vec4 bitSh = vec4(256. * 256. * 256., 256. * 256., 256., 1.);',
+      'const vec4 bitMsk = vec4(0.,vec3(1./256.0));',
+      'const vec4 bitShifts = vec4(1.) / bitSh;',
+
+      '#define FLOAT_MAX  1.70141184e38',
+      '#define FLOAT_MIN  1.17549435e-38',
+
+      'lowp vec4 encode_float(highp float v) {',
+      'highp float av = abs(v);',
+
+      '//Handle special cases',
+      'if(av < FLOAT_MIN) {',
+      'return vec4(0.0, 0.0, 0.0, 0.0);',
+      '} else if(v > FLOAT_MAX) {',
+      'return vec4(127.0, 128.0, 0.0, 0.0) / 255.0;',
+      '} else if(v < -FLOAT_MAX) {',
+      'return vec4(255.0, 128.0, 0.0, 0.0) / 255.0;',
+      '}',
+
+      'highp vec4 c = vec4(0,0,0,0);',
+
+      '//Compute exponent and mantissa',
+      'highp float e = floor(log2(av));',
+      'highp float m = av * pow(2.0, -e) - 1.0;',
+
+      //Unpack mantissa
+      'c[1] = floor(128.0 * m);',
+      'm -= c[1] / 128.0;',
+      'c[2] = floor(32768.0 * m);',
+      'm -= c[2] / 32768.0;',
+      'c[3] = floor(8388608.0 * m);',
+
+      '//Unpack exponent',
+      'highp float ebias = e + 127.0;',
+      'c[0] = floor(ebias / 2.0);',
+      'ebias -= c[0] * 2.0;',
+      'c[1] += floor(ebias) * 128.0;',
+
+      '//Unpack sign bit',
+      'c[0] += 128.0 * step(0.0, -v);',
+
+      '//Scale back to range',
+      'return c / 255.0;',
+      '}',
+
+      'vec4 pack(const in float depth)',
+      '{',
+      'const vec4 bit_shift = vec4(256.0*256.0*256.0, 256.0*256.0, 256.0, 1.0);',
+      'const vec4 bit_mask  = vec4(0.0, 1.0/256.0, 1.0/256.0, 1.0/256.0);',
+      'vec4 res = fract(depth * bit_shift);',
+      'res -= res.xxyz * bit_mask;',
+      'return res;',
+      '}',
+
+      'float unpack(const in vec4 rgba_depth)',
+      '{',
+      'const vec4 bit_shift = vec4(1.0/(256.0*256.0*256.0), 1.0/(256.0*256.0), 1.0/256.0, 1.0);',
+      'float depth = dot(rgba_depth, bit_shift);',
+      'return depth;',
+      '}',
+
+      'uniform float uTime;',
+      'uniform float uScale;',
+      'uniform sampler2D tNoise;',
+
+      'attribute vec4 particlePositionsStartTime;',
+      'attribute vec4 particleVelColSizeLife;',
+
+      'varying vec4 vColor;',
+      'varying float lifeLeft;',
+
+      'void main() {',
+
+      '// unpack things from our attributes',
+      'vColor = encode_float( particleVelColSizeLife.y );',
+
+      '// convert our velocity back into a value we can use',
+      'vec4 velTurb = encode_float( particleVelColSizeLife.x );',
+      'vec3 velocity = vec3( velTurb.xyz );',
+      'float turbulence = velTurb.w;',
+
+      'vec3 newPosition;',
+
+      'float timeElapsed = uTime - particlePositionsStartTime.a;',
+
+      'lifeLeft = 1. - (timeElapsed / particleVelColSizeLife.w);',
+
+      'gl_PointSize = ( uScale * particleVelColSizeLife.z ) * lifeLeft;',
+
+      'velocity.x = ( velocity.x - .5 ) * 3.;',
+      'velocity.y = ( velocity.y - .5 ) * 3.;',
+      'velocity.z = ( velocity.z - .5 ) * 3.;',
+
+      'newPosition = particlePositionsStartTime.xyz + ( velocity * 10. ) * ( uTime - particlePositionsStartTime.a );',
+
+      'vec3 noise = texture2D( tNoise, vec2( newPosition.x * .015 + (uTime * .05), newPosition.y * .02 + (uTime * .015) )).rgb;',
+      'vec3 noiseVel = ( noise.rgb - .5 ) * 30.;',
+
+      'newPosition = mix(newPosition, newPosition + vec3(noiseVel * ( turbulence * 5. ) ), (timeElapsed / particleVelColSizeLife.a) );',
+
+      'if( velocity.y > 0. && velocity.y < .05 ) {',
+      'lifeLeft = 0.;',
+      '}',
+
+      'if( velocity.x < -1.45 ) {',
+      'lifeLeft = 0.;',
+      '}',
+
+      'if( timeElapsed > 0. ) {',
+      'gl_Position = projectionMatrix * modelViewMatrix * vec4( newPosition, 1.0 );',
+      '} else {',
+      'gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );',
+      'lifeLeft = 0.;',
+      'gl_PointSize = 0.;',
+      '}',
+      '}'
+
+    ].join("\n"),
+
+    fragmentShader: [
+
+      'float scaleLinear(float value, vec2 valueDomain) {',
+      'return (value - valueDomain.x) / (valueDomain.y - valueDomain.x);',
+      '}',
+
+      'float scaleLinear(float value, vec2 valueDomain, vec2 valueRange) {',
+      'return mix(valueRange.x, valueRange.y, scaleLinear(value, valueDomain));',
+      '}',
+
+      'varying vec4 vColor;',
+      'varying float lifeLeft;',
+
+      'uniform sampler2D tSprite;',
+
+      'void main() {',
+
+      'float alpha = 0.;',
+
+      'if( lifeLeft > .995 ) {',
+      'alpha = scaleLinear( lifeLeft, vec2(1., .995), vec2(0., 1.));//mix( 0., 1., ( lifeLeft - .95 ) * 100. ) * .75;',
+      '} else {',
+      'alpha = lifeLeft * .75;',
+      '}',
+
+      'vec4 tex = texture2D( tSprite, gl_PointCoord );',
+
+      'gl_FragColor = vec4( vColor.rgb * tex.a, alpha * tex.a );',
+      '}'
+
+    ].join("\n")
+
+  };
+
+  // preload a million random numbers
+  self.rand = [];
+
+  for (var i = 1e5; i > 0; i--) {
+    self.rand.push(Math.random() - .5);
+  }
+
+  self.random = function() {
+    return ++i >= self.rand.length ? self.rand[i = 1] : self.rand[i];
+  }
+
+  self.particleNoiseTex = THREE.ImageUtils.loadTexture("textures/perlin-512.png");
+  self.particleNoiseTex.wrapS = self.particleNoiseTex.wrapT = THREE.RepeatWrapping;
+
+  self.particleSpriteTex = THREE.ImageUtils.loadTexture("textures/particle2.png");
+  self.particleSpriteTex.wrapS = self.particleSpriteTex.wrapT = THREE.RepeatWrapping;
+
+  self.particleShaderMat = new THREE.ShaderMaterial({
+    transparent: true,
+    depthWrite: false,
+    uniforms: {
+      "uTime": {
+        type: "f",
+        value: 0.0
+      },
+      "uScale": {
+        type: "f",
+        value: 1.0
+      },
+      "tNoise": {
+        type: "t",
+        value: self.particleNoiseTex
+      },
+      "tSprite": {
+        type: "t",
+        value: self.particleSpriteTex
+      }
+    },
+    attributes: {
+      "particlePositionsStartTime": {
+        type: "v4",
+        value: []
+      },
+      "particleVelColSizeLife": {
+        type: "v4",
+        value: []
+      }
+    },
+    blending: THREE.AdditiveBlending,
+    vertexShader: GPUParticleShader.vertexShader,
+    fragmentShader: GPUParticleShader.fragmentShader
+  });
+
+  // define defaults for all values
+  self.particleShaderMat.defaultAttributeValues.particlePositionsStartTime = [0, 0, 0, 0];
+  self.particleShaderMat.defaultAttributeValues.particleVelColSizeLife = [0, 0, 0, 0];
+
+  self.particleContainers = [];
+
+
+  // extend Object3D
+  THREE.Object3D.apply(this, arguments);
+
+  this.init = function() {
+
+    for (var i = 0; i < self.PARTICLE_CONTAINERS; i++) {
+
+      var c = new THREE.GPUParticleContainer(self.PARTICLES_PER_CONTAINER, self);
+      self.particleContainers.push(c);
+      self.add(c);
+
+    }
+
+  }
+
+  this.spawnParticle = function(options) {
+
+    self.PARTICLE_CURSOR++;
+    if (self.PARTICLE_CURSOR >= self.PARTICLE_COUNT) {
+      self.PARTICLE_CURSOR = 1;
+    }
+
+    var currentContainer = self.particleContainers[Math.floor(self.PARTICLE_CURSOR / self.PARTICLES_PER_CONTAINER)];
+
+    currentContainer.spawnParticle(options);
+
+  }
+
+  this.update = function(time) {
+    for (var i = 0; i < self.PARTICLE_CONTAINERS; i++) {
+
+      self.particleContainers[i].update(time);
+
+    }
+  };
+
+  this.init();
+
+}
+
+THREE.GPUParticleSystem.prototype = Object.create(THREE.Object3D.prototype);
+THREE.GPUParticleSystem.prototype.constructor = THREE.GPUParticleSystem;
+
+
+// Subclass for particle containers, allows for very large arrays to be spread out
+THREE.GPUParticleContainer = function(maxParticles, particleSystem) {
+
+  var self = this;
+  self.PARTICLE_COUNT = maxParticles || 100000;
+  self.PARTICLE_CURSOR = 0;
+  self.time = 0;
+  self.DPR = window.devicePixelRatio;
+  self.GPUParticleSystem = particleSystem;
+
+  var particlesPerArray = Math.floor(self.PARTICLE_COUNT / self.MAX_ATTRIBUTES);
+
+  // extend Object3D
+  THREE.Object3D.apply(this, arguments);
+
+  // construct a couple small arrays used for packing variables into floats etc
+  var UINT8_VIEW = new Uint8Array(4)
+  var FLOAT_VIEW = new Float32Array(UINT8_VIEW.buffer)
+
+  function decodeFloat(x, y, z, w) {
+    UINT8_VIEW[0] = Math.floor(w)
+    UINT8_VIEW[1] = Math.floor(z)
+    UINT8_VIEW[2] = Math.floor(y)
+    UINT8_VIEW[3] = Math.floor(x)
+    return FLOAT_VIEW[0]
+  }
+
+  function componentToHex(c) {
+    var hex = c.toString(16);
+    return hex.length == 1 ? "0" + hex : hex;
+  }
+
+  function rgbToHex(r, g, b) {
+    return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
+  }
+
+  function hexToRgb(hex) {
+    var r = hex >> 16;
+    var g = (hex & 0x00FF00) >> 8;
+    var b = hex & 0x0000FF;
+
+    if (r > 0) r--;
+    if (g > 0) g--;
+    if (b > 0) b--;
+
+    return [r, g, b];
+  };
+
+  self.particles = [];
+  self.deadParticles = [];
+  self.particlesAvailableSlot = [];
+
+  // create a container for particles
+  self.particleUpdate = false;
+
+  // Shader Based Particle System
+  self.particleShaderGeo = new THREE.BufferGeometry();
+
+  // new hyper compressed attributes
+  self.particleVertices = new Float32Array(self.PARTICLE_COUNT * 3); // position
+  self.particlePositionsStartTime = new Float32Array(self.PARTICLE_COUNT * 4); // position
+  self.particleVelColSizeLife = new Float32Array(self.PARTICLE_COUNT * 4);
+
+  for (var i = 0; i < self.PARTICLE_COUNT; i++) {
+    self.particlePositionsStartTime[i * 4 + 0] = 100; //x
+    self.particlePositionsStartTime[i * 4 + 1] = 0; //y
+    self.particlePositionsStartTime[i * 4 + 2] = 0.0; //z
+    self.particlePositionsStartTime[i * 4 + 3] = 0.0; //startTime
+
+    self.particleVertices[i * 3 + 0] = 0; //x
+    self.particleVertices[i * 3 + 1] = 0; //y
+    self.particleVertices[i * 3 + 2] = 0.0; //z
+
+    self.particleVelColSizeLife[i * 4 + 0] = decodeFloat(128, 128, 0, 0); //vel
+    self.particleVelColSizeLife[i * 4 + 1] = decodeFloat(0, 254, 0, 254); //color
+    self.particleVelColSizeLife[i * 4 + 2] = 1.0; //size
+    self.particleVelColSizeLife[i * 4 + 3] = 0.0; //lifespan
+  }
+
+  self.particleShaderGeo.addAttribute('position', new THREE.BufferAttribute(self.particleVertices, 3));
+  self.particleShaderGeo.addAttribute('particlePositionsStartTime', new THREE.DynamicBufferAttribute(self.particlePositionsStartTime, 4));
+  self.particleShaderGeo.addAttribute('particleVelColSizeLife', new THREE.DynamicBufferAttribute(self.particleVelColSizeLife, 4));
+
+  self.posStart = self.particleShaderGeo.getAttribute('particlePositionsStartTime')
+  self.velCol = self.particleShaderGeo.getAttribute('particleVelColSizeLife');
+
+  self.particleShaderMat = self.GPUParticleSystem.particleShaderMat;
+
+  this.init = function() {
+    self.particleSystem = new THREE.PointCloud(self.particleShaderGeo, self.particleShaderMat);
+    self.particleSystem.frustumCulled = false;
+    this.add(self.particleSystem);
+  };
+
+  var options = {},
+    position = new THREE.Vector3(),
+    velocity = new THREE.Vector3(),
+    positionRandomness = 0.,
+    velocityRandomness = 0.,
+    color = 0xffffff,
+    colorRandomness = 0.,
+    turbulence = 0.,
+    lifetime = 0.,
+    size = 0.,
+    sizeRandomness = 0.,
+    i;
+
+  var maxVel = 2;
+  var maxSource = 250;
+  this.offset = 0;
+  this.count = 0;
+
+  this.spawnParticle = function(options) {
+
+    options = options || {};
+
+    // setup reasonable default values for all arguments
+    position = options.position !== undefined ? position.copy(options.position) : position.set(0., 0., 0.);
+    velocity = options.velocity !== undefined ? velocity.copy(options.velocity) : velocity.set(0., 0., 0.);
+    positionRandomness = options.positionRandomness !== undefined ? options.positionRandomness : 0.0;
+    velocityRandomness = options.velocityRandomness !== undefined ? options.velocityRandomness : 0.0;
+    color = options.color !== undefined ? options.color : 0xffffff;
+    colorRandomness = options.colorRandomness !== undefined ? options.colorRandomness : 1.0;
+    turbulence = options.turbulence !== undefined ? options.turbulence : 1.0;
+    lifetime = options.lifetime !== undefined ? options.lifetime : 5.0;
+    size = options.size !== undefined ? options.size : 10;
+    sizeRandomness = options.sizeRandomness !== undefined ? options.sizeRandomness : 0.0,
+      smoothPosition = options.smoothPosition !== undefined ? options.smoothPosition : false;
+
+    if (self.DPR !== undefined) size *= self.DPR;
+
+    i = self.PARTICLE_CURSOR;
+
+    self.posStart.array[i * 4 + 0] = position.x + ((particleSystem.random()) * positionRandomness); // - ( velocity.x * particleSystem.random() ); //x
+    self.posStart.array[i * 4 + 1] = position.y + ((particleSystem.random()) * positionRandomness); // - ( velocity.y * particleSystem.random() ); //y
+    self.posStart.array[i * 4 + 2] = position.z + ((particleSystem.random()) * positionRandomness); // - ( velocity.z * particleSystem.random() ); //z
+    self.posStart.array[i * 4 + 3] = self.time + (particleSystem.random() * 2e-2); //startTime
+
+    if (smoothPosition === true) {
+      self.posStart.array[i * 4 + 0] += -(velocity.x * particleSystem.random()); //x
+      self.posStart.array[i * 4 + 1] += -(velocity.y * particleSystem.random()); //y
+      self.posStart.array[i * 4 + 2] += -(velocity.z * particleSystem.random()); //z
+    }
+
+    var velX = velocity.x + (particleSystem.random()) * velocityRandomness;
+    var velY = velocity.y + (particleSystem.random()) * velocityRandomness;
+    var velZ = velocity.z + (particleSystem.random()) * velocityRandomness;
+
+    // convert turbulence rating to something we can pack into a vec4
+    var turbulence = Math.floor(turbulence * 254);
+
+    // clamp our value to between 0. and 1.
+    velX = Math.floor(maxSource * ((velX - -maxVel) / (maxVel - -maxVel)));
+    velY = Math.floor(maxSource * ((velY - -maxVel) / (maxVel - -maxVel)));
+    velZ = Math.floor(maxSource * ((velZ - -maxVel) / (maxVel - -maxVel)));
+
+    self.velCol.array[i * 4 + 0] = decodeFloat(velX, velY, velZ, turbulence); //vel
+
+    var rgb = hexToRgb(color);
+
+    for (var c = 0; c < rgb.length; c++) {
+      rgb[c] = Math.floor(rgb[c] + ((particleSystem.random()) * colorRandomness) * 254);
+      if (rgb[c] > 254) rgb[c] = 254;
+      if (rgb[c] < 0) rgb[c] = 0;
+    }
+
+    self.velCol.array[i * 4 + 1] = decodeFloat(rgb[0], rgb[1], rgb[2], 254); //color
+    self.velCol.array[i * 4 + 2] = size + (particleSystem.random()) * sizeRandomness; //size
+    self.velCol.array[i * 4 + 3] = lifetime; //lifespan
+
+    if (this.offset == 0) {
+      this.offset = self.PARTICLE_CURSOR;
+    }
+
+    self.count++;
+
+    self.PARTICLE_CURSOR++;
+
+    if (self.PARTICLE_CURSOR >= self.PARTICLE_COUNT) {
+      self.PARTICLE_CURSOR = 0;
+    }
+
+    self.particleUpdate = true;
+
+  }
+
+  this.update = function(time) {
+
+    self.time = time;
+    self.particleShaderMat.uniforms['uTime'].value = time;
+
+    this.geometryUpdate();
+
+  };
+
+  this.geometryUpdate = function() {
+    if (self.particleUpdate == true) {
+      self.particleUpdate = false;
+
+      // if we can get away with a partial buffer update, do so
+      if (self.offset + self.count < self.PARTICLE_COUNT) {
+        self.posStart.updateRange.offset = self.velCol.updateRange.offset = self.offset * 4;
+        self.posStart.updateRange.count = self.velCol.updateRange.count = self.count * 4;
+      } else {
+        self.posStart.updateRange.offset = 0;
+        self.posStart.updateRange.count = self.velCol.updateRange.count = (self.PARTICLE_COUNT * 4);
+      }
+
+      self.posStart.needsUpdate = true;
+      self.velCol.needsUpdate = true;
+
+      self.offset = 0;
+      self.count = 0;
+    }
+  }
+
+  this.init();
+
+}
+
+THREE.GPUParticleContainer.prototype = Object.create(THREE.Object3D.prototype);
+THREE.GPUParticleContainer.prototype.constructor = THREE.GPUParticleContainer;

+ 1 - 1
src/extras/core/Gyroscope.js → examples/js/Gyroscope.js

@@ -29,7 +29,7 @@ THREE.Gyroscope.prototype.updateMatrixWorld = ( function () {
 
 		if ( this.matrixWorldNeedsUpdate || force ) {
 
-			if ( this.parent ) {
+			if ( this.parent !== null ) {
 
 				this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
 

+ 3 - 7
examples/js/MD2Character.js

@@ -39,7 +39,7 @@ THREE.MD2Character = function () {
 
 		// BODY
 
-		var loader = new THREE.JSONLoader();
+		var loader = new THREE.MD2Loader();
 
 		loader.load( config.baseUrl + config.body, function( geo ) {
 
@@ -199,12 +199,8 @@ THREE.MD2Character = function () {
 
 	function createPart( geometry, skinMap ) {
 
-		geometry.computeMorphNormals();
-
-		var whiteMap = THREE.ImageUtils.generateDataTexture( 1, 1, new THREE.Color( 0xffffff ) );
-		var materialWireframe = new THREE.MeshPhongMaterial( { color: 0xffaa00, specular: 0x111111, shininess: 50, wireframe: true, shading: THREE.SmoothShading, map: whiteMap, morphTargets: true, morphNormals: true, metal: false } );
-
-		var materialTexture = new THREE.MeshPhongMaterial( { color: 0xffffff, specular: 0x111111, shininess: 50, wireframe: false, shading: THREE.SmoothShading, map: skinMap, morphTargets: true, morphNormals: true, metal: false } );
+		var materialWireframe = new THREE.MeshLambertMaterial( { color: 0xffaa00, wireframe: true, shading: THREE.SmoothShading, morphTargets: true, morphNormals: true } );
+		var materialTexture = new THREE.MeshLambertMaterial( { color: 0xffffff, wireframe: false, shading: THREE.SmoothShading, map: skinMap, morphTargets: true, morphNormals: true } );
 
 		//
 

+ 3 - 7
examples/js/MD2CharacterComplex.js

@@ -152,7 +152,7 @@ THREE.MD2CharacterComplex = function () {
 
 		// BODY
 
-		var loader = new THREE.JSONLoader();
+		var loader = new THREE.MD2Loader();
 
 		loader.load( config.baseUrl + config.body, function( geo ) {
 
@@ -522,12 +522,8 @@ THREE.MD2CharacterComplex = function () {
 
 	function createPart( geometry, skinMap ) {
 
-		geometry.computeMorphNormals();
-
-		var whiteMap = THREE.ImageUtils.generateDataTexture( 1, 1, new THREE.Color( 0xffffff ) );
-		var materialWireframe = new THREE.MeshPhongMaterial( { color: 0xffaa00, specular: 0x111111, shininess: 50, wireframe: true, shading: THREE.SmoothShading, map: whiteMap, morphTargets: true, morphNormals: true, metal: true } );
-
-		var materialTexture = new THREE.MeshPhongMaterial( { color: 0xffffff, specular: 0x111111, shininess: 50, wireframe: false, shading: THREE.SmoothShading, map: skinMap, morphTargets: true, morphNormals: true, metal: true } );
+		var materialWireframe = new THREE.MeshLambertMaterial( { color: 0xffaa00, wireframe: true, shading: THREE.SmoothShading, morphTargets: true, morphNormals: true } );
+		var materialTexture = new THREE.MeshLambertMaterial( { color: 0xffffff, wireframe: false, shading: THREE.SmoothShading, map: skinMap, morphTargets: true, morphNormals: true } );
 
 		//
 

+ 15 - 15
examples/js/MarchingCubes.js

@@ -47,8 +47,6 @@ THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors )
 		this.vlist = new Float32Array( 12 * 3 );
 		this.nlist = new Float32Array( 12 * 3 );
 
-		this.firstDraw = true;
-
 		// immediate render mode simulator
 
 		this.maxCount = 4096; // TODO: find the fastest size for this buffer
@@ -430,12 +428,14 @@ THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors )
 
 	this.end = function( renderCallback ) {
 
-		if ( this.count === 0 )
-			return;
+		if ( this.count === 0 ) return;
+
+		for ( var i = this.count * 3; i < this.positionArray.length; i ++ ) {
 
-		for ( var i = this.count * 3; i < this.positionArray.length; i ++ )
 			this.positionArray[ i ] = 0.0;
 
+		}
+
 		this.hasPositions = true;
 		this.hasNormals = true;
 
@@ -657,22 +657,22 @@ THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors )
 
 		// Triangulate. Yeah, this is slow.
 
-		var q, x, y, z, fx, fy, fz, y_offset, z_offset, smin2 = this.size - 2;
+		var smin2 = this.size - 2;
 
-		for ( z = 1; z < smin2; z ++ ) {
+		for ( var z = 1; z < smin2; z ++ ) {
 
-			z_offset = this.size2 * z;
-			fz = ( z - this.halfsize ) / this.halfsize; //+ 1
+			var z_offset = this.size2 * z;
+			var fz = ( z - this.halfsize ) / this.halfsize; //+ 1
 
-			for ( y = 1; y < smin2; y ++ ) {
+			for ( var y = 1; y < smin2; y ++ ) {
 
-				y_offset = z_offset + this.size * y;
-				fy = ( y - this.halfsize ) / this.halfsize; //+ 1
+				var y_offset = z_offset + this.size * y;
+				var fy = ( y - this.halfsize ) / this.halfsize; //+ 1
 
-				for ( x = 1; x < smin2; x ++ ) {
+				for ( var x = 1; x < smin2; x ++ ) {
 
-					fx = ( x - this.halfsize ) / this.halfsize; //+ 1
-					q = y_offset + x;
+					var fx = ( x - this.halfsize ) / this.halfsize; //+ 1
+					var q = y_offset + x;
 
 					this.polygonize( fx, fy, fz, q, this.isolation, renderCallback );
 

+ 4 - 4
examples/js/Mirror.js

@@ -37,7 +37,7 @@ THREE.ShaderLib[ 'mirror' ] = {
 		"float blendOverlay(float base, float blend) {",
 			"return( base < 0.5 ? ( 2.0 * base * blend ) : (1.0 - 2.0 * ( 1.0 - base ) * ( 1.0 - blend ) ) );",
 		"}",
-		
+
 		"void main() {",
 
 			"vec4 color = texture2DProj(mirrorSampler, mirrorCoord);",
@@ -76,7 +76,7 @@ THREE.Mirror = function ( renderer, camera, options ) {
 	this.rotationMatrix = new THREE.Matrix4();
 	this.lookAtPosition = new THREE.Vector3( 0, 0, - 1 );
 	this.clipPlane = new THREE.Vector4();
-	
+
 	// For debug only, show the normal and plane of the mirror
 	var debugMode = options.debugMode !== undefined ? options.debugMode : false;
 
@@ -257,7 +257,7 @@ THREE.Mirror.prototype.render = function () {
 	// Render the mirrored view of the current scene into the target texture
 	var scene = this;
 
-	while ( scene.parent !== undefined ) {
+	while ( scene.parent !== null ) {
 
 		scene = scene.parent;
 
@@ -286,7 +286,7 @@ THREE.Mirror.prototype.renderTemp = function () {
 	// Render the mirrored view of the current scene into the target texture
 	var scene = this;
 
-	while ( scene.parent !== undefined ) {
+	while ( scene.parent !== null ) {
 
 		scene = scene.parent;
 

+ 1 - 1
examples/js/Ocean.js

@@ -210,7 +210,7 @@ THREE.Ocean.prototype.generateMesh = function () {
 
 	var geometry = new THREE.PlaneBufferGeometry( this.geometrySize, this.geometrySize, this.geometryResolution, this.geometryResolution );
 
-	geometry.applyMatrix( new THREE.Matrix4().makeRotationX( - Math.PI / 2 ) );
+	geometry.rotateX( - Math.PI / 2 );
 
 	this.oceanMesh = new THREE.Mesh( geometry, this.materialOcean );
 

+ 0 - 981
examples/js/Sparks.js

@@ -1,981 +0,0 @@
-/*
- * @author zz85 (http://github.com/zz85 http://www.lab4games.net/zz85/blog)
- *
- * a simple to use javascript 3d particles system inspired by FliNT and Stardust
- * created with TWEEN.js and THREE.js
- *
- * for feature requests or bugs, please visit https://github.com/zz85/sparks.js
- *
- * licensed under the MIT license
- */
-
-var SPARKS = {};
-
-/********************************
-* Emitter Class
-*
-*   Creates and Manages Particles
-*********************************/
-
-SPARKS.Emitter = function ( counter ) {
-
-	this._counter = counter ? counter : new SPARKS.SteadyCounter( 10 ); // provides number of particles to produce
-
-	this._particles = [];
-
-
-	this._initializers = []; // use for creation of particles
-	this._actions = [];     // uses action to update particles
-	this._activities = [];  //  not supported yet
-
-	this._handlers = [];
-
-	this.callbacks = {};
-
-};
-
-
-SPARKS.Emitter.prototype = {
-
-	_TIMESTEP: 15,
-	_timer: null,
-	_lastTime: null,
-	_timerStep: 10,
-	_velocityVerlet: true,
-
-	// run its built in timer / stepping
-	start: function() {
-
-		this._lastTime = Date.now();
-		this._timer = setTimeout( this.step, this._timerStep, this );
-		this._isRunning = true;
-
-	},
-
-	stop: function() {
-
-		this._isRunning = false;
-		clearTimeout( this._timer );
-
-	},
-
-	isRunning: function() {
-
-		return this._isRunning & true;
-
-	},
-
-	// Step gets called upon by the engine
-	// but attempts to call update() on a regular basics
-	// This method is also described in http://gameclosure.com/2011/04/11/deterministic-delta-tee-in-js-games/
-	step: function( emitter ) {
-
-		var time = Date.now();
-		var elapsed = time - emitter._lastTime;
-
-		if ( ! this._velocityVerlet ) {
-
-			// if elapsed is way higher than time step, (usually after switching tabs, or excution cached in ff)
-			// we will drop cycles. perhaps set to a limit of 10 or something?
-			var maxBlock = emitter._TIMESTEP * 20;
-
-			if ( elapsed >= maxBlock ) {
-
-				//console.log('warning: sparks.js is fast fowarding engine, skipping steps', elapsed / emitter._TIMESTEP);
-				//emitter.update( (elapsed - maxBlock) / 1000);
-				elapsed = maxBlock;
-
-			}
-
-			while ( elapsed >= emitter._TIMESTEP ) {
-
-				emitter.update( emitter._TIMESTEP / 1000 );
-				elapsed -= emitter._TIMESTEP;
-
-			}
-			emitter._lastTime = time - elapsed;
-
-		} else {
-
-			emitter.update( elapsed / 1000 );
-			emitter._lastTime = time;
-
-		}
-
-
-
-		if ( emitter._isRunning )
-		setTimeout( emitter.step, emitter._timerStep, emitter );
-
-	},
-
-
-	// Update particle engine in seconds, not milliseconds
-	update: function( time ) {
-
-		var i, j;
-		var len = this._counter.updateEmitter( this, time );
-
-		// Create particles
-		for ( i = 0; i < len; i ++ ) {
-
-			this.createParticle();
-
-		}
-
-		// Update activities
-		len = this._activities.length;
-		for ( i = 0; i < len; i ++ ) {
-
-			this._activities[ i ].update( this, time );
-
-		}
-
-
-		len = this._actions.length;
-
-		var particle;
-		var action;
-		var len2 = this._particles.length;
-
-		for ( j = 0; j < len; j ++ ) {
-
-			action = this._actions[ j ];
-			for ( i = 0; i < len2; ++ i ) {
-
-				particle = this._particles[ i ];
-				action.update( this, particle, time );
-
-			}
-
-		}
-
-
-		// remove dead particles
-		for ( i = len2; i --; ) {
-
-			particle = this._particles[ i ];
-			if ( particle.isDead ) {
-
-				//particle =
-				this._particles.splice( i, 1 );
-				this.dispatchEvent( "dead", particle );
-				SPARKS.VectorPool.release( particle.position ); //
-				SPARKS.VectorPool.release( particle.velocity );
-
-			} else {
-
-				this.dispatchEvent( "updated", particle );
-
-			}
-
-		}
-
-		this.dispatchEvent( "loopUpdated" );
-
-	},
-
-	createParticle: function() {
-
-		var particle = new SPARKS.Particle();
-		// In future, use a Particle Factory
-		var len = this._initializers.length, i;
-
-		for ( i = 0; i < len; i ++ ) {
-
-			this._initializers[ i ].initialize( this, particle );
-
-		}
-
-		this._particles.push( particle );
-
-		this.dispatchEvent( "created", particle ); // ParticleCreated
-
-		return particle;
-
-	},
-
-	addInitializer: function ( initializer ) {
-
-		this._initializers.push( initializer );
-
-	},
-
-	addAction: function ( action ) {
-
-		this._actions.push( action );
-
-	},
-
-	removeInitializer: function ( initializer ) {
-
-		var index = this._initializers.indexOf( initializer );
-		if ( index > - 1 ) {
-
-			this._initializers.splice( index, 1 );
-
-		}
-
-	},
-
-	removeAction: function ( action ) {
-
-		var index = this._actions.indexOf( action );
-		if ( index > - 1 ) {
-
-			this._actions.splice( index, 1 );
-
-		}
-		//console.log('removeAction', index, this._actions);
-
-	},
-
-	addCallback: function( name, callback ) {
-
-		this.callbacks[ name ] = callback;
-
-	},
-
-	dispatchEvent: function( name, args ) {
-
-		var callback = this.callbacks[ name ];
-		if ( callback ) {
-
-			callback( args );
-
-		}
-
-	}
-
-
-};
-
-
-/*
- * Constant Names for
- * Events called by emitter.dispatchEvent()
- *
- */
-SPARKS.EVENT_PARTICLE_CREATED = "created";
-SPARKS.EVENT_PARTICLE_UPDATED = "updated";
-SPARKS.EVENT_PARTICLE_DEAD = "dead";
-SPARKS.EVENT_LOOP_UPDATED = "loopUpdated";
-
-
-
-/*
- * Steady Counter attempts to produces a particle rate steadily
- *
- */
-
-// Number of particles per seconds
-SPARKS.SteadyCounter = function( rate ) {
-
-	this.rate = rate;
-
-	// we use a shortfall counter to make up for slow emitters
-	this.leftover = 0;
-
-};
-
-SPARKS.SteadyCounter.prototype.updateEmitter = function( emitter, time ) {
-
-	var targetRelease = time * this.rate + this.leftover;
-	var actualRelease = Math.floor( targetRelease );
-
-	this.leftover = targetRelease - actualRelease;
-
-	return actualRelease;
-
-};
-
-
-/*
- * Shot Counter produces specified particles
- * on a single impluse or burst
- */
-
-SPARKS.ShotCounter = function( particles ) {
-
-	this.particles = particles;
-	this.used = false;
-
-};
-
-SPARKS.ShotCounter.prototype.updateEmitter = function( emitter, time ) {
-
-	if ( this.used ) {
-
-		return 0;
-
-	} else {
-
-		this.used = true;
-
-	}
-
-	return this.particles;
-
-};
-
-
-/********************************
-* Particle Class
-*
-*   Represents a single particle
-*********************************/
-SPARKS.Particle = function() {
-
-	/**
-	     * The lifetime of the particle, in seconds.
-	     */
-	this.lifetime = 0;
-
-	/**
-	     * The age of the particle, in seconds.
-	     */
-	this.age = 0;
-
-	/**
-	     * The energy of the particle.
-	     */
-	this.energy = 1;
-
-	/**
-	     * Whether the particle is dead and should be removed from the stage.
-	     */
-	this.isDead = false;
-
-	this.target = null; // tag
-
-	/**
-	     * For 3D
-	     */
-	
-	this.position = SPARKS.VectorPool.get().set( 0, 0, 0 ); //new THREE.Vector3( 0, 0, 0 );
-	this.velocity = SPARKS.VectorPool.get().set( 0, 0, 0 ); //new THREE.Vector3( 0, 0, 0 );
-	this._oldvelocity = SPARKS.VectorPool.get().set( 0, 0, 0 );
-	// rotation vec3
-	// angVelocity vec3
-	// faceAxis vec3
-
-};
-
-
-/********************************
-* Action Classes
-*
-*   An abstract class which have
-*   update function
-*********************************/
-SPARKS.Action = function() {
-
-	this._priority = 0;
-
-};
-
-
-SPARKS.Age = function( easing ) {
-
-	this._easing = ( easing == null ) ? TWEEN.Easing.Linear.None : easing;
-
-};
-
-SPARKS.Age.prototype.update = function ( emitter, particle, time ) {
-
-	particle.age += time;
-	if ( particle.age >= particle.lifetime ) {
-
-		particle.energy = 0;
-		particle.isDead = true;
-
-	} else {
-
-		var t = this._easing( particle.age / particle.lifetime );
-		particle.energy = - 1 * t + 1;
-
-	}
-
-};
-
-/*
-// Mark particle as dead when particle's < 0
-
-SPARKS.Death = function(easing) {
-    this._easing = (easing == null) ? TWEEN.Linear.None : easing;
-};
-
-SPARKS.Death.prototype.update = function (emitter, particle, time) {
-    if (particle.life <= 0) {
-        particle.isDead = true;
-    }
-};
-*/
-
-
-SPARKS.Move = function() {
-
-};
-
-SPARKS.Move.prototype.update = function( emitter, particle, time ) {
-
-	// attempt verlet velocity updating.
-	var p = particle.position;
-	var v = particle.velocity;
-	var old = particle._oldvelocity;
-
-	if ( this._velocityVerlet ) {
-
-		p.x += ( v.x + old.x ) * 0.5 * time;
-		p.y += ( v.y + old.y ) * 0.5 * time;
-		p.z += ( v.z + old.z ) * 0.5 * time;
-
-	} else {
-
-		p.x += v.x * time;
-		p.y += v.y * time;
-		p.z += v.z * time;
-
-	}
-
-	//  OldVel = Vel;
-	// Vel = Vel + Accel * dt;
-	// Pos = Pos + (vel + Vel + Accel * dt) * 0.5 * dt;
-
-
-
-};
-
-/* Marks particles found in specified zone dead */
-SPARKS.DeathZone = function( zone ) {
-
-	this.zone = zone;
-
-};
-
-SPARKS.DeathZone.prototype.update = function( emitter, particle, time ) {
-
-	if ( this.zone.contains( particle.position ) ) {
-
-		particle.isDead = true;
-
-	}
-
-};
-
-/*
- * SPARKS.ActionZone applies an action when particle is found in zone
- */
-SPARKS.ActionZone = function( action, zone ) {
-
-	this.action = action;
-	this.zone = zone;
-
-};
-
-SPARKS.ActionZone.prototype.update = function( emitter, particle, time ) {
-
-	if ( this.zone.contains( particle.position ) ) {
-
-		this.action.update( emitter, particle, time );
-
-	}
-
-};
-
-/*
- * Accelerate action affects velocity in specified 3d direction
- */
-SPARKS.Accelerate = function( x, y, z ) {
-
-	if ( x instanceof THREE.Vector3 ) {
-
-		this.acceleration = x;
-		return;
-
-	}
-
-	this.acceleration = new THREE.Vector3( x, y, z );
-
-};
-
-SPARKS.Accelerate.prototype.update = function( emitter, particle, time ) {
-
-	var acc = this.acceleration;
-
-	var v = particle.velocity;
-
-	particle._oldvelocity.set( v.x, v.y, v.z );
-
-	v.x += acc.x * time;
-	v.y += acc.y * time;
-	v.z += acc.z * time;
-
-};
-
-/*
- * Accelerate Factor accelerate based on a factor of particle's velocity.
- */
-SPARKS.AccelerateFactor = function( factor ) {
-
-	this.factor = factor;
-
-};
-
-SPARKS.AccelerateFactor.prototype.update = function( emitter, particle, time ) {
-
-	var factor = this.factor;
-
-	var v = particle.velocity;
-	var len = v.length();
-	var adjFactor;
-	if ( len > 0 ) {
-
-		adjFactor = factor * time / len;
-		adjFactor += 1;
-
-		v.multiplyScalar( adjFactor );
-		// v.x *= adjFactor;
-		// 	    v.y *= adjFactor;
-		// 	    v.z *= adjFactor;
-
-	}
-
-};
-
-/*
-AccelerateNormal
- * AccelerateVelocity affects velocity based on its velocity direction
- */
-SPARKS.AccelerateVelocity = function( factor ) {
-
-	this.factor = factor;
-
-};
-
-SPARKS.AccelerateVelocity.prototype.update = function( emitter, particle, time ) {
-
-	var factor = this.factor;
-
-	var v = particle.velocity;
-
-
-	v.z += - v.x * factor;
-	v.y += v.z * factor;
-	v.x +=  v.y * factor;
-
-};
-
-
-/* Set the max ammount of x,y,z drift movements in a second */
-SPARKS.RandomDrift = function( x, y, z ) {
-
-	if ( x instanceof THREE.Vector3 ) {
-
-		this.drift = x;
-		return;
-
-	}
-
-	this.drift = new THREE.Vector3( x, y, z );
-
-};
-
-
-SPARKS.RandomDrift.prototype.update = function( emitter, particle, time ) {
-
-	var drift = this.drift;
-
-	var v = particle.velocity;
-
-	v.x += ( Math.random() - 0.5 ) * drift.x * time;
-	v.y += ( Math.random() - 0.5 ) * drift.y * time;
-	v.z += ( Math.random() - 0.5 ) * drift.z * time;
-
-};
-
-/********************************
-* Zone Classes
-*
-*   An abstract classes which have
-*   getLocation() function
-*********************************/
-SPARKS.Zone = function() {
-};
-
-// TODO, contains() for Zone
-
-SPARKS.PointZone = function( pos ) {
-
-	this.pos = pos;
-
-};
-
-SPARKS.PointZone.prototype.getLocation = function() {
-
-	return this.pos;
-
-};
-
-SPARKS.PointZone = function( pos ) {
-
-	this.pos = pos;
-
-};
-
-SPARKS.PointZone.prototype.getLocation = function() {
-
-	return this.pos;
-
-};
-
-SPARKS.LineZone = function( start, end ) {
-
-	this.start = start;
-	this.end = end;
-	this._length = end.clone().sub( start );
-
-};
-
-SPARKS.LineZone.prototype.getLocation = function() {
-
-	var len = this._length.clone();
-
-	len.multiplyScalar( Math.random() );
-	return len.add( this.start );
-
-};
-
-// Basically a RectangleZone
-SPARKS.ParallelogramZone = function( corner, side1, side2 ) {
-
-	this.corner = corner;
-	this.side1 = side1;
-	this.side2 = side2;
-
-};
-
-SPARKS.ParallelogramZone.prototype.getLocation = function() {
-
-	var d1 = this.side1.clone().multiplyScalar( Math.random() );
-	var d2 = this.side2.clone().multiplyScalar( Math.random() );
-	d1.add( d2 );
-	return d1.add( this.corner );
-
-};
-
-SPARKS.CubeZone = function( position, x, y, z ) {
-
-	this.position = position;
-	this.x = x;
-	this.y = y;
-	this.z = z;
-
-};
-
-SPARKS.CubeZone.prototype.getLocation = function() {
-
-	//TODO use pool?
-
-	var location = this.position.clone();
-	location.x += Math.random() * this.x;
-	location.y += Math.random() * this.y;
-	location.z += Math.random() * this.z;
-
-	return location;
-
-};
-
-
-SPARKS.CubeZone.prototype.contains = function( position ) {
-
-	var startX = this.position.x;
-	var startY = this.position.y;
-	var startZ = this.position.z;
-	var x = this.x; // width
-	var y = this.y; // depth
-	var z = this.z; // height
-
-	if ( x < 0 ) {
-
-		startX += x;
-		x = Math.abs( x );
-
-	}
-
-	if ( y < 0 ) {
-
-		startY += y;
-		y = Math.abs( y );
-
-	}
-
-	if ( z < 0 ) {
-
-		startZ += z;
-		z = Math.abs( z );
-
-	}
-
-	var diffX = position.x - startX;
-	var diffY = position.y - startY;
-	var diffZ = position.z - startZ;
-
-	if ( ( diffX > 0 ) && ( diffX < x ) &&
-			( diffY > 0 ) && ( diffY < y ) &&
-			( diffZ > 0 ) && ( diffZ < z ) ) {
-
-		return true;
-
-	}
-
-	return false;
-
-};
-
-
-
-/**
- * The constructor creates a DiscZone 3D zone.
- *
- * @param centre The point at the center of the disc.
- * @param normal A vector normal to the disc.
- * @param outerRadius The outer radius of the disc.
- * @param innerRadius The inner radius of the disc. This defines the hole
- * in the center of the disc. If set to zero, there is no hole.
- */
-
-/*
-// BUGGY!!
-SPARKS.DiscZone = function(center, radiusNormal, outerRadius, innerRadius) {
-    this.center = center;
-	this.radiusNormal = radiusNormal;
-	this.outerRadius = (outerRadius==undefined) ? 0 : outerRadius;
-	this.innerRadius = (innerRadius==undefined) ? 0 : innerRadius;
-
-};
-
-SPARKS.DiscZone.prototype.getLocation = function() {
-    var rand = Math.random();
-	var _innerRadius = this.innerRadius;
-	var _outerRadius = this.outerRadius;
-	var center = this.center;
-	var _normal = this.radiusNormal;
-
-	_distToOrigin = _normal.dot( center );
-
-	var radius = _innerRadius + (1 - rand * rand ) * ( _outerRadius - _innerRadius );
-	var angle = Math.random() * SPARKS.Utils.TWOPI;
-
-	var _distToOrigin = _normal.dot( center );
-	var axes = SPARKS.Utils.getPerpendiculars( _normal.clone() );
-	var _planeAxis1 = axes[0];
-	var _planeAxis2 = axes[1];
-
-	var p = _planeAxis1.clone();
-	p.multiplyScalar( radius * Math.cos( angle ) );
-	var p2 = _planeAxis2.clone();
-	p2.multiplyScalar( radius * Math.sin( angle ) );
-	p.add( p2 );
-	return _center.add( p );
-
-};
-*/
-
-SPARKS.SphereCapZone = function( x, y, z, minr, maxr, angle ) {
-
-	this.x = x;
-	this.y = y;
-	this.z = z;
-	this.minr = minr;
-	this.maxr = maxr;
-	this.angle = angle;
-
-};
-
-SPARKS.SphereCapZone.prototype.getLocation = function() {
-
-	var theta = Math.PI * 2  * SPARKS.Utils.random();
-	var r = SPARKS.Utils.random();
-
-	//new THREE.Vector3
-	var v =  SPARKS.VectorPool.get().set( r * Math.cos( theta ), - 1 / Math.tan( this.angle * SPARKS.Utils.DEGREE_TO_RADIAN ), r * Math.sin( theta ) );
-
-	//v.length = StardustMath.interpolate(0, _minRadius, 1, _maxRadius, Math.random());
-
-	var i = this.minr - ( ( this.minr - this.maxr ) *  Math.random() );
-	v.multiplyScalar( i );
-
-	v.__markedForReleased = true;
-
-	return v;
-
-};
-
-
-/********************************
-* Initializer Classes
-*
-*   Classes which initializes
-*   particles. Implements initialize( emitter:Emitter, particle:Particle )
-*********************************/
-
-// Specifies random life between max and min
-SPARKS.Lifetime = function( min, max ) {
-
-	this._min = min;
-
-	this._max = max ? max : min;
-
-};
-
-SPARKS.Lifetime.prototype.initialize = function( emitter/*Emitter*/, particle/*Particle*/ ) {
-
-	particle.lifetime = this._min + SPARKS.Utils.random() * ( this._max - this._min );
-
-};
-
-
-SPARKS.Position = function( zone ) {
-
-	this.zone = zone;
-
-};
-
-SPARKS.Position.prototype.initialize = function( emitter/*Emitter*/, particle/*Particle*/ ) {
-
-	var pos = this.zone.getLocation();
-	particle.position.set( pos.x, pos.y, pos.z );
-
-};
-
-SPARKS.Velocity = function( zone ) {
-
-	this.zone = zone;
-
-};
-
-SPARKS.Velocity.prototype.initialize = function( emitter/*Emitter*/, particle/*Particle*/ ) {
-
-	var pos = this.zone.getLocation();
-	particle.velocity.set( pos.x, pos.y, pos.z );
-	if ( pos.__markedForReleased ) {
-
-		//console.log("release");
-		SPARKS.VectorPool.release( pos );
-		pos.__markedForReleased = false;
-
-	}
-
-};
-
-SPARKS.Target = function( target, callback ) {
-
-	this.target = target;
-	this.callback = callback;
-
-};
-
-SPARKS.Target.prototype.initialize = function( emitter, particle ) {
-
-	if ( this.callback ) {
-
-		particle.target = this.callback();
-
-	} else {
-
-		particle.target = this.target;
-
-	}
-
-};
-
-/********************************
-* VectorPool
-*
-*  Reuse much of Vectors if possible
-*********************************/
-
-SPARKS.VectorPool = {
-	__pools: [],
-
-	// Get a new Vector
-	get: function() {
-
-		if ( this.__pools.length > 0 ) {
-
-			return this.__pools.pop();
-
-		}
-
-		return this._addToPool();
-
-	},
-
-	// Release a vector back into the pool
-	release: function( v ) {
-
-		this.__pools.push( v );
-
-	},
-
-	// Create a bunch of vectors and add to the pool
-	_addToPool: function() {
-
-		//console.log("creating some pools");
-
-		for ( var i = 0, size = 100; i < size; i ++ ) {
-
-			this.__pools.push( new THREE.Vector3() );
-
-		}
-
-		return new THREE.Vector3();
-
-	}
-
-
-
-};
-
-
-/********************************
-* Util Classes
-*
-*   Classes which initializes
-*   particles. Implements initialize( emitter:Emitter, particle:Particle )
-*********************************/
-SPARKS.Utils = {
-	random: function() {
-
-		return Math.random();
-
-	},
-	DEGREE_TO_RADIAN: Math.PI / 180,
-	TWOPI: Math.PI * 2,
-
-	getPerpendiculars: function( normal ) {
-
-		var p1 = this.getPerpendicular( normal );
-		var p2 = normal.cross( p1 );
-		p2.normalize();
-		return [ p1, p2 ];
-
-	},
-
-	getPerpendicular: function( v ) {
-
-		if ( v.x == 0 ) {
-
-			return new THREE.Vector3D( 1, 0, 0 );
-
-		} else {
-
-			var temp = new THREE.Vector3( v.y, - v.x, 0 );
-			return temp.normalize();
-
-		}
-
-	}
-
-};

+ 6 - 0
examples/js/controls/DeviceOrientationControls.js

@@ -88,6 +88,12 @@ THREE.DeviceOrientationControls = function ( object ) {
 
 	};
 
+	this.dispose = function () {
+
+		this.disconnect();
+
+	};
+
 	this.connect();
 
 };

+ 6 - 0
examples/js/controls/DragControls.js

@@ -96,6 +96,12 @@ THREE.DragControls = function( _camera, _objects, _domElement ) {
 	
 	};
 
+	this.dispose = function() {
+
+		me.deactivate();
+
+	};
+
 	this.activate();
 
 	function onDocumentMouseMove( event ) {

+ 21 - 2
examples/js/controls/EditorControls.js

@@ -203,11 +203,30 @@ THREE.EditorControls = function ( object, domElement ) {
 
 	}
 
-	domElement.addEventListener( 'contextmenu', function ( event ) {
+	function contextmenu( event ) {
 
 		event.preventDefault();
 
-	}, false );
+	}
+
+	this.dispose = function() {
+
+		domElement.removeEventListener( 'contextmenu', contextmenu, false );
+		domElement.removeEventListener( 'mousedown', onMouseDown, false );
+		domElement.removeEventListener( 'mousewheel', onMouseWheel, false );
+		domElement.removeEventListener( 'DOMMouseScroll', onMouseWheel, false ); // firefox
+
+		domElement.removeEventListener( 'mousemove', onMouseMove, false );
+		domElement.removeEventListener( 'mouseup', onMouseUp, false );
+		domElement.removeEventListener( 'mouseout', onMouseUp, false );
+		domElement.removeEventListener( 'dblclick', onMouseUp, false );
+
+		domElement.removeEventListener( 'touchstart', touchStart, false );
+		domElement.removeEventListener( 'touchmove', touchMove, false );
+
+	}
+
+	domElement.addEventListener( 'contextmenu', contextmenu, false );
 	domElement.addEventListener( 'mousedown', onMouseDown, false );
 	domElement.addEventListener( 'mousewheel', onMouseWheel, false );
 	domElement.addEventListener( 'DOMMouseScroll', onMouseWheel, false ); // firefox

+ 26 - 8
examples/js/controls/FirstPersonControls.js

@@ -253,19 +253,37 @@ THREE.FirstPersonControls = function ( object, domElement ) {
 
 	};
 
-
-	this.domElement.addEventListener( 'contextmenu', function ( event ) {
+	function contextmenu( event ) {
 
 		event.preventDefault();
 
-	}, false );
+	}
+
+	this.dispose = function() {
+
+		this.domElement.removeEventListener( 'contextmenu', contextmenu, false );
+		this.domElement.removeEventListener( 'mousedown', _onMouseDown, false );
+		this.domElement.removeEventListener( 'mousemove', _onMouseMove, false );
+		this.domElement.removeEventListener( 'mouseup', _onMouseUp, false );
+
+		window.removeEventListener( 'keydown', _onKeyDown, false );
+		window.removeEventListener( 'keyup', _onKeyUp, false );
+
+	}
+
+	var _onMouseMove = bind( this, this.onMouseMove );
+	var _onMouseDown = bind( this, this.onMouseDown );
+	var _onMouseUp = bind( this, this.onMouseUp );
+	var _onKeyDown = bind( this, this.onKeyDown );
+	var _onKeyUp = bind( this, this.onKeyUp );
 
-	this.domElement.addEventListener( 'mousemove', bind( this, this.onMouseMove ), false );
-	this.domElement.addEventListener( 'mousedown', bind( this, this.onMouseDown ), false );
-	this.domElement.addEventListener( 'mouseup', bind( this, this.onMouseUp ), false );
+	this.domElement.addEventListener( 'contextmenu', contextmenu, false );
+	this.domElement.addEventListener( 'mousemove', _onMouseMove, false );
+	this.domElement.addEventListener( 'mousedown', _onMouseDown, false );
+	this.domElement.addEventListener( 'mouseup', _onMouseUp, false );
 
-	window.addEventListener( 'keydown', bind( this, this.onKeyDown ), false );
-	window.addEventListener( 'keyup', bind( this, this.onKeyUp ), false );
+	window.addEventListener( 'keydown', _onKeyDown, false );
+	window.addEventListener( 'keyup', _onKeyUp, false );
 
 	function bind( scope, fn ) {
 

+ 27 - 7
examples/js/controls/FlyControls.js

@@ -254,18 +254,38 @@ THREE.FlyControls = function ( object, domElement ) {
 
 	}
 
-	this.domElement.addEventListener( 'contextmenu', function ( event ) {
+	function contextmenu( event ) {
 
 		event.preventDefault();
 
-	}, false );
+	}
+
+	this.dispose = function() {
+
+		this.domElement.removeEventListener( 'contextmenu', contextmenu, false );
+		this.domElement.removeEventListener( 'mousedown', _mousedown, false );
+		this.domElement.removeEventListener( 'mousemove', _mousemove, false );
+		this.domElement.removeEventListener( 'mouseup', _mouseup, false );
+
+		window.removeEventListener( 'keydown', _keydown, false );
+		window.removeEventListener( 'keyup', _keyup, false );
+
+	}
+
+	var _mousemove = bind( this, this.mousemove );
+	var _mousedown = bind( this, this.mousedown );
+	var _mouseup = bind( this, this.mouseup );
+	var _keydown = bind( this, this.keydown );
+	var _keyup = bind( this, this.keyup );
+
+	this.domElement.addEventListener( 'contextmenu', contextmenu, false );
 
-	this.domElement.addEventListener( 'mousemove', bind( this, this.mousemove ), false );
-	this.domElement.addEventListener( 'mousedown', bind( this, this.mousedown ), false );
-	this.domElement.addEventListener( 'mouseup',   bind( this, this.mouseup ), false );
+	this.domElement.addEventListener( 'mousemove', _mousemove, false );
+	this.domElement.addEventListener( 'mousedown', _mousedown, false );
+	this.domElement.addEventListener( 'mouseup',   _mouseup, false );
 
-	window.addEventListener( 'keydown', bind( this, this.keydown ), false );
-	window.addEventListener( 'keyup',   bind( this, this.keyup ), false );
+	window.addEventListener( 'keydown', _keydown, false );
+	window.addEventListener( 'keyup',   _keyup, false );
 
 	this.updateMovementVector();
 	this.updateRotationVector();

+ 6 - 0
examples/js/controls/MouseControls.js

@@ -50,6 +50,12 @@ THREE.MouseControls = function ( object ) {
 
 	};
 
+	this.dispose = function() {
+
+		document.removeEventListener( 'mousemove', onMouseMove, false );
+
+	}
+
 	document.addEventListener( 'mousemove', onMouseMove, false );
 
 };

+ 26 - 5
examples/js/controls/OrbitControls.js

@@ -392,7 +392,7 @@
 
 		}
 
-		this.update = function() {
+		this.update = function () {
 
 			if ( this.autoRotate && state === STATE.NONE ) {
 
@@ -509,11 +509,11 @@
 
 				if ( dollyDelta.y > 0 ) {
 
-					contraint.dollyIn( getZoomScale() );
+					constraint.dollyIn( getZoomScale() );
 
 				} else if ( dollyDelta.y < 0 ) {
 
-					contraint.dollyOut( getZoomScale() );
+					constraint.dollyOut( getZoomScale() );
 
 				}
 
@@ -750,11 +750,32 @@
 
 		}
 
-		this.domElement.addEventListener( 'contextmenu', function ( event ) {
+		function contextmenu( event ) {
 
 			event.preventDefault();
 
-		}, false );
+		}
+
+		this.dispose = function() {
+
+			this.domElement.removeEventListener( 'contextmenu', contextmenu, false );
+			this.domElement.removeEventListener( 'mousedown', onMouseDown, false );
+			this.domElement.removeEventListener( 'mousewheel', onMouseWheel, false );
+			this.domElement.removeEventListener( 'DOMMouseScroll', onMouseWheel, false ); // firefox
+
+			this.domElement.removeEventListener( 'touchstart', touchstart, false );
+			this.domElement.removeEventListener( 'touchend', touchend, false );
+			this.domElement.removeEventListener( 'touchmove', touchmove, false );
+
+			document.removeEventListener( 'mousemove', onMouseMove, false );
+			document.removeEventListener( 'mouseup', onMouseUp, false );
+
+			window.removeEventListener( 'keydown', onKeyDown, false );
+
+		}
+
+		this.domElement.addEventListener( 'contextmenu', contextmenu, false );
+
 		this.domElement.addEventListener( 'mousedown', onMouseDown, false );
 		this.domElement.addEventListener( 'mousewheel', onMouseWheel, false );
 		this.domElement.addEventListener( 'DOMMouseScroll', onMouseWheel, false ); // firefox

+ 23 - 3
examples/js/controls/OrthographicTrackballControls.js

@@ -606,14 +606,34 @@ THREE.OrthographicTrackballControls = function ( object, domElement ) {
 
 	}
 
-	this.domElement.addEventListener( 'contextmenu', function ( event ) {
+	function contextmenu( event ) {
 
 		event.preventDefault();
 
-	}, false );
+	}
 
-	this.domElement.addEventListener( 'mousedown', mousedown, false );
+	this.dispose = function() {
+
+		this.domElement.removeEventListener( 'contextmenu', contextmenu, false );
+		this.domElement.removeEventListener( 'mousedown', mousedown, false );
+		this.domElement.removeEventListener( 'mousewheel', mousewheel, false );
+		this.domElement.removeEventListener( 'DOMMouseScroll', mousewheel, false ); // firefox
+
+		this.domElement.removeEventListener( 'touchstart', touchstart, false );
+		this.domElement.removeEventListener( 'touchend', touchend, false );
+		this.domElement.removeEventListener( 'touchmove', touchmove, false );
+
+		document.removeEventListener( 'mousemove', mousemove, false );
+		document.removeEventListener( 'mouseup', mouseup, false );
 
+		window.removeEventListener( 'keydown', keydown, false );
+		window.removeEventListener( 'keyup', keyup, false );
+
+	}
+
+
+	this.domElement.addEventListener( 'contextmenu', contextmenu, false );
+	this.domElement.addEventListener( 'mousedown', mousedown, false );
 	this.domElement.addEventListener( 'mousewheel', mousewheel, false );
 	this.domElement.addEventListener( 'DOMMouseScroll', mousewheel, false ); // firefox
 

+ 6 - 0
examples/js/controls/PointerLockControls.js

@@ -31,6 +31,12 @@ THREE.PointerLockControls = function ( camera ) {
 
 	};
 
+	this.dispose = function() {
+
+		document.removeEventListener( 'mousemove', onMouseMove, false );
+
+	}
+
 	document.addEventListener( 'mousemove', onMouseMove, false );
 
 	this.enabled = false;

+ 22 - 3
examples/js/controls/TrackballControls.js

@@ -586,14 +586,33 @@ THREE.TrackballControls = function ( object, domElement ) {
 
 	}
 
-	this.domElement.addEventListener( 'contextmenu', function ( event ) {
+	function contextmenu( event ) {
 
 		event.preventDefault();
 
-	}, false );
+	}
 
-	this.domElement.addEventListener( 'mousedown', mousedown, false );
+	this.dispose = function() {
+
+		this.domElement.removeEventListener( 'contextmenu', contextmenu, false );
+		this.domElement.removeEventListener( 'mousedown', mousedown, false );
+		this.domElement.removeEventListener( 'mousewheel', mousewheel, false );
+		this.domElement.removeEventListener( 'DOMMouseScroll', mousewheel, false ); // firefox
+
+		this.domElement.removeEventListener( 'touchstart', touchstart, false );
+		this.domElement.removeEventListener( 'touchend', touchend, false );
+		this.domElement.removeEventListener( 'touchmove', touchmove, false );
+
+		document.removeEventListener( 'mousemove', mousemove, false );
+		document.removeEventListener( 'mouseup', mouseup, false );
 
+		window.removeEventListener( 'keydown', keydown, false );
+		window.removeEventListener( 'keyup', keyup, false );
+
+	}
+
+	this.domElement.addEventListener( 'contextmenu', contextmenu, false );
+	this.domElement.addEventListener( 'mousedown', mousedown, false );
 	this.domElement.addEventListener( 'mousewheel', mousewheel, false );
 	this.domElement.addEventListener( 'DOMMouseScroll', mousewheel, false ); // firefox
 

+ 6 - 0
examples/js/controls/VRControls.js

@@ -116,4 +116,10 @@ THREE.VRControls = function ( object, onError ) {
 
 	};
 
+	this.dispose = function () {
+
+		vrInputs = [];
+
+	};
+
 };

+ 1 - 1
examples/js/effects/AnaglyphEffect.js

@@ -105,7 +105,7 @@ THREE.AnaglyphEffect = function ( renderer, width, height ) {
 
 		scene.updateMatrixWorld();
 
-		if ( camera.parent === undefined ) camera.updateMatrixWorld();
+		if ( camera.parent === null ) camera.updateMatrixWorld();
 
 		var hasCameraChanged = ( _aspect !== camera.aspect ) || ( _near !== camera.near ) || ( _far !== camera.far ) || ( _fov !== camera.fov );
 

+ 1 - 1
examples/js/effects/ParallaxBarrierEffect.js

@@ -104,7 +104,7 @@ THREE.ParallaxBarrierEffect = function ( renderer ) {
 
 		scene.updateMatrixWorld();
 
-		if ( camera.parent === undefined ) camera.updateMatrixWorld();
+		if ( camera.parent === null ) camera.updateMatrixWorld();
 
 		var hasCameraChanged = ( _aspect !== camera.aspect ) || ( _near !== camera.near ) || ( _far !== camera.far ) || ( _fov !== camera.fov );
 

+ 2 - 2
examples/js/effects/StereoEffect.js

@@ -78,8 +78,8 @@ THREE.StereoEffect = function ( renderer ) {
 
 		scene.updateMatrixWorld();
 
-		if ( camera.parent === undefined ) camera.updateMatrixWorld();
-	
+		if ( camera.parent === null ) camera.updateMatrixWorld();
+
 		camera.matrixWorld.decompose( _position, _quaternion, _scale );
 
 		// Effective fov of the camera

+ 1 - 1
examples/js/effects/VREffect.js

@@ -133,7 +133,7 @@ THREE.VREffect = function ( renderer, onError ) {
 			renderer.enableScissorTest( true );
 			renderer.clear();
 
-			if ( camera.parent === undefined ) camera.updateMatrixWorld();
+			if ( camera.parent === null ) camera.updateMatrixWorld();
 
 			cameraL.projectionMatrix = fovToProjection( eyeFOVL, true, camera.near, camera.far );
 			cameraR.projectionMatrix = fovToProjection( eyeFOVR, true, camera.near, camera.far );

+ 0 - 754
examples/js/exporters/SceneExporter.js

@@ -1,754 +0,0 @@
-/**
- * @author alteredq / http://alteredqualia.com/
- */
-
-THREE.SceneExporter = function () {};
-
-THREE.SceneExporter.prototype = {
-
-	constructor: THREE.SceneExporter,
-
-	parse: function ( scene ) {
-
-		var position = Vector3String( scene.position );
-		var rotation = Vector3String( scene.rotation );
-		var scale = Vector3String( scene.scale );
-
-		var nobjects = 0;
-		var ngeometries = 0;
-		var nmaterials = 0;
-		var ntextures = 0;
-
-		var objectsArray = [];
-		var geometriesArray = [];
-		var materialsArray = [];
-		var texturesArray = [];
-		var fogsArray = [];
-
-		var geometriesMap = {};
-		var materialsMap = {};
-		var texturesMap = {};
-
-		// extract objects, geometries, materials, textures
-
-		var checkTexture = function ( map ) {
-
-			if ( ! map ) return;
-
-			if ( ! ( map.id in texturesMap ) ) {
-
-				texturesMap[ map.id ] = true;
-				texturesArray.push( TextureString( map ) );
-				ntextures += 1;
-
-			}
-
-		};
-
-		var linesArray = [];
-
-		function createObjectsList( object, pad ) {
-
-			for ( var i = 0; i < object.children.length; i ++ ) {
-
-				var node = object.children[ i ];
-
-				if ( node instanceof THREE.Mesh ) {
-
-					linesArray.push( MeshString( node, pad ) );
-					nobjects += 1;
-
-					if ( ! ( node.geometry.id in geometriesMap ) ) {
-
-						geometriesMap[ node.geometry.id ] = true;
-						geometriesArray.push( GeometryString( node.geometry ) );
-						ngeometries += 1;
-
-					}
-
-					if ( ! ( node.material.id in materialsMap ) ) {
-
-						materialsMap[ node.material.id ] = true;
-						materialsArray.push( MaterialString( node.material ) );
-						nmaterials += 1;
-
-						checkTexture( node.material.map );
-						checkTexture( node.material.envMap );
-						checkTexture( node.material.lightMap );
-						checkTexture( node.material.specularMap );
-						checkTexture( node.material.bumpMap );
-						checkTexture( node.material.normalMap );
-
-					}
-
-				} else if ( node instanceof THREE.Light ) {
-
-					linesArray.push( LightString( node, pad ) );
-					nobjects += 1;
-
-				} else if ( node instanceof THREE.Camera ) {
-
-					linesArray.push( CameraString( node, pad ) );
-					nobjects += 1;
-
-				} else if ( node instanceof THREE.Object3D ) {
-
-					linesArray.push( ObjectString( node, pad ) );
-					nobjects += 1;
-
-				}
-
-				if ( node.children.length > 0 ) {
-
-					linesArray.push( PaddingString( pad + 1 ) + '\t\t"children" : {' );
-
-				}
-
-				createObjectsList( node, pad + 2 );
-
-				if ( node.children.length > 0 ) {
-
-					linesArray.push( PaddingString( pad + 1 ) + "\t\t}" );
-
-				}
-
-				linesArray.push( PaddingString( pad ) + "\t\t}" + ( i < object.children.length - 1 ? ",\n" : "" ) );
-
-			}
-
-		}
-
-		createObjectsList( scene, 0 );
-
-		var objects = linesArray.join( "\n" );
-
-		// extract fog
-
-		if ( scene.fog ) {
-
-			fogsArray.push( FogString( scene.fog ) );
-
-		}
-
-		// generate sections
-
-		var geometries = generateMultiLineString( geometriesArray, ",\n\n\t" );
-		var materials = generateMultiLineString( materialsArray, ",\n\n\t" );
-		var textures = generateMultiLineString( texturesArray, ",\n\n\t" );
-		var fogs = generateMultiLineString( fogsArray, ",\n\n\t" );
-
-		// generate defaults
-
-		var activeCamera = null;
-
-		scene.traverse( function ( node ) {
-
-			if ( node instanceof THREE.Camera && node.userData.active ) {
-
-				activeCamera = node;
-
-			}
-
-		} );
-
-		var defcamera = LabelString( activeCamera ? getObjectName( activeCamera ) : "" );
-		var deffog = LabelString( scene.fog ? getFogName( scene.fog ) : "" );
-
-		// templates
-
-		function Vector2String( v ) {
-
-			return "[" + v.x + "," + v.y + "]";
-
-		}
-
-		function Vector3String( v ) {
-
-			return "[" + v.x + "," + v.y + "," + v.z + "]";
-
-		}
-
-		function ColorString( c ) {
-
-			return "[" + c.r.toFixed( 3 ) + "," + c.g.toFixed( 3 ) + "," + c.b.toFixed( 3 ) + "]";
-
-		}
-
-		function LabelString( s ) {
-
-			return '"' + s + '"';
-
-		}
-
-		function NumConstantString( c ) {
-
-			var constants = [ "NearestFilter", "NearestMipMapNearestFilter", "NearestMipMapLinearFilter",
-							  "LinearFilter", "LinearMipMapNearestFilter", "LinearMipMapLinearFilter" ];
-
-			for ( var i = 0; i < constants.length; i ++ ) {
-
-				if ( THREE[ constants[ i ] ] === c ) return LabelString( constants[ i ] );
-
-			}
-
-			return "";
-
-		}
-
-		function PaddingString( n ) {
-
-			var output = "";
-
-			for ( var i = 0; i < n; i ++ ) output += "\t";
-
-			return output;
-
-		}
-
-
-		//
-
-		function LightString( o, n ) {
-
-			if ( o instanceof THREE.AmbientLight ) {
-
-				var output = [
-
-				'\t\t' + LabelString( getObjectName( o ) ) + ' : {',
-				'	"type"  : "AmbientLight",',
-				'	"color" : ' + o.color.getHex() + ( o.children.length ? ',' : '' )
-
-				];
-
-			} else if ( o instanceof THREE.DirectionalLight ) {
-
-				var output = [
-
-				'\t\t' + LabelString( getObjectName( o ) ) + ' : {',
-				'	"type"      : "DirectionalLight",',
-				'	"color"     : ' + o.color.getHex() + ',',
-				'	"intensity" : ' + o.intensity + ',',
-				'	"direction" : ' + Vector3String( o.position ) + ',',
-				'	"target"    : ' + LabelString( getObjectName( o.target ) ) + ( o.children.length ? ',' : '' )
-
-				];
-
-			} else if ( o instanceof THREE.PointLight ) {
-
-				var output = [
-
-				'\t\t' + LabelString( getObjectName( o ) ) + ' : {',
-				'	"type"           : "PointLight",',
-				'	"color"          : ' + o.color.getHex() + ',',
-				'	"intensity"      : ' + o.intensity + ',',
-				'	"position"       : ' + Vector3String( o.position ) + ',',
-				'	"decay"          : ' + o.decay + ',',
-				'	"distance"       : ' + o.distance + ( o.children.length ? ',' : '' )
-
-				];
-
-			} else if ( o instanceof THREE.SpotLight ) {
-
-				var output = [
-
-				'\t\t' + LabelString( getObjectName( o ) ) + ' : {',
-				'	"type"           : "SpotLight",',
-				'	"color"          : ' + o.color.getHex() + ',',
-				'	"intensity"      : ' + o.intensity + ',',
-				'	"position"       : ' + Vector3String( o.position ) + ',',
-				'	"distance"       : ' + o.distance + ',',
-				'	"angle"          : ' + o.angle + ',',
-				'	"exponent"       : ' + o.exponent + ',',
-				'	"decay"          : ' + o.decay + ',',
-				'	"target"         : ' + LabelString( getObjectName( o.target ) ) + ( o.children.length ? ',' : '' )
-
-				];
-
-			} else if ( o instanceof THREE.HemisphereLight ) {
-
-				var output = [
-
-				'\t\t' + LabelString( getObjectName( o ) ) + ' : {',
-				'	"type"        : "HemisphereLight",',
-				'	"skyColor"    : ' + o.color.getHex() + ',',
-				'	"groundColor" : ' + o.groundColor.getHex() + ',',
-				'	"intensity"   : ' + o.intensity + ',',
-				'	"position"    : ' + Vector3String( o.position ) + ( o.children.length ? ',' : '' )
-
-				];
-
-			} else {
-
-				var output = [];
-
-			}
-
-			return generateMultiLineString( output, '\n\t\t', n );
-
-		}
-
-		function CameraString( o, n ) {
-
-			if ( o instanceof THREE.PerspectiveCamera ) {
-
-				var output = [
-
-				'\t\t' + LabelString( getObjectName( o ) ) + ' : {',
-				'	"type"     : "PerspectiveCamera",',
-				'	"fov"      : ' + o.fov + ',',
-				'	"aspect"   : ' + o.aspect + ',',
-				'	"near"     : ' + o.near + ',',
-				'	"far"      : ' + o.far + ',',
-				'	"position" : ' + Vector3String( o.position ) + ( o.children.length ? ',' : '' )
-
-				];
-
-			} else if ( o instanceof THREE.OrthographicCamera ) {
-
-				var output = [
-
-				'\t\t' + LabelString( getObjectName( o ) ) + ' : {',
-				'	"type"     : "OrthographicCamera",',
-				'	"left"     : ' + o.left + ',',
-				'	"right"    : ' + o.right + ',',
-				'	"top"      : ' + o.top + ',',
-				'	"bottom"   : ' + o.bottom + ',',
-				'	"near"     : ' + o.near + ',',
-				'	"far"      : ' + o.far + ',',
-				'	"position" : ' + Vector3String( o.position ) + ( o.children.length ? ',' : '' )
-
-				];
-
-			} else {
-
-				var output = [];
-
-			}
-
-			return generateMultiLineString( output, '\n\t\t', n );
-
-		}
-
-		function ObjectString( o, n ) {
-
-			var output = [
-
-			'\t\t' + LabelString( getObjectName( o ) ) + ' : {',
-			'	"position" : ' + Vector3String( o.position ) + ',',
-			'	"rotation" : ' + Vector3String( o.rotation ) + ',',
-			'	"scale"	   : ' + Vector3String( o.scale ) + ',',
-			'	"visible"  : ' + o.visible + ( o.children.length ? ',' : '' )
-
-			];
-
-			return generateMultiLineString( output, '\n\t\t', n );
-
-		}
-
-		function MeshString( o, n ) {
-
-			var output = [
-
-			'\t\t' + LabelString( getObjectName( o ) ) + ' : {',
-			'	"geometry" : ' + LabelString( getGeometryName( o.geometry ) ) + ',',
-			'	"material" : ' + LabelString( getMaterialName( o.material ) ) + ',',
-			'	"position" : ' + Vector3String( o.position ) + ',',
-			'	"rotation" : ' + Vector3String( o.rotation ) + ',',
-			'	"scale"	   : ' + Vector3String( o.scale ) + ',',
-			'	"visible"  : ' + o.visible + ( o.children.length ? ',' : '' )
-
-			];
-
-			return generateMultiLineString( output, '\n\t\t', n );
-
-		}
-
-		//
-
-		function GeometryString( g ) {
-
-			if ( g instanceof THREE.SphereGeometry ) {
-
-				var output = [
-
-				'\t' + LabelString( getGeometryName( g ) ) + ': {',
-				'	"type"    : "sphere",',
-				'	"radius"  : ' 		 + g.parameters.radius + ',',
-				'	"widthSegments"  : ' + g.parameters.widthSegments + ',',
-				'	"heightSegments" : ' + g.parameters.heightSegments,
-				'}'
-
-				];
-
-			} else if ( g instanceof THREE.BoxGeometry ) {
-
-				var output = [
-
-				'\t' + LabelString( getGeometryName( g ) ) + ': {',
-				'	"type"    : "cube",',
-				'	"width"  : '  + g.parameters.width  + ',',
-				'	"height"  : ' + g.parameters.height + ',',
-				'	"depth"  : '  + g.parameters.depth  + ',',
-				'	"widthSegments"  : ' + g.widthSegments + ',',
-				'	"heightSegments" : ' + g.heightSegments + ',',
-				'	"depthSegments" : '  + g.depthSegments,
-				'}'
-
-				];
-
-			} else if ( g instanceof THREE.PlaneGeometry ) {
-
-				var output = [
-
-				'\t' + LabelString( getGeometryName( g ) ) + ': {',
-				'	"type"    : "plane",',
-				'	"width"  : '  + g.width  + ',',
-				'	"height"  : ' + g.height + ',',
-				'	"widthSegments"  : ' + g.widthSegments + ',',
-				'	"heightSegments" : ' + g.heightSegments,
-				'}'
-
-				];
-
-			} else if ( g instanceof THREE.Geometry ) {
-
-				if ( g.sourceType === "ascii" || g.sourceType === "ctm" || g.sourceType === "stl" || g.sourceType === "vtk" ) {
-
-					var output = [
-
-					'\t' + LabelString( getGeometryName( g ) ) + ': {',
-					'	"type" : ' + LabelString( g.sourceType ) + ',',
-					'	"url"  : ' + LabelString( g.sourceFile ),
-					'}'
-
-					];
-
-				} else {
-
-					var output = [];
-
-				}
-
-			} else {
-
-				var output = [];
-
-			}
-
-			return generateMultiLineString( output, '\n\t\t' );
-
-		}
-
-		function MaterialString( m ) {
-
-			if ( m instanceof THREE.MeshBasicMaterial ) {
-
-				var output = [
-
-				'\t' + LabelString( getMaterialName( m ) ) + ': {',
-				'	"type"    : "MeshBasicMaterial",',
-				'	"parameters"  : {',
-				'		"color"  : ' 	+ m.color.getHex() + ',',
-
-				m.map ? 		'		"map" : ' + LabelString( getTextureName( m.map ) ) + ',' : '',
-				m.envMap ? 		'		"envMap" : ' + LabelString( getTextureName( m.envMap ) ) + ',' : '',
-				m.specularMap ? '		"specularMap" : ' + LabelString( getTextureName( m.specularMap ) ) + ',' : '',
-				m.lightMap ? 	'		"lightMap" : ' + LabelString( getTextureName( m.lightMap ) ) + ',' : '',
-
-				'		"reflectivity"  : ' + m.reflectivity + ',',
-				'		"transparent" : ' + m.transparent + ',',
-				'		"opacity" : ' 	+ m.opacity + ',',
-				'		"wireframe" : ' + m.wireframe + ',',
-				'		"wireframeLinewidth" : ' + m.wireframeLinewidth,
-				'	}',
-				'}'
-
-				];
-
-
-			} else if ( m instanceof THREE.MeshLambertMaterial ) {
-
-				var output = [
-
-				'\t' + LabelString( getMaterialName( m ) ) + ': {',
-				'	"type"    : "MeshLambertMaterial",',
-				'	"parameters"  : {',
-				'		"color"  : ' 	+ m.color.getHex() + ',',
-				'		"emissive"  : ' + m.emissive.getHex() + ',',
-
-				m.map ? 		'		"map" : ' + LabelString( getTextureName( m.map ) ) + ',' : '',
-				m.envMap ? 		'		"envMap" : ' + LabelString( getTextureName( m.envMap ) ) + ',' : '',
-				m.specularMap ? '		"specularMap" : ' + LabelString( getTextureName( m.specularMap ) ) + ',' : '',
-				m.lightMap ? 	'		"lightMap" : ' + LabelString( getTextureName( m.lightMap ) ) + ',' : '',
-
-				'		"reflectivity"  : ' + m.reflectivity + ',',
-				'		"transparent" : ' + m.transparent + ',',
-				'		"opacity" : ' 	+ m.opacity + ',',
-				'		"wireframe" : ' + m.wireframe + ',',
-				'		"wireframeLinewidth" : ' + m.wireframeLinewidth,
-				'	}',
-				'}'
-
-				];
-
-			} else if ( m instanceof THREE.MeshPhongMaterial ) {
-
-				var output = [
-
-				'\t' + LabelString( getMaterialName( m ) ) + ': {',
-				'	"type"    : "MeshPhongMaterial",',
-				'	"parameters"  : {',
-				'		"color"  : ' 	+ m.color.getHex() + ',',
-				'		"emissive"  : ' + m.emissive.getHex() + ',',
-				'		"specular"  : ' + m.specular.getHex() + ',',
-				'		"shininess" : ' + m.shininess + ',',
-
-				m.map ? 		'		"map" : ' + LabelString( getTextureName( m.map ) ) + ',' : '',
-				m.envMap ? 		'		"envMap" : ' + LabelString( getTextureName( m.envMap ) ) + ',' : '',
-				m.specularMap ? '		"specularMap" : ' + LabelString( getTextureName( m.specularMap ) ) + ',' : '',
-				m.lightMap ? 	'		"lightMap" : ' + LabelString( getTextureName( m.lightMap ) ) + ',' : '',
-				m.normalMap ? 	'		"normalMap" : ' + LabelString( getTextureName( m.normalMap ) ) + ',' : '',
-				m.bumpMap ? 	'		"bumpMap" : ' + LabelString( getTextureName( m.bumpMap ) ) + ',' : '',
-
-				'		"bumpScale"  : ' + m.bumpScale + ',',
-				'		"reflectivity"  : ' + m.reflectivity + ',',
-				'		"transparent" : ' + m.transparent + ',',
-				'		"opacity" : ' 	+ m.opacity + ',',
-				'		"wireframe" : ' + m.wireframe + ',',
-				'		"wireframeLinewidth" : ' + m.wireframeLinewidth,
-				'	}',
-				'}'
-
-				];
-
-			} else if ( m instanceof THREE.MeshDepthMaterial ) {
-
-				var output = [
-
-				'\t' + LabelString( getMaterialName( m ) ) + ': {',
-				'	"type"    : "MeshDepthMaterial",',
-				'	"parameters"  : {',
-				'		"transparent" : ' + m.transparent + ',',
-				'		"opacity" : ' 	+ m.opacity + ',',
-				'		"wireframe" : ' + m.wireframe + ',',
-				'		"wireframeLinewidth" : ' + m.wireframeLinewidth,
-				'	}',
-				'}'
-
-				];
-
-			} else if ( m instanceof THREE.MeshNormalMaterial ) {
-
-				var output = [
-
-				'\t' + LabelString( getMaterialName( m ) ) + ': {',
-				'	"type"    : "MeshNormalMaterial",',
-				'	"parameters"  : {',
-				'		"transparent" : ' + m.transparent + ',',
-				'		"opacity" : ' 	+ m.opacity + ',',
-				'		"wireframe" : ' + m.wireframe + ',',
-				'		"wireframeLinewidth" : ' + m.wireframeLinewidth,
-				'	}',
-				'}'
-
-				];
-
-			} else if ( m instanceof THREE.MeshFaceMaterial ) {
-
-				var output = [
-
-				'\t' + LabelString( getMaterialName( m ) ) + ': {',
-				'	"type"    : "MeshFaceMaterial",',
-				'	"parameters"  : {}',
-				'}'
-
-				];
-
-			}
-
-			return generateMultiLineString( output, '\n\t\t' );
-
-		}
-
-		function TextureString( t ) {
-
-			// here would be also an option to use data URI
-			// with embedded image from "t.image.src"
-			// (that's a side effect of using FileReader to load images)
-
-			var output = [
-
-			'\t' + LabelString( getTextureName( t ) ) + ': {',
-			'	"url"    : "' + t.sourceFile + '",',
-			'	"repeat" : ' + Vector2String( t.repeat ) + ',',
-			'	"offset" : ' + Vector2String( t.offset ) + ',',
-			'	"magFilter" : ' + NumConstantString( t.magFilter ) + ',',
-			'	"minFilter" : ' + NumConstantString( t.minFilter ) + ',',
-			'	"anisotropy" : ' + t.anisotropy,
-			'}'
-
-			];
-
-			return generateMultiLineString( output, '\n\t\t' );
-
-		}
-
-		//
-
-		function FogString( f ) {
-
-			if ( f instanceof THREE.Fog ) {
-
-				var output = [
-
-				'\t' + LabelString( getFogName( f ) ) + ': {',
-				'	"type"  : "linear",',
-				'	"color" : ' + ColorString( f.color ) + ',',
-				'	"near"  : '  + f.near + ',',
-				'	"far"   : '    + f.far,
-				'}'
-
-				];
-
-			} else if ( f instanceof THREE.FogExp2 ) {
-
-				var output = [
-
-				'\t' + LabelString( getFogName( f ) ) + ': {',
-				'	"type"    : "exp2",',
-				'	"color"   : '  + ColorString( f.color ) + ',',
-				'	"density" : ' + f.density,
-				'}'
-
-				];
-
-			} else {
-
-				var output = [];
-
-			}
-
-			return generateMultiLineString( output, '\n\t\t' );
-
-		}
-
-		//
-
-		function generateMultiLineString( lines, separator, padding ) {
-
-			var cleanLines = [];
-
-			for ( var i = 0; i < lines.length; i ++ ) {
-
-				var line = lines[ i ];
-
-				if ( line ) {
-
-					if ( padding ) line = PaddingString( padding ) + line;
-					cleanLines.push(  line );
-
-				}
-
-			}
-
-			return cleanLines.join( separator );
-
-		}
-
-		function getObjectName( o ) {
-
-			return o.name ? o.name : "Object_" + o.id;
-
-		}
-
-		function getGeometryName( g ) {
-
-			return g.name ? g.name : "Geometry_" + g.id;
-
-		}
-
-		function getMaterialName( m ) {
-
-			return m.name ? m.name : "Material_" + m.id;
-
-		}
-
-		function getTextureName( t ) {
-
-			return t.name ? t.name : "Texture_" + t.id;
-
-		}
-
-		function getFogName( f ) {
-
-			return f.name ? f.name : "Default fog";
-
-		}
-
-		//
-
-		var output = [
-			'{',
-			'	"metadata": {',
-			'		"formatVersion" : 3.2,',
-			'		"type"		: "scene",',
-			'		"generatedBy"	: "SceneExporter",',
-			'		"objects"       : ' + nobjects + ',',
-			'		"geometries"    : ' + ngeometries + ',',
-			'		"materials"     : ' + nmaterials + ',',
-			'		"textures"      : ' + ntextures,
-			'	},',
-			'',
-			'	"urlBaseType": "relativeToScene",',
-			'',
-
-			'	"objects" :',
-			'	{',
-			objects,
-			'	},',
-			'',
-
-			'	"geometries" :',
-			'	{',
-			'\t' + 	geometries,
-			'	},',
-			'',
-
-			'	"materials" :',
-			'	{',
-			'\t' + 	materials,
-			'	},',
-			'',
-
-			'	"textures" :',
-			'	{',
-			'\t' + 	textures,
-			'	},',
-			'',
-
-			'	"fogs" :',
-			'	{',
-			'\t' + 	fogs,
-			'	},',
-			'',
-
-			'	"transform" :',
-			'	{',
-			'		"position"  : ' + position + ',',
-			'		"rotation"  : ' + rotation + ',',
-			'		"scale"     : ' + scale,
-			'	},',
-			'',
-			'	"defaults" :',
-			'	{',
-			'		"camera"  : ' + defcamera + ',',
-			'		"fog"  	  : ' + deffog,
-			'	}',
-			'}'
-		].join( '\n' );
-
-		return JSON.parse( output );
-
-	}
-
-};

+ 8 - 18
examples/js/loaders/AssimpJSONLoader.js

@@ -188,27 +188,17 @@ THREE.AssimpJSONLoader.prototype = {
 
 			function convertColors( in_color, out_faces ) {
 
-				var i, e, face, a, b, c;
-
-				function makeColor( start ) {
+				for ( var i = 0, e = out_faces.length; i < e; ++ i ) {
 
-					var col = new THREE.Color( );
-					col.setRGB( arr[ 0 ], arr[ 1 ], arr[ 2 ] );
-					// TODO: what about alpha?
-					return col;
-
-				}
+					var face = out_faces[ i ];
+					var a = face.a * 4;
+					var b = face.b * 4;
+					var c = face.c * 4;
 
-				for ( i = 0, e = out_faces.length; i < e; ++ i ) {
-
-					face = out_faces[ i ];
-					a = face.a * 4;
-					b = face.b * 4;
-					c = face.c * 4;
 					face.vertexColors = [
-						makeColor( a ),
-						makeColor( b ),
-						makeColor( c )
+						new THREE.Color().fromArray( a ),
+						new THREE.Color().fromArray( b ),
+						new THREE.Color().fromArray( c )
 					];
 
 				}

+ 7 - 7
examples/js/loaders/BinaryLoader.js

@@ -232,7 +232,7 @@ THREE.BinaryLoader.prototype = {
 									  + metaData.nquad_smooth_uv * ( metaData.vertex_index_bytes*4 + metaData.material_index_bytes + metaData.normal_index_bytes*4 + metaData.uv_index_bytes*4 );
 							console.log( "total bytes: " + total );
 				*/
-				
+
 				return metaData;
 
 			}
@@ -429,7 +429,7 @@ THREE.BinaryLoader.prototype = {
 
 					m = materialIndexBuffer[ i ];
 
-					scope.faces.push( new THREE.Face3( a, b, c ) );
+					scope.faces.push( new THREE.Face3( a, b, c, null, null, m ) );
 
 				}
 
@@ -451,8 +451,8 @@ THREE.BinaryLoader.prototype = {
 
 					m = materialIndexBuffer[ i ];
 
-					scope.faces.push( new THREE.Face3( a, b, d ) );
-					scope.faces.push( new THREE.Face3( b, c, d ) );
+					scope.faces.push( new THREE.Face3( a, b, d, null, null, m ) );
+					scope.faces.push( new THREE.Face3( b, c, d, null, null, m ) );
 
 				}
 
@@ -495,7 +495,7 @@ THREE.BinaryLoader.prototype = {
 						new THREE.Vector3( nax, nay, naz ),
 						new THREE.Vector3( nbx, nby, nbz ),
 						new THREE.Vector3( ncx, ncy, ncz )
-					] ) );
+					], null, m ) );
 
 				}
 
@@ -544,13 +544,13 @@ THREE.BinaryLoader.prototype = {
 						new THREE.Vector3( nax, nay, naz ),
 						new THREE.Vector3( nbx, nby, nbz ),
 						new THREE.Vector3( ndx, ndy, ndz )
-					] ) );
+					], null, m ) );
 
 					scope.faces.push( new THREE.Face3( b, c, d, [
 						new THREE.Vector3( nbx, nby, nbz ),
 						new THREE.Vector3( ncx, ncy, ncz ),
 						new THREE.Vector3( ndx, ndy, ndz )
-					] ) );
+					], null, m ) );
 
 				}
 

+ 314 - 0
examples/js/loaders/MD2Loader.js

@@ -0,0 +1,314 @@
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
+
+THREE.MD2Loader = function ( manager ) {
+
+	this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
+
+};
+
+THREE.MD2Loader.prototype = {
+
+	constructor: THREE.MD2Loader,
+
+	load: function ( url, onLoad, onProgress, onError ) {
+
+		var scope = this;
+
+		var loader = new THREE.XHRLoader( scope.manager );
+		loader.setCrossOrigin( this.crossOrigin );
+		loader.setResponseType( 'arraybuffer' );
+		loader.load( url, function ( buffer ) {
+
+			onLoad( scope.parse( buffer ) );
+
+		}, onProgress, onError );
+
+	},
+
+	setCrossOrigin: function ( value ) {
+
+		this.crossOrigin = value;
+
+	},
+
+	parse: ( function () {
+
+		var normals = [
+			[ -0.525731,  0.000000,  0.850651 ], [ -0.442863,  0.238856,  0.864188 ],
+			[ -0.295242,  0.000000,  0.955423 ], [ -0.309017,  0.500000,  0.809017 ],
+			[ -0.162460,  0.262866,  0.951056 ], [  0.000000,  0.000000,  1.000000 ],
+			[  0.000000,  0.850651,  0.525731 ], [ -0.147621,  0.716567,  0.681718 ],
+			[  0.147621,  0.716567,  0.681718 ], [  0.000000,  0.525731,  0.850651 ],
+			[  0.309017,  0.500000,  0.809017 ], [  0.525731,  0.000000,  0.850651 ],
+			[  0.295242,  0.000000,  0.955423 ], [  0.442863,  0.238856,  0.864188 ],
+			[  0.162460,  0.262866,  0.951056 ], [ -0.681718,  0.147621,  0.716567 ],
+			[ -0.809017,  0.309017,  0.500000 ], [ -0.587785,  0.425325,  0.688191 ],
+			[ -0.850651,  0.525731,  0.000000 ], [ -0.864188,  0.442863,  0.238856 ],
+			[ -0.716567,  0.681718,  0.147621 ], [ -0.688191,  0.587785,  0.425325 ],
+			[ -0.500000,  0.809017,  0.309017 ], [ -0.238856,  0.864188,  0.442863 ],
+			[ -0.425325,  0.688191,  0.587785 ], [ -0.716567,  0.681718, -0.147621 ],
+			[ -0.500000,  0.809017, -0.309017 ], [ -0.525731,  0.850651,  0.000000 ],
+			[  0.000000,  0.850651, -0.525731 ], [ -0.238856,  0.864188, -0.442863 ],
+			[  0.000000,  0.955423, -0.295242 ], [ -0.262866,  0.951056, -0.162460 ],
+			[  0.000000,  1.000000,  0.000000 ], [  0.000000,  0.955423,  0.295242 ],
+			[ -0.262866,  0.951056,  0.162460 ], [  0.238856,  0.864188,  0.442863 ],
+			[  0.262866,  0.951056,  0.162460 ], [  0.500000,  0.809017,  0.309017 ],
+			[  0.238856,  0.864188, -0.442863 ], [  0.262866,  0.951056, -0.162460 ],
+			[  0.500000,  0.809017, -0.309017 ], [  0.850651,  0.525731,  0.000000 ],
+			[  0.716567,  0.681718,  0.147621 ], [  0.716567,  0.681718, -0.147621 ],
+			[  0.525731,  0.850651,  0.000000 ], [  0.425325,  0.688191,  0.587785 ],
+			[  0.864188,  0.442863,  0.238856 ], [  0.688191,  0.587785,  0.425325 ],
+			[  0.809017,  0.309017,  0.500000 ], [  0.681718,  0.147621,  0.716567 ],
+			[  0.587785,  0.425325,  0.688191 ], [  0.955423,  0.295242,  0.000000 ],
+			[  1.000000,  0.000000,  0.000000 ], [  0.951056,  0.162460,  0.262866 ],
+			[  0.850651, -0.525731,  0.000000 ], [  0.955423, -0.295242,  0.000000 ],
+			[  0.864188, -0.442863,  0.238856 ], [  0.951056, -0.162460,  0.262866 ],
+			[  0.809017, -0.309017,  0.500000 ], [  0.681718, -0.147621,  0.716567 ],
+			[  0.850651,  0.000000,  0.525731 ], [  0.864188,  0.442863, -0.238856 ],
+			[  0.809017,  0.309017, -0.500000 ], [  0.951056,  0.162460, -0.262866 ],
+			[  0.525731,  0.000000, -0.850651 ], [  0.681718,  0.147621, -0.716567 ],
+			[  0.681718, -0.147621, -0.716567 ], [  0.850651,  0.000000, -0.525731 ],
+			[  0.809017, -0.309017, -0.500000 ], [  0.864188, -0.442863, -0.238856 ],
+			[  0.951056, -0.162460, -0.262866 ], [  0.147621,  0.716567, -0.681718 ],
+			[  0.309017,  0.500000, -0.809017 ], [  0.425325,  0.688191, -0.587785 ],
+			[  0.442863,  0.238856, -0.864188 ], [  0.587785,  0.425325, -0.688191 ],
+			[  0.688191,  0.587785, -0.425325 ], [ -0.147621,  0.716567, -0.681718 ],
+			[ -0.309017,  0.500000, -0.809017 ], [  0.000000,  0.525731, -0.850651 ],
+			[ -0.525731,  0.000000, -0.850651 ], [ -0.442863,  0.238856, -0.864188 ],
+			[ -0.295242,  0.000000, -0.955423 ], [ -0.162460,  0.262866, -0.951056 ],
+			[  0.000000,  0.000000, -1.000000 ], [  0.295242,  0.000000, -0.955423 ],
+			[  0.162460,  0.262866, -0.951056 ], [ -0.442863, -0.238856, -0.864188 ],
+			[ -0.309017, -0.500000, -0.809017 ], [ -0.162460, -0.262866, -0.951056 ],
+			[  0.000000, -0.850651, -0.525731 ], [ -0.147621, -0.716567, -0.681718 ],
+			[  0.147621, -0.716567, -0.681718 ], [  0.000000, -0.525731, -0.850651 ],
+			[  0.309017, -0.500000, -0.809017 ], [  0.442863, -0.238856, -0.864188 ],
+			[  0.162460, -0.262866, -0.951056 ], [  0.238856, -0.864188, -0.442863 ],
+			[  0.500000, -0.809017, -0.309017 ], [  0.425325, -0.688191, -0.587785 ],
+			[  0.716567, -0.681718, -0.147621 ], [  0.688191, -0.587785, -0.425325 ],
+			[  0.587785, -0.425325, -0.688191 ], [  0.000000, -0.955423, -0.295242 ],
+			[  0.000000, -1.000000,  0.000000 ], [  0.262866, -0.951056, -0.162460 ],
+			[  0.000000, -0.850651,  0.525731 ], [  0.000000, -0.955423,  0.295242 ],
+			[  0.238856, -0.864188,  0.442863 ], [  0.262866, -0.951056,  0.162460 ],
+			[  0.500000, -0.809017,  0.309017 ], [  0.716567, -0.681718,  0.147621 ],
+			[  0.525731, -0.850651,  0.000000 ], [ -0.238856, -0.864188, -0.442863 ],
+			[ -0.500000, -0.809017, -0.309017 ], [ -0.262866, -0.951056, -0.162460 ],
+			[ -0.850651, -0.525731,  0.000000 ], [ -0.716567, -0.681718, -0.147621 ],
+			[ -0.716567, -0.681718,  0.147621 ], [ -0.525731, -0.850651,  0.000000 ],
+			[ -0.500000, -0.809017,  0.309017 ], [ -0.238856, -0.864188,  0.442863 ],
+			[ -0.262866, -0.951056,  0.162460 ], [ -0.864188, -0.442863,  0.238856 ],
+			[ -0.809017, -0.309017,  0.500000 ], [ -0.688191, -0.587785,  0.425325 ],
+			[ -0.681718, -0.147621,  0.716567 ], [ -0.442863, -0.238856,  0.864188 ],
+			[ -0.587785, -0.425325,  0.688191 ], [ -0.309017, -0.500000,  0.809017 ],
+			[ -0.147621, -0.716567,  0.681718 ], [ -0.425325, -0.688191,  0.587785 ],
+			[ -0.162460, -0.262866,  0.951056 ], [  0.442863, -0.238856,  0.864188 ],
+			[  0.162460, -0.262866,  0.951056 ], [  0.309017, -0.500000,  0.809017 ],
+			[  0.147621, -0.716567,  0.681718 ], [  0.000000, -0.525731,  0.850651 ],
+			[  0.425325, -0.688191,  0.587785 ], [  0.587785, -0.425325,  0.688191 ],
+			[  0.688191, -0.587785,  0.425325 ], [ -0.955423,  0.295242,  0.000000 ],
+			[ -0.951056,  0.162460,  0.262866 ], [ -1.000000,  0.000000,  0.000000 ],
+			[ -0.850651,  0.000000,  0.525731 ], [ -0.955423, -0.295242,  0.000000 ],
+			[ -0.951056, -0.162460,  0.262866 ], [ -0.864188,  0.442863, -0.238856 ],
+			[ -0.951056,  0.162460, -0.262866 ], [ -0.809017,  0.309017, -0.500000 ],
+			[ -0.864188, -0.442863, -0.238856 ], [ -0.951056, -0.162460, -0.262866 ],
+			[ -0.809017, -0.309017, -0.500000 ], [ -0.681718,  0.147621, -0.716567 ],
+			[ -0.681718, -0.147621, -0.716567 ], [ -0.850651,  0.000000, -0.525731 ],
+			[ -0.688191,  0.587785, -0.425325 ], [ -0.587785,  0.425325, -0.688191 ],
+			[ -0.425325,  0.688191, -0.587785 ], [ -0.425325, -0.688191, -0.587785 ],
+			[ -0.587785, -0.425325, -0.688191 ], [ -0.688191, -0.587785, -0.425325 ]
+		];
+
+		return function ( buffer ) {
+
+			var data = new DataView( buffer );
+
+			// http://tfc.duke.free.fr/coding/md2-specs-en.html
+
+			var header = {};
+			var headerNames = [
+				'ident', 'version',
+				'skinwidth', 'skinheight',
+				'framesize',
+				'num_skins', 'num_vertices', 'num_st', 'num_tris', 'num_glcmds', 'num_frames',
+				'offset_skins', 'offset_st', 'offset_tris', 'offset_frames', 'offset_glcmds', 'offset_end'
+			];
+
+			for ( var i = 0; i < headerNames.length; i ++ ) {
+
+				header[ headerNames[ i ] ] = data.getInt32( i * 4, true );
+
+			}
+
+			if ( header.ident !== 844121161 || header.version !== 8 ) {
+
+				console.error( 'Not a valid MD2 file' );
+				return;
+
+			}
+
+			if ( header.offset_end !== data.byteLength ) {
+
+				console.error( 'Corrupted MD2 file' );
+				return;
+
+			}
+
+			//
+
+			var geometry = new THREE.Geometry();
+
+			// uvs
+
+			var uvs = [];
+			var offset = header.offset_st;
+
+			for ( var i = 0; i < header.num_st; i ++, offset += 4 ) {
+
+				var u = data.getInt16( offset + 0, true );
+				var v = data.getInt16( offset + 2, true );
+
+				var uv = new THREE.Vector2( u / header.skinwidth, 1 - ( v / header.skinheight ) );
+
+				uvs.push( uv );
+
+			}
+
+			// triangles
+
+			var offset = header.offset_tris;
+
+			for ( var i = 0; i < header.num_tris; i ++ ) {
+
+				var a = data.getUint16( offset + 0, true );
+				var b = data.getUint16( offset + 2, true );
+				var c = data.getUint16( offset + 4, true );
+
+				var face = new THREE.Face3( a, b, c );
+
+				geometry.faces.push( face );
+
+				geometry.faceVertexUvs[ 0 ].push( [
+					uvs[ data.getUint16( offset + 6, true ) ],
+					uvs[ data.getUint16( offset + 8, true ) ],
+					uvs[ data.getUint16( offset + 10, true ) ]
+				] );
+
+				offset += 12;
+
+			}
+
+			// frames
+
+			var translation = new THREE.Vector3();
+			var scale = new THREE.Vector3();
+
+			var offset = header.offset_frames;
+
+			for ( var i = 0; i < header.num_frames; i ++ ) {
+
+				scale.set(
+					data.getFloat32( offset + 0, true ),
+					data.getFloat32( offset + 4, true ),
+					data.getFloat32( offset + 8, true )
+				);
+
+				translation.set(
+					data.getFloat32( offset + 12, true ),
+					data.getFloat32( offset + 16, true ),
+					data.getFloat32( offset + 20, true )
+				);
+
+				offset += 24;
+
+				var string = [];
+
+				for ( var j = 0; j < 16; j ++ ) {
+
+					string[ j ] = data.getUint8( offset + j, true );
+
+				}
+
+				var frame = {
+					name: String.fromCharCode.apply( null, string ),
+					vertices: [],
+					normals: []
+				};
+
+				offset += 16;
+
+				for ( var j = 0; j < header.num_vertices; j ++ ) {
+
+					var x = data.getUint8( offset ++, true );
+					var y = data.getUint8( offset ++, true );
+					var z = data.getUint8( offset ++, true );
+					var n = data.getUint8( offset ++, true );
+
+					var vertex = new THREE.Vector3(
+						x * scale.x + translation.x,
+						z * scale.z + translation.z,
+						y * scale.y + translation.y
+					);
+
+					var normal = new THREE.Vector3(
+						normals[ n ][ 0 ], normals[ n ][ 2 ], normals[ n ][ 1 ]
+					);
+
+					frame.vertices.push( vertex );
+					frame.normals.push( normal );
+
+				}
+
+				geometry.morphTargets.push( frame );
+
+			}
+
+			// Static
+
+			geometry.vertices = geometry.morphTargets[ 0 ].vertices;
+
+			var morphTarget = geometry.morphTargets[ 0 ];
+
+			for ( var j = 0, jl = geometry.faces.length; j < jl; j ++ ) {
+
+				var face = geometry.faces[ j ];
+
+				face.vertexNormals = [
+					morphTarget.normals[ face.a ],
+					morphTarget.normals[ face.b ],
+					morphTarget.normals[ face.c ]
+				];
+
+			}
+
+
+			// Convert to geometry.morphNormals
+
+			for ( var i = 0, l = geometry.morphTargets.length; i < l; i ++ ) {
+
+				var morphTarget = geometry.morphTargets[ i ];
+				var vertexNormals = [];
+
+				for ( var j = 0, jl = geometry.faces.length; j < jl; j ++ ) {
+
+					var face = geometry.faces[ j ];
+
+					vertexNormals.push( {
+						a: morphTarget.normals[ face.a ],
+						b: morphTarget.normals[ face.b ],
+						c: morphTarget.normals[ face.c ]
+					} );
+
+				}
+
+				geometry.morphNormals.push( { vertexNormals: vertexNormals } );
+
+			}
+
+			return geometry;
+
+		}
+
+	} )()
+
+}

+ 42 - 18
examples/js/loaders/VTKLoader.js

@@ -37,43 +37,67 @@ THREE.VTKLoader.prototype = {
 		var indices = [];
 		var positions = [];
 
-		var pattern, result;
+		var result;
 
 		// float float float
 
-		pattern = /([\+|\-]?[\d]+[\.][\d|\-|e]+)[ ]+([\+|\-]?[\d]+[\.][\d|\-|e]+)[ ]+([\+|\-]?[\d]+[\.][\d|\-|e]+)/g;
+		var pat3Floats = /([\-]?[\d]+[\.]?[\d|\-|e]*)[ ]+([\-]?[\d]+[\.]?[\d|\-|e]*)[ ]+([\-]?[\d]+[\.]?[\d|\-|e]*)/g;
+		var patTriangle = /^3[ ]+([\d]+)[ ]+([\d]+)[ ]+([\d]+)/;
+		var patQuad = /^4[ ]+([\d]+)[ ]+([\d]+)[ ]+([\d]+)[ ]+([\d]+)/;
+		var patPOINTS = /^POINTS /;
+		var patPOLYGONS = /^POLYGONS /;
+		var inPointsSection = false;
+		var inPolygonsSection = false;
 
-		while ( ( result = pattern.exec( data ) ) !== null ) {
+		var lines = data.split('\n');
+		for ( var i = 0; i < lines.length; ++i ) {
 
-			// ["1.0 2.0 3.0", "1.0", "2.0", "3.0"]
+			line = lines[i];
 
-			positions.push( parseFloat( result[ 1 ] ), parseFloat( result[ 2 ] ), parseFloat( result[ 3 ] ) );
+			if ( inPointsSection ) {
 
-		}
+				// get the vertices
 
-		// 3 int int int
+				while ( ( result = pat3Floats.exec( line ) ) !== null ) {
+					positions.push( parseFloat( result[ 1 ] ), parseFloat( result[ 2 ] ), parseFloat( result[ 3 ] ) );
+				}
+			}
+			else if ( inPolygonsSection ) {
 
-		pattern = /3[ ]+([\d]+)[ ]+([\d]+)[ ]+([\d]+)/g;
+				result = patTriangle.exec(line);
 
-		while ( ( result = pattern.exec( data ) ) !== null ) {
+				if ( result !== null ) {
 
-			// ["3 1 2 3", "1", "2", "3"]
+					// 3 int int int
+					// triangle
 
-			indices.push( parseInt( result[ 1 ] ), parseInt( result[ 2 ] ), parseInt( result[ 3 ] ) );
+					indices.push( parseInt( result[ 1 ] ), parseInt( result[ 2 ] ), parseInt( result[ 3 ] ) );
+				}
+				else {
 
-		}
+					result = patQuad.exec(line);
 
-		// 4 int int int int
+					if ( result !== null ) {
 
-		pattern = /4[ ]+([\d]+)[ ]+([\d]+)[ ]+([\d]+)[ ]+([\d]+)/g;
+						// 4 int int int int
+						// break quad into two triangles
 
-		while ( ( result = pattern.exec( data ) ) !== null ) {
+						indices.push( parseInt( result[ 1 ] ), parseInt( result[ 2 ] ), parseInt( result[ 4 ] ) );
+						indices.push( parseInt( result[ 2 ] ), parseInt( result[ 3 ] ), parseInt( result[ 4 ] ) );
+					}
 
-			// ["4 1 2 3 4", "1", "2", "3", "4"]
+				}
 
-			indices.push( parseInt( result[ 1 ] ), parseInt( result[ 2 ] ), parseInt( result[ 4 ] ) );
-			indices.push( parseInt( result[ 2 ] ), parseInt( result[ 3 ] ), parseInt( result[ 4 ] ) );
+			}
 
+			if ( patPOLYGONS.exec(line) !== null ) {
+				inPointsSection = false;
+				inPolygonsSection = true;
+			}
+			if ( patPOINTS.exec(line) !== null ) {
+				inPolygonsSection = false;
+				inPointsSection = true;
+			}
 		}
 
 		var geometry = new THREE.BufferGeometry();

+ 1 - 3
examples/js/loaders/ctm/CTMLoader.js

@@ -246,9 +246,7 @@ THREE.CTMLoader.prototype.createModel = function ( file, callback ) {
 	Model.prototype.constructor = Model;
 
 	var geometry = new Model();
-
-	geometry.computeOffsets();
-
+	
 	// compute vertex normals if not present in the CTM model
 	if ( geometry.attributes.normal === undefined ) {
 		geometry.computeVertexNormals();

+ 1 - 1
examples/js/loaders/gltf/glTFLoader.js

@@ -1209,7 +1209,7 @@ THREE.glTFLoader.prototype.load = function( url, callback ) {
 								}
 							}
 
-							threeMesh.bind(new THREE.Skeleton(bones, boneInverses, false));
+							threeMesh.bind( new THREE.Skeleton( bones, boneInverses, false ), threeMesh.matrixWorld );
 						}
 
 						if (threeMesh) {

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 407 - 350
examples/js/loaders/sea3d/SEA3DLoader.js


+ 2 - 4
examples/js/math/Lut.js

@@ -327,9 +327,8 @@ THREE.Lut.prototype = {
 
 		contextTitle.fillText( this.legend.labels.title.toString() + this.legend.labels.um.toString(), borderThickness, this.legend.labels.fontsize + borderThickness );
 
-		var txtTitle = new THREE.Texture( canvasTitle );
+		var txtTitle = new THREE.CanvasTexture( canvasTitle );
 		txtTitle.minFilter = THREE.LinearFilter;
-		txtTitle.needsUpdate = true;
 
 		var spriteMaterialTitle = new THREE.SpriteMaterial( { map: txtTitle, useScreenCoordinates: false } );
 
@@ -408,9 +407,8 @@ THREE.Lut.prototype = {
 
 				contextTick.fillText( value.toString(), borderThickness, this.legend.labels.fontsize + borderThickness );
 
-				var txtTick = new THREE.Texture( canvasTick );
+				var txtTick = new THREE.CanvasTexture( canvasTick );
 				txtTick.minFilter = THREE.LinearFilter;
-				txtTick.needsUpdate = true;
 
 				var spriteMaterialTick = new THREE.SpriteMaterial( { map: txtTick, useScreenCoordinates: false } );
 

+ 1 - 1
examples/js/renderers/CSS2DRenderer.js

@@ -90,7 +90,7 @@ THREE.CSS2DRenderer = function () {
 
 		scene.updateMatrixWorld();
 
-		if ( camera.parent === undefined ) camera.updateMatrixWorld();
+		if ( camera.parent === null ) camera.updateMatrixWorld();
 
 		camera.matrixWorldInverse.getInverse( camera.matrixWorld );
 

+ 1 - 1
examples/js/renderers/CSS3DRenderer.js

@@ -227,7 +227,7 @@ THREE.CSS3DRenderer = function () {
 
 		scene.updateMatrixWorld();
 
-		if ( camera.parent === undefined ) camera.updateMatrixWorld();
+		if ( camera.parent === null ) camera.updateMatrixWorld();
 
 		camera.matrixWorldInverse.getInverse( camera.matrixWorld );
 

+ 1 - 1
examples/js/renderers/CSS3DStereoRenderer.js

@@ -254,7 +254,7 @@ THREE.CSS3DStereoRenderer = function () {
 
 		scene.updateMatrixWorld();
 
-		if ( camera.parent === undefined ) camera.updateMatrixWorld();
+		if ( camera.parent === null ) camera.updateMatrixWorld();
 
 		camera.matrixWorld.decompose( _position, _quaternion, _scale );
 

+ 6 - 5
examples/js/renderers/Projector.js

@@ -325,7 +325,7 @@ THREE.Projector = function () {
 		_renderData.elements.length = 0;
 
 		if ( scene.autoUpdate === true ) scene.updateMatrixWorld();
-		if ( camera.parent === undefined ) camera.updateMatrixWorld();
+		if ( camera.parent === null ) camera.updateMatrixWorld();
 
 		_viewMatrix.copy( camera.matrixWorldInverse.getInverse( camera.matrixWorld ) );
 		_viewProjectionMatrix.multiplyMatrices( camera.projectionMatrix, _viewMatrix );
@@ -347,7 +347,9 @@ THREE.Projector = function () {
 
 			} else if ( object instanceof THREE.Mesh || object instanceof THREE.Line || object instanceof THREE.Sprite ) {
 
-				if ( object.material.visible === false ) return;
+				var material = object.material;
+
+				if ( material.visible === false ) return;
 
 				if ( object.frustumCulled === false || _frustum.intersectsObject( object ) === true ) {
 
@@ -437,11 +439,10 @@ THREE.Projector = function () {
 							for ( var o = 0; o < offsets.length; o ++ ) {
 
 								var offset = offsets[ o ];
-								var index = offset.index;
 
 								for ( var i = offset.start, l = offset.start + offset.count; i < l; i += 3 ) {
 
-									renderList.pushTriangle( indices[ i ] + index, indices[ i + 1 ] + index, indices[ i + 2 ] + index );
+									renderList.pushTriangle( indices[ i ], indices[ i + 1 ], indices[ i + 2 ] );
 
 								}
 
@@ -517,7 +518,7 @@ THREE.Projector = function () {
 						var face = faces[ f ];
 
 						material = isFaceMaterial === true
-							 ? objectMaterials.materials[ 0 ] // objectMaterials.materials[ face.materialIndex ]
+							 ? objectMaterials.materials[ face.materialIndex ]
 							 : object.material;
 
 						if ( material === undefined ) continue;

+ 1 - 1
examples/js/renderers/RaytracingRenderer.js

@@ -493,7 +493,7 @@ THREE.RaytracingRenderer = function ( parameters ) {
 
 		// update camera matrices
 
-		if ( camera.parent === undefined ) camera.updateMatrixWorld();
+		if ( camera.parent === null ) camera.updateMatrixWorld();
 
 		camera.matrixWorldInverse.getInverse( camera.matrixWorld );
 		cameraPosition.setFromMatrixPosition( camera.matrixWorld );

+ 191 - 12
examples/js/renderers/SoftwareRenderer.js

@@ -40,7 +40,10 @@ THREE.SoftwareRenderer = function ( parameters ) {
 	var blockShift = 3;
 	var blockSize = 1 << blockShift;
 	var maxZVal = ( 1 << 24 ); // Note: You want to size this so you don't get overflows.
-
+	var lineMode = false;
+	var lookVector = new THREE.Vector3( 0, 0, 1 );
+	var crossVector = new THREE.Vector3();        
+    
 	var rectx1 = Infinity, recty1 = Infinity;
 	var rectx2 = 0, recty2 = 0;
 
@@ -141,6 +144,7 @@ THREE.SoftwareRenderer = function ( parameters ) {
 
 	};
 
+    // TODO: Check why autoClear can't be false.
 	this.render = function ( scene, camera ) {
 
 		if ( this.autoClear === true ) this.clear();
@@ -252,6 +256,18 @@ THREE.SoftwareRenderer = function ( parameters ) {
 
 				}
 
+			} else if ( element instanceof THREE.RenderableLine ) {
+				
+				var shader = getMaterialShader( material );
+
+				drawLine(
+					element.v1.positionScreen,
+					element.v2.positionScreen,
+					element.vertexColors[0],
+					element.vertexColors[1],
+					shader,
+					material
+				);
 			}
 
 		}
@@ -288,6 +304,53 @@ THREE.SoftwareRenderer = function ( parameters ) {
 
 	};
 
+	function setSize( width, height ) {
+        
+		canvasWBlocks = Math.floor( width / blockSize );
+		canvasHBlocks = Math.floor( height / blockSize );
+		canvasWidth   = canvasWBlocks * blockSize;
+		canvasHeight  = canvasHBlocks * blockSize;
+
+		var fixScale = 1 << subpixelBits;
+
+		viewportXScale =  fixScale * canvasWidth  / 2;
+		viewportYScale = -fixScale * canvasHeight / 2;
+		viewportZScale =             maxZVal      / 2;
+              
+		viewportXOffs  =  fixScale * canvasWidth  / 2 + 0.5;
+		viewportYOffs  =  fixScale * canvasHeight / 2 + 0.5;
+		viewportZOffs  =             maxZVal      / 2 + 0.5;
+        
+		canvas.width = canvasWidth;
+		canvas.height = canvasHeight;
+
+		context.fillStyle = clearColor.getStyle();
+		context.fillRect( 0, 0, canvasWidth, canvasHeight );
+
+		imagedata = context.getImageData( 0, 0, canvasWidth, canvasHeight );
+		data = imagedata.data;
+
+		zbuffer = new Int32Array( data.length / 4 );
+
+		numBlocks = canvasWBlocks * canvasHBlocks;
+		blockMaxZ = new Int32Array( numBlocks );
+		blockFlags = new Uint8Array( numBlocks );
+
+		for ( var i = 0, l = zbuffer.length; i < l; i ++ ) {
+
+			zbuffer[ i ] = maxZVal;
+
+		}
+
+		for ( var i = 0; i < numBlocks; i ++ ) {
+
+			blockFlags[ i ] = BLOCK_ISCLEAR;
+
+		}
+
+		cleanColorBuffer();
+	}
+    
 	function cleanColorBuffer() {
 
 		var size = canvasWidth * canvasHeight * 4;
@@ -462,9 +525,9 @@ THREE.SoftwareRenderer = function ( parameters ) {
 			material.addEventListener( 'update', onMaterialUpdate );
 
 			if ( material instanceof THREE.MeshBasicMaterial ||
-				 material instanceof THREE.MeshLambertMaterial ||
-				 material instanceof THREE.MeshPhongMaterial ||
-				 material instanceof THREE.SpriteMaterial ) {
+				material instanceof THREE.MeshLambertMaterial ||
+				material instanceof THREE.MeshPhongMaterial ||
+				material instanceof THREE.SpriteMaterial ) {
 
 				if ( material instanceof THREE.MeshLambertMaterial ) {
 
@@ -493,12 +556,6 @@ THREE.SoftwareRenderer = function ( parameters ) {
 					var texture = new THREE.SoftwareRenderer.Texture();
 					texture.fromImage( material.map.image );
 
-					material.map.addEventListener( 'update', function ( event ) {
-
-						texture.fromImage( event.target.image );
-
-					} );
-
 					textures[ material.map.id ] = texture;
 
 					if ( material instanceof THREE.MeshBasicMaterial
@@ -543,6 +600,19 @@ THREE.SoftwareRenderer = function ( parameters ) {
 
 				}
 
+			} else if ( material instanceof THREE.LineBasicMaterial ) {
+                
+				var string = [
+					'var colorOffset = offset * 4;',
+					'buffer[ colorOffset ] = material.color.r * (color1.r+color2.r) * 0.5 * 255;',
+					'buffer[ colorOffset + 1 ] = material.color.g * (color1.g+color2.g) * 0.5 * 255;',
+					'buffer[ colorOffset + 2 ] = material.color.b * (color1.b+color2.b) * 0.5 * 255;',
+					'buffer[ colorOffset + 3 ] = 255;',
+					'depthBuf[ offset ] = depth;'
+				].join('\n');
+
+				shader = new Function( 'buffer, depthBuf, offset, depth, color1, color2, material', string );
+
 			} else {
 
 				var string = [
@@ -554,7 +624,7 @@ THREE.SoftwareRenderer = function ( parameters ) {
 					'depthBuf[ offset ] = depth;'
 				].join( '\n' );
 
-				shader = new Function( 'buffer, depthBuf, offset, depth, u, v', string );
+				shader = new Function( 'buffer, depthBuf, offset, depth, u, v, n, face, material', string );
 
 			}
 
@@ -771,7 +841,6 @@ THREE.SoftwareRenderer = function ( parameters ) {
 
 		// Loop through blocks
 		var linestep = canvasWidth - q;
-		var scale = 1.0 / ( c1 + c2 + c3 );
 
 		var cb1 = c1;
 		var cb2 = c2;
@@ -1124,7 +1193,117 @@ THREE.SoftwareRenderer = function ( parameters ) {
 		}
 
 	}
+    
+	// When drawing line, the blockShiftShift has to be zero. In order to clean pixel
+	// Using color1 and color2 to interpolation pixel color
+	// LineWidth is according to material.linewidth
+	function drawLine( v1, v2, color1, color2, shader, material ) {
+        
+		// While the line mode is enable, blockSize has to be changed to 0.
+		if ( !lineMode ) {
+			lineMode = true;            
+			blockShift = 0;
+			blockSize = 1 << blockShift;
+
+			setSize( canvas.width, canvas.height );
+		}
+
+		// TODO: Implement per-pixel z-clipping
+		if ( v1.z < -1 || v1.z > 1 || v2.z < -1 || v2.z > 1 ) return;
+
+		var halfLineWidth = Math.floor( (material.linewidth-1) * 0.5 );
+      
+		// https://gist.github.com/2486101
+		// explanation: http://pouet.net/topic.php?which=8760&page=1
+
+		// 28.4 fixed-point coordinates
+		var x1 = (v1.x * viewportXScale + viewportXOffs) | 0;
+		var x2 = (v2.x * viewportXScale + viewportXOffs) | 0;
+
+		var y1 = (v1.y * viewportYScale + viewportYOffs) | 0;
+		var y2 = (v2.y * viewportYScale + viewportYOffs) | 0;
+
+		var z1 = (v1.z * viewportZScale + viewportZOffs) | 0;
+		var z2 = (v2.z * viewportZScale + viewportZOffs) | 0;
+
+		// Deltas
+		var dx12 = x1 - x2, dy12 = y1 - y2, dz12 = z1 - z2;
 
+		// Bounding rectangle
+		var minx = Math.max( ( Math.min( x1, x2 ) + subpixelBias ) >> subpixelBits, 0 );
+		var maxx = Math.min( ( Math.max( x1, x2 ) + subpixelBias ) >> subpixelBits, canvasWidth );
+		var miny = Math.max( ( Math.min( y1, y2 ) + subpixelBias ) >> subpixelBits, 0 );
+		var maxy = Math.min( ( Math.max( y1, y2 ) + subpixelBias ) >> subpixelBits, canvasHeight );
+		var minz = Math.max( ( Math.min( z1, z2 ) + subpixelBias ) >> subpixelBits, 0 );
+		var maxz = Math.min( ( Math.max( z1, z2 ) + subpixelBias ) >> subpixelBits, 0 );
+
+		rectx1 = Math.min( minx, rectx1 );
+		rectx2 = Math.max( maxx, rectx2 );
+		recty1 = Math.min( miny, recty1 );
+		recty2 = Math.max( maxy, recty2 );
+
+		// Get the line's unit vector and cross vector
+		var length = Math.sqrt((dy12 * dy12) + (dx12 * dx12));
+		var unitX = (dx12 / length);
+		var unitY = (dy12 / length);
+		var unitZ = (dz12 / length);        
+		var pixelX, pixelY, pixelZ;
+		var pX, pY, pZ;
+		crossVector.set( unitX, unitY, unitZ );
+		crossVector.cross( lookVector );
+		crossVector.normalize();
+            
+		while (length > 0) {
+
+			// Get this pixel.
+			pixelX = (x2 + length * unitX);
+			pixelY = (y2 + length * unitY);
+			pixelZ = (z2 + length * unitZ);               
+
+			pixelX = (pixelX + subpixelBias) >> subpixelBits;
+			pixelY = (pixelY + subpixelBias) >> subpixelBits;
+			pZ = (pixelZ + subpixelBias) >> subpixelBits;
+
+			// Draw line with line width
+			for ( var i = -halfLineWidth; i <= halfLineWidth; ++i ) {
+
+				// Compute the line pixels.
+				// Get the pixels on the vector that crosses to the line vector
+				pX = Math.floor((pixelX + crossVector.x * i));
+				pY = Math.floor((pixelY + crossVector.y * i));                    
+
+				// if pixel is over the rect. Continue
+				if ( rectx1 >= pX || rectx2 <= pX || recty1 >= pY 
+					|| recty2 <= pY )
+				continue;
+
+				// Find this pixel at which block
+				var blockX = pX >> blockShift;
+				var blockY = pY >> blockShift;
+				var blockId = blockX + blockY * canvasWBlocks;
+
+				// Compare the pixel depth width z block.
+				if ( blockMaxZ[ blockId ] < minz ) continue;
+
+				blockMaxZ[ blockId ] = Math.min( blockMaxZ[ blockId ], maxz );                    
+
+				var bflags = blockFlags[ blockId ];
+				if ( bflags & BLOCK_NEEDCLEAR ) clearBlock( blockX, blockY );
+				blockFlags[ blockId ] = bflags & ~( BLOCK_ISCLEAR | BLOCK_NEEDCLEAR );                   
+		        
+				// draw pixel
+				var offset = pX + pY * canvasWidth;
+
+				if ( pZ < zbuffer[ offset ] ) {		 
+					shader( data, zbuffer, offset, pZ, color1, color2, material );								
+				}
+			}
+
+			--length;
+		}           
+
+	}
+    
 	function clearBlock( blockX, blockY ) {
 
 		var zoffset = blockX * blockSize + blockY * blockSize * canvasWidth;

+ 1 - 1
examples/misc_controls_deviceorientation.html

@@ -65,7 +65,7 @@
 						scene = new THREE.Scene();
 
 						var geometry = new THREE.SphereGeometry( 500, 16, 8 );
-						geometry.applyMatrix( new THREE.Matrix4().makeScale( -1, 1, 1 ) );
+						geometry.scale( - 1, 1, 1 );
 
 						var material = new THREE.MeshBasicMaterial( {
 							map: THREE.ImageUtils.loadTexture( 'textures/2294472375_24a3b8ef46_o.jpg' )

+ 1 - 1
examples/misc_controls_pointerlock.html

@@ -267,7 +267,7 @@
 				// floor
 
 				geometry = new THREE.PlaneGeometry( 2000, 2000, 100, 100 );
-				geometry.applyMatrix( new THREE.Matrix4().makeRotationX( - Math.PI / 2 ) );
+				geometry.rotateX( - Math.PI / 2 );
 
 				for ( var i = 0, l = geometry.vertices.length; i < l; i ++ ) {
 

+ 1 - 1
examples/misc_lookat.html

@@ -68,7 +68,7 @@
 				scene.add( sphere );
 
 				var geometry = new THREE.CylinderGeometry( 0, 10, 100, 3 );
-				geometry.applyMatrix( new THREE.Matrix4().makeRotationFromEuler( new THREE.Euler( Math.PI / 2, Math.PI, 0 ) ) );
+				geometry.rotateX( Math.PI / 2 );
 
 				var material = new THREE.MeshNormalMaterial();
 

+ 13 - 10
examples/misc_ubiquity_test.html

@@ -145,19 +145,22 @@
 
 				// SPRITES
 
-				var texture = THREE.ImageUtils.loadTexture( 'textures/sprite.png' );
-				var material = new THREE.SpriteMaterial( { map: texture, transparent: true } );
+				THREE.ImageUtils.loadTexture( 'textures/sprite.png', null, function ( texture ) {
 
-				for ( var i = 0; i < 50; i ++ ) {
+					var material = new THREE.SpriteMaterial( { map: texture, transparent: true } );
 
-					var sprite = new THREE.Sprite( material );
-					sprite.position.x = Math.random() * 1000 - 500;
-					sprite.position.y = Math.random() * 1000 - 500;
-					sprite.position.z = Math.random() * 1000 - 500;
-					sprite.scale.set( 64, 64, 1 );
-					scene.add( sprite );
+					for ( var i = 0; i < 50; i ++ ) {
 
-				}
+						var sprite = new THREE.Sprite( material );
+						sprite.position.x = Math.random() * 1000 - 500;
+						sprite.position.y = Math.random() * 1000 - 500;
+						sprite.position.z = Math.random() * 1000 - 500;
+						sprite.scale.set( 64, 64, 1 );
+						scene.add( sprite );
+
+					}
+					
+				} );
 
 				for ( var i = 0; i < 50; i ++ ) {
 

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 15
examples/models/animated/ogro/ogro-light.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 72
examples/models/animated/ogro/weapon-light.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 15
examples/models/animated/ratamahatta/ratamahatta.js


+ 0 - 73
examples/models/animated/ratamahatta/ratamahatta.txt

@@ -1,73 +0,0 @@
-11-02-98
-
-================================================================
-
-Model Name              : Ratamahatta
-
-installation directory  : quake2/baseq2/players/Ratamahatta
-
-Author                  : Brian "EvilBastard" Collins
-
-additional skins by     :
-
-	'Gearwhore'  by MrRogers
-	'Jaws'       by Claudius Brunnecker
-
-Email Address           : [email protected]
-
-Website Address         : http://www.deviousassassins.com/EvilBastard/
-
-Model description       : 
-
-	It's been a long time in the making, but he's finaly done. This PPM is the prize of the Bodyshop Q2 tournament won by Tank Abbot. I hope he likes it  ;P
-
-Model Info	        :
-	Ratamahatta is a fun loving guy, who like to pull the wings off files, and similarly amusing things. After a long day of gratuitous destruction and rolling around in his own filth, Rat always enjoys a spot of tea.
-
-Additional Credits to   : 
-	
-	* Idsoftware 
-	* NST!!! Know it and love it
-
-Thanks to               :
-
-	Npherno and MrRogers for all the help
-	Virus[DA] for hosting my website.
-	Rogue13 and John McPherson for the advise and input.
-
-================================================================
-
-* Play Information *
-
-New Sounds              : NO
-
-CTF Skins               : YES
-
-VWEP Support            : No
-
-
-* Construction *
-
-Poly Count              : 666 tris.md2 / 119 weapon.md2
-
-Vert Count              : 344 tris.md2 / 85 weapon.md2
-
-Skin Count              : 4 DM, 2 CTF
-
-Base		        : Forgotten One
-
-Editor used             : 
-		Modeling - lightwave	
-		Animation- lightwave + puppetmaster
-		Skining  - NST 
-		Painting - Photoshop, NST
-		Viewing  - Skin View 
-		
-Known Bugs              : None that i know of.
-
-
-* Copyright / Permissions *
-QUAKE(R) and QUAKE II(R) are registered trademarks of id Software, Inc.
-Feel free to edit my model as you see fit, just be sure to mention me
-in the readme file. This model is not to be distributed as part of any
-commercial product.

+ 0 - 2
examples/models/animated/ratamahatta/readme.txt

@@ -1,2 +0,0 @@
-Ratamahatta character by Brian Collins
-From http://planetquake.gamespy.com/View.php?view=Quake2.Detail&id=368

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 193
examples/models/animated/ratamahatta/w_bfg.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 224
examples/models/animated/ratamahatta/w_blaster.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 224
examples/models/animated/ratamahatta/w_chaingun.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 224
examples/models/animated/ratamahatta/w_glauncher.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 224
examples/models/animated/ratamahatta/w_hyperblaster.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 224
examples/models/animated/ratamahatta/w_machinegun.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 215
examples/models/animated/ratamahatta/w_railgun.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 80
examples/models/animated/ratamahatta/w_rlauncher.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 224
examples/models/animated/ratamahatta/w_shotgun.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 224
examples/models/animated/ratamahatta/w_sshotgun.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 226
examples/models/animated/ratamahatta/weapon.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 0
examples/models/json/teapot-claraio.json


+ 0 - 0
examples/models/animated/ogro/Ogro.txt → examples/models/md2/ogro/Ogro.txt


BIN
examples/models/md2/ogro/ogro.md2


+ 0 - 0
examples/models/animated/ogro/skins/arboshak.png → examples/models/md2/ogro/skins/arboshak.png


+ 0 - 0
examples/models/animated/ogro/skins/ctf_b.png → examples/models/md2/ogro/skins/ctf_b.png


+ 0 - 0
examples/models/animated/ogro/skins/ctf_r.png → examples/models/md2/ogro/skins/ctf_r.png


+ 0 - 0
examples/models/animated/ogro/skins/darkam.png → examples/models/md2/ogro/skins/darkam.png


+ 0 - 0
examples/models/animated/ogro/skins/freedom.png → examples/models/md2/ogro/skins/freedom.png


이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.