From 6a43b6fe856d1da11a3d15f2a648af9459acef0f Mon Sep 17 00:00:00 2001 From: Kon Date: Mon, 4 Mar 2013 05:54:36 +0900 Subject: [PATCH 1/3] Added more tests to three-tests.ts --- threejs/three-tests.ts | 13837 ++++++++++++++++++++++++++++++--------- threejs/three.d.ts | 39 +- 2 files changed, 10813 insertions(+), 3063 deletions(-) diff --git a/threejs/three-tests.ts b/threejs/three-tests.ts index c086e3aaf2..2d59266c3b 100644 --- a/threejs/three-tests.ts +++ b/threejs/three-tests.ts @@ -2,3076 +2,10805 @@ /// // https://github.com/mrdoob/three.js/tree/master/test/unit/math - -var x = 2; -var y = 3; -var z = 4; -var w = 5; - -var negInf2 = new THREE.Vector2( -Infinity, -Infinity ); -var posInf2 = new THREE.Vector2( Infinity, Infinity ); - -var zero2 = new THREE.Vector2(); -var one2 = new THREE.Vector2( 1, 1 ); -var two2 = new THREE.Vector2( 2, 2 ); - -var negInf3 = new THREE.Vector3( -Infinity, -Infinity, -Infinity ); -var posInf3 = new THREE.Vector3( Infinity, Infinity, Infinity ); - -var zero3 = new THREE.Vector3(); -var one3 = new THREE.Vector3( 1, 1, 1 ); -var two3 = new THREE.Vector3( 2, 2, 2 ); - -(QUnit.module)( "Box2" ); - -test( "constructor", function() { - var a = new THREE.Box2(); - ok( a.min.equals( posInf2 ), "Passed!" ); - ok( a.max.equals( negInf2 ), "Passed!" ); - - a = new THREE.Box2( zero2.clone(), zero2.clone() ); - ok( a.min.equals( zero2 ), "Passed!" ); - ok( a.max.equals( zero2 ), "Passed!" ); - - a = new THREE.Box2( zero2.clone(), one2.clone() ); - ok( a.min.equals( zero2 ), "Passed!" ); - ok( a.max.equals( one2 ), "Passed!" ); -}); - -test( "copy", function() { - var a = new THREE.Box2( zero2.clone(), one2.clone() ); - var b = new THREE.Box2().copy( a ); - ok( b.min.equals( zero2 ), "Passed!" ); - ok( b.max.equals( one2 ), "Passed!" ); - - // ensure that it is a true copy - a.min = zero2; - a.max = one2; - ok( b.min.equals( zero2 ), "Passed!" ); - ok( b.max.equals( one2 ), "Passed!" ); -}); - -test( "set", function() { - var a = new THREE.Box2(); - - a.set( zero2, one2 ); - ok( a.min.equals( zero2 ), "Passed!" ); - ok( a.max.equals( one2 ), "Passed!" ); -}); - -test( "empty/makeEmpty", function() { - var a = new THREE.Box2(); - - ok( a.empty(), "Passed!" ); - - var a = new THREE.Box2( zero2.clone(), one2.clone() ); - ok( ! a.empty(), "Passed!" ); - - a.makeEmpty(); - ok( a.empty(), "Passed!" ); -}); - -test( "center", function() { - var a = new THREE.Box2( zero2.clone(), zero2.clone() ); - - ok( a.center().equals( zero2 ), "Passed!" ); - - a = new THREE.Box2( zero2, one2 ); - var midpoint = one2.clone().multiplyScalar( 0.5 ); - ok( a.center().equals( midpoint ), "Passed!" ); -}); - -test( "size", function() { - var a = new THREE.Box2( zero2.clone(), zero2.clone() ); - - ok( a.size().equals( zero2 ), "Passed!" ); - - a = new THREE.Box2( zero2.clone(), one2.clone() ); - ok( a.size().equals( one2 ), "Passed!" ); -}); - -test( "expandByPoint", function() { - var a = new THREE.Box2( zero2.clone(), zero2.clone() ); - - a.expandByPoint( zero2 ); - ok( a.size().equals( zero2 ), "Passed!" ); - - a.expandByPoint( one2 ); - ok( a.size().equals( one2 ), "Passed!" ); - - a.expandByPoint( one2.clone().negate() ); - ok( a.size().equals( one2.clone().multiplyScalar( 2 ) ), "Passed!" ); - ok( a.center().equals( zero2 ), "Passed!" ); -}); - -test( "expandByVector", function() { - var a = new THREE.Box2( zero2.clone(), zero2.clone() ); - - a.expandByVector( zero2 ); - ok( a.size().equals( zero2 ), "Passed!" ); - - a.expandByVector( one2 ); - ok( a.size().equals( one2.clone().multiplyScalar( 2 ) ), "Passed!" ); - ok( a.center().equals( zero2 ), "Passed!" ); -}); - -test( "expandByScalar", function() { - var a = new THREE.Box2( zero2.clone(), zero2.clone() ); - - a.expandByScalar( 0 ); - ok( a.size().equals( zero2 ), "Passed!" ); - - a.expandByScalar( 1 ); - ok( a.size().equals( one2.clone().multiplyScalar( 2 ) ), "Passed!" ); - ok( a.center().equals( zero2 ), "Passed!" ); -}); - -test( "containsPoint", function() { - var a = new THREE.Box2( zero2.clone(), zero2.clone() ); - - ok( a.containsPoint( zero2 ), "Passed!" ); - ok( ! a.containsPoint( one2 ), "Passed!" ); - - a.expandByScalar( 1 ); - ok( a.containsPoint( zero2 ), "Passed!" ); - ok( a.containsPoint( one2 ), "Passed!" ); - ok( a.containsPoint( one2.clone().negate() ), "Passed!" ); -}); - -test( "containsBox", function() { - var a = new THREE.Box2( zero2.clone(), zero2.clone() ); - var b = new THREE.Box2( zero2.clone(), one2.clone() ); - var c = new THREE.Box2( one2.clone().negate(), one2.clone() ); - - ok( a.containsBox( a ), "Passed!" ); - ok( ! a.containsBox( b ), "Passed!" ); - ok( ! a.containsBox( c ), "Passed!" ); - - ok( b.containsBox( a ), "Passed!" ); - ok( c.containsBox( a ), "Passed!" ); - ok( ! b.containsBox( c ), "Passed!" ); -}); - -test( "getParameter", function() { - var a = new THREE.Box2( zero2.clone(), one2.clone() ); - var b = new THREE.Box2( one2.clone().negate(), one2.clone() ); - - ok( a.getParameter( new THREE.Vector2( 0, 0 ) ).equals( new THREE.Vector2( 0, 0 ) ), "Passed!" ); - ok( a.getParameter( new THREE.Vector2( 1, 1 ) ).equals( new THREE.Vector2( 1, 1 ) ), "Passed!" ); - - ok( b.getParameter( new THREE.Vector2( -1, -1 ) ).equals( new THREE.Vector2( 0, 0 ) ), "Passed!" ); - ok( b.getParameter( new THREE.Vector2( 0, 0 ) ).equals( new THREE.Vector2( 0.5, 0.5 ) ), "Passed!" ); - ok( b.getParameter( new THREE.Vector2( 1, 1 ) ).equals( new THREE.Vector2( 1, 1 ) ), "Passed!" ); -}); - -test( "clampPoint", function() { - var a = new THREE.Box2( zero2.clone(), zero2.clone() ); - var b = new THREE.Box2( one2.clone().negate(), one2.clone() ); - - ok( a.clampPoint( new THREE.Vector2( 0, 0 ) ).equals( new THREE.Vector2( 0, 0 ) ), "Passed!" ); - ok( a.clampPoint( new THREE.Vector2( 1, 1 ) ).equals( new THREE.Vector2( 0, 0 ) ), "Passed!" ); - ok( a.clampPoint( new THREE.Vector2( -1, -1 ) ).equals( new THREE.Vector2( 0, 0 ) ), "Passed!" ); - - ok( b.clampPoint( new THREE.Vector2( 2, 2 ) ).equals( new THREE.Vector2( 1, 1 ) ), "Passed!" ); - ok( b.clampPoint( new THREE.Vector2( 1, 1 ) ).equals( new THREE.Vector2( 1, 1 ) ), "Passed!" ); - ok( b.clampPoint( new THREE.Vector2( 0, 0 ) ).equals( new THREE.Vector2( 0, 0 ) ), "Passed!" ); - ok( b.clampPoint( new THREE.Vector2( -1, -1 ) ).equals( new THREE.Vector2( -1, -1 ) ), "Passed!" ); - ok( b.clampPoint( new THREE.Vector2( -2, -2 ) ).equals( new THREE.Vector2( -1, -1 ) ), "Passed!" ); -}); - -test( "distanceToPoint", function() { - var a = new THREE.Box2( zero2.clone(), zero2.clone() ); - var b = new THREE.Box2( one2.clone().negate(), one2.clone() ); - - ok( a.distanceToPoint( new THREE.Vector2( 0, 0 ) ) == 0, "Passed!" ); - ok( a.distanceToPoint( new THREE.Vector2( 1, 1 ) ) == Math.sqrt( 2 ), "Passed!" ); - ok( a.distanceToPoint( new THREE.Vector2( -1, -1 ) ) == Math.sqrt( 2 ), "Passed!" ); - - ok( b.distanceToPoint( new THREE.Vector2( 2, 2 ) ) == Math.sqrt( 2 ), "Passed!" ); - ok( b.distanceToPoint( new THREE.Vector2( 1, 1 ) ) == 0, "Passed!" ); - ok( b.distanceToPoint( new THREE.Vector2( 0, 0 ) ) == 0, "Passed!" ); - ok( b.distanceToPoint( new THREE.Vector2( -1, -1 ) ) == 0, "Passed!" ); - ok( b.distanceToPoint( new THREE.Vector2( -2, -2 ) ) == Math.sqrt( 2 ), "Passed!" ); -}); - -test( "distanceToPoint", function() { - var a = new THREE.Box2( zero2.clone(), zero2.clone() ); - var b = new THREE.Box2( one2.clone().negate(), one2.clone() ); - - ok( a.distanceToPoint( new THREE.Vector2( 0, 0 ) ) == 0, "Passed!" ); - ok( a.distanceToPoint( new THREE.Vector2( 1, 1 ) ) == Math.sqrt( 2 ), "Passed!" ); - ok( a.distanceToPoint( new THREE.Vector2( -1, -1 ) ) == Math.sqrt( 2 ), "Passed!" ); - - ok( b.distanceToPoint( new THREE.Vector2( 2, 2 ) ) == Math.sqrt( 2 ), "Passed!" ); - ok( b.distanceToPoint( new THREE.Vector2( 1, 1 ) ) == 0, "Passed!" ); - ok( b.distanceToPoint( new THREE.Vector2( 0, 0 ) ) == 0, "Passed!" ); - ok( b.distanceToPoint( new THREE.Vector2( -1, -1 ) ) == 0, "Passed!" ); - ok( b.distanceToPoint( new THREE.Vector2( -2, -2 ) ) == Math.sqrt( 2 ), "Passed!" ); -}); - -test( "isIntersectionBox", function() { - var a = new THREE.Box2( zero2.clone(), zero2.clone() ); - var b = new THREE.Box2( zero2.clone(), one2.clone() ); - var c = new THREE.Box2( one2.clone().negate(), one2.clone() ); - - ok( a.isIntersectionBox( a ), "Passed!" ); - ok( a.isIntersectionBox( b ), "Passed!" ); - ok( a.isIntersectionBox( c ), "Passed!" ); - - ok( b.isIntersectionBox( a ), "Passed!" ); - ok( c.isIntersectionBox( a ), "Passed!" ); - ok( b.isIntersectionBox( c ), "Passed!" ); - - b.translate( new THREE.Vector2( 2, 2 ) ); - ok( ! a.isIntersectionBox( b ), "Passed!" ); - ok( ! b.isIntersectionBox( a ), "Passed!" ); - ok( ! b.isIntersectionBox( c ), "Passed!" ); -}); - -test( "intersect", function() { - var a = new THREE.Box2( zero2.clone(), zero2.clone() ); - var b = new THREE.Box2( zero2.clone(), one2.clone() ); - var c = new THREE.Box2( one2.clone().negate(), one2.clone() ); - - ok( a.clone().intersect( a ).equals( a ), "Passed!" ); - ok( a.clone().intersect( b ).equals( a ), "Passed!" ); - ok( b.clone().intersect( b ).equals( b ), "Passed!" ); - ok( a.clone().intersect( c ).equals( a ), "Passed!" ); - ok( b.clone().intersect( c ).equals( b ), "Passed!" ); - ok( c.clone().intersect( c ).equals( c ), "Passed!" ); -}); - -test( "union", function() { - var a = new THREE.Box2( zero2.clone(), zero2.clone() ); - var b = new THREE.Box2( zero2.clone(), one2.clone() ); - var c = new THREE.Box2( one2.clone().negate(), one2.clone() ); - - ok( a.clone().union( a ).equals( a ), "Passed!" ); - ok( a.clone().union( b ).equals( b ), "Passed!" ); - ok( a.clone().union( c ).equals( c ), "Passed!" ); - ok( b.clone().union( c ).equals( c ), "Passed!" ); -}); - -test( "translate", function() { - var a = new THREE.Box2( zero2.clone(), zero2.clone() ); - var b = new THREE.Box2( zero2.clone(), one2.clone() ); - var c = new THREE.Box2( one2.clone().negate(), one2.clone() ); - var d = new THREE.Box2( one2.clone().negate(), zero2.clone() ); - - ok( a.clone().translate( one2 ).equals( new THREE.Box2( one2, one2 ) ), "Passed!" ); - ok( a.clone().translate( one2 ).translate( one2.clone().negate() ).equals( a ), "Passed!" ); - ok( d.clone().translate( one2 ).equals( b ), "Passed!" ); - ok( b.clone().translate( one2.clone().negate() ).equals( d ), "Passed!" ); -}); - -test( "constructor", function() { - var a = new THREE.Box3(); - ok( a.min.equals( posInf3 ), "Passed!" ); - ok( a.max.equals( negInf3 ), "Passed!" ); - - a = new THREE.Box3( zero3.clone(), zero3.clone() ); - ok( a.min.equals( zero3 ), "Passed!" ); - ok( a.max.equals( zero3 ), "Passed!" ); - - a = new THREE.Box3( zero3.clone(), one3.clone() ); - ok( a.min.equals( zero3 ), "Passed!" ); - ok( a.max.equals( one3 ), "Passed!" ); -}); - -test( "copy", function() { - var a = new THREE.Box3( zero3.clone(), one3.clone() ); - var b = new THREE.Box3().copy( a ); - ok( b.min.equals( zero3 ), "Passed!" ); - ok( b.max.equals( one3 ), "Passed!" ); - - // ensure that it is a true copy - a.min = zero3; - a.max = one3; - ok( b.min.equals( zero3 ), "Passed!" ); - ok( b.max.equals( one3 ), "Passed!" ); -}); - -test( "set", function() { - var a = new THREE.Box3(); - - a.set( zero3, one3 ); - ok( a.min.equals( zero3 ), "Passed!" ); - ok( a.max.equals( one3 ), "Passed!" ); -}); - -test( "empty/makeEmpty", function() { - var a = new THREE.Box3(); - - ok( a.empty(), "Passed!" ); - - var a = new THREE.Box3( zero3.clone(), one3.clone() ); - ok( ! a.empty(), "Passed!" ); - - a.makeEmpty(); - ok( a.empty(), "Passed!" ); -}); - -test( "center", function() { - var a = new THREE.Box3( zero3.clone(), zero3.clone() ); - - ok( a.center().equals( zero3 ), "Passed!" ); - - a = new THREE.Box3( zero3.clone(), one3.clone() ); - var midpoint = one3.clone().multiplyScalar( 0.5 ); - ok( a.center().equals( midpoint ), "Passed!" ); -}); - -test( "size", function() { - var a = new THREE.Box3( zero3.clone(), zero3.clone() ); - - ok( a.size().equals( zero3 ), "Passed!" ); - - a = new THREE.Box3( zero3.clone(), one3.clone() ); - ok( a.size().equals( one3 ), "Passed!" ); -}); - -test( "expandByPoint", function() { - var a = new THREE.Box3( zero3.clone(), zero3.clone() ); - - a.expandByPoint( zero3 ); - ok( a.size().equals( zero3 ), "Passed!" ); - - a.expandByPoint( one3 ); - ok( a.size().equals( one3 ), "Passed!" ); - - a.expandByPoint( one3.clone().negate() ); - ok( a.size().equals( one3.clone().multiplyScalar( 2 ) ), "Passed!" ); - ok( a.center().equals( zero3 ), "Passed!" ); -}); - -test( "expandByVector", function() { - var a = new THREE.Box3( zero3.clone(), zero3.clone() ); - - a.expandByVector( zero3 ); - ok( a.size().equals( zero3 ), "Passed!" ); - - a.expandByVector( one3 ); - ok( a.size().equals( one3.clone().multiplyScalar( 2 ) ), "Passed!" ); - ok( a.center().equals( zero3 ), "Passed!" ); -}); - -test( "expandByScalar", function() { - var a = new THREE.Box3( zero3.clone(), zero3.clone() ); - - a.expandByScalar( 0 ); - ok( a.size().equals( zero3 ), "Passed!" ); - - a.expandByScalar( 1 ); - ok( a.size().equals( one3.clone().multiplyScalar( 2 ) ), "Passed!" ); - ok( a.center().equals( zero3 ), "Passed!" ); -}); - -test( "containsPoint", function() { - var a = new THREE.Box3( zero3.clone(), zero3.clone() ); - - ok( a.containsPoint( zero3 ), "Passed!" ); - ok( ! a.containsPoint( one3 ), "Passed!" ); - - a.expandByScalar( 1 ); - ok( a.containsPoint( zero3 ), "Passed!" ); - ok( a.containsPoint( one3 ), "Passed!" ); - ok( a.containsPoint( one3.clone().negate() ), "Passed!" ); -}); - -test( "containsBox", function() { - var a = new THREE.Box3( zero3.clone(), zero3.clone() ); - var b = new THREE.Box3( zero3.clone(), one3.clone() ); - var c = new THREE.Box3( one3.clone().negate(), one3.clone() ); - - ok( a.containsBox( a ), "Passed!" ); - ok( ! a.containsBox( b ), "Passed!" ); - ok( ! a.containsBox( c ), "Passed!" ); - - ok( b.containsBox( a ), "Passed!" ); - ok( c.containsBox( a ), "Passed!" ); - ok( ! b.containsBox( c ), "Passed!" ); -}); - -test( "getParameter", function() { - var a = new THREE.Box3( zero3.clone(), one3.clone() ); - var b = new THREE.Box3( one3.clone().negate(), one3.clone() ); - - ok( a.getParameter( new THREE.Vector3( 0, 0, 0 ) ).equals( new THREE.Vector3( 0, 0, 0 ) ), "Passed!" ); - ok( a.getParameter( new THREE.Vector3( 1, 1, 1 ) ).equals( new THREE.Vector3( 1, 1, 1 ) ), "Passed!" ); - - ok( b.getParameter( new THREE.Vector3( -1, -1, -1 ) ).equals( new THREE.Vector3( 0, 0, 0 ) ), "Passed!" ); - ok( b.getParameter( new THREE.Vector3( 0, 0, 0 ) ).equals( new THREE.Vector3( 0.5, 0.5, 0.5 ) ), "Passed!" ); - ok( b.getParameter( new THREE.Vector3( 1, 1, 1 ) ).equals( new THREE.Vector3( 1, 1, 1 ) ), "Passed!" ); -}); - -test( "clampPoint", function() { - var a = new THREE.Box3( zero3.clone(), zero3.clone() ); - var b = new THREE.Box3( one3.clone().negate(), one3.clone() ); - - ok( a.clampPoint( new THREE.Vector3( 0, 0, 0 ) ).equals( new THREE.Vector3( 0, 0, 0 ) ), "Passed!" ); - ok( a.clampPoint( new THREE.Vector3( 1, 1, 1 ) ).equals( new THREE.Vector3( 0, 0, 0 ) ), "Passed!" ); - ok( a.clampPoint( new THREE.Vector3( -1, -1, -1 ) ).equals( new THREE.Vector3( 0, 0, 0 ) ), "Passed!" ); - - ok( b.clampPoint( new THREE.Vector3( 2, 2, 2 ) ).equals( new THREE.Vector3( 1, 1, 1 ) ), "Passed!" ); - ok( b.clampPoint( new THREE.Vector3( 1, 1, 1 ) ).equals( new THREE.Vector3( 1, 1, 1 ) ), "Passed!" ); - ok( b.clampPoint( new THREE.Vector3( 0, 0, 0 ) ).equals( new THREE.Vector3( 0, 0, 0 ) ), "Passed!" ); - ok( b.clampPoint( new THREE.Vector3( -1, -1, -1 ) ).equals( new THREE.Vector3( -1, -1, -1 ) ), "Passed!" ); - ok( b.clampPoint( new THREE.Vector3( -2, -2, -2 ) ).equals( new THREE.Vector3( -1, -1, -1 ) ), "Passed!" ); -}); - -test( "distanceToPoint", function() { - var a = new THREE.Box3( zero3.clone(), zero3.clone() ); - var b = new THREE.Box3( one3.clone().negate(), one3.clone() ); - - ok( a.distanceToPoint( new THREE.Vector3( 0, 0, 0 ) ) == 0, "Passed!" ); - ok( a.distanceToPoint( new THREE.Vector3( 1, 1, 1 ) ) == Math.sqrt( 3 ), "Passed!" ); - ok( a.distanceToPoint( new THREE.Vector3( -1, -1, -1 ) ) == Math.sqrt( 3 ), "Passed!" ); - - ok( b.distanceToPoint( new THREE.Vector3( 2, 2, 2 ) ) == Math.sqrt( 3 ), "Passed!" ); - ok( b.distanceToPoint( new THREE.Vector3( 1, 1, 1 ) ) == 0, "Passed!" ); - ok( b.distanceToPoint( new THREE.Vector3( 0, 0, 0 ) ) == 0, "Passed!" ); - ok( b.distanceToPoint( new THREE.Vector3( -1, -1, -1 ) ) == 0, "Passed!" ); - ok( b.distanceToPoint( new THREE.Vector3( -2, -2, -2 ) ) == Math.sqrt( 3 ), "Passed!" ); -}); - -test( "distanceToPoint", function() { - var a = new THREE.Box3( zero3.clone(), zero3.clone() ); - var b = new THREE.Box3( one3.clone().negate(), one3.clone() ); - - ok( a.distanceToPoint( new THREE.Vector3( 0, 0, 0 ) ) == 0, "Passed!" ); - ok( a.distanceToPoint( new THREE.Vector3( 1, 1, 1 ) ) == Math.sqrt( 3 ), "Passed!" ); - ok( a.distanceToPoint( new THREE.Vector3( -1, -1, -1 ) ) == Math.sqrt( 3 ), "Passed!" ); - - ok( b.distanceToPoint( new THREE.Vector3( 2, 2, 2 ) ) == Math.sqrt( 3 ), "Passed!" ); - ok( b.distanceToPoint( new THREE.Vector3( 1, 1, 1 ) ) == 0, "Passed!" ); - ok( b.distanceToPoint( new THREE.Vector3( 0, 0, 0 ) ) == 0, "Passed!" ); - ok( b.distanceToPoint( new THREE.Vector3( -1, -1, -1 ) ) == 0, "Passed!" ); - ok( b.distanceToPoint( new THREE.Vector3( -2, -2, -2 ) ) == Math.sqrt( 3 ), "Passed!" ); -}); - -test( "isIntersectionBox", function() { - var a = new THREE.Box3( zero3.clone(), zero3.clone() ); - var b = new THREE.Box3( zero3.clone(), one3.clone() ); - var c = new THREE.Box3( one3.clone().negate(), one3.clone() ); - - ok( a.isIntersectionBox( a ), "Passed!" ); - ok( a.isIntersectionBox( b ), "Passed!" ); - ok( a.isIntersectionBox( c ), "Passed!" ); - - ok( b.isIntersectionBox( a ), "Passed!" ); - ok( c.isIntersectionBox( a ), "Passed!" ); - ok( b.isIntersectionBox( c ), "Passed!" ); - - b.translate( new THREE.Vector3( 2, 2, 2 ) ); - ok( ! a.isIntersectionBox( b ), "Passed!" ); - ok( ! b.isIntersectionBox( a ), "Passed!" ); - ok( ! b.isIntersectionBox( c ), "Passed!" ); -}); - -test( "getBoundingSphere", function() { - var a = new THREE.Box3( zero3.clone(), zero3.clone() ); - var b = new THREE.Box3( zero3.clone(), one3.clone() ); - var c = new THREE.Box3( one3.clone().negate(), one3.clone() ); - - ok( a.getBoundingSphere().equals( new THREE.Sphere( zero3, 0 ) ), "Passed!" ); - ok( b.getBoundingSphere().equals( new THREE.Sphere( one3.clone().multiplyScalar( 0.5 ), Math.sqrt( 3 ) * 0.5 ) ), "Passed!" ); - ok( c.getBoundingSphere().equals( new THREE.Sphere( zero3, Math.sqrt( 12 ) * 0.5 ) ), "Passed!" ); -}); - -test( "intersect", function() { - var a = new THREE.Box3( zero3.clone(), zero3.clone() ); - var b = new THREE.Box3( zero3.clone(), one3.clone() ); - var c = new THREE.Box3( one3.clone().negate(), one3.clone() ); - - ok( a.clone().intersect( a ).equals( a ), "Passed!" ); - ok( a.clone().intersect( b ).equals( a ), "Passed!" ); - ok( b.clone().intersect( b ).equals( b ), "Passed!" ); - ok( a.clone().intersect( c ).equals( a ), "Passed!" ); - ok( b.clone().intersect( c ).equals( b ), "Passed!" ); - ok( c.clone().intersect( c ).equals( c ), "Passed!" ); -}); - -test( "union", function() { - var a = new THREE.Box3( zero3.clone(), zero3.clone() ); - var b = new THREE.Box3( zero3.clone(), one3.clone() ); - var c = new THREE.Box3( one3.clone().negate(), one3.clone() ); - - ok( a.clone().union( a ).equals( a ), "Passed!" ); - ok( a.clone().union( b ).equals( b ), "Passed!" ); - ok( a.clone().union( c ).equals( c ), "Passed!" ); - ok( b.clone().union( c ).equals( c ), "Passed!" ); -}); - -var compareBox = function ( a, b, threshold? ) { - threshold = threshold || 0.0001; - return ( a.min.distanceTo( b.min ) < threshold && - a.max.distanceTo( b.max ) < threshold ); -}; - -test( "applyMatrix4", function() { - var a = new THREE.Box3( zero3.clone(), zero3.clone() ); - var b = new THREE.Box3( zero3.clone(), one3.clone() ); - var c = new THREE.Box3( one3.clone().negate(), one3.clone() ); - var d = new THREE.Box3( one3.clone().negate(), zero3.clone() ); - - var m = new THREE.Matrix4().makeTranslation( 1, -2, 1 ); - var t1 = new THREE.Vector3( 1, -2, 1 ); - - ok( compareBox( a.clone().applyMatrix4( m ), a.clone().translate( t1 ) ), "Passed!" ); - ok( compareBox( b.clone().applyMatrix4( m ), b.clone().translate( t1 ) ), "Passed!" ); - ok( compareBox( c.clone().applyMatrix4( m ), c.clone().translate( t1 ) ), "Passed!" ); - ok( compareBox( d.clone().applyMatrix4( m ), d.clone().translate( t1 ) ), "Passed!" ); -}); - -test( "translate", function() { - var a = new THREE.Box3( zero3.clone(), zero3.clone() ); - var b = new THREE.Box3( zero3.clone(), one3.clone() ); - var c = new THREE.Box3( one3.clone().negate(), one3.clone() ); - var d = new THREE.Box3( one3.clone().negate(), zero3.clone() ); - - ok( a.clone().translate( one3 ).equals( new THREE.Box3( one3, one3 ) ), "Passed!" ); - ok( a.clone().translate( one3 ).translate( one3.clone().negate() ).equals( a ), "Passed!" ); - ok( d.clone().translate( one3 ).equals( b ), "Passed!" ); - ok( b.clone().translate( one3.clone().negate() ).equals( d ), "Passed!" ); -}); - -test( "constructor", function(){ - var c = new THREE.Color(); - ok( c.r, "Red: " + c.r ); - ok( c.g, "Green: " + c.g ); - ok( c.b, "Blue: " + c.g ); -}); - -test( "copyHex", function(){ - var c = new THREE.Color(); - var c2 = new THREE.Color(0xF5FFFA); - c.copy(c2); - ok(c.getHex() == c2.getHex(), "Hex c: " + c.getHex() + " Hex c2: " + c2.getHex()); -}); - -test( "copyColorString", function(){ - var c = new THREE.Color(); - var c2 = new THREE.Color('ivory'); - c.copy(c2); - ok(c.getHex() == c2.getHex(), "Hex c: " + c.getHex() + " Hex c2: " + c2.getHex()); -}); - -test( "setRGB", function(){ - var c = new THREE.Color() - c.setRGB(255, 2, 1); - ok( c.r == 255, "Red: " + c.r ); - ok( c.g == 2, "Green: " + c.g ); - ok( c.b == 1, "Blue: " + c.b ); -}); - -test( "copyGammaToLinear", function(){ - var c = new THREE.Color(); - var c2 = new THREE.Color(); - c2.setRGB(2, 4, 8) - c.copyGammaToLinear(c2) - ok( c.r == 4, "Red c: " + c.r + " Red c2: " + c2.r); - ok( c.g == 16, "Green c: " + c.g + " Green c2: " + c2.g); - ok( c.b == 64, "Blue c: " + c.b + " Blue c2: " + c2.b); -}); - -test( "copyLinearToGamma", function(){ - var c = new THREE.Color(); - var c2 = new THREE.Color(); - c2.setRGB(4, 9, 16) - c.copyLinearToGamma(c2) - ok( c.r == 2, "Red c: " + c.r + " Red c2: " + c2.r); - ok( c.g == 3, "Green c: " + c.g + " Green c2: " + c2.g); - ok( c.b == 4, "Blue c: " + c.b + " Blue c2: " + c2.b); -}); - - -test( "convertGammaToLinear", function(){ - var c = new THREE.Color(); - c.setRGB(2, 4, 8) - c.convertGammaToLinear() - ok( c.r == 4, "Red: " + c.r ); - ok( c.g == 16, "Green: " + c.g ); - ok( c.b == 64, "Blue: " + c.b ); -}); - - -test( "convertLinearToGamma", function(){ - var c = new THREE.Color(); - c.setRGB(4, 9, 16) - c.convertLinearToGamma() - ok( c.r == 2, "Red: " + c.r ); - ok( c.g == 3, "Green: " + c.g ); - ok( c.b == 4, "Blue: " + c.b ); -}); - -test("setWithNum", function(){ - var c = new THREE.Color(); - c.set(0xFF0000); - ok( c.r == 1, "Red: " + c.r ); - ok( c.g == 0, "Green: " + c.g ); - ok( c.b == 0, "Blue: " + c.b ); -}); - - -test( "setWithString", function(){ - var c = new THREE.Color(); - c.set('silver'); - ok(c.getHex() == 0xC0C0C0, "Hex c: " + c.getHex()); -}); - - -test( "clone", function(){ - var c = new THREE.Color('teal'); - var c2 = c.clone(); - ok(c2.getHex() == 0x008080, "Hex c2: " + c2.getHex()); -}); - -test( "lerp", function(){ - var c = new THREE.Color(); - var c2 = new THREE.Color(); - c.setRGB(0, 0, 0); - c.lerp(c2, 2); - ok( c.r == 2, "Red: " + c.r ); - ok( c.g == 2, "Green: " + c.g ); - ok( c.b == 2, "Blue: " + c.b ); - -}); - - -test( "setStyleRGBRed", function(){ - var c = new THREE.Color(); - c.setStyle('rgb(255,0,0)'); - ok( c.r == 1, "Red: " + c.r ); - ok( c.g == 0, "Green: " + c.g ); - ok( c.b == 0, "Blue: " + c.b ); -}); - -test( "setStyleRGBPercent", function(){ - var c = new THREE.Color(); - c.setStyle('rgb(100%,50%,10%)'); - ok( c.r == 1, "Red: " + c.r ); - ok( c.g == 0.5, "Green: " + c.g ); - ok( c.b == 0.1, "Blue: " + c.b ); -}); - -test( "setStyleHexSkyBlue", function(){ - var c = new THREE.Color(); - c.setStyle('#87CEEB'); - ok(c.getHex() == 0x87CEEB, "Hex c: " + c.getHex()); -}); - -test( "setStyleHex2Olive", function(){ - var c = new THREE.Color(); - c.setStyle('#F00'); - ok(c.getHex() == 0xFF0000, "Hex c: " + c.getHex()); -}); - -test( "setStyleColorName", function(){ - var c = new THREE.Color(); - c.setStyle('powderblue'); - ok(c.getHex() == 0xB0E0E6, "Hex c: " + c.getHex()); -}); - - -test( "getHex", function(){ - var c = new THREE.Color('red'); - var res = c.getHex(); - ok( res == 0xFF0000, "Hex: " + res ); -}); - -test( "setHex", function(){ - var c = new THREE.Color(); - c.setHex(0xFA8072); - ok( c.getHex() == 0xFA8072, "Hex: " + c.getHex()); -}); - -test( "getHexString", function(){ - var c = new THREE.Color('tomato'); - var res = c.getHexString(); - ok( res == 'ff6347', "Hex: " + res ); -}); - -test( "getStyle", function(){ - var c = new THREE.Color('plum'); - var res = c.getStyle(); - ok( res == 'rgb(221,160,221)', "style: " + res ); -}); - -test( "getHSL", function () { - var c = new THREE.Color( 0x80ffff ); - var hsl = c.getHSL(); - - ok( hsl.h == 0.5, "hue: " + hsl.h ); - ok( hsl.s == 1.0, "saturation: " + hsl.s ); - - - //ok( (Math.round(parseFloat(hsl.l)*100)/100) == 0.75, "lightness: " + hsl.l ); - ok( (Math.round(hsl.l*100)/100) == 0.75, "lightness: " + hsl.l ); -}); - -test( "setHSL", function () { - var c = new THREE.Color(); - c.setHSL(0.75, 1.0, 0.25); - var hsl = c.getHSL(); - - ok( hsl.h == 0.75, "hue: " + hsl.h ); - ok( hsl.s == 1.00, "saturation: " + hsl.s ); - ok( hsl.l == 0.25, "lightness: " + hsl.l ); -}); - -var unit3 = new THREE.Vector3( 1, 0, 0 ); - -var planeEquals = function ( a, b, tolerance ) { - tolerance = tolerance || 0.0001; - if( a.normal.distanceTo( b.normal ) > tolerance ) { - return false; - } - if( Math.abs( a.constant - b.constant ) > tolerance ) { - return false; - } - return true; -}; - -test( "constructor", function() { - var a = new THREE.Frustum(); - - ok( a.planes !== undefined, "Passed!" ); - ok( a.planes.length === 6, "Passed!" ); - - var pDefault = new THREE.Plane(); - for( var i = 0; i < 6; i ++ ) { - ok( a.planes[i].equals( pDefault ), "Passed!" ); - } - - var p0 = new THREE.Plane( unit3, -1 ); - var p1 = new THREE.Plane( unit3, 1 ); - var p2 = new THREE.Plane( unit3, 2 ); - var p3 = new THREE.Plane( unit3, 3 ); - var p4 = new THREE.Plane( unit3, 4 ); - var p5 = new THREE.Plane( unit3, 5 ); - - a = new THREE.Frustum( p0, p1, p2, p3, p4, p5 ); - ok( a.planes[0].equals( p0 ), "Passed!" ); - ok( a.planes[1].equals( p1 ), "Passed!" ); - ok( a.planes[2].equals( p2 ), "Passed!" ); - ok( a.planes[3].equals( p3 ), "Passed!" ); - ok( a.planes[4].equals( p4 ), "Passed!" ); - ok( a.planes[5].equals( p5 ), "Passed!" ); -}); - -test( "copy", function() { - - var p0 = new THREE.Plane( unit3, -1 ); - var p1 = new THREE.Plane( unit3, 1 ); - var p2 = new THREE.Plane( unit3, 2 ); - var p3 = new THREE.Plane( unit3, 3 ); - var p4 = new THREE.Plane( unit3, 4 ); - var p5 = new THREE.Plane( unit3, 5 ); - - var b = new THREE.Frustum( p0, p1, p2, p3, p4, p5 ); - var a = new THREE.Frustum().copy( b ); - ok( a.planes[0].equals( p0 ), "Passed!" ); - ok( a.planes[1].equals( p1 ), "Passed!" ); - ok( a.planes[2].equals( p2 ), "Passed!" ); - ok( a.planes[3].equals( p3 ), "Passed!" ); - ok( a.planes[4].equals( p4 ), "Passed!" ); - ok( a.planes[5].equals( p5 ), "Passed!" ); - - // ensure it is a true copy by modifying source - b.planes[0] = p1; - ok( a.planes[0].equals( p0 ), "Passed!" ); -}); - -test( "setFromMatrix/makeOrthographic/containsPoint", function() { - var m = new THREE.Matrix4().makeOrthographic( -1, 1, -1, 1, 1, 100 ) - var a = new THREE.Frustum().setFromMatrix( m ); - - ok( ! a.containsPoint( new THREE.Vector3( 0, 0, 0 ) ), "Passed!" ); - ok( a.containsPoint( new THREE.Vector3( 0, 0, -50 ) ), "Passed!" ); - ok( a.containsPoint( new THREE.Vector3( 0, 0, -1.001 ) ), "Passed!" ); - ok( a.containsPoint( new THREE.Vector3( -1, -1, -1.001 ) ), "Passed!" ); - ok( ! a.containsPoint( new THREE.Vector3( -1.1, -1.1, -1.001 ) ), "Passed!" ); - ok( a.containsPoint( new THREE.Vector3( 1, 1, -1.001 ) ), "Passed!" ); - ok( ! a.containsPoint( new THREE.Vector3( 1.1, 1.1, -1.001 ) ), "Passed!" ); - ok( a.containsPoint( new THREE.Vector3( 0, 0, -100 ) ), "Passed!" ); - ok( a.containsPoint( new THREE.Vector3( -1, -1, -100 ) ), "Passed!" ); - ok( ! a.containsPoint( new THREE.Vector3( -1.1, -1.1, -100.1 ) ), "Passed!" ); - ok( a.containsPoint( new THREE.Vector3( 1, 1, -100 ) ), "Passed!" ); - ok( ! a.containsPoint( new THREE.Vector3( 1.1, 1.1, -100.1 ) ), "Passed!" ); - ok( ! a.containsPoint( new THREE.Vector3( 0, 0, -101 ) ), "Passed!" ); - -}); - -test( "setFromMatrix/makeFrustum/containsPoint", function() { - var m = new THREE.Matrix4().makeFrustum( -1, 1, -1, 1, 1, 100 ) - var a = new THREE.Frustum().setFromMatrix( m ); - - ok( ! a.containsPoint( new THREE.Vector3( 0, 0, 0 ) ), "Passed!" ); - ok( a.containsPoint( new THREE.Vector3( 0, 0, -50 ) ), "Passed!" ); - ok( a.containsPoint( new THREE.Vector3( 0, 0, -1.001 ) ), "Passed!" ); - ok( a.containsPoint( new THREE.Vector3( -1, -1, -1.001 ) ), "Passed!" ); - ok( ! a.containsPoint( new THREE.Vector3( -1.1, -1.1, -1.001 ) ), "Passed!" ); - ok( a.containsPoint( new THREE.Vector3( 1, 1, -1.001 ) ), "Passed!" ); - ok( ! a.containsPoint( new THREE.Vector3( 1.1, 1.1, -1.001 ) ), "Passed!" ); - ok( a.containsPoint( new THREE.Vector3( 0, 0, -99.999 ) ), "Passed!" ); - ok( a.containsPoint( new THREE.Vector3( -99.999, -99.999, -99.999 ) ), "Passed!" ); - ok( ! a.containsPoint( new THREE.Vector3( -100.1, -100.1, -100.1 ) ), "Passed!" ); - ok( a.containsPoint( new THREE.Vector3( 99.999, 99.999, -99.999 ) ), "Passed!" ); - ok( ! a.containsPoint( new THREE.Vector3( 100.1, 100.1, -100.1 ) ), "Passed!" ); - ok( ! a.containsPoint( new THREE.Vector3( 0, 0, -101 ) ), "Passed!" ); -}); - -test( "setFromMatrix/makeFrustum/intersectsSphere", function() { - var m = new THREE.Matrix4().makeFrustum( -1, 1, -1, 1, 1, 100 ) - var a = new THREE.Frustum().setFromMatrix( m ); - - ok( ! a.intersectsSphere( new THREE.Sphere( new THREE.Vector3( 0, 0, 0 ), 0 ) ), "Passed!" ); - ok( ! a.intersectsSphere( new THREE.Sphere( new THREE.Vector3( 0, 0, 0 ), 0.9 ) ), "Passed!" ); - ok( a.intersectsSphere( new THREE.Sphere( new THREE.Vector3( 0, 0, 0 ), 1.1 ) ), "Passed!" ); - ok( a.intersectsSphere( new THREE.Sphere( new THREE.Vector3( 0, 0, -50 ), 0 ) ), "Passed!" ); - ok( a.intersectsSphere( new THREE.Sphere( new THREE.Vector3( 0, 0, -1.001 ), 0 ) ), "Passed!" ); - ok( a.intersectsSphere( new THREE.Sphere( new THREE.Vector3( -1, -1, -1.001 ), 0 ) ), "Passed!" ); - ok( ! a.intersectsSphere( new THREE.Sphere( new THREE.Vector3( -1.1, -1.1, -1.001 ), 0 ) ), "Passed!" ); - ok( a.intersectsSphere( new THREE.Sphere( new THREE.Vector3( -1.1, -1.1, -1.001 ), 0.5 ) ), "Passed!" ); - ok( a.intersectsSphere( new THREE.Sphere( new THREE.Vector3( 1, 1, -1.001 ), 0 ) ), "Passed!" ); - ok( ! a.intersectsSphere( new THREE.Sphere( new THREE.Vector3( 1.1, 1.1, -1.001 ), 0 ) ), "Passed!" ); - ok( a.intersectsSphere( new THREE.Sphere( new THREE.Vector3( 1.1, 1.1, -1.001 ), 0.5 ) ), "Passed!" ); - ok( a.intersectsSphere( new THREE.Sphere( new THREE.Vector3( 0, 0, -99.999 ), 0 ) ), "Passed!" ); - ok( a.intersectsSphere( new THREE.Sphere( new THREE.Vector3( -99.999, -99.999, -99.999 ), 0 ) ), "Passed!" ); - ok( ! a.intersectsSphere( new THREE.Sphere( new THREE.Vector3( -100.1, -100.1, -100.1 ), 0 ) ), "Passed!" ); - ok( a.intersectsSphere( new THREE.Sphere( new THREE.Vector3( -100.1, -100.1, -100.1 ), 0.5 ) ), "Passed!" ); - ok( a.intersectsSphere( new THREE.Sphere( new THREE.Vector3( 99.999, 99.999, -99.999 ), 0 ) ), "Passed!" ); - ok( ! a.intersectsSphere( new THREE.Sphere( new THREE.Vector3( 100.1, 100.1, -100.1 ), 0 ) ), "Passed!" ); - ok( a.intersectsSphere( new THREE.Sphere( new THREE.Vector3( 100.1, 100.1, -100.1 ), 0.2 ) ), "Passed!" ); - ok( ! a.intersectsSphere( new THREE.Sphere( new THREE.Vector3( 0, 0, -101 ), 0 ) ), "Passed!" ); - ok( a.intersectsSphere( new THREE.Sphere( new THREE.Vector3( 0, 0, -101 ), 1.1 ) ), "Passed!" ); -}); - -test( "clone", function() { - - var p0 = new THREE.Plane( unit3, -1 ); - var p1 = new THREE.Plane( unit3, 1 ); - var p2 = new THREE.Plane( unit3, 2 ); - var p3 = new THREE.Plane( unit3, 3 ); - var p4 = new THREE.Plane( unit3, 4 ); - var p5 = new THREE.Plane( unit3, 5 ); - - var b = new THREE.Frustum( p0, p1, p2, p3, p4, p5 ); - var a = b.clone(); - ok( a.planes[0].equals( p0 ), "Passed!" ); - ok( a.planes[1].equals( p1 ), "Passed!" ); - ok( a.planes[2].equals( p2 ), "Passed!" ); - ok( a.planes[3].equals( p3 ), "Passed!" ); - ok( a.planes[4].equals( p4 ), "Passed!" ); - ok( a.planes[5].equals( p5 ), "Passed!" ); - - // ensure it is a true copy by modifying source - a.planes[0].copy( p1 ); - ok( b.planes[0].equals( p0 ), "Passed!" ); -}); - - -test( "constructor/equals", function() { - var a = new THREE.Line3(); - ok( a.start.equals( zero3 ), "Passed!" ); - ok( a.end.equals( zero3 ), "Passed!" ); - - a = new THREE.Line3( two3.clone(), one3.clone() ); - ok( a.start.equals( two3 ), "Passed!" ); - ok( a.end.equals( one3 ), "Passed!" ); -}); - -test( "copy/equals", function() { - var a = new THREE.Line3( zero3.clone(), one3.clone() ); - var b = new THREE.Line3().copy( a ); - ok( b.start.equals( zero3 ), "Passed!" ); - ok( b.end.equals( one3 ), "Passed!" ); - - // ensure that it is a true copy - a.start = zero3; - a.end = one3; - ok( b.start.equals( zero3 ), "Passed!" ); - ok( b.end.equals( one3 ), "Passed!" ); -}); - -test( "set", function() { - var a = new THREE.Line3(); - - a.set( one3, one3 ); - ok( a.start.equals( one3 ), "Passed!" ); - ok( a.end.equals( one3 ), "Passed!" ); -}); - -test( "at", function() { - var a = new THREE.Line3( one3.clone(), new THREE.Vector3( 1, 1, 2 ) ); - - ok( a.at( -1 ).distanceTo( new THREE.Vector3( 1, 1, 0 ) ) < 0.0001, "Passed!" ); - ok( a.at( 0 ).distanceTo( one3.clone() ) < 0.0001, "Passed!" ); - ok( a.at( 1 ).distanceTo( new THREE.Vector3( 1, 1, 2 ) ) < 0.0001, "Passed!" ); - ok( a.at( 2 ).distanceTo( new THREE.Vector3( 1, 1, 3 ) ) < 0.0001, "Passed!" ); -}); - -test( "closestPointToPoint/closestPointToPointParameter", function() { - var a = new THREE.Line3( one3.clone(), new THREE.Vector3( 1, 1, 2 ) ); - - // nearby the ray - ok( a.closestPointToPointParameter( zero3.clone(), true ) == 0, "Passed!" ); - var b1 = a.closestPointToPoint( zero3.clone(), true ); - ok( b1.distanceTo( new THREE.Vector3( 1, 1, 1 ) ) < 0.0001, "Passed!" ); - - // nearby the ray - ok( a.closestPointToPointParameter( zero3.clone(), false ) == -1, "Passed!" ); - var b2 = a.closestPointToPoint( zero3.clone(), false ); - console.log( b2 ); - ok( b2.distanceTo( new THREE.Vector3( 1, 1, 0 ) ) < 0.0001, "Passed!" ); - - // nearby the ray - ok( a.closestPointToPointParameter( new THREE.Vector3( 1, 1, 5 ), true ) == 1, "Passed!" ); - var b = a.closestPointToPoint( new THREE.Vector3( 1, 1, 5 ), true ); - ok( b.distanceTo( new THREE.Vector3( 1, 1, 2 ) ) < 0.0001, "Passed!" ); - - // exactly on the ray - ok( a.closestPointToPointParameter( one3.clone(), true ) == 0, "Passed!" ); - var c = a.closestPointToPoint( one3.clone(), true ); - ok( c.distanceTo( one3.clone() ) < 0.0001, "Passed!" ); -}); - - - -var matrixEquals3 = function( a, b, tolerance? ) { - tolerance = tolerance || 0.0001; - if( a.elements.length != b.elements.length ) { - return false; - } - for( var i = 0, il = a.elements.length; i < il; i ++ ) { - var delta = a.elements[i] - b.elements[i]; - if( delta > tolerance ) { - return false; - } - } - return true; -}; - - -var toMatrix4 = function( m3 ) { - var result = new THREE.Matrix4(); - var re = result.elements; - var me = m3.elements; - re[0] = me[0]; - re[1] = me[1]; - re[2] = me[2]; - re[4] = me[3]; - re[5] = me[4]; - re[6] = me[5]; - re[8] = me[6]; - re[9] = me[7]; - re[10] = me[8]; - - return result; -}; - -test( "constructor", function() { - var a = new THREE.Matrix3(); - ok( a.determinant() == 1, "Passed!" ); - - var b = new THREE.Matrix3( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); - ok( b.elements[0] == 0 ); - ok( b.elements[1] == 3 ); - ok( b.elements[2] == 6 ); - ok( b.elements[3] == 1 ); - ok( b.elements[4] == 4 ); - ok( b.elements[5] == 7 ); - ok( b.elements[6] == 2 ); - ok( b.elements[7] == 5 ); - ok( b.elements[8] == 8 ); - - ok( ! matrixEquals3( a, b ), "Passed!" ); -}); - -test( "copy", function() { - var a = new THREE.Matrix3( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); - var b = new THREE.Matrix3().copy( a ); - - ok( matrixEquals3( a, b ), "Passed!" ); - - // ensure that it is a true copy - a.elements[0] = 2; - ok( ! matrixEquals3( a, b ), "Passed!" ); -}); - -test( "set", function() { - var b = new THREE.Matrix3(); - ok( b.determinant() == 1, "Passed!" ); - - b.set( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); - ok( b.elements[0] == 0 ); - ok( b.elements[1] == 3 ); - ok( b.elements[2] == 6 ); - ok( b.elements[3] == 1 ); - ok( b.elements[4] == 4 ); - ok( b.elements[5] == 7 ); - ok( b.elements[6] == 2 ); - ok( b.elements[7] == 5 ); - ok( b.elements[8] == 8 ); -}); - -test( "identity", function() { - var b = new THREE.Matrix3( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); - ok( b.elements[0] == 0 ); - ok( b.elements[1] == 3 ); - ok( b.elements[2] == 6 ); - ok( b.elements[3] == 1 ); - ok( b.elements[4] == 4 ); - ok( b.elements[5] == 7 ); - ok( b.elements[6] == 2 ); - ok( b.elements[7] == 5 ); - ok( b.elements[8] == 8 ); - - var a = new THREE.Matrix3(); - ok( ! matrixEquals3( a, b ), "Passed!" ); - - b.identity(); - ok( matrixEquals3( a, b ), "Passed!" ); -}); - -test( "multiplyScalar", function() { - var b = new THREE.Matrix3( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); - ok( b.elements[0] == 0 ); - ok( b.elements[1] == 3 ); - ok( b.elements[2] == 6 ); - ok( b.elements[3] == 1 ); - ok( b.elements[4] == 4 ); - ok( b.elements[5] == 7 ); - ok( b.elements[6] == 2 ); - ok( b.elements[7] == 5 ); - ok( b.elements[8] == 8 ); - - b.multiplyScalar( 2 ); - ok( b.elements[0] == 0*2 ); - ok( b.elements[1] == 3*2 ); - ok( b.elements[2] == 6*2 ); - ok( b.elements[3] == 1*2 ); - ok( b.elements[4] == 4*2 ); - ok( b.elements[5] == 7*2 ); - ok( b.elements[6] == 2*2 ); - ok( b.elements[7] == 5*2 ); - ok( b.elements[8] == 8*2 ); -}); - -test( "determinant", function() { - var a = new THREE.Matrix3(); - ok( a.determinant() == 1, "Passed!" ); - - a.elements[0] = 2; - ok( a.determinant() == 2, "Passed!" ); - - a.elements[0] = 0; - ok( a.determinant() == 0, "Passed!" ); - - // calculated via http://www.euclideanspace.com/maths/algebra/matrix/functions/determinant/threeD/index.htm - a.set( 2, 3, 4, 5, 13, 7, 8, 9, 11 ); - ok( a.determinant() == -73, "Passed!" ); -}); - - -test( "getInverse", function() { - var identity = new THREE.Matrix4(); - var a = new THREE.Matrix4(); - var b = new THREE.Matrix3( 0, 0, 0, 0, 0, 0, 0, 0, 0 ); - - //var c = new THREE.Matrix4( 0, 0, 0, 0, 0, 0, 0, 0, 0 ); - var c = new THREE.Matrix4( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ); - - ok( ! matrixEquals3( a, b ), "Passed!" ); - b.getInverse( a, false ); - ok( matrixEquals3( b, new THREE.Matrix3() ), "Passed!" ); - - try { - b.getInverse( c, true ); - ok( false, "Passed!" ); // should never get here. - } - catch( err ) { - ok( true, "Passed!" ); - } - - var testMatrices = [ - new THREE.Matrix4().makeRotationX( 0.3 ), - new THREE.Matrix4().makeRotationX( -0.3 ), - new THREE.Matrix4().makeRotationY( 0.3 ), - new THREE.Matrix4().makeRotationY( -0.3 ), - new THREE.Matrix4().makeRotationZ( 0.3 ), - new THREE.Matrix4().makeRotationZ( -0.3 ), - new THREE.Matrix4().makeScale( 1, 2, 3 ), - new THREE.Matrix4().makeScale( 1/8, 1/2, 1/3 ) - ]; - - for( var i = 0, il = testMatrices.length; i < il; i ++ ) { - var m = testMatrices[i]; - var mInverse3 = new THREE.Matrix3().getInverse( m ); - - var mInverse = toMatrix4( mInverse3 ); - - // the determinant of the inverse should be the reciprocal - ok( Math.abs( m.determinant() * mInverse3.determinant() - 1 ) < 0.0001, "Passed!" ); - ok( Math.abs( m.determinant() * mInverse.determinant() - 1 ) < 0.0001, "Passed!" ); - - var mProduct = new THREE.Matrix4().multiplyMatrices( m, mInverse ); - ok( Math.abs( mProduct.determinant() - 1 ) < 0.0001, "Passed!" ); - ok( matrixEquals3( mProduct, identity ), "Passed!" ); - } -}); - -test( "transpose", function() { - var a = new THREE.Matrix3(); - var b = a.clone().transpose(); - ok( matrixEquals3( a, b ), "Passed!" ); - - b = new THREE.Matrix3( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); - var c = b.clone().transpose(); - ok( ! matrixEquals3( b, c ), "Passed!" ); - c.transpose(); - ok( matrixEquals3( b, c ), "Passed!" ); -}); - -test( "clone", function() { - var a = new THREE.Matrix3( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); - var b = a.clone(); - - ok( matrixEquals3( a, b ), "Passed!" ); - - // ensure that it is a true copy - a.elements[0] = 2; - ok( ! matrixEquals3( a, b ), "Passed!" ); -}); - -var matrixEquals4 = function( a, b, tolerance? ) { - tolerance = tolerance || 0.0001; - if( a.elements.length != b.elements.length ) { - return false; - } - for( var i = 0, il = a.elements.length; i < il; i ++ ) { - var delta = a.elements[i] - b.elements[i]; - if( delta > tolerance ) { - return false; - } - } - return true; -}; - -test( "constructor", function() { - var a = new THREE.Matrix4(); - ok( a.determinant() == 1, "Passed!" ); - - var b = new THREE.Matrix4( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); - ok( b.elements[0] == 0 ); - ok( b.elements[1] == 4 ); - ok( b.elements[2] == 8 ); - ok( b.elements[3] == 12 ); - ok( b.elements[4] == 1 ); - ok( b.elements[5] == 5 ); - ok( b.elements[6] == 9 ); - ok( b.elements[7] == 13 ); - ok( b.elements[8] == 2 ); - ok( b.elements[9] == 6 ); - ok( b.elements[10] == 10 ); - ok( b.elements[11] == 14 ); - ok( b.elements[12] == 3 ); - ok( b.elements[13] == 7 ); - ok( b.elements[14] == 11 ); - ok( b.elements[15] == 15 ); - - ok( ! matrixEquals4( a, b ), "Passed!" ); -}); - -test( "copy", function() { - var a = new THREE.Matrix4( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); - var b = new THREE.Matrix4().copy( a ); - - ok( matrixEquals4( a, b ), "Passed!" ); - - // ensure that it is a true copy - a.elements[0] = 2; - ok( ! matrixEquals4( a, b ), "Passed!" ); -}); - -test( "set", function() { - var b = new THREE.Matrix4(); - ok( b.determinant() == 1, "Passed!" ); - - b.set( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); - ok( b.elements[0] == 0 ); - ok( b.elements[1] == 4 ); - ok( b.elements[2] == 8 ); - ok( b.elements[3] == 12 ); - ok( b.elements[4] == 1 ); - ok( b.elements[5] == 5 ); - ok( b.elements[6] == 9 ); - ok( b.elements[7] == 13 ); - ok( b.elements[8] == 2 ); - ok( b.elements[9] == 6 ); - ok( b.elements[10] == 10 ); - ok( b.elements[11] == 14 ); - ok( b.elements[12] == 3 ); - ok( b.elements[13] == 7 ); - ok( b.elements[14] == 11 ); - ok( b.elements[15] == 15 ); -}); - -test( "identity", function() { - var b = new THREE.Matrix4( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); - ok( b.elements[0] == 0 ); - ok( b.elements[1] == 4 ); - ok( b.elements[2] == 8 ); - ok( b.elements[3] == 12 ); - ok( b.elements[4] == 1 ); - ok( b.elements[5] == 5 ); - ok( b.elements[6] == 9 ); - ok( b.elements[7] == 13 ); - ok( b.elements[8] == 2 ); - ok( b.elements[9] == 6 ); - ok( b.elements[10] == 10 ); - ok( b.elements[11] == 14 ); - ok( b.elements[12] == 3 ); - ok( b.elements[13] == 7 ); - ok( b.elements[14] == 11 ); - ok( b.elements[15] == 15 ); - - var a = new THREE.Matrix4(); - ok( ! matrixEquals4( a, b ), "Passed!" ); - - b.identity(); - ok( matrixEquals4( a, b ), "Passed!" ); -}); - -test( "multiplyScalar", function() { - var b = new THREE.Matrix4( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); - ok( b.elements[0] == 0 ); - ok( b.elements[1] == 4 ); - ok( b.elements[2] == 8 ); - ok( b.elements[3] == 12 ); - ok( b.elements[4] == 1 ); - ok( b.elements[5] == 5 ); - ok( b.elements[6] == 9 ); - ok( b.elements[7] == 13 ); - ok( b.elements[8] == 2 ); - ok( b.elements[9] == 6 ); - ok( b.elements[10] == 10 ); - ok( b.elements[11] == 14 ); - ok( b.elements[12] == 3 ); - ok( b.elements[13] == 7 ); - ok( b.elements[14] == 11 ); - ok( b.elements[15] == 15 ); - - b.multiplyScalar( 2 ); - ok( b.elements[0] == 0*2 ); - ok( b.elements[1] == 4*2 ); - ok( b.elements[2] == 8*2 ); - ok( b.elements[3] == 12*2 ); - ok( b.elements[4] == 1*2 ); - ok( b.elements[5] == 5*2 ); - ok( b.elements[6] == 9*2 ); - ok( b.elements[7] == 13*2 ); - ok( b.elements[8] == 2*2 ); - ok( b.elements[9] == 6*2 ); - ok( b.elements[10] == 10*2 ); - ok( b.elements[11] == 14*2 ); - ok( b.elements[12] == 3*2 ); - ok( b.elements[13] == 7*2 ); - ok( b.elements[14] == 11*2 ); - ok( b.elements[15] == 15*2 ); -}); - -test( "determinant", function() { - var a = new THREE.Matrix4(); - ok( a.determinant() == 1, "Passed!" ); - - a.elements[0] = 2; - ok( a.determinant() == 2, "Passed!" ); - - a.elements[0] = 0; - ok( a.determinant() == 0, "Passed!" ); - - // calculated via http://www.euclideanspace.com/maths/algebra/matrix/functions/determinant/fourD/index.htm - a.set( 2, 3, 4, 5, -1, -21, -3, -4, 6, 7, 8, 10, -8, -9, -10, -12 ); - ok( a.determinant() == 76, "Passed!" ); -}); - -test( "getInverse", function() { - var identity = new THREE.Matrix4(); - - var a = new THREE.Matrix4(); - var b = new THREE.Matrix4( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ); - var c = new THREE.Matrix4( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ); - - ok( ! matrixEquals4( a, b ), "Passed!" ); - b.getInverse( a, false ); - ok( matrixEquals4( b, new THREE.Matrix4() ), "Passed!" ); - - try { - b.getInverse( c, true ); - ok( false, "Passed!" ); // should never get here. - } - catch( err ) { - ok( true, "Passed!" ); - } - - var testMatrices = [ - new THREE.Matrix4().makeRotationX( 0.3 ), - new THREE.Matrix4().makeRotationX( -0.3 ), - new THREE.Matrix4().makeRotationY( 0.3 ), - new THREE.Matrix4().makeRotationY( -0.3 ), - new THREE.Matrix4().makeRotationZ( 0.3 ), - new THREE.Matrix4().makeRotationZ( -0.3 ), - new THREE.Matrix4().makeScale( 1, 2, 3 ), - new THREE.Matrix4().makeScale( 1/8, 1/2, 1/3 ), - new THREE.Matrix4().makeFrustum( -1, 1, -1, 1, 1, 1000 ), - new THREE.Matrix4().makeFrustum( -16, 16, -9, 9, 0.1, 10000 ), - new THREE.Matrix4().makeTranslation( 1, 2, 3 ) - ]; - - for( var i = 0, il = testMatrices.length; i < il; i ++ ) { - var m = testMatrices[i]; - - var mInverse = new THREE.Matrix4().getInverse( m ); - - // the determinant of the inverse should be the reciprocal - ok( Math.abs( m.determinant() * mInverse.determinant() - 1 ) < 0.0001, "Passed!" ); - - var mProduct = new THREE.Matrix4().multiplyMatrices( m, mInverse ); - - // the determinant of the identity matrix is 1 - ok( Math.abs( mProduct.determinant() - 1 ) < 0.0001, "Passed!" ); - ok( matrixEquals4( mProduct, identity ), "Passed!" ); - } -}); - -test( "transpose", function() { - var a = new THREE.Matrix4(); - var b = a.clone().transpose(); - ok( matrixEquals4( a, b ), "Passed!" ); - - b = new THREE.Matrix4( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); - var c = b.clone().transpose(); - ok( ! matrixEquals4( b, c ), "Passed!" ); - c.transpose(); - ok( matrixEquals4( b, c ), "Passed!" ); -}); - -test( "clone", function() { - var a = new THREE.Matrix4( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); - var b = a.clone(); - - ok( matrixEquals4( a, b ), "Passed!" ); - - // ensure that it is a true copy - a.elements[0] = 2; - ok( ! matrixEquals4( a, b ), "Passed!" ); -}); - - -var comparePlane = function ( a, b, threshold? ) { - threshold = threshold || 0.0001; - return ( a.normal.distanceTo( b.normal ) < threshold && - Math.abs( a.constant - b.constant ) < threshold ); -}; - - -test( "constructor", function() { - var a = new THREE.Plane(); - ok( a.normal.x == 1, "Passed!" ); - ok( a.normal.y == 0, "Passed!" ); - ok( a.normal.z == 0, "Passed!" ); - ok( a.constant == 0, "Passed!" ); - - a = new THREE.Plane( one3.clone(), 0 ); - ok( a.normal.x == 1, "Passed!" ); - ok( a.normal.y == 1, "Passed!" ); - ok( a.normal.z == 1, "Passed!" ); - ok( a.constant == 0, "Passed!" ); - - a = new THREE.Plane( one3.clone(), 1 ); - ok( a.normal.x == 1, "Passed!" ); - ok( a.normal.y == 1, "Passed!" ); - ok( a.normal.z == 1, "Passed!" ); - ok( a.constant == 1, "Passed!" ); -}); - -test( "copy", function() { - var a = new THREE.Plane( new THREE.Vector3( x, y, z ), w ); - var b = new THREE.Plane().copy( a ); - ok( b.normal.x == x, "Passed!" ); - ok( b.normal.y == y, "Passed!" ); - ok( b.normal.z == z, "Passed!" ); - ok( b.constant == w, "Passed!" ); - - // ensure that it is a true copy - a.normal.x = 0; - a.normal.y = -1; - a.normal.z = -2; - a.constant = -3; - ok( b.normal.x == x, "Passed!" ); - ok( b.normal.y == y, "Passed!" ); - ok( b.normal.z == z, "Passed!" ); - ok( b.constant == w, "Passed!" ); -}); - -test( "set", function() { - var a = new THREE.Plane(); - ok( a.normal.x == 1, "Passed!" ); - ok( a.normal.y == 0, "Passed!" ); - ok( a.normal.z == 0, "Passed!" ); - ok( a.constant == 0, "Passed!" ); - - var b = a.clone().set( new THREE.Vector3( x, y, z ), w ); - ok( b.normal.x == x, "Passed!" ); - ok( b.normal.y == y, "Passed!" ); - ok( b.normal.z == z, "Passed!" ); - ok( b.constant == w, "Passed!" ); -}); - -test( "setComponents", function() { - var a = new THREE.Plane(); - ok( a.normal.x == 1, "Passed!" ); - ok( a.normal.y == 0, "Passed!" ); - ok( a.normal.z == 0, "Passed!" ); - ok( a.constant == 0, "Passed!" ); - - var b = a.clone().setComponents( x, y, z , w ); - ok( b.normal.x == x, "Passed!" ); - ok( b.normal.y == y, "Passed!" ); - ok( b.normal.z == z, "Passed!" ); - ok( b.constant == w, "Passed!" ); -}); - -test( "setFromNormalAndCoplanarPoint", function() { - var normal = one3.clone().normalize(); - var a = new THREE.Plane().setFromNormalAndCoplanarPoint( normal, zero3 ); - - ok( a.normal.equals( normal ), "Passed!" ); - ok( a.constant == 0, "Passed!" ); -}); - -test( "normalize", function() { - var a = new THREE.Plane( new THREE.Vector3( 2, 0, 0 ), 2 ); - - a.normalize(); - ok( a.normal.length() == 1, "Passed!" ); - ok( a.normal.equals( new THREE.Vector3( 1, 0, 0 ) ), "Passed!" ); - ok( a.constant == 1, "Passed!" ); -}); - -test( "negate/distanceToPoint", function() { - var a = new THREE.Plane( new THREE.Vector3( 2, 0, 0 ), -2 ); - - a.normalize(); - ok( a.distanceToPoint( new THREE.Vector3( 4, 0, 0 ) ) === 3, "Passed!" ); - ok( a.distanceToPoint( new THREE.Vector3( 1, 0, 0 ) ) === 0, "Passed!" ); - - a.negate(); - ok( a.distanceToPoint( new THREE.Vector3( 4, 0, 0 ) ) === -3, "Passed!" ); - ok( a.distanceToPoint( new THREE.Vector3( 1, 0, 0 ) ) === 0, "Passed!" ); -}); - -test( "distanceToPoint", function() { - var a = new THREE.Plane( new THREE.Vector3( 2, 0, 0 ), -2 ); - - a.normalize(); - ok( a.distanceToPoint( a.projectPoint( zero3.clone() ) ) === 0, "Passed!" ); - ok( a.distanceToPoint( new THREE.Vector3( 4, 0, 0 ) ) === 3, "Passed!" ); -}); - -test( "distanceToSphere", function() { - var a = new THREE.Plane( new THREE.Vector3( 1, 0, 0 ), 0 ); - - var b = new THREE.Sphere( new THREE.Vector3( 2, 0, 0 ), 1 ); - - ok( a.distanceToSphere( b ) === 1, "Passed!" ); - - a.set( new THREE.Vector3( 1, 0, 0 ), 2 ); - ok( a.distanceToSphere( b ) === 3, "Passed!" ); - a.set( new THREE.Vector3( 1, 0, 0 ), -2 ); - ok( a.distanceToSphere( b ) === -1, "Passed!" ); -}); - -test( "isInterestionLine/intersectLine", function() { - var a = new THREE.Plane( new THREE.Vector3( 1, 0, 0 ), 0 ); - - var l1 = new THREE.Line3( new THREE.Vector3( -10, 0, 0 ), new THREE.Vector3( 10, 0, 0 ) ); - ok( a.isIntersectionLine( l1 ), "Passed!" ); - ok( a.intersectLine( l1 ).equals( new THREE.Vector3( 0, 0, 0 ) ), "Passed!" ); - - a = new THREE.Plane( new THREE.Vector3( 1, 0, 0 ), -3 ); - - ok( a.isIntersectionLine( l1 ), "Passed!" ); - ok( a.intersectLine( l1 ).equals( new THREE.Vector3( 3, 0, 0 ) ), "Passed!" ); - - - a = new THREE.Plane( new THREE.Vector3( 1, 0, 0 ), -11 ); - - ok( ! a.isIntersectionLine( l1 ), "Passed!" ); - ok( a.intersectLine( l1 ) === undefined, "Passed!" ); - - a = new THREE.Plane( new THREE.Vector3( 1, 0, 0 ), 11 ); - - ok( ! a.isIntersectionLine( l1 ), "Passed!" ); - ok( a.intersectLine( l1 ) === undefined, "Passed!" ); - -}); - -test( "projectPoint", function() { - var a = new THREE.Plane( new THREE.Vector3( 1, 0, 0 ), 0 ); - - ok( a.projectPoint( new THREE.Vector3( 10, 0, 0 ) ).equals( zero3 ), "Passed!" ); - ok( a.projectPoint( new THREE.Vector3( -10, 0, 0 ) ).equals( zero3 ), "Passed!" ); - - a = new THREE.Plane( new THREE.Vector3( 0, 1, 0 ), -1 ); - ok( a.projectPoint( new THREE.Vector3( 0, 0, 0 ) ).equals( new THREE.Vector3( 0, 1, 0 ) ), "Passed!" ); - ok( a.projectPoint( new THREE.Vector3( 0, 1, 0 ) ).equals( new THREE.Vector3( 0, 1, 0 ) ), "Passed!" ); - -}); - -test( "orthoPoint", function() { - var a = new THREE.Plane( new THREE.Vector3( 1, 0, 0 ), 0 ); - - ok( a.orthoPoint( new THREE.Vector3( 10, 0, 0 ) ).equals( new THREE.Vector3( 10, 0, 0 ) ), "Passed!" ); - ok( a.orthoPoint( new THREE.Vector3( -10, 0, 0 ) ).equals( new THREE.Vector3( -10, 0, 0 ) ), "Passed!" ); -}); - -test( "coplanarPoint", function() { - var a = new THREE.Plane( new THREE.Vector3( 1, 0, 0 ), 0 ); - ok( a.distanceToPoint( a.coplanarPoint() ) === 0, "Passed!" ); - - a = new THREE.Plane( new THREE.Vector3( 0, 1, 0 ), -1 ); - ok( a.distanceToPoint( a.coplanarPoint() ) === 0, "Passed!" ); -}); - -test( "applyMatrix4/translate", function() { - - var a = new THREE.Plane( new THREE.Vector3( 1, 0, 0 ), 0 ); - - var m = new THREE.Matrix4(); - m.makeRotationZ( Math.PI * 0.5 ); - - ok( comparePlane( a.clone().applyMatrix4( m ), new THREE.Plane( new THREE.Vector3( 0, 1, 0 ), 0 ) ), "Passed!" ); - - a = new THREE.Plane( new THREE.Vector3( 0, 1, 0 ), -1 ); - ok( comparePlane( a.clone().applyMatrix4( m ), new THREE.Plane( new THREE.Vector3( -1, 0, 0 ), -1 ) ), "Passed!" ); - - m.makeTranslation( 1, 1, 1 ); - ok( comparePlane( a.clone().applyMatrix4( m ), a.clone().translate( new THREE.Vector3( 1, 1, 1 ) ) ), "Passed!" ); -}); - -var orders = [ 'XYZ', 'YXZ', 'ZXY', 'ZYX', 'YZX', 'XZY' ]; -var eulerAngles = new THREE.Vector3( 0.1, -0.3, 0.25 ); - - - -var qSub = function ( a, b ) { - var result = new THREE.Quaternion(); - result.copy( a ); - - result.x -= b.x; - result.y -= b.y; - result.z -= b.z; - result.w -= b.w; - - return result; - -}; - -test( "constructor", function() { - var a = new THREE.Quaternion(); - ok( a.x == 0, "Passed!" ); - ok( a.y == 0, "Passed!" ); - ok( a.z == 0, "Passed!" ); - ok( a.w == 1, "Passed!" ); - - a = new THREE.Quaternion( x, y, z, w ); - ok( a.x === x, "Passed!" ); - ok( a.y === y, "Passed!" ); - ok( a.z === z, "Passed!" ); - ok( a.w === w, "Passed!" ); -}); - -test( "copy", function() { - var a = new THREE.Quaternion( x, y, z, w ); - var b = new THREE.Quaternion().copy( a ); - ok( b.x == x, "Passed!" ); - ok( b.y == y, "Passed!" ); - ok( b.z == z, "Passed!" ); - ok( b.w == w, "Passed!" ); - - // ensure that it is a true copy - a.x = 0; - a.y = -1; - a.z = 0; - a.w = -1; - ok( b.x == x, "Passed!" ); - ok( b.y == y, "Passed!" ); -}); - -test( "set", function() { - var a = new THREE.Quaternion(); - ok( a.x == 0, "Passed!" ); - ok( a.y == 0, "Passed!" ); - ok( a.z == 0, "Passed!" ); - ok( a.w == 1, "Passed!" ); - - a.set( x, y, z, w ); - ok( a.x == x, "Passed!" ); - ok( a.y == y, "Passed!" ); - ok( a.z === z, "Passed!" ); - ok( a.w === w, "Passed!" ); -}); - -test( "setFromAxisAngle", function() { - - // TODO: find cases to validate. - ok( true, "Passed!" ); - - var zero = new THREE.Quaternion(); - - var a = new THREE.Quaternion().setFromAxisAngle( new THREE.Vector3( 1, 0, 0 ), 0 ); - ok( a.equals( zero ), "Passed!" ); - a = new THREE.Quaternion().setFromAxisAngle( new THREE.Vector3( 0, 1, 0 ), 0 ); - ok( a.equals( zero ), "Passed!" ); - a = new THREE.Quaternion().setFromAxisAngle( new THREE.Vector3( 0, 0, 1 ), 0 ); - ok( a.equals( zero ), "Passed!" ); - - var b1 = new THREE.Quaternion().setFromAxisAngle( new THREE.Vector3( 1, 0, 0 ), Math.PI ); - ok( ! a.equals( b1 ), "Passed!" ); - var b2 = new THREE.Quaternion().setFromAxisAngle( new THREE.Vector3( 1, 0, 0 ), -Math.PI ); - ok( ! a.equals( b2 ), "Passed!" ); - - b1.multiply( b2 ); - ok( a.equals( b1 ), "Passed!" ); -}); - - -test( "setFromEuler/setEulerFromQuaternion", function() { - - var angles = [ new THREE.Vector3( 1, 0, 0 ), new THREE.Vector3( 0, 1, 0 ), new THREE.Vector3( 0, 0, 1 ) ]; - - // ensure euler conversion to/from Quaternion matches. - for( var i = 0; i < orders.length; i ++ ) { - for( var j = 0; j < angles.length; j ++ ) { - var eulers2 = new THREE.Vector3().setEulerFromQuaternion( new THREE.Quaternion().setFromEuler( angles[j], orders[i] ), orders[i] ); - - ok( eulers2.distanceTo( angles[j] ) < 0.001, "Passed!" ); - } - } - -}); - -test( "setFromEuler/setFromRotationMatrix", function() { - - // ensure euler conversion for Quaternion matches that of Matrix4 - for( var i = 0; i < orders.length; i ++ ) { - var q = new THREE.Quaternion().setFromEuler( eulerAngles, orders[i] ); - var m = new THREE.Matrix4().setRotationFromEuler( eulerAngles, orders[i] ); - var q2 = new THREE.Quaternion().setFromRotationMatrix( m ); - - ok( qSub( q, q2 ).length() < 0.001, "Passed!" ); - } - -}); - -test( "normalize/length/lengthSq", function() { - var a = new THREE.Quaternion( x, y, z, w ); - var b = new THREE.Quaternion( -x, -y, -z, -w ); - - ok( a.length() != 1, "Passed!"); - ok( a.lengthSq() != 1, "Passed!"); - a.normalize(); - ok( a.length() == 1, "Passed!"); - ok( a.lengthSq() == 1, "Passed!"); - - a.set( 0, 0, 0, 0 ); - ok( a.lengthSq() == 0, "Passed!"); - ok( a.length() == 0, "Passed!"); - a.normalize(); - ok( a.lengthSq() == 1, "Passed!"); - ok( a.length() == 1, "Passed!"); -}); - -test( "inverse/conjugate", function() { - var a = new THREE.Quaternion( x, y, z, w ); - - // TODO: add better validation here. - - var b = a.clone().conjugate(); - - ok( a.x == -b.x, "Passed!" ); - ok( a.y == -b.y, "Passed!" ); - ok( a.z == -b.z, "Passed!" ); - ok( a.w == b.w, "Passed!" ); -}); - - -test( "multiplyQuaternions/multiply", function() { - - var angles = [ new THREE.Vector3( 1, 0, 0 ), new THREE.Vector3( 0, 1, 0 ), new THREE.Vector3( 0, 0, 1 ) ]; - - var q1 = new THREE.Quaternion().setFromEuler( angles[0], "XYZ" ); - var q2 = new THREE.Quaternion().setFromEuler( angles[1], "XYZ" ); - var q3 = new THREE.Quaternion().setFromEuler( angles[2], "XYZ" ); - - var q = new THREE.Quaternion().multiplyQuaternions( q1, q2 ).multiply( q3 ); - - var m1 = new THREE.Matrix4().setRotationFromEuler( angles[0], "XYZ" ); - var m2 = new THREE.Matrix4().setRotationFromEuler( angles[1], "XYZ" ); - var m3 = new THREE.Matrix4().setRotationFromEuler( angles[2], "XYZ" ); - - var m = new THREE.Matrix4().multiplyMatrices( m1, m2 ).multiply( m3 ); - - var qFromM = new THREE.Quaternion().setFromRotationMatrix( m ); - - ok( qSub( q, qFromM ).length() < 0.001, "Passed!" ); -}); - -test( "multiplyVector3", function() { - - var angles = [ new THREE.Vector3( 1, 0, 0 ), new THREE.Vector3( 0, 1, 0 ), new THREE.Vector3( 0, 0, 1 ) ]; - - // ensure euler conversion for Quaternion matches that of Matrix4 - for( var i = 0; i < orders.length; i ++ ) { - for( var j = 0; j < angles.length; j ++ ) { - var q = new THREE.Quaternion().setFromEuler( angles[j], orders[i] ); - var m = new THREE.Matrix4().setRotationFromEuler( angles[j], orders[i] ); - - var v0 = new THREE.Vector3(1, 0, 0); - var qv = v0.clone().applyQuaternion( q ); - var mv = v0.clone().applyMatrix4( m ); - - ok( qv.distanceTo( mv ) < 0.001, "Passed!" ); - } - } - -}); - -test( "equals", function() { - var a = new THREE.Quaternion( x, y, z, w ); - var b = new THREE.Quaternion( -x, -y, -z, -w ); - - ok( a.x != b.x, "Passed!" ); - ok( a.y != b.y, "Passed!" ); - - ok( ! a.equals( b ), "Passed!" ); - ok( ! b.equals( a ), "Passed!" ); - - a.copy( b ); - ok( a.x == b.x, "Passed!" ); - ok( a.y == b.y, "Passed!" ); - - ok( a.equals( b ), "Passed!" ); - ok( b.equals( a ), "Passed!" ); -}); - - -test( "constructor/equals", function() { - var a = new THREE.Ray(); - ok( a.origin.equals( zero3 ), "Passed!" ); - ok( a.direction.equals( zero3 ), "Passed!" ); - - a = new THREE.Ray( two3.clone(), one3.clone() ); - ok( a.origin.equals( two3 ), "Passed!" ); - ok( a.direction.equals( one3 ), "Passed!" ); -}); - -test( "copy/equals", function() { - var a = new THREE.Ray( zero3.clone(), one3.clone() ); - var b = new THREE.Ray().copy( a ); - ok( b.origin.equals( zero3 ), "Passed!" ); - ok( b.direction.equals( one3 ), "Passed!" ); - - // ensure that it is a true copy - a.origin = zero3; - a.direction = one3; - ok( b.origin.equals( zero3 ), "Passed!" ); - ok( b.direction.equals( one3 ), "Passed!" ); -}); - -test( "set", function() { - var a = new THREE.Ray(); - - a.set( one3, one3 ); - ok( a.origin.equals( one3 ), "Passed!" ); - ok( a.direction.equals( one3 ), "Passed!" ); -}); - -test( "at", function() { - var a = new THREE.Ray( one3.clone(), new THREE.Vector3( 0, 0, 1 ) ); - - ok( a.at( 0 ).equals( one3 ), "Passed!" ); - ok( a.at( -1 ).equals( new THREE.Vector3( 1, 1, 0 ) ), "Passed!" ); - ok( a.at( 1 ).equals( new THREE.Vector3( 1, 1, 2 ) ), "Passed!" ); -}); - -test( "recast/clone", function() { - var a = new THREE.Ray( one3.clone(), new THREE.Vector3( 0, 0, 1 ) ); - - ok( a.recast( 0 ).equals( a ), "Passed!" ); - - var b = a.clone(); - ok( b.recast( -1 ).equals( new THREE.Ray( new THREE.Vector3( 1, 1, 0 ), new THREE.Vector3( 0, 0, 1 ) ) ), "Passed!" ); - - var c = a.clone(); - ok( c.recast( 1 ).equals( new THREE.Ray( new THREE.Vector3( 1, 1, 2 ), new THREE.Vector3( 0, 0, 1 ) ) ), "Passed!" ); - - var d = a.clone(); - var e = d.clone().recast( 1 ); - ok( d.equals( a ), "Passed!" ); - ok( ! e.equals( d ), "Passed!" ); - ok( e.equals( c ), "Passed!" ); -}); - -test( "closestPointToPoint", function() { - var a = new THREE.Ray( one3.clone(), new THREE.Vector3( 0, 0, 1 ) ); - - // nearby the ray - var b = a.closestPointToPoint( zero3 ); - ok( b.equals( new THREE.Vector3( 1, 1, 0 ) ), "Passed!" ); - - // exactly on the ray - var c = a.closestPointToPoint( one3 ); - ok( c.equals( one3 ), "Passed!" ); -}); - -test( "distanceToPoint", function() { - var a = new THREE.Ray( one3.clone(), new THREE.Vector3( 0, 0, 1 ) ); - - // nearby the ray - var b = a.distanceToPoint( zero3 ); - ok( b == Math.sqrt( 2 ), "Passed!" ); - - // exactly on the ray - var c = a.distanceToPoint( one3 ); - ok( c == 0, "Passed!" ); -}); - -test( "isIntersectionSphere", function() { - var a = new THREE.Ray( one3.clone(), new THREE.Vector3( 0, 0, 1 ) ); - var b = new THREE.Sphere( zero3, 0.5 ); - var c = new THREE.Sphere( zero3, 1.5 ); - var d = new THREE.Sphere( one3, 0.1 ); - var e = new THREE.Sphere( two3, 0.1 ); - var f = new THREE.Sphere( two3, 1 ); - - ok( ! a.isIntersectionSphere( b ), "Passed!" ); - ok( a.isIntersectionSphere( c ), "Passed!" ); - ok( a.isIntersectionSphere( d ), "Passed!" ); - ok( ! a.isIntersectionSphere( e ), "Passed!" ); - ok( ! a.isIntersectionSphere( f ), "Passed!" ); -}); - -test( "isIntersectionPlane", function() { - var a = new THREE.Ray( one3.clone(), new THREE.Vector3( 0, 0, 1 ) ); - - // parallel plane behind - var b = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3( 0, 0, 1 ), one3.clone().sub( new THREE.Vector3( 0, 0, -1 ) ) ); - ok( a.isIntersectionPlane( b ), "Passed!" ); - - // parallel plane coincident with origin - var c = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3( 0, 0, 1 ), one3.clone().sub( new THREE.Vector3( 0, 0, 0 ) ) ); - ok( a.isIntersectionPlane( c ), "Passed!" ); - - // parallel plane infront - var d = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3( 0, 0, 1 ), one3.clone().sub( new THREE.Vector3( 0, 0, 1 ) ) ); - ok( a.isIntersectionPlane( d ), "Passed!" ); - - // perpendical ray that overlaps exactly - var e = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3( 1, 0, 0 ), one3 ); - ok( a.isIntersectionPlane( e ), "Passed!" ); - - // perpendical ray that doesn't overlap - var f = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3( 1, 0, 0 ), zero3 ); - ok( ! a.isIntersectionPlane( f ), "Passed!" ); -}); - -test( "intersectPlane", function() { - var a = new THREE.Ray( one3.clone(), new THREE.Vector3( 0, 0, 1 ) ); - - // parallel plane behind - var b = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3( 0, 0, 1 ), new THREE.Vector3( 1, 1, -1 ) ); - ok( a.intersectPlane( b ).equals( new THREE.Vector3( 1, 1, -1 ) ), "Passed!" ); - - // parallel plane coincident with origin - var c = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3( 0, 0, 1 ), new THREE.Vector3( 1, 1, 0 ) ); - ok( a.intersectPlane( c ).equals( new THREE.Vector3( 1, 1, 0 ) ), "Passed!" ); - - // parallel plane infront - var d = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3( 0, 0, 1 ), new THREE.Vector3( 1, 1, 1 ) ); - ok( a.intersectPlane( d ).equals( new THREE.Vector3( 1, 1, 1 ) ), "Passed!" ); - - // perpendical ray that overlaps exactly - var e = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3( 1, 0, 0 ), one3 ); - ok( a.intersectPlane( e ).equals( a.origin ), "Passed!" ); - - // perpendical ray that doesn't overlap - var f = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3( 1, 0, 0 ), zero3 ); - ok( a.intersectPlane( f ) === undefined, "Passed!" ); -}); - - -test( "applyMatrix4", function() { - var a = new THREE.Ray( one3.clone(), new THREE.Vector3( 0, 0, 1 ) ); - var m = new THREE.Matrix4().identity(); - - ok( a.clone().applyMatrix4( m ).equals( a ), "Passed!" ); - - a = new THREE.Ray( zero3.clone(), new THREE.Vector3( 0, 0, 1 ) ); - m.rotateByAxis( new THREE.Vector3( 0, 0, 1 ), Math.PI ); - ok( a.clone().applyMatrix4( m ).equals( a ), "Passed!" ); - - m.identity().rotateX( Math.PI ); - var b = a.clone(); - b.direction.negate(); - var a2 = a.clone().applyMatrix4( m ); - ok( a2.origin.distanceTo( b.origin ) < 0.0001, "Passed!" ); - ok( a2.direction.distanceTo( b.direction ) < 0.0001, "Passed!" ); - - a.origin = new THREE.Vector3( 0, 0, 1 ); - b.origin = new THREE.Vector3( 0, 0, -1 ); - var a2 = a.clone().applyMatrix4( m ); - ok( a2.origin.distanceTo( b.origin ) < 0.0001, "Passed!" ); - ok( a2.direction.distanceTo( b.direction ) < 0.0001, "Passed!" ); -}); - - -test( "constructor", function() { - var a = new THREE.Sphere(); - ok( a.center.equals( zero3 ), "Passed!" ); - ok( a.radius == 0, "Passed!" ); - - a = new THREE.Sphere( one3.clone(), 1 ); - ok( a.center.equals( one3 ), "Passed!" ); - ok( a.radius == 1, "Passed!" ); -}); - -test( "copy", function() { - var a = new THREE.Sphere( one3.clone(), 1 ); - var b = new THREE.Sphere().copy( a ); - - ok( b.center.equals( one3 ), "Passed!" ); - ok( b.radius == 1, "Passed!" ); - - // ensure that it is a true copy - a.center = zero3; - a.radius = 0; - ok( b.center.equals( one3 ), "Passed!" ); - ok( b.radius == 1, "Passed!" ); -}); - -test( "set", function() { - var a = new THREE.Sphere(); - ok( a.center.equals( zero3 ), "Passed!" ); - ok( a.radius == 0, "Passed!" ); - - a.set( one3, 1 ); - ok( a.center.equals( one3 ), "Passed!" ); - ok( a.radius == 1, "Passed!" ); -}); - -test( "empty", function() { - var a = new THREE.Sphere(); - ok( a.empty(), "Passed!" ); - - a.set( one3, 1 ); - ok( ! a.empty(), "Passed!" ); -}); - -test( "containsPoint", function() { - var a = new THREE.Sphere( one3.clone(), 1 ); - - ok( ! a.containsPoint( zero3 ), "Passed!" ); - ok( a.containsPoint( one3 ), "Passed!" ); -}); - -test( "distanceToPoint", function() { - var a = new THREE.Sphere( one3.clone(), 1 ); - - ok( ( a.distanceToPoint( zero3 ) - 0.7320 ) < 0.001, "Passed!" ); - ok( a.distanceToPoint( one3 ) === -1, "Passed!" ); -}); - -test( "intersectsSphere", function() { - var a = new THREE.Sphere( one3.clone(), 1 ); - var b = new THREE.Sphere( zero3.clone(), 1 ); - var c = new THREE.Sphere( zero3.clone(), 0.25 ); - - ok( a.intersectsSphere( b ) , "Passed!" ); - ok( ! a.intersectsSphere( c ) , "Passed!" ); -}); - -test( "clampPoint", function() { - var a = new THREE.Sphere( one3.clone(), 1 ); - - ok( a.clampPoint( new THREE.Vector3( 1, 1, 3 ) ).equals( new THREE.Vector3( 1, 1, 2 ) ), "Passed!" ); - ok( a.clampPoint( new THREE.Vector3( 1, 1, -3 ) ).equals( new THREE.Vector3( 1, 1, 0 ) ), "Passed!" ); -}); - -test( "getBoundingBox", function() { - var a = new THREE.Sphere( one3.clone(), 1 ); - - ok( a.getBoundingBox().equals( new THREE.Box3( zero3, two3 ) ), "Passed!" ); - - a.set( zero3, 0 ) - ok( a.getBoundingBox().equals( new THREE.Box3( zero3, zero3 ) ), "Passed!" ); -}); - -test( "applyMatrix4", function() { - var a = new THREE.Sphere( one3.clone(), 1 ); - - var m = new THREE.Matrix4().makeTranslation( 1, -2, 1 ); - - ok( a.clone().applyMatrix4( m ).getBoundingBox().equals( a.getBoundingBox().applyMatrix4( m ) ), "Passed!" ); -}); - -test( "translate", function() { - var a = new THREE.Sphere( one3.clone(), 1 ); - - a.translate( one3.clone().negate() ); - ok( a.center.equals( zero3 ), "Passed!" ); -}); - -test( "constructor", function() { - var a = new THREE.Triangle(); - ok( a.a.equals( zero3 ), "Passed!" ); - ok( a.b.equals( zero3 ), "Passed!" ); - ok( a.c.equals( zero3 ), "Passed!" ); - - a = new THREE.Triangle( one3.clone().negate(), one3.clone(), two3.clone() ); - ok( a.a.equals( one3.clone().negate() ), "Passed!" ); - ok( a.b.equals( one3 ), "Passed!" ); - ok( a.c.equals( two3 ), "Passed!" ); -}); - -test( "copy", function() { - var a = new THREE.Triangle( one3.clone().negate(), one3.clone(), two3.clone() ); - var b = new THREE.Triangle().copy( a ); - ok( b.a.equals( one3.clone().negate() ), "Passed!" ); - ok( b.b.equals( one3 ), "Passed!" ); - ok( b.c.equals( two3 ), "Passed!" ); - - // ensure that it is a true copy - a.a = one3; - a.b = zero3; - a.c = zero3; - ok( b.a.equals( one3.clone().negate() ), "Passed!" ); - ok( b.b.equals( one3 ), "Passed!" ); - ok( b.c.equals( two3 ), "Passed!" ); -}); - -test( "setFromPointsAndIndices", function() { - var a = new THREE.Triangle(); - - var points = [ one3, one3.clone().negate(), two3 ]; - a.setFromPointsAndIndices( points, 1, 0, 2 ); - ok( a.a.equals( one3.clone().negate() ), "Passed!" ); - ok( a.b.equals( one3 ), "Passed!" ); - ok( a.c.equals( two3 ), "Passed!" ); - -}); - -test( "set", function() { - var a = new THREE.Triangle(); - - a.set( one3.clone().negate(), one3, two3 ); - ok( a.a.equals( one3.clone().negate() ), "Passed!" ); - ok( a.b.equals( one3 ), "Passed!" ); - ok( a.c.equals( two3 ), "Passed!" ); - -}); - -test( "area", function() { - var a = new THREE.Triangle(); - - ok( a.area() == 0, "Passed!" ); - - a = new THREE.Triangle( new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 1, 0, 0 ), new THREE.Vector3( 0, 1, 0 ) ); - ok( a.area() == 0.5, "Passed!" ); - - a = new THREE.Triangle( new THREE.Vector3( 2, 0, 0 ), new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 0, 0, 2 ) ); - ok( a.area() == 2, "Passed!" ); - - // colinear triangle. - a = new THREE.Triangle( new THREE.Vector3( 2, 0, 0 ), new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 3, 0, 0 ) ); - ok( a.area() == 0, "Passed!" ); -}); - -test( "midpoint", function() { - var a = new THREE.Triangle(); - - ok( a.midpoint().equals( new THREE.Vector3( 0, 0, 0 ) ), "Passed!" ); - - a = new THREE.Triangle( new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 1, 0, 0 ), new THREE.Vector3( 0, 1, 0 ) ); - ok( a.midpoint().equals( new THREE.Vector3( 1/3, 1/3, 0 ) ), "Passed!" ); - - a = new THREE.Triangle( new THREE.Vector3( 2, 0, 0 ), new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 0, 0, 2 ) ); - ok( a.midpoint().equals( new THREE.Vector3( 2/3, 0, 2/3 ) ), "Passed!" ); -}); - -test( "normal", function() { - var a = new THREE.Triangle(); - - ok( a.normal().equals( new THREE.Vector3( 0, 0, 0 ) ), "Passed!" ); - - a = new THREE.Triangle( new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 1, 0, 0 ), new THREE.Vector3( 0, 1, 0 ) ); - ok( a.normal().equals( new THREE.Vector3( 0, 0, 1 ) ), "Passed!" ); - - a = new THREE.Triangle( new THREE.Vector3( 2, 0, 0 ), new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 0, 0, 2 ) ); - ok( a.normal().equals( new THREE.Vector3( 0, 1, 0 ) ), "Passed!" ); -}); - -test( "plane", function() { - var a = new THREE.Triangle(); - - // artificial normal is created in this case. - ok( a.plane().distanceToPoint( a.a ) == 0, "Passed!" ); - ok( a.plane().distanceToPoint( a.b ) == 0, "Passed!" ); - ok( a.plane().distanceToPoint( a.c ) == 0, "Passed!" ); - ok( a.plane().normal.equals( a.normal() ), "Passed!" ); - - a = new THREE.Triangle( new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 1, 0, 0 ), new THREE.Vector3( 0, 1, 0 ) ); - ok( a.plane().distanceToPoint( a.a ) == 0, "Passed!" ); - ok( a.plane().distanceToPoint( a.b ) == 0, "Passed!" ); - ok( a.plane().distanceToPoint( a.c ) == 0, "Passed!" ); - ok( a.plane().normal.equals( a.normal() ), "Passed!" ); - - a = new THREE.Triangle( new THREE.Vector3( 2, 0, 0 ), new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 0, 0, 2 ) ); - ok( a.plane().distanceToPoint( a.a ) == 0, "Passed!" ); - ok( a.plane().distanceToPoint( a.b ) == 0, "Passed!" ); - ok( a.plane().distanceToPoint( a.c ) == 0, "Passed!" ); - ok( a.plane().normal.clone().normalize().equals( a.normal() ), "Passed!" ); -}); - -test( "barycoordFromPoint", function() { - var a = new THREE.Triangle(); - - var bad = new THREE.Vector3( -2, -1, -1 ); - - ok( a.barycoordFromPoint( a.a ).equals( bad ), "Passed!" ); - ok( a.barycoordFromPoint( a.b ).equals( bad ), "Passed!" ); - ok( a.barycoordFromPoint( a.c ).equals( bad ), "Passed!" ); - - a = new THREE.Triangle( new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 1, 0, 0 ), new THREE.Vector3( 0, 1, 0 ) ); - ok( a.barycoordFromPoint( a.a ).equals( new THREE.Vector3( 1, 0, 0 ) ), "Passed!" ); - ok( a.barycoordFromPoint( a.b ).equals( new THREE.Vector3( 0, 1, 0 ) ), "Passed!" ); - ok( a.barycoordFromPoint( a.c ).equals( new THREE.Vector3( 0, 0, 1 ) ), "Passed!" ); - ok( a.barycoordFromPoint( a.midpoint() ).distanceTo( new THREE.Vector3( 1/3, 1/3, 1/3 ) ) < 0.0001, "Passed!" ); - - a = new THREE.Triangle( new THREE.Vector3( 2, 0, 0 ), new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 0, 0, 2 ) ); - ok( a.barycoordFromPoint( a.a ).equals( new THREE.Vector3( 1, 0, 0 ) ), "Passed!" ); - ok( a.barycoordFromPoint( a.b ).equals( new THREE.Vector3( 0, 1, 0 ) ), "Passed!" ); - ok( a.barycoordFromPoint( a.c ).equals( new THREE.Vector3( 0, 0, 1 ) ), "Passed!" ); - ok( a.barycoordFromPoint( a.midpoint() ).distanceTo( new THREE.Vector3( 1/3, 1/3, 1/3 ) ) < 0.0001, "Passed!" ); -}); - -test( "containsPoint", function() { - var a = new THREE.Triangle(); - - ok( ! a.containsPoint( a.a ), "Passed!" ); - ok( ! a.containsPoint( a.b ), "Passed!" ); - ok( ! a.containsPoint( a.c ), "Passed!" ); - - a = new THREE.Triangle( new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 1, 0, 0 ), new THREE.Vector3( 0, 1, 0 ) ); - ok( a.containsPoint( a.a ), "Passed!" ); - ok( a.containsPoint( a.b ), "Passed!" ); - ok( a.containsPoint( a.c ), "Passed!" ); - ok( a.containsPoint( a.midpoint() ), "Passed!" ); - ok( ! a.containsPoint( new THREE.Vector3( -1, -1, -1 ) ), "Passed!" ); - - a = new THREE.Triangle( new THREE.Vector3( 2, 0, 0 ), new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 0, 0, 2 ) ); - ok( a.containsPoint( a.a ), "Passed!" ); - ok( a.containsPoint( a.b ), "Passed!" ); - ok( a.containsPoint( a.c ), "Passed!" ); - ok( a.containsPoint( a.midpoint() ), "Passed!" ); - ok( ! a.containsPoint( new THREE.Vector3( -1, -1, -1 ) ), "Passed!" ); -}); - - -test( "constructor", function() { - var a = new THREE.Vector2(); - ok( a.x == 0, "Passed!" ); - ok( a.y == 0, "Passed!" ); - - a = new THREE.Vector2( x, y ); - ok( a.x === x, "Passed!" ); - ok( a.y === y, "Passed!" ); -}); - -test( "copy", function() { - var a = new THREE.Vector2( x, y ); - var b = new THREE.Vector2().copy( a ); - ok( b.x == x, "Passed!" ); - ok( b.y == y, "Passed!" ); - - // ensure that it is a true copy - a.x = 0; - a.y = -1; - ok( b.x == x, "Passed!" ); - ok( b.y == y, "Passed!" ); -}); - -test( "set", function() { - var a = new THREE.Vector2(); - ok( a.x == 0, "Passed!" ); - ok( a.y == 0, "Passed!" ); - - a.set( x, y ); - ok( a.x == x, "Passed!" ); - ok( a.y == y, "Passed!" ); -}); - -test( "setX,setY", function() { - var a = new THREE.Vector2(); - ok( a.x == 0, "Passed!" ); - ok( a.y == 0, "Passed!" ); - - a.setX( x ); - a.setY( y ); - ok( a.x == x, "Passed!" ); - ok( a.y == y, "Passed!" ); -}); - -test( "setComponent,getComponent", function() { - var a = new THREE.Vector2(); - ok( a.x == 0, "Passed!" ); - ok( a.y == 0, "Passed!" ); - - a.setComponent( 0, 1 ); - a.setComponent( 1, 2 ); - ok( a.getComponent( 0 ) == 1, "Passed!" ); - ok( a.getComponent( 1 ) == 2, "Passed!" ); -}); - -test( "add", function() { - var a = new THREE.Vector2( x, y ); - var b = new THREE.Vector2( -x, -y ); - - a.add( b ); - ok( a.x == 0, "Passed!" ); - ok( a.y == 0, "Passed!" ); - - var c = new THREE.Vector2().addVectors( b, b ); - ok( c.x == -2*x, "Passed!" ); - ok( c.y == -2*y, "Passed!" ); -}); - -test( "sub", function() { - var a = new THREE.Vector2( x, y ); - var b = new THREE.Vector2( -x, -y ); - - a.sub( b ); - ok( a.x == 2*x, "Passed!" ); - ok( a.y == 2*y, "Passed!" ); - - var c = new THREE.Vector2().subVectors( a, a ); - ok( c.x == 0, "Passed!" ); - ok( c.y == 0, "Passed!" ); -}); - -test( "multiply/divide", function() { - var a = new THREE.Vector2( x, y ); - var b = new THREE.Vector2( -x, -y ); - - a.multiplyScalar( -2 ); - ok( a.x == x*-2, "Passed!" ); - ok( a.y == y*-2, "Passed!" ); - - b.multiplyScalar( -2 ); - ok( b.x == 2*x, "Passed!" ); - ok( b.y == 2*y, "Passed!" ); - - a.divideScalar( -2 ); - ok( a.x == x, "Passed!" ); - ok( a.y == y, "Passed!" ); - - b.divideScalar( -2 ); - ok( b.x == -x, "Passed!" ); - ok( b.y == -y, "Passed!" ); -}); - - -test( "min/max/clamp", function() { - var a = new THREE.Vector2( x, y ); - var b = new THREE.Vector2( -x, -y ); - var c = new THREE.Vector2(); - - c.copy( a ).min( b ); - ok( c.x == -x, "Passed!" ); - ok( c.y == -y, "Passed!" ); - - c.copy( a ).max( b ); - ok( c.x == x, "Passed!" ); - ok( c.y == y, "Passed!" ); - - c.set( -2*x, 2*y ); - c.clamp( b, a ); - ok( c.x == -x, "Passed!" ); - ok( c.y == y, "Passed!" ); -}); - -test( "negate", function() { - var a = new THREE.Vector2( x, y ); - - a.negate(); - ok( a.x == -x, "Passed!" ); - ok( a.y == -y, "Passed!" ); -}); - -test( "dot", function() { - var a = new THREE.Vector2( x, y ); - var b = new THREE.Vector2( -x, -y ); - var c = new THREE.Vector2(); - - var result = a.dot( b ); - ok( result == (-x*x-y*y), "Passed!" ); - - result = a.dot( c ); - ok( result == 0, "Passed!" ); -}); - -test( "length/lengthSq", function() { - var a = new THREE.Vector2( x, 0 ); - var b = new THREE.Vector2( 0, -y ); - var c = new THREE.Vector2(); - - ok( a.length() == x, "Passed!" ); - ok( a.lengthSq() == x*x, "Passed!" ); - ok( b.length() == y, "Passed!" ); - ok( b.lengthSq() == y*y, "Passed!" ); - ok( c.length() == 0, "Passed!" ); - ok( c.lengthSq() == 0, "Passed!" ); - - a.set( x, y ); - ok( a.length() == Math.sqrt( x*x + y*y ), "Passed!" ); - ok( a.lengthSq() == ( x*x + y*y ), "Passed!" ); -}); - -test( "normalize", function() { - var a = new THREE.Vector2( x, 0 ); - var b = new THREE.Vector2( 0, -y ); - var c = new THREE.Vector2(); - - a.normalize(); - ok( a.length() == 1, "Passed!" ); - ok( a.x == 1, "Passed!" ); - - b.normalize(); - ok( b.length() == 1, "Passed!" ); - ok( b.y == -1, "Passed!" ); -}); - -test( "distanceTo/distanceToSquared", function() { - var a = new THREE.Vector2( x, 0 ); - var b = new THREE.Vector2( 0, -y ); - var c = new THREE.Vector2(); - - ok( a.distanceTo( c ) == x, "Passed!" ); - ok( a.distanceToSquared( c ) == x*x, "Passed!" ); - - ok( b.distanceTo( c ) == y, "Passed!" ); - ok( b.distanceToSquared( c ) == y*y, "Passed!" ); -}); - -test( "setLength", function() { - var a = new THREE.Vector2( x, 0 ); - - ok( a.length() == x, "Passed!" ); - a.setLength( y ); - ok( a.length() == y, "Passed!" ); - - a = new THREE.Vector2( 0, 0 ); - ok( a.length() == 0, "Passed!" ); - a.setLength( y ); - ok( a.length() == 0, "Passed!" ); -}); - -test( "lerp/clone", function() { - var a = new THREE.Vector2( x, 0 ); - var b = new THREE.Vector2( 0, -y ); - - ok( a.lerp( a, 0 ).equals( a.lerp( a, 0.5 ) ), "Passed!" ); - ok( a.lerp( a, 0 ).equals( a.lerp( a, 1 ) ), "Passed!" ); - - ok( a.clone().lerp( b, 0 ).equals( a ), "Passed!" ); - - ok( a.clone().lerp( b, 0.5 ).x == x*0.5, "Passed!" ); - ok( a.clone().lerp( b, 0.5 ).y == -y*0.5, "Passed!" ); - - ok( a.clone().lerp( b, 1 ).equals( b ), "Passed!" ); -}); - -test( "equals", function() { - var a = new THREE.Vector2( x, 0 ); - var b = new THREE.Vector2( 0, -y ); - - ok( a.x != b.x, "Passed!" ); - ok( a.y != b.y, "Passed!" ); - - ok( ! a.equals( b ), "Passed!" ); - ok( ! b.equals( a ), "Passed!" ); - - a.copy( b ); - ok( a.x == b.x, "Passed!" ); - ok( a.y == b.y, "Passed!" ); - - ok( a.equals( b ), "Passed!" ); - ok( b.equals( a ), "Passed!" ); -}); - - -test( "constructor", function() { - var a = new THREE.Vector3(); - ok( a.x == 0, "Passed!" ); - ok( a.y == 0, "Passed!" ); - ok( a.z == 0, "Passed!" ); - - a = new THREE.Vector3( x, y, z ); - ok( a.x === x, "Passed!" ); - ok( a.y === y, "Passed!" ); - ok( a.z === z, "Passed!" ); -}); - -test( "copy", function() { - var a = new THREE.Vector3( x, y, z ); - var b = new THREE.Vector3().copy( a ); - ok( b.x == x, "Passed!" ); - ok( b.y == y, "Passed!" ); - ok( b.z == z, "Passed!" ); - - // ensure that it is a true copy - a.x = 0; - a.y = -1; - a.z = -2; - ok( b.x == x, "Passed!" ); - ok( b.y == y, "Passed!" ); - ok( b.z == z, "Passed!" ); -}); - -test( "set", function() { - var a = new THREE.Vector3(); - ok( a.x == 0, "Passed!" ); - ok( a.y == 0, "Passed!" ); - ok( a.z == 0, "Passed!" ); - - a.set( x, y, z ); - ok( a.x == x, "Passed!" ); - ok( a.y == y, "Passed!" ); - ok( a.z == z, "Passed!" ); -}); - -test( "setX,setY,setZ", function() { - var a = new THREE.Vector3(); - ok( a.x == 0, "Passed!" ); - ok( a.y == 0, "Passed!" ); - ok( a.z == 0, "Passed!" ); - - a.setX( x ); - a.setY( y ); - a.setZ( z ); - - ok( a.x == x, "Passed!" ); - ok( a.y == y, "Passed!" ); - ok( a.z == z, "Passed!" ); -}); - -test( "setComponent,getComponent", function() { - var a = new THREE.Vector3(); - ok( a.x == 0, "Passed!" ); - ok( a.y == 0, "Passed!" ); - ok( a.z == 0, "Passed!" ); - - a.setComponent( 0, 1 ); - a.setComponent( 1, 2 ); - a.setComponent( 2, 3 ); - ok( a.getComponent( 0 ) == 1, "Passed!" ); - ok( a.getComponent( 1 ) == 2, "Passed!" ); - ok( a.getComponent( 2 ) == 3, "Passed!" ); -}); - -test( "add", function() { - var a = new THREE.Vector3( x, y, z ); - var b = new THREE.Vector3( -x, -y, -z ); - - a.add( b ); - ok( a.x == 0, "Passed!" ); - ok( a.y == 0, "Passed!" ); - ok( a.z == 0, "Passed!" ); - - var c = new THREE.Vector3().addVectors( b, b ); - ok( c.x == -2*x, "Passed!" ); - ok( c.y == -2*y, "Passed!" ); - ok( c.z == -2*z, "Passed!" ); -}); - -test( "sub", function() { - var a = new THREE.Vector3( x, y, z ); - var b = new THREE.Vector3( -x, -y, -z ); - - a.sub( b ); - ok( a.x == 2*x, "Passed!" ); - ok( a.y == 2*y, "Passed!" ); - ok( a.z == 2*z, "Passed!" ); - - var c = new THREE.Vector3().subVectors( a, a ); - ok( c.x == 0, "Passed!" ); - ok( c.y == 0, "Passed!" ); - ok( c.z == 0, "Passed!" ); -}); - -test( "multiply/divide", function() { - var a = new THREE.Vector3( x, y, z ); - var b = new THREE.Vector3( -x, -y, -z ); - - a.multiplyScalar( -2 ); - ok( a.x == x*-2, "Passed!" ); - ok( a.y == y*-2, "Passed!" ); - ok( a.z == z*-2, "Passed!" ); - - b.multiplyScalar( -2 ); - ok( b.x == 2*x, "Passed!" ); - ok( b.y == 2*y, "Passed!" ); - ok( b.z == 2*z, "Passed!" ); - - a.divideScalar( -2 ); - ok( a.x == x, "Passed!" ); - ok( a.y == y, "Passed!" ); - ok( a.z == z, "Passed!" ); - - b.divideScalar( -2 ); - ok( b.x == -x, "Passed!" ); - ok( b.y == -y, "Passed!" ); - ok( b.z == -z, "Passed!" ); -}); - -test( "min/max/clamp", function() { - var a = new THREE.Vector3( x, y, z ); - var b = new THREE.Vector3( -x, -y, -z ); - var c = new THREE.Vector3(); - - c.copy( a ).min( b ); - ok( c.x == -x, "Passed!" ); - ok( c.y == -y, "Passed!" ); - ok( c.z == -z, "Passed!" ); - - c.copy( a ).max( b ); - ok( c.x == x, "Passed!" ); - ok( c.y == y, "Passed!" ); - ok( c.z == z, "Passed!" ); - - c.set( -2*x, 2*y, -2*z ); - c.clamp( b, a ); - ok( c.x == -x, "Passed!" ); - ok( c.y == y, "Passed!" ); - ok( c.z == -z, "Passed!" ); -}); - -test( "negate", function() { - var a = new THREE.Vector3( x, y, z ); - - a.negate(); - ok( a.x == -x, "Passed!" ); - ok( a.y == -y, "Passed!" ); - ok( a.z == -z, "Passed!" ); -}); - -test( "dot", function() { - var a = new THREE.Vector3( x, y, z ); - var b = new THREE.Vector3( -x, -y, -z ); - var c = new THREE.Vector3(); - - var result = a.dot( b ); - ok( result == (-x*x-y*y-z*z), "Passed!" ); - - result = a.dot( c ); - ok( result == 0, "Passed!" ); -}); - -test( "length/lengthSq", function() { - var a = new THREE.Vector3( x, 0, 0 ); - var b = new THREE.Vector3( 0, -y, 0 ); - var c = new THREE.Vector3( 0, 0, z ); - var d = new THREE.Vector3(); - - ok( a.length() == x, "Passed!" ); - ok( a.lengthSq() == x*x, "Passed!" ); - ok( b.length() == y, "Passed!" ); - ok( b.lengthSq() == y*y, "Passed!" ); - ok( c.length() == z, "Passed!" ); - ok( c.lengthSq() == z*z, "Passed!" ); - ok( d.length() == 0, "Passed!" ); - ok( d.lengthSq() == 0, "Passed!" ); - - a.set( x, y, z ); - ok( a.length() == Math.sqrt( x*x + y*y + z*z ), "Passed!" ); - ok( a.lengthSq() == ( x*x + y*y + z*z ), "Passed!" ); -}); - -test( "normalize", function() { - var a = new THREE.Vector3( x, 0, 0 ); - var b = new THREE.Vector3( 0, -y, 0 ); - var c = new THREE.Vector3( 0, 0, z ); - - a.normalize(); - ok( a.length() == 1, "Passed!" ); - ok( a.x == 1, "Passed!" ); - - b.normalize(); - ok( b.length() == 1, "Passed!" ); - ok( b.y == -1, "Passed!" ); - - c.normalize(); - ok( c.length() == 1, "Passed!" ); - ok( c.z == 1, "Passed!" ); -}); - -test( "distanceTo/distanceToSquared", function() { - var a = new THREE.Vector3( x, 0, 0 ); - var b = new THREE.Vector3( 0, -y, 0 ); - var c = new THREE.Vector3( 0, 0, z ); - var d = new THREE.Vector3(); - - ok( a.distanceTo( d ) == x, "Passed!" ); - ok( a.distanceToSquared( d ) == x*x, "Passed!" ); - - ok( b.distanceTo( d ) == y, "Passed!" ); - ok( b.distanceToSquared( d ) == y*y, "Passed!" ); - - ok( c.distanceTo( d ) == z, "Passed!" ); - ok( c.distanceToSquared( d ) == z*z, "Passed!" ); -}); - -test( "setLength", function() { - var a = new THREE.Vector3( x, 0, 0 ); - - ok( a.length() == x, "Passed!" ); - a.setLength( y ); - ok( a.length() == y, "Passed!" ); - - a = new THREE.Vector3( 0, 0, 0 ); - ok( a.length() == 0, "Passed!" ); - a.setLength( y ); - ok( a.length() == 0, "Passed!" ); - -}); - -test( "projectOnVector", function() { - var a = new THREE.Vector3( 1, 0, 0 ); - var b = new THREE.Vector3(); - var normal = new THREE.Vector3( 10, 0, 0 ); - - ok( b.copy( a ).projectOnVector( normal ).equals( new THREE.Vector3( 1, 0, 0 ) ), "Passed!" ); - - a.set( 0, 1, 0 ); - ok( b.copy( a ).projectOnVector( normal ).equals( new THREE.Vector3( 0, 0, 0 ) ), "Passed!" ); - - a.set( 0, 0, -1 ); - ok( b.copy( a ).projectOnVector( normal ).equals( new THREE.Vector3( 0, 0, 0 ) ), "Passed!" ); - - a.set( -1, 0, 0 ); - ok( b.copy( a ).projectOnVector( normal ).equals( new THREE.Vector3( -1, 0, 0 ) ), "Passed!" ); - -}); - -test( "projectOnPlane", function() { - var a = new THREE.Vector3( 1, 0, 0 ); - var b = new THREE.Vector3(); - var normal = new THREE.Vector3( 1, 0, 0 ); - - ok( b.copy( a ).projectOnPlane( normal ).equals( new THREE.Vector3( 0, 0, 0 ) ), "Passed!" ); - - a.set( 0, 1, 0 ); - ok( b.copy( a ).projectOnPlane( normal ).equals( new THREE.Vector3( 0, 1, 0 ) ), "Passed!" ); - - a.set( 0, 0, -1 ); - ok( b.copy( a ).projectOnPlane( normal ).equals( new THREE.Vector3( 0, 0, -1 ) ), "Passed!" ); - - a.set( -1, 0, 0 ); - ok( b.copy( a ).projectOnPlane( normal ).equals( new THREE.Vector3( 0, 0, 0 ) ), "Passed!" ); - -}); - -test( "reflect", function() { - var a = new THREE.Vector3( 1, 0, 0 ); - var normal = new THREE.Vector3( 1, 0, 0 ); - var b = new THREE.Vector3( 0, 0, 0 ); - - ok( b.copy( a ).reflect( normal ).equals( new THREE.Vector3( 1, 0, 0 ) ), "Passed!" ); - - a.set( 1, -1, 0 ); - ok( b.copy( a ).reflect( normal ).equals( new THREE.Vector3( 1, 1, 0 ) ), "Passed!" ); - - a.set( 1, -1, 0 ); - normal.set( 0, -1, 0 ); - ok( b.copy( a ).reflect( normal ).equals( new THREE.Vector3( -1, -1, 0 ) ), "Passed!" ); -}); - -test( "angleTo", function() { - var a = new THREE.Vector3( 0, -0.18851655680720186, 0.9820700116639124 ); - var b = new THREE.Vector3( 0, 0.18851655680720186, -0.9820700116639124 ); - - equal( a.angleTo( a ), 0 ); - equal( a.angleTo( b ), Math.PI ); - - var x = new THREE.Vector3( 1, 0, 0 ); - var y = new THREE.Vector3( 0, 1, 0 ); - var z = new THREE.Vector3( 0, 0, 1 ); - - equal( x.angleTo( y ), Math.PI / 2 ); - equal( x.angleTo( z ), Math.PI / 2 ); - equal( z.angleTo( x ), Math.PI / 2 ); - - ok( Math.abs( x.angleTo( new THREE.Vector3( 1, 1, 0 ) ) - ( Math.PI / 4 ) ) < 0.0000001 ); -}); - -test( "lerp/clone", function() { - var a = new THREE.Vector3( x, 0, z ); - var b = new THREE.Vector3( 0, -y, 0 ); - - ok( a.lerp( a, 0 ).equals( a.lerp( a, 0.5 ) ), "Passed!" ); - ok( a.lerp( a, 0 ).equals( a.lerp( a, 1 ) ), "Passed!" ); - - ok( a.clone().lerp( b, 0 ).equals( a ), "Passed!" ); - - ok( a.clone().lerp( b, 0.5 ).x == x*0.5, "Passed!" ); - ok( a.clone().lerp( b, 0.5 ).y == -y*0.5, "Passed!" ); - ok( a.clone().lerp( b, 0.5 ).z == z*0.5, "Passed!" ); - - ok( a.clone().lerp( b, 1 ).equals( b ), "Passed!" ); -}); - -test( "equals", function() { - var a = new THREE.Vector3( x, 0, z ); - var b = new THREE.Vector3( 0, -y, 0 ); - - ok( a.x != b.x, "Passed!" ); - ok( a.y != b.y, "Passed!" ); - ok( a.z != b.z, "Passed!" ); - - ok( ! a.equals( b ), "Passed!" ); - ok( ! b.equals( a ), "Passed!" ); - - a.copy( b ); - ok( a.x == b.x, "Passed!" ); - ok( a.y == b.y, "Passed!" ); - ok( a.z == b.z, "Passed!" ); - - ok( a.equals( b ), "Passed!" ); - ok( b.equals( a ), "Passed!" ); -}); - - -test( "constructor", function() { - var a = new THREE.Vector4(); - ok( a.x == 0, "Passed!" ); - ok( a.y == 0, "Passed!" ); - ok( a.z == 0, "Passed!" ); - ok( a.w == 1, "Passed!" ); - - a = new THREE.Vector4( x, y, z, w ); - ok( a.x === x, "Passed!" ); - ok( a.y === y, "Passed!" ); - ok( a.z === z, "Passed!" ); - ok( a.w === w, "Passed!" ); -}); - -test( "copy", function() { - var a = new THREE.Vector4( x, y, z, w ); - var b = new THREE.Vector4().copy( a ); - ok( b.x == x, "Passed!" ); - ok( b.y == y, "Passed!" ); - ok( b.z == z, "Passed!" ); - ok( b.w == w, "Passed!" ); - - // ensure that it is a true copy - a.x = 0; - a.y = -1; - a.z = -2; - a.w = -3; - ok( b.x == x, "Passed!" ); - ok( b.y == y, "Passed!" ); - ok( b.z == z, "Passed!" ); - ok( b.w == w, "Passed!" ); -}); - -test( "set", function() { - var a = new THREE.Vector4(); - ok( a.x == 0, "Passed!" ); - ok( a.y == 0, "Passed!" ); - ok( a.z == 0, "Passed!" ); - ok( a.w == 1, "Passed!" ); - - a.set( x, y, z, w ); - ok( a.x == x, "Passed!" ); - ok( a.y == y, "Passed!" ); - ok( a.z == z, "Passed!" ); - ok( a.w == w, "Passed!" ); -}); - -test( "setX,setY,setZ,setW", function() { - var a = new THREE.Vector4(); - ok( a.x == 0, "Passed!" ); - ok( a.y == 0, "Passed!" ); - ok( a.z == 0, "Passed!" ); - ok( a.w == 1, "Passed!" ); - - a.setX( x ); - a.setY( y ); - a.setZ( z ); - a.setW( w ); - - ok( a.x == x, "Passed!" ); - ok( a.y == y, "Passed!" ); - ok( a.z == z, "Passed!" ); - ok( a.w == w, "Passed!" ); -}); - -test( "setComponent,getComponent", function() { - var a = new THREE.Vector4(); - ok( a.x == 0, "Passed!" ); - ok( a.y == 0, "Passed!" ); - ok( a.z == 0, "Passed!" ); - ok( a.w == 1, "Passed!" ); - - a.setComponent( 0, 1 ); - a.setComponent( 1, 2 ); - a.setComponent( 2, 3 ); - a.setComponent( 3, 4 ); - ok( a.getComponent( 0 ) == 1, "Passed!" ); - ok( a.getComponent( 1 ) == 2, "Passed!" ); - ok( a.getComponent( 2 ) == 3, "Passed!" ); - ok( a.getComponent( 3 ) == 4, "Passed!" ); -}); - -test( "add", function() { - var a = new THREE.Vector4( x, y, z, w ); - var b = new THREE.Vector4( -x, -y, -z, -w ); - - a.add( b ); - ok( a.x == 0, "Passed!" ); - ok( a.y == 0, "Passed!" ); - ok( a.z == 0, "Passed!" ); - ok( a.w == 0, "Passed!" ); - - var c = new THREE.Vector4().addVectors( b, b ); - ok( c.x == -2*x, "Passed!" ); - ok( c.y == -2*y, "Passed!" ); - ok( c.z == -2*z, "Passed!" ); - ok( c.w == -2*w, "Passed!" ); -}); - -test( "sub", function() { - var a = new THREE.Vector4( x, y, z, w ); - var b = new THREE.Vector4( -x, -y, -z, -w ); - - a.sub( b ); - ok( a.x == 2*x, "Passed!" ); - ok( a.y == 2*y, "Passed!" ); - ok( a.z == 2*z, "Passed!" ); - ok( a.w == 2*w, "Passed!" ); - - var c = new THREE.Vector4().subVectors( a, a ); - ok( c.x == 0, "Passed!" ); - ok( c.y == 0, "Passed!" ); - ok( c.z == 0, "Passed!" ); - ok( c.w == 0, "Passed!" ); -}); - -test( "multiply/divide", function() { - var a = new THREE.Vector4( x, y, z, w ); - var b = new THREE.Vector4( -x, -y, -z, -w ); - - a.multiplyScalar( -2 ); - ok( a.x == x*-2, "Passed!" ); - ok( a.y == y*-2, "Passed!" ); - ok( a.z == z*-2, "Passed!" ); - ok( a.w == w*-2, "Passed!" ); - - b.multiplyScalar( -2 ); - ok( b.x == 2*x, "Passed!" ); - ok( b.y == 2*y, "Passed!" ); - ok( b.z == 2*z, "Passed!" ); - ok( b.w == 2*w, "Passed!" ); - - a.divideScalar( -2 ); - ok( a.x == x, "Passed!" ); - ok( a.y == y, "Passed!" ); - ok( a.z == z, "Passed!" ); - ok( a.w == w, "Passed!" ); - - b.divideScalar( -2 ); - ok( b.x == -x, "Passed!" ); - ok( b.y == -y, "Passed!" ); - ok( b.z == -z, "Passed!" ); - ok( b.w == -w, "Passed!" ); -}); - -test( "min/max/clamp", function() { - var a = new THREE.Vector4( x, y, z, w ); - var b = new THREE.Vector4( -x, -y, -z, -w ); - var c = new THREE.Vector4(); - - c.copy( a ).min( b ); - ok( c.x == -x, "Passed!" ); - ok( c.y == -y, "Passed!" ); - ok( c.z == -z, "Passed!" ); - ok( c.w == -w, "Passed!" ); - - c.copy( a ).max( b ); - ok( c.x == x, "Passed!" ); - ok( c.y == y, "Passed!" ); - ok( c.z == z, "Passed!" ); - ok( c.w == w, "Passed!" ); - - c.set( -2*x, 2*y, -2*z, 2*w ); - c.clamp( b, a ); - ok( c.x == -x, "Passed!" ); - ok( c.y == y, "Passed!" ); - ok( c.z == -z, "Passed!" ); - ok( c.w == w, "Passed!" ); -}); - -test( "negate", function() { - var a = new THREE.Vector4( x, y, z, w ); - - a.negate(); - ok( a.x == -x, "Passed!" ); - ok( a.y == -y, "Passed!" ); - ok( a.z == -z, "Passed!" ); - ok( a.w == -w, "Passed!" ); -}); - -test( "dot", function() { - var a = new THREE.Vector4( x, y, z, w ); - var b = new THREE.Vector4( -x, -y, -z, -w ); - var c = new THREE.Vector4( 0, 0, 0, 0 ); - - var result = a.dot( b ); - ok( result == (-x*x-y*y-z*z-w*w), "Passed!" ); - - result = a.dot( c ); - ok( result == 0, "Passed!" ); -}); - -test( "length/lengthSq", function() { - var a = new THREE.Vector4( x, 0, 0, 0 ); - var b = new THREE.Vector4( 0, -y, 0, 0 ); - var c = new THREE.Vector4( 0, 0, z, 0 ); - var d = new THREE.Vector4( 0, 0, 0, w ); - var e = new THREE.Vector4( 0, 0, 0, 0 ); - - ok( a.length() == x, "Passed!" ); - ok( a.lengthSq() == x*x, "Passed!" ); - ok( b.length() == y, "Passed!" ); - ok( b.lengthSq() == y*y, "Passed!" ); - ok( c.length() == z, "Passed!" ); - ok( c.lengthSq() == z*z, "Passed!" ); - ok( d.length() == w, "Passed!" ); - ok( d.lengthSq() == w*w, "Passed!" ); - ok( e.length() == 0, "Passed!" ); - ok( e.lengthSq() == 0, "Passed!" ); - - a.set( x, y, z, w ); - ok( a.length() == Math.sqrt( x*x + y*y + z*z + w*w ), "Passed!" ); - ok( a.lengthSq() == ( x*x + y*y + z*z + w*w ), "Passed!" ); -}); - -test( "normalize", function() { - var a = new THREE.Vector4( x, 0, 0, 0 ); - var b = new THREE.Vector4( 0, -y, 0, 0 ); - var c = new THREE.Vector4( 0, 0, z, 0 ); - var d = new THREE.Vector4( 0, 0, 0, -w ); - - a.normalize(); - ok( a.length() == 1, "Passed!" ); - ok( a.x == 1, "Passed!" ); - - b.normalize(); - ok( b.length() == 1, "Passed!" ); - ok( b.y == -1, "Passed!" ); - - c.normalize(); - ok( c.length() == 1, "Passed!" ); - ok( c.z == 1, "Passed!" ); - - d.normalize(); - ok( d.length() == 1, "Passed!" ); - ok( d.w == -1, "Passed!" ); -}); - /* -test( "distanceTo/distanceToSquared", function() { - var a = new THREE.Vector4( x, 0, 0, 0 ); - var b = new THREE.Vector4( 0, -y, 0, 0 ); - var c = new THREE.Vector4( 0, 0, z, 0 ); - var d = new THREE.Vector4( 0, 0, 0, -w ); - var e = new THREE.Vector4(); - - ok( a.distanceTo( e ) == x, "Passed!" ); - ok( a.distanceToSquared( e ) == x*x, "Passed!" ); +The MIT License - ok( b.distanceTo( e ) == y, "Passed!" ); - ok( b.distanceToSquared( e ) == y*y, "Passed!" ); +Copyright (c) 2010-2013 three.js authors - ok( c.distanceTo( e ) == z, "Passed!" ); - ok( c.distanceToSquared( e ) == z*z, "Passed!" ); +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: - ok( d.distanceTo( e ) == w, "Passed!" ); - ok( d.distanceToSquared( e ) == w*w, "Passed!" ); -}); +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. */ +()=>{ + var x = 2; + var y = 3; + var z = 4; + var w = 5; -test( "setLength", function() { - var a = new THREE.Vector4( x, 0, 0, 0 ); + var negInf2 = new THREE.Vector2( -Infinity, -Infinity ); + var posInf2 = new THREE.Vector2( Infinity, Infinity ); - ok( a.length() == x, "Passed!" ); - a.setLength( y ); - ok( a.length() == y, "Passed!" ); + var zero2 = new THREE.Vector2(); + var one2 = new THREE.Vector2( 1, 1 ); + var two2 = new THREE.Vector2( 2, 2 ); - a = new THREE.Vector4( 0, 0, 0, 0 ); - ok( a.length() == 0, "Passed!" ); - a.setLength( y ); - ok( a.length() == 0, "Passed!" ); -}); + var negInf3 = new THREE.Vector3( -Infinity, -Infinity, -Infinity ); + var posInf3 = new THREE.Vector3( Infinity, Infinity, Infinity ); -test( "lerp/clone", function() { - var a = new THREE.Vector4( x, 0, z, 0 ); - var b = new THREE.Vector4( 0, -y, 0, -w ); + var zero3 = new THREE.Vector3(); + var one3 = new THREE.Vector3( 1, 1, 1 ); + var two3 = new THREE.Vector3( 2, 2, 2 ); - ok( a.lerp( a, 0 ).equals( a.lerp( a, 0.5 ) ), "Passed!" ); - ok( a.lerp( a, 0 ).equals( a.lerp( a, 1 ) ), "Passed!" ); + (QUnit.module)( "Box2" ); - ok( a.clone().lerp( b, 0 ).equals( a ), "Passed!" ); + test( "constructor", function() { + var a = new THREE.Box2(); + ok( a.min.equals( posInf2 ), "Passed!" ); + ok( a.max.equals( negInf2 ), "Passed!" ); - ok( a.clone().lerp( b, 0.5 ).x == x*0.5, "Passed!" ); - ok( a.clone().lerp( b, 0.5 ).y == -y*0.5, "Passed!" ); - ok( a.clone().lerp( b, 0.5 ).z == z*0.5, "Passed!" ); - ok( a.clone().lerp( b, 0.5 ).w == -w*0.5, "Passed!" ); + a = new THREE.Box2( zero2.clone(), zero2.clone() ); + ok( a.min.equals( zero2 ), "Passed!" ); + ok( a.max.equals( zero2 ), "Passed!" ); - ok( a.clone().lerp( b, 1 ).equals( b ), "Passed!" ); -}); + a = new THREE.Box2( zero2.clone(), one2.clone() ); + ok( a.min.equals( zero2 ), "Passed!" ); + ok( a.max.equals( one2 ), "Passed!" ); + }); -test( "equals", function() { - var a = new THREE.Vector4( x, 0, z, 0 ); - var b = new THREE.Vector4( 0, -y, 0, -w ); + test( "copy", function() { + var a = new THREE.Box2( zero2.clone(), one2.clone() ); + var b = new THREE.Box2().copy( a ); + ok( b.min.equals( zero2 ), "Passed!" ); + ok( b.max.equals( one2 ), "Passed!" ); - ok( a.x != b.x, "Passed!" ); - ok( a.y != b.y, "Passed!" ); - ok( a.z != b.z, "Passed!" ); - ok( a.w != b.w, "Passed!" ); + // ensure that it is a true copy + a.min = zero2; + a.max = one2; + ok( b.min.equals( zero2 ), "Passed!" ); + ok( b.max.equals( one2 ), "Passed!" ); + }); - ok( ! a.equals( b ), "Passed!" ); - ok( ! b.equals( a ), "Passed!" ); + test( "set", function() { + var a = new THREE.Box2(); - a.copy( b ); - ok( a.x == b.x, "Passed!" ); - ok( a.y == b.y, "Passed!" ); - ok( a.z == b.z, "Passed!" ); - ok( a.w == b.w, "Passed!" ); + a.set( zero2, one2 ); + ok( a.min.equals( zero2 ), "Passed!" ); + ok( a.max.equals( one2 ), "Passed!" ); + }); - ok( a.equals( b ), "Passed!" ); - ok( b.equals( a ), "Passed!" ); -}); \ No newline at end of file + test( "empty/makeEmpty", function() { + var a = new THREE.Box2(); + + ok( a.empty(), "Passed!" ); + + var a = new THREE.Box2( zero2.clone(), one2.clone() ); + ok( ! a.empty(), "Passed!" ); + + a.makeEmpty(); + ok( a.empty(), "Passed!" ); + }); + + test( "center", function() { + var a = new THREE.Box2( zero2.clone(), zero2.clone() ); + + ok( a.center().equals( zero2 ), "Passed!" ); + + a = new THREE.Box2( zero2, one2 ); + var midpoint = one2.clone().multiplyScalar( 0.5 ); + ok( a.center().equals( midpoint ), "Passed!" ); + }); + + test( "size", function() { + var a = new THREE.Box2( zero2.clone(), zero2.clone() ); + + ok( a.size().equals( zero2 ), "Passed!" ); + + a = new THREE.Box2( zero2.clone(), one2.clone() ); + ok( a.size().equals( one2 ), "Passed!" ); + }); + + test( "expandByPoint", function() { + var a = new THREE.Box2( zero2.clone(), zero2.clone() ); + + a.expandByPoint( zero2 ); + ok( a.size().equals( zero2 ), "Passed!" ); + + a.expandByPoint( one2 ); + ok( a.size().equals( one2 ), "Passed!" ); + + a.expandByPoint( one2.clone().negate() ); + ok( a.size().equals( one2.clone().multiplyScalar( 2 ) ), "Passed!" ); + ok( a.center().equals( zero2 ), "Passed!" ); + }); + + test( "expandByVector", function() { + var a = new THREE.Box2( zero2.clone(), zero2.clone() ); + + a.expandByVector( zero2 ); + ok( a.size().equals( zero2 ), "Passed!" ); + + a.expandByVector( one2 ); + ok( a.size().equals( one2.clone().multiplyScalar( 2 ) ), "Passed!" ); + ok( a.center().equals( zero2 ), "Passed!" ); + }); + + test( "expandByScalar", function() { + var a = new THREE.Box2( zero2.clone(), zero2.clone() ); + + a.expandByScalar( 0 ); + ok( a.size().equals( zero2 ), "Passed!" ); + + a.expandByScalar( 1 ); + ok( a.size().equals( one2.clone().multiplyScalar( 2 ) ), "Passed!" ); + ok( a.center().equals( zero2 ), "Passed!" ); + }); + + test( "containsPoint", function() { + var a = new THREE.Box2( zero2.clone(), zero2.clone() ); + + ok( a.containsPoint( zero2 ), "Passed!" ); + ok( ! a.containsPoint( one2 ), "Passed!" ); + + a.expandByScalar( 1 ); + ok( a.containsPoint( zero2 ), "Passed!" ); + ok( a.containsPoint( one2 ), "Passed!" ); + ok( a.containsPoint( one2.clone().negate() ), "Passed!" ); + }); + + test( "containsBox", function() { + var a = new THREE.Box2( zero2.clone(), zero2.clone() ); + var b = new THREE.Box2( zero2.clone(), one2.clone() ); + var c = new THREE.Box2( one2.clone().negate(), one2.clone() ); + + ok( a.containsBox( a ), "Passed!" ); + ok( ! a.containsBox( b ), "Passed!" ); + ok( ! a.containsBox( c ), "Passed!" ); + + ok( b.containsBox( a ), "Passed!" ); + ok( c.containsBox( a ), "Passed!" ); + ok( ! b.containsBox( c ), "Passed!" ); + }); + + test( "getParameter", function() { + var a = new THREE.Box2( zero2.clone(), one2.clone() ); + var b = new THREE.Box2( one2.clone().negate(), one2.clone() ); + + ok( a.getParameter( new THREE.Vector2( 0, 0 ) ).equals( new THREE.Vector2( 0, 0 ) ), "Passed!" ); + ok( a.getParameter( new THREE.Vector2( 1, 1 ) ).equals( new THREE.Vector2( 1, 1 ) ), "Passed!" ); + + ok( b.getParameter( new THREE.Vector2( -1, -1 ) ).equals( new THREE.Vector2( 0, 0 ) ), "Passed!" ); + ok( b.getParameter( new THREE.Vector2( 0, 0 ) ).equals( new THREE.Vector2( 0.5, 0.5 ) ), "Passed!" ); + ok( b.getParameter( new THREE.Vector2( 1, 1 ) ).equals( new THREE.Vector2( 1, 1 ) ), "Passed!" ); + }); + + test( "clampPoint", function() { + var a = new THREE.Box2( zero2.clone(), zero2.clone() ); + var b = new THREE.Box2( one2.clone().negate(), one2.clone() ); + + ok( a.clampPoint( new THREE.Vector2( 0, 0 ) ).equals( new THREE.Vector2( 0, 0 ) ), "Passed!" ); + ok( a.clampPoint( new THREE.Vector2( 1, 1 ) ).equals( new THREE.Vector2( 0, 0 ) ), "Passed!" ); + ok( a.clampPoint( new THREE.Vector2( -1, -1 ) ).equals( new THREE.Vector2( 0, 0 ) ), "Passed!" ); + + ok( b.clampPoint( new THREE.Vector2( 2, 2 ) ).equals( new THREE.Vector2( 1, 1 ) ), "Passed!" ); + ok( b.clampPoint( new THREE.Vector2( 1, 1 ) ).equals( new THREE.Vector2( 1, 1 ) ), "Passed!" ); + ok( b.clampPoint( new THREE.Vector2( 0, 0 ) ).equals( new THREE.Vector2( 0, 0 ) ), "Passed!" ); + ok( b.clampPoint( new THREE.Vector2( -1, -1 ) ).equals( new THREE.Vector2( -1, -1 ) ), "Passed!" ); + ok( b.clampPoint( new THREE.Vector2( -2, -2 ) ).equals( new THREE.Vector2( -1, -1 ) ), "Passed!" ); + }); + + test( "distanceToPoint", function() { + var a = new THREE.Box2( zero2.clone(), zero2.clone() ); + var b = new THREE.Box2( one2.clone().negate(), one2.clone() ); + + ok( a.distanceToPoint( new THREE.Vector2( 0, 0 ) ) == 0, "Passed!" ); + ok( a.distanceToPoint( new THREE.Vector2( 1, 1 ) ) == Math.sqrt( 2 ), "Passed!" ); + ok( a.distanceToPoint( new THREE.Vector2( -1, -1 ) ) == Math.sqrt( 2 ), "Passed!" ); + + ok( b.distanceToPoint( new THREE.Vector2( 2, 2 ) ) == Math.sqrt( 2 ), "Passed!" ); + ok( b.distanceToPoint( new THREE.Vector2( 1, 1 ) ) == 0, "Passed!" ); + ok( b.distanceToPoint( new THREE.Vector2( 0, 0 ) ) == 0, "Passed!" ); + ok( b.distanceToPoint( new THREE.Vector2( -1, -1 ) ) == 0, "Passed!" ); + ok( b.distanceToPoint( new THREE.Vector2( -2, -2 ) ) == Math.sqrt( 2 ), "Passed!" ); + }); + + test( "distanceToPoint", function() { + var a = new THREE.Box2( zero2.clone(), zero2.clone() ); + var b = new THREE.Box2( one2.clone().negate(), one2.clone() ); + + ok( a.distanceToPoint( new THREE.Vector2( 0, 0 ) ) == 0, "Passed!" ); + ok( a.distanceToPoint( new THREE.Vector2( 1, 1 ) ) == Math.sqrt( 2 ), "Passed!" ); + ok( a.distanceToPoint( new THREE.Vector2( -1, -1 ) ) == Math.sqrt( 2 ), "Passed!" ); + + ok( b.distanceToPoint( new THREE.Vector2( 2, 2 ) ) == Math.sqrt( 2 ), "Passed!" ); + ok( b.distanceToPoint( new THREE.Vector2( 1, 1 ) ) == 0, "Passed!" ); + ok( b.distanceToPoint( new THREE.Vector2( 0, 0 ) ) == 0, "Passed!" ); + ok( b.distanceToPoint( new THREE.Vector2( -1, -1 ) ) == 0, "Passed!" ); + ok( b.distanceToPoint( new THREE.Vector2( -2, -2 ) ) == Math.sqrt( 2 ), "Passed!" ); + }); + + test( "isIntersectionBox", function() { + var a = new THREE.Box2( zero2.clone(), zero2.clone() ); + var b = new THREE.Box2( zero2.clone(), one2.clone() ); + var c = new THREE.Box2( one2.clone().negate(), one2.clone() ); + + ok( a.isIntersectionBox( a ), "Passed!" ); + ok( a.isIntersectionBox( b ), "Passed!" ); + ok( a.isIntersectionBox( c ), "Passed!" ); + + ok( b.isIntersectionBox( a ), "Passed!" ); + ok( c.isIntersectionBox( a ), "Passed!" ); + ok( b.isIntersectionBox( c ), "Passed!" ); + + b.translate( new THREE.Vector2( 2, 2 ) ); + ok( ! a.isIntersectionBox( b ), "Passed!" ); + ok( ! b.isIntersectionBox( a ), "Passed!" ); + ok( ! b.isIntersectionBox( c ), "Passed!" ); + }); + + test( "intersect", function() { + var a = new THREE.Box2( zero2.clone(), zero2.clone() ); + var b = new THREE.Box2( zero2.clone(), one2.clone() ); + var c = new THREE.Box2( one2.clone().negate(), one2.clone() ); + + ok( a.clone().intersect( a ).equals( a ), "Passed!" ); + ok( a.clone().intersect( b ).equals( a ), "Passed!" ); + ok( b.clone().intersect( b ).equals( b ), "Passed!" ); + ok( a.clone().intersect( c ).equals( a ), "Passed!" ); + ok( b.clone().intersect( c ).equals( b ), "Passed!" ); + ok( c.clone().intersect( c ).equals( c ), "Passed!" ); + }); + + test( "union", function() { + var a = new THREE.Box2( zero2.clone(), zero2.clone() ); + var b = new THREE.Box2( zero2.clone(), one2.clone() ); + var c = new THREE.Box2( one2.clone().negate(), one2.clone() ); + + ok( a.clone().union( a ).equals( a ), "Passed!" ); + ok( a.clone().union( b ).equals( b ), "Passed!" ); + ok( a.clone().union( c ).equals( c ), "Passed!" ); + ok( b.clone().union( c ).equals( c ), "Passed!" ); + }); + + test( "translate", function() { + var a = new THREE.Box2( zero2.clone(), zero2.clone() ); + var b = new THREE.Box2( zero2.clone(), one2.clone() ); + var c = new THREE.Box2( one2.clone().negate(), one2.clone() ); + var d = new THREE.Box2( one2.clone().negate(), zero2.clone() ); + + ok( a.clone().translate( one2 ).equals( new THREE.Box2( one2, one2 ) ), "Passed!" ); + ok( a.clone().translate( one2 ).translate( one2.clone().negate() ).equals( a ), "Passed!" ); + ok( d.clone().translate( one2 ).equals( b ), "Passed!" ); + ok( b.clone().translate( one2.clone().negate() ).equals( d ), "Passed!" ); + }); + + test( "constructor", function() { + var a = new THREE.Box3(); + ok( a.min.equals( posInf3 ), "Passed!" ); + ok( a.max.equals( negInf3 ), "Passed!" ); + + a = new THREE.Box3( zero3.clone(), zero3.clone() ); + ok( a.min.equals( zero3 ), "Passed!" ); + ok( a.max.equals( zero3 ), "Passed!" ); + + a = new THREE.Box3( zero3.clone(), one3.clone() ); + ok( a.min.equals( zero3 ), "Passed!" ); + ok( a.max.equals( one3 ), "Passed!" ); + }); + + test( "copy", function() { + var a = new THREE.Box3( zero3.clone(), one3.clone() ); + var b = new THREE.Box3().copy( a ); + ok( b.min.equals( zero3 ), "Passed!" ); + ok( b.max.equals( one3 ), "Passed!" ); + + // ensure that it is a true copy + a.min = zero3; + a.max = one3; + ok( b.min.equals( zero3 ), "Passed!" ); + ok( b.max.equals( one3 ), "Passed!" ); + }); + + test( "set", function() { + var a = new THREE.Box3(); + + a.set( zero3, one3 ); + ok( a.min.equals( zero3 ), "Passed!" ); + ok( a.max.equals( one3 ), "Passed!" ); + }); + + test( "empty/makeEmpty", function() { + var a = new THREE.Box3(); + + ok( a.empty(), "Passed!" ); + + var a = new THREE.Box3( zero3.clone(), one3.clone() ); + ok( ! a.empty(), "Passed!" ); + + a.makeEmpty(); + ok( a.empty(), "Passed!" ); + }); + + test( "center", function() { + var a = new THREE.Box3( zero3.clone(), zero3.clone() ); + + ok( a.center().equals( zero3 ), "Passed!" ); + + a = new THREE.Box3( zero3.clone(), one3.clone() ); + var midpoint = one3.clone().multiplyScalar( 0.5 ); + ok( a.center().equals( midpoint ), "Passed!" ); + }); + + test( "size", function() { + var a = new THREE.Box3( zero3.clone(), zero3.clone() ); + + ok( a.size().equals( zero3 ), "Passed!" ); + + a = new THREE.Box3( zero3.clone(), one3.clone() ); + ok( a.size().equals( one3 ), "Passed!" ); + }); + + test( "expandByPoint", function() { + var a = new THREE.Box3( zero3.clone(), zero3.clone() ); + + a.expandByPoint( zero3 ); + ok( a.size().equals( zero3 ), "Passed!" ); + + a.expandByPoint( one3 ); + ok( a.size().equals( one3 ), "Passed!" ); + + a.expandByPoint( one3.clone().negate() ); + ok( a.size().equals( one3.clone().multiplyScalar( 2 ) ), "Passed!" ); + ok( a.center().equals( zero3 ), "Passed!" ); + }); + + test( "expandByVector", function() { + var a = new THREE.Box3( zero3.clone(), zero3.clone() ); + + a.expandByVector( zero3 ); + ok( a.size().equals( zero3 ), "Passed!" ); + + a.expandByVector( one3 ); + ok( a.size().equals( one3.clone().multiplyScalar( 2 ) ), "Passed!" ); + ok( a.center().equals( zero3 ), "Passed!" ); + }); + + test( "expandByScalar", function() { + var a = new THREE.Box3( zero3.clone(), zero3.clone() ); + + a.expandByScalar( 0 ); + ok( a.size().equals( zero3 ), "Passed!" ); + + a.expandByScalar( 1 ); + ok( a.size().equals( one3.clone().multiplyScalar( 2 ) ), "Passed!" ); + ok( a.center().equals( zero3 ), "Passed!" ); + }); + + test( "containsPoint", function() { + var a = new THREE.Box3( zero3.clone(), zero3.clone() ); + + ok( a.containsPoint( zero3 ), "Passed!" ); + ok( ! a.containsPoint( one3 ), "Passed!" ); + + a.expandByScalar( 1 ); + ok( a.containsPoint( zero3 ), "Passed!" ); + ok( a.containsPoint( one3 ), "Passed!" ); + ok( a.containsPoint( one3.clone().negate() ), "Passed!" ); + }); + + test( "containsBox", function() { + var a = new THREE.Box3( zero3.clone(), zero3.clone() ); + var b = new THREE.Box3( zero3.clone(), one3.clone() ); + var c = new THREE.Box3( one3.clone().negate(), one3.clone() ); + + ok( a.containsBox( a ), "Passed!" ); + ok( ! a.containsBox( b ), "Passed!" ); + ok( ! a.containsBox( c ), "Passed!" ); + + ok( b.containsBox( a ), "Passed!" ); + ok( c.containsBox( a ), "Passed!" ); + ok( ! b.containsBox( c ), "Passed!" ); + }); + + test( "getParameter", function() { + var a = new THREE.Box3( zero3.clone(), one3.clone() ); + var b = new THREE.Box3( one3.clone().negate(), one3.clone() ); + + ok( a.getParameter( new THREE.Vector3( 0, 0, 0 ) ).equals( new THREE.Vector3( 0, 0, 0 ) ), "Passed!" ); + ok( a.getParameter( new THREE.Vector3( 1, 1, 1 ) ).equals( new THREE.Vector3( 1, 1, 1 ) ), "Passed!" ); + + ok( b.getParameter( new THREE.Vector3( -1, -1, -1 ) ).equals( new THREE.Vector3( 0, 0, 0 ) ), "Passed!" ); + ok( b.getParameter( new THREE.Vector3( 0, 0, 0 ) ).equals( new THREE.Vector3( 0.5, 0.5, 0.5 ) ), "Passed!" ); + ok( b.getParameter( new THREE.Vector3( 1, 1, 1 ) ).equals( new THREE.Vector3( 1, 1, 1 ) ), "Passed!" ); + }); + + test( "clampPoint", function() { + var a = new THREE.Box3( zero3.clone(), zero3.clone() ); + var b = new THREE.Box3( one3.clone().negate(), one3.clone() ); + + ok( a.clampPoint( new THREE.Vector3( 0, 0, 0 ) ).equals( new THREE.Vector3( 0, 0, 0 ) ), "Passed!" ); + ok( a.clampPoint( new THREE.Vector3( 1, 1, 1 ) ).equals( new THREE.Vector3( 0, 0, 0 ) ), "Passed!" ); + ok( a.clampPoint( new THREE.Vector3( -1, -1, -1 ) ).equals( new THREE.Vector3( 0, 0, 0 ) ), "Passed!" ); + + ok( b.clampPoint( new THREE.Vector3( 2, 2, 2 ) ).equals( new THREE.Vector3( 1, 1, 1 ) ), "Passed!" ); + ok( b.clampPoint( new THREE.Vector3( 1, 1, 1 ) ).equals( new THREE.Vector3( 1, 1, 1 ) ), "Passed!" ); + ok( b.clampPoint( new THREE.Vector3( 0, 0, 0 ) ).equals( new THREE.Vector3( 0, 0, 0 ) ), "Passed!" ); + ok( b.clampPoint( new THREE.Vector3( -1, -1, -1 ) ).equals( new THREE.Vector3( -1, -1, -1 ) ), "Passed!" ); + ok( b.clampPoint( new THREE.Vector3( -2, -2, -2 ) ).equals( new THREE.Vector3( -1, -1, -1 ) ), "Passed!" ); + }); + + test( "distanceToPoint", function() { + var a = new THREE.Box3( zero3.clone(), zero3.clone() ); + var b = new THREE.Box3( one3.clone().negate(), one3.clone() ); + + ok( a.distanceToPoint( new THREE.Vector3( 0, 0, 0 ) ) == 0, "Passed!" ); + ok( a.distanceToPoint( new THREE.Vector3( 1, 1, 1 ) ) == Math.sqrt( 3 ), "Passed!" ); + ok( a.distanceToPoint( new THREE.Vector3( -1, -1, -1 ) ) == Math.sqrt( 3 ), "Passed!" ); + + ok( b.distanceToPoint( new THREE.Vector3( 2, 2, 2 ) ) == Math.sqrt( 3 ), "Passed!" ); + ok( b.distanceToPoint( new THREE.Vector3( 1, 1, 1 ) ) == 0, "Passed!" ); + ok( b.distanceToPoint( new THREE.Vector3( 0, 0, 0 ) ) == 0, "Passed!" ); + ok( b.distanceToPoint( new THREE.Vector3( -1, -1, -1 ) ) == 0, "Passed!" ); + ok( b.distanceToPoint( new THREE.Vector3( -2, -2, -2 ) ) == Math.sqrt( 3 ), "Passed!" ); + }); + + test( "distanceToPoint", function() { + var a = new THREE.Box3( zero3.clone(), zero3.clone() ); + var b = new THREE.Box3( one3.clone().negate(), one3.clone() ); + + ok( a.distanceToPoint( new THREE.Vector3( 0, 0, 0 ) ) == 0, "Passed!" ); + ok( a.distanceToPoint( new THREE.Vector3( 1, 1, 1 ) ) == Math.sqrt( 3 ), "Passed!" ); + ok( a.distanceToPoint( new THREE.Vector3( -1, -1, -1 ) ) == Math.sqrt( 3 ), "Passed!" ); + + ok( b.distanceToPoint( new THREE.Vector3( 2, 2, 2 ) ) == Math.sqrt( 3 ), "Passed!" ); + ok( b.distanceToPoint( new THREE.Vector3( 1, 1, 1 ) ) == 0, "Passed!" ); + ok( b.distanceToPoint( new THREE.Vector3( 0, 0, 0 ) ) == 0, "Passed!" ); + ok( b.distanceToPoint( new THREE.Vector3( -1, -1, -1 ) ) == 0, "Passed!" ); + ok( b.distanceToPoint( new THREE.Vector3( -2, -2, -2 ) ) == Math.sqrt( 3 ), "Passed!" ); + }); + + test( "isIntersectionBox", function() { + var a = new THREE.Box3( zero3.clone(), zero3.clone() ); + var b = new THREE.Box3( zero3.clone(), one3.clone() ); + var c = new THREE.Box3( one3.clone().negate(), one3.clone() ); + + ok( a.isIntersectionBox( a ), "Passed!" ); + ok( a.isIntersectionBox( b ), "Passed!" ); + ok( a.isIntersectionBox( c ), "Passed!" ); + + ok( b.isIntersectionBox( a ), "Passed!" ); + ok( c.isIntersectionBox( a ), "Passed!" ); + ok( b.isIntersectionBox( c ), "Passed!" ); + + b.translate( new THREE.Vector3( 2, 2, 2 ) ); + ok( ! a.isIntersectionBox( b ), "Passed!" ); + ok( ! b.isIntersectionBox( a ), "Passed!" ); + ok( ! b.isIntersectionBox( c ), "Passed!" ); + }); + + test( "getBoundingSphere", function() { + var a = new THREE.Box3( zero3.clone(), zero3.clone() ); + var b = new THREE.Box3( zero3.clone(), one3.clone() ); + var c = new THREE.Box3( one3.clone().negate(), one3.clone() ); + + ok( a.getBoundingSphere().equals( new THREE.Sphere( zero3, 0 ) ), "Passed!" ); + ok( b.getBoundingSphere().equals( new THREE.Sphere( one3.clone().multiplyScalar( 0.5 ), Math.sqrt( 3 ) * 0.5 ) ), "Passed!" ); + ok( c.getBoundingSphere().equals( new THREE.Sphere( zero3, Math.sqrt( 12 ) * 0.5 ) ), "Passed!" ); + }); + + test( "intersect", function() { + var a = new THREE.Box3( zero3.clone(), zero3.clone() ); + var b = new THREE.Box3( zero3.clone(), one3.clone() ); + var c = new THREE.Box3( one3.clone().negate(), one3.clone() ); + + ok( a.clone().intersect( a ).equals( a ), "Passed!" ); + ok( a.clone().intersect( b ).equals( a ), "Passed!" ); + ok( b.clone().intersect( b ).equals( b ), "Passed!" ); + ok( a.clone().intersect( c ).equals( a ), "Passed!" ); + ok( b.clone().intersect( c ).equals( b ), "Passed!" ); + ok( c.clone().intersect( c ).equals( c ), "Passed!" ); + }); + + test( "union", function() { + var a = new THREE.Box3( zero3.clone(), zero3.clone() ); + var b = new THREE.Box3( zero3.clone(), one3.clone() ); + var c = new THREE.Box3( one3.clone().negate(), one3.clone() ); + + ok( a.clone().union( a ).equals( a ), "Passed!" ); + ok( a.clone().union( b ).equals( b ), "Passed!" ); + ok( a.clone().union( c ).equals( c ), "Passed!" ); + ok( b.clone().union( c ).equals( c ), "Passed!" ); + }); + + var compareBox = function ( a, b, threshold? ) { + threshold = threshold || 0.0001; + return ( a.min.distanceTo( b.min ) < threshold && + a.max.distanceTo( b.max ) < threshold ); + }; + + test( "applyMatrix4", function() { + var a = new THREE.Box3( zero3.clone(), zero3.clone() ); + var b = new THREE.Box3( zero3.clone(), one3.clone() ); + var c = new THREE.Box3( one3.clone().negate(), one3.clone() ); + var d = new THREE.Box3( one3.clone().negate(), zero3.clone() ); + + var m = new THREE.Matrix4().makeTranslation( 1, -2, 1 ); + var t1 = new THREE.Vector3( 1, -2, 1 ); + + ok( compareBox( a.clone().applyMatrix4( m ), a.clone().translate( t1 ) ), "Passed!" ); + ok( compareBox( b.clone().applyMatrix4( m ), b.clone().translate( t1 ) ), "Passed!" ); + ok( compareBox( c.clone().applyMatrix4( m ), c.clone().translate( t1 ) ), "Passed!" ); + ok( compareBox( d.clone().applyMatrix4( m ), d.clone().translate( t1 ) ), "Passed!" ); + }); + + test( "translate", function() { + var a = new THREE.Box3( zero3.clone(), zero3.clone() ); + var b = new THREE.Box3( zero3.clone(), one3.clone() ); + var c = new THREE.Box3( one3.clone().negate(), one3.clone() ); + var d = new THREE.Box3( one3.clone().negate(), zero3.clone() ); + + ok( a.clone().translate( one3 ).equals( new THREE.Box3( one3, one3 ) ), "Passed!" ); + ok( a.clone().translate( one3 ).translate( one3.clone().negate() ).equals( a ), "Passed!" ); + ok( d.clone().translate( one3 ).equals( b ), "Passed!" ); + ok( b.clone().translate( one3.clone().negate() ).equals( d ), "Passed!" ); + }); + + test( "constructor", function(){ + var c = new THREE.Color(); + ok( c.r, "Red: " + c.r ); + ok( c.g, "Green: " + c.g ); + ok( c.b, "Blue: " + c.g ); + }); + + test( "copyHex", function(){ + var c = new THREE.Color(); + var c2 = new THREE.Color(0xF5FFFA); + c.copy(c2); + ok(c.getHex() == c2.getHex(), "Hex c: " + c.getHex() + " Hex c2: " + c2.getHex()); + }); + + test( "copyColorString", function(){ + var c = new THREE.Color(); + var c2 = new THREE.Color('ivory'); + c.copy(c2); + ok(c.getHex() == c2.getHex(), "Hex c: " + c.getHex() + " Hex c2: " + c2.getHex()); + }); + + test( "setRGB", function(){ + var c = new THREE.Color() + c.setRGB(255, 2, 1); + ok( c.r == 255, "Red: " + c.r ); + ok( c.g == 2, "Green: " + c.g ); + ok( c.b == 1, "Blue: " + c.b ); + }); + + test( "copyGammaToLinear", function(){ + var c = new THREE.Color(); + var c2 = new THREE.Color(); + c2.setRGB(2, 4, 8) + c.copyGammaToLinear(c2) + ok( c.r == 4, "Red c: " + c.r + " Red c2: " + c2.r); + ok( c.g == 16, "Green c: " + c.g + " Green c2: " + c2.g); + ok( c.b == 64, "Blue c: " + c.b + " Blue c2: " + c2.b); + }); + + test( "copyLinearToGamma", function(){ + var c = new THREE.Color(); + var c2 = new THREE.Color(); + c2.setRGB(4, 9, 16) + c.copyLinearToGamma(c2) + ok( c.r == 2, "Red c: " + c.r + " Red c2: " + c2.r); + ok( c.g == 3, "Green c: " + c.g + " Green c2: " + c2.g); + ok( c.b == 4, "Blue c: " + c.b + " Blue c2: " + c2.b); + }); + + + test( "convertGammaToLinear", function(){ + var c = new THREE.Color(); + c.setRGB(2, 4, 8) + c.convertGammaToLinear() + ok( c.r == 4, "Red: " + c.r ); + ok( c.g == 16, "Green: " + c.g ); + ok( c.b == 64, "Blue: " + c.b ); + }); + + + test( "convertLinearToGamma", function(){ + var c = new THREE.Color(); + c.setRGB(4, 9, 16) + c.convertLinearToGamma() + ok( c.r == 2, "Red: " + c.r ); + ok( c.g == 3, "Green: " + c.g ); + ok( c.b == 4, "Blue: " + c.b ); + }); + + test("setWithNum", function(){ + var c = new THREE.Color(); + c.set(0xFF0000); + ok( c.r == 1, "Red: " + c.r ); + ok( c.g == 0, "Green: " + c.g ); + ok( c.b == 0, "Blue: " + c.b ); + }); + + + test( "setWithString", function(){ + var c = new THREE.Color(); + c.set('silver'); + ok(c.getHex() == 0xC0C0C0, "Hex c: " + c.getHex()); + }); + + + test( "clone", function(){ + var c = new THREE.Color('teal'); + var c2 = c.clone(); + ok(c2.getHex() == 0x008080, "Hex c2: " + c2.getHex()); + }); + + test( "lerp", function(){ + var c = new THREE.Color(); + var c2 = new THREE.Color(); + c.setRGB(0, 0, 0); + c.lerp(c2, 2); + ok( c.r == 2, "Red: " + c.r ); + ok( c.g == 2, "Green: " + c.g ); + ok( c.b == 2, "Blue: " + c.b ); + + }); + + + test( "setStyleRGBRed", function(){ + var c = new THREE.Color(); + c.setStyle('rgb(255,0,0)'); + ok( c.r == 1, "Red: " + c.r ); + ok( c.g == 0, "Green: " + c.g ); + ok( c.b == 0, "Blue: " + c.b ); + }); + + test( "setStyleRGBPercent", function(){ + var c = new THREE.Color(); + c.setStyle('rgb(100%,50%,10%)'); + ok( c.r == 1, "Red: " + c.r ); + ok( c.g == 0.5, "Green: " + c.g ); + ok( c.b == 0.1, "Blue: " + c.b ); + }); + + test( "setStyleHexSkyBlue", function(){ + var c = new THREE.Color(); + c.setStyle('#87CEEB'); + ok(c.getHex() == 0x87CEEB, "Hex c: " + c.getHex()); + }); + + test( "setStyleHex2Olive", function(){ + var c = new THREE.Color(); + c.setStyle('#F00'); + ok(c.getHex() == 0xFF0000, "Hex c: " + c.getHex()); + }); + + test( "setStyleColorName", function(){ + var c = new THREE.Color(); + c.setStyle('powderblue'); + ok(c.getHex() == 0xB0E0E6, "Hex c: " + c.getHex()); + }); + + + test( "getHex", function(){ + var c = new THREE.Color('red'); + var res = c.getHex(); + ok( res == 0xFF0000, "Hex: " + res ); + }); + + test( "setHex", function(){ + var c = new THREE.Color(); + c.setHex(0xFA8072); + ok( c.getHex() == 0xFA8072, "Hex: " + c.getHex()); + }); + + test( "getHexString", function(){ + var c = new THREE.Color('tomato'); + var res = c.getHexString(); + ok( res == 'ff6347', "Hex: " + res ); + }); + + test( "getStyle", function(){ + var c = new THREE.Color('plum'); + var res = c.getStyle(); + ok( res == 'rgb(221,160,221)', "style: " + res ); + }); + + test( "getHSL", function () { + var c = new THREE.Color( 0x80ffff ); + var hsl = c.getHSL(); + + ok( hsl.h == 0.5, "hue: " + hsl.h ); + ok( hsl.s == 1.0, "saturation: " + hsl.s ); + + + //ok( (Math.round(parseFloat(hsl.l)*100)/100) == 0.75, "lightness: " + hsl.l ); + ok( (Math.round(hsl.l*100)/100) == 0.75, "lightness: " + hsl.l ); + }); + + test( "setHSL", function () { + var c = new THREE.Color(); + c.setHSL(0.75, 1.0, 0.25); + var hsl = c.getHSL(); + + ok( hsl.h == 0.75, "hue: " + hsl.h ); + ok( hsl.s == 1.00, "saturation: " + hsl.s ); + ok( hsl.l == 0.25, "lightness: " + hsl.l ); + }); + + var unit3 = new THREE.Vector3( 1, 0, 0 ); + + var planeEquals = function ( a, b, tolerance ) { + tolerance = tolerance || 0.0001; + if( a.normal.distanceTo( b.normal ) > tolerance ) { + return false; + } + if( Math.abs( a.constant - b.constant ) > tolerance ) { + return false; + } + return true; + }; + + test( "constructor", function() { + var a = new THREE.Frustum(); + + ok( a.planes !== undefined, "Passed!" ); + ok( a.planes.length === 6, "Passed!" ); + + var pDefault = new THREE.Plane(); + for( var i = 0; i < 6; i ++ ) { + ok( a.planes[i].equals( pDefault ), "Passed!" ); + } + + var p0 = new THREE.Plane( unit3, -1 ); + var p1 = new THREE.Plane( unit3, 1 ); + var p2 = new THREE.Plane( unit3, 2 ); + var p3 = new THREE.Plane( unit3, 3 ); + var p4 = new THREE.Plane( unit3, 4 ); + var p5 = new THREE.Plane( unit3, 5 ); + + a = new THREE.Frustum( p0, p1, p2, p3, p4, p5 ); + ok( a.planes[0].equals( p0 ), "Passed!" ); + ok( a.planes[1].equals( p1 ), "Passed!" ); + ok( a.planes[2].equals( p2 ), "Passed!" ); + ok( a.planes[3].equals( p3 ), "Passed!" ); + ok( a.planes[4].equals( p4 ), "Passed!" ); + ok( a.planes[5].equals( p5 ), "Passed!" ); + }); + + test( "copy", function() { + + var p0 = new THREE.Plane( unit3, -1 ); + var p1 = new THREE.Plane( unit3, 1 ); + var p2 = new THREE.Plane( unit3, 2 ); + var p3 = new THREE.Plane( unit3, 3 ); + var p4 = new THREE.Plane( unit3, 4 ); + var p5 = new THREE.Plane( unit3, 5 ); + + var b = new THREE.Frustum( p0, p1, p2, p3, p4, p5 ); + var a = new THREE.Frustum().copy( b ); + ok( a.planes[0].equals( p0 ), "Passed!" ); + ok( a.planes[1].equals( p1 ), "Passed!" ); + ok( a.planes[2].equals( p2 ), "Passed!" ); + ok( a.planes[3].equals( p3 ), "Passed!" ); + ok( a.planes[4].equals( p4 ), "Passed!" ); + ok( a.planes[5].equals( p5 ), "Passed!" ); + + // ensure it is a true copy by modifying source + b.planes[0] = p1; + ok( a.planes[0].equals( p0 ), "Passed!" ); + }); + + test( "setFromMatrix/makeOrthographic/containsPoint", function() { + var m = new THREE.Matrix4().makeOrthographic( -1, 1, -1, 1, 1, 100 ) + var a = new THREE.Frustum().setFromMatrix( m ); + + ok( ! a.containsPoint( new THREE.Vector3( 0, 0, 0 ) ), "Passed!" ); + ok( a.containsPoint( new THREE.Vector3( 0, 0, -50 ) ), "Passed!" ); + ok( a.containsPoint( new THREE.Vector3( 0, 0, -1.001 ) ), "Passed!" ); + ok( a.containsPoint( new THREE.Vector3( -1, -1, -1.001 ) ), "Passed!" ); + ok( ! a.containsPoint( new THREE.Vector3( -1.1, -1.1, -1.001 ) ), "Passed!" ); + ok( a.containsPoint( new THREE.Vector3( 1, 1, -1.001 ) ), "Passed!" ); + ok( ! a.containsPoint( new THREE.Vector3( 1.1, 1.1, -1.001 ) ), "Passed!" ); + ok( a.containsPoint( new THREE.Vector3( 0, 0, -100 ) ), "Passed!" ); + ok( a.containsPoint( new THREE.Vector3( -1, -1, -100 ) ), "Passed!" ); + ok( ! a.containsPoint( new THREE.Vector3( -1.1, -1.1, -100.1 ) ), "Passed!" ); + ok( a.containsPoint( new THREE.Vector3( 1, 1, -100 ) ), "Passed!" ); + ok( ! a.containsPoint( new THREE.Vector3( 1.1, 1.1, -100.1 ) ), "Passed!" ); + ok( ! a.containsPoint( new THREE.Vector3( 0, 0, -101 ) ), "Passed!" ); + + }); + + test( "setFromMatrix/makeFrustum/containsPoint", function() { + var m = new THREE.Matrix4().makeFrustum( -1, 1, -1, 1, 1, 100 ) + var a = new THREE.Frustum().setFromMatrix( m ); + + ok( ! a.containsPoint( new THREE.Vector3( 0, 0, 0 ) ), "Passed!" ); + ok( a.containsPoint( new THREE.Vector3( 0, 0, -50 ) ), "Passed!" ); + ok( a.containsPoint( new THREE.Vector3( 0, 0, -1.001 ) ), "Passed!" ); + ok( a.containsPoint( new THREE.Vector3( -1, -1, -1.001 ) ), "Passed!" ); + ok( ! a.containsPoint( new THREE.Vector3( -1.1, -1.1, -1.001 ) ), "Passed!" ); + ok( a.containsPoint( new THREE.Vector3( 1, 1, -1.001 ) ), "Passed!" ); + ok( ! a.containsPoint( new THREE.Vector3( 1.1, 1.1, -1.001 ) ), "Passed!" ); + ok( a.containsPoint( new THREE.Vector3( 0, 0, -99.999 ) ), "Passed!" ); + ok( a.containsPoint( new THREE.Vector3( -99.999, -99.999, -99.999 ) ), "Passed!" ); + ok( ! a.containsPoint( new THREE.Vector3( -100.1, -100.1, -100.1 ) ), "Passed!" ); + ok( a.containsPoint( new THREE.Vector3( 99.999, 99.999, -99.999 ) ), "Passed!" ); + ok( ! a.containsPoint( new THREE.Vector3( 100.1, 100.1, -100.1 ) ), "Passed!" ); + ok( ! a.containsPoint( new THREE.Vector3( 0, 0, -101 ) ), "Passed!" ); + }); + + test( "setFromMatrix/makeFrustum/intersectsSphere", function() { + var m = new THREE.Matrix4().makeFrustum( -1, 1, -1, 1, 1, 100 ) + var a = new THREE.Frustum().setFromMatrix( m ); + + ok( ! a.intersectsSphere( new THREE.Sphere( new THREE.Vector3( 0, 0, 0 ), 0 ) ), "Passed!" ); + ok( ! a.intersectsSphere( new THREE.Sphere( new THREE.Vector3( 0, 0, 0 ), 0.9 ) ), "Passed!" ); + ok( a.intersectsSphere( new THREE.Sphere( new THREE.Vector3( 0, 0, 0 ), 1.1 ) ), "Passed!" ); + ok( a.intersectsSphere( new THREE.Sphere( new THREE.Vector3( 0, 0, -50 ), 0 ) ), "Passed!" ); + ok( a.intersectsSphere( new THREE.Sphere( new THREE.Vector3( 0, 0, -1.001 ), 0 ) ), "Passed!" ); + ok( a.intersectsSphere( new THREE.Sphere( new THREE.Vector3( -1, -1, -1.001 ), 0 ) ), "Passed!" ); + ok( ! a.intersectsSphere( new THREE.Sphere( new THREE.Vector3( -1.1, -1.1, -1.001 ), 0 ) ), "Passed!" ); + ok( a.intersectsSphere( new THREE.Sphere( new THREE.Vector3( -1.1, -1.1, -1.001 ), 0.5 ) ), "Passed!" ); + ok( a.intersectsSphere( new THREE.Sphere( new THREE.Vector3( 1, 1, -1.001 ), 0 ) ), "Passed!" ); + ok( ! a.intersectsSphere( new THREE.Sphere( new THREE.Vector3( 1.1, 1.1, -1.001 ), 0 ) ), "Passed!" ); + ok( a.intersectsSphere( new THREE.Sphere( new THREE.Vector3( 1.1, 1.1, -1.001 ), 0.5 ) ), "Passed!" ); + ok( a.intersectsSphere( new THREE.Sphere( new THREE.Vector3( 0, 0, -99.999 ), 0 ) ), "Passed!" ); + ok( a.intersectsSphere( new THREE.Sphere( new THREE.Vector3( -99.999, -99.999, -99.999 ), 0 ) ), "Passed!" ); + ok( ! a.intersectsSphere( new THREE.Sphere( new THREE.Vector3( -100.1, -100.1, -100.1 ), 0 ) ), "Passed!" ); + ok( a.intersectsSphere( new THREE.Sphere( new THREE.Vector3( -100.1, -100.1, -100.1 ), 0.5 ) ), "Passed!" ); + ok( a.intersectsSphere( new THREE.Sphere( new THREE.Vector3( 99.999, 99.999, -99.999 ), 0 ) ), "Passed!" ); + ok( ! a.intersectsSphere( new THREE.Sphere( new THREE.Vector3( 100.1, 100.1, -100.1 ), 0 ) ), "Passed!" ); + ok( a.intersectsSphere( new THREE.Sphere( new THREE.Vector3( 100.1, 100.1, -100.1 ), 0.2 ) ), "Passed!" ); + ok( ! a.intersectsSphere( new THREE.Sphere( new THREE.Vector3( 0, 0, -101 ), 0 ) ), "Passed!" ); + ok( a.intersectsSphere( new THREE.Sphere( new THREE.Vector3( 0, 0, -101 ), 1.1 ) ), "Passed!" ); + }); + + test( "clone", function() { + + var p0 = new THREE.Plane( unit3, -1 ); + var p1 = new THREE.Plane( unit3, 1 ); + var p2 = new THREE.Plane( unit3, 2 ); + var p3 = new THREE.Plane( unit3, 3 ); + var p4 = new THREE.Plane( unit3, 4 ); + var p5 = new THREE.Plane( unit3, 5 ); + + var b = new THREE.Frustum( p0, p1, p2, p3, p4, p5 ); + var a = b.clone(); + ok( a.planes[0].equals( p0 ), "Passed!" ); + ok( a.planes[1].equals( p1 ), "Passed!" ); + ok( a.planes[2].equals( p2 ), "Passed!" ); + ok( a.planes[3].equals( p3 ), "Passed!" ); + ok( a.planes[4].equals( p4 ), "Passed!" ); + ok( a.planes[5].equals( p5 ), "Passed!" ); + + // ensure it is a true copy by modifying source + a.planes[0].copy( p1 ); + ok( b.planes[0].equals( p0 ), "Passed!" ); + }); + + + test( "constructor/equals", function() { + var a = new THREE.Line3(); + ok( a.start.equals( zero3 ), "Passed!" ); + ok( a.end.equals( zero3 ), "Passed!" ); + + a = new THREE.Line3( two3.clone(), one3.clone() ); + ok( a.start.equals( two3 ), "Passed!" ); + ok( a.end.equals( one3 ), "Passed!" ); + }); + + test( "copy/equals", function() { + var a = new THREE.Line3( zero3.clone(), one3.clone() ); + var b = new THREE.Line3().copy( a ); + ok( b.start.equals( zero3 ), "Passed!" ); + ok( b.end.equals( one3 ), "Passed!" ); + + // ensure that it is a true copy + a.start = zero3; + a.end = one3; + ok( b.start.equals( zero3 ), "Passed!" ); + ok( b.end.equals( one3 ), "Passed!" ); + }); + + test( "set", function() { + var a = new THREE.Line3(); + + a.set( one3, one3 ); + ok( a.start.equals( one3 ), "Passed!" ); + ok( a.end.equals( one3 ), "Passed!" ); + }); + + test( "at", function() { + var a = new THREE.Line3( one3.clone(), new THREE.Vector3( 1, 1, 2 ) ); + + ok( a.at( -1 ).distanceTo( new THREE.Vector3( 1, 1, 0 ) ) < 0.0001, "Passed!" ); + ok( a.at( 0 ).distanceTo( one3.clone() ) < 0.0001, "Passed!" ); + ok( a.at( 1 ).distanceTo( new THREE.Vector3( 1, 1, 2 ) ) < 0.0001, "Passed!" ); + ok( a.at( 2 ).distanceTo( new THREE.Vector3( 1, 1, 3 ) ) < 0.0001, "Passed!" ); + }); + + test( "closestPointToPoint/closestPointToPointParameter", function() { + var a = new THREE.Line3( one3.clone(), new THREE.Vector3( 1, 1, 2 ) ); + + // nearby the ray + ok( a.closestPointToPointParameter( zero3.clone(), true ) == 0, "Passed!" ); + var b1 = a.closestPointToPoint( zero3.clone(), true ); + ok( b1.distanceTo( new THREE.Vector3( 1, 1, 1 ) ) < 0.0001, "Passed!" ); + + // nearby the ray + ok( a.closestPointToPointParameter( zero3.clone(), false ) == -1, "Passed!" ); + var b2 = a.closestPointToPoint( zero3.clone(), false ); + console.log( b2 ); + ok( b2.distanceTo( new THREE.Vector3( 1, 1, 0 ) ) < 0.0001, "Passed!" ); + + // nearby the ray + ok( a.closestPointToPointParameter( new THREE.Vector3( 1, 1, 5 ), true ) == 1, "Passed!" ); + var b = a.closestPointToPoint( new THREE.Vector3( 1, 1, 5 ), true ); + ok( b.distanceTo( new THREE.Vector3( 1, 1, 2 ) ) < 0.0001, "Passed!" ); + + // exactly on the ray + ok( a.closestPointToPointParameter( one3.clone(), true ) == 0, "Passed!" ); + var c = a.closestPointToPoint( one3.clone(), true ); + ok( c.distanceTo( one3.clone() ) < 0.0001, "Passed!" ); + }); + + + + var matrixEquals3 = function( a, b, tolerance? ) { + tolerance = tolerance || 0.0001; + if( a.elements.length != b.elements.length ) { + return false; + } + for( var i = 0, il = a.elements.length; i < il; i ++ ) { + var delta = a.elements[i] - b.elements[i]; + if( delta > tolerance ) { + return false; + } + } + return true; + }; + + + var toMatrix4 = function( m3 ) { + var result = new THREE.Matrix4(); + var re = result.elements; + var me = m3.elements; + re[0] = me[0]; + re[1] = me[1]; + re[2] = me[2]; + re[4] = me[3]; + re[5] = me[4]; + re[6] = me[5]; + re[8] = me[6]; + re[9] = me[7]; + re[10] = me[8]; + + return result; + }; + + test( "constructor", function() { + var a = new THREE.Matrix3(); + ok( a.determinant() == 1, "Passed!" ); + + var b = new THREE.Matrix3( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); + ok( b.elements[0] == 0 ); + ok( b.elements[1] == 3 ); + ok( b.elements[2] == 6 ); + ok( b.elements[3] == 1 ); + ok( b.elements[4] == 4 ); + ok( b.elements[5] == 7 ); + ok( b.elements[6] == 2 ); + ok( b.elements[7] == 5 ); + ok( b.elements[8] == 8 ); + + ok( ! matrixEquals3( a, b ), "Passed!" ); + }); + + test( "copy", function() { + var a = new THREE.Matrix3( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); + var b = new THREE.Matrix3().copy( a ); + + ok( matrixEquals3( a, b ), "Passed!" ); + + // ensure that it is a true copy + a.elements[0] = 2; + ok( ! matrixEquals3( a, b ), "Passed!" ); + }); + + test( "set", function() { + var b = new THREE.Matrix3(); + ok( b.determinant() == 1, "Passed!" ); + + b.set( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); + ok( b.elements[0] == 0 ); + ok( b.elements[1] == 3 ); + ok( b.elements[2] == 6 ); + ok( b.elements[3] == 1 ); + ok( b.elements[4] == 4 ); + ok( b.elements[5] == 7 ); + ok( b.elements[6] == 2 ); + ok( b.elements[7] == 5 ); + ok( b.elements[8] == 8 ); + }); + + test( "identity", function() { + var b = new THREE.Matrix3( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); + ok( b.elements[0] == 0 ); + ok( b.elements[1] == 3 ); + ok( b.elements[2] == 6 ); + ok( b.elements[3] == 1 ); + ok( b.elements[4] == 4 ); + ok( b.elements[5] == 7 ); + ok( b.elements[6] == 2 ); + ok( b.elements[7] == 5 ); + ok( b.elements[8] == 8 ); + + var a = new THREE.Matrix3(); + ok( ! matrixEquals3( a, b ), "Passed!" ); + + b.identity(); + ok( matrixEquals3( a, b ), "Passed!" ); + }); + + test( "multiplyScalar", function() { + var b = new THREE.Matrix3( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); + ok( b.elements[0] == 0 ); + ok( b.elements[1] == 3 ); + ok( b.elements[2] == 6 ); + ok( b.elements[3] == 1 ); + ok( b.elements[4] == 4 ); + ok( b.elements[5] == 7 ); + ok( b.elements[6] == 2 ); + ok( b.elements[7] == 5 ); + ok( b.elements[8] == 8 ); + + b.multiplyScalar( 2 ); + ok( b.elements[0] == 0*2 ); + ok( b.elements[1] == 3*2 ); + ok( b.elements[2] == 6*2 ); + ok( b.elements[3] == 1*2 ); + ok( b.elements[4] == 4*2 ); + ok( b.elements[5] == 7*2 ); + ok( b.elements[6] == 2*2 ); + ok( b.elements[7] == 5*2 ); + ok( b.elements[8] == 8*2 ); + }); + + test( "determinant", function() { + var a = new THREE.Matrix3(); + ok( a.determinant() == 1, "Passed!" ); + + a.elements[0] = 2; + ok( a.determinant() == 2, "Passed!" ); + + a.elements[0] = 0; + ok( a.determinant() == 0, "Passed!" ); + + // calculated via http://www.euclideanspace.com/maths/algebra/matrix/functions/determinant/threeD/index.htm + a.set( 2, 3, 4, 5, 13, 7, 8, 9, 11 ); + ok( a.determinant() == -73, "Passed!" ); + }); + + + test( "getInverse", function() { + var identity = new THREE.Matrix4(); + var a = new THREE.Matrix4(); + var b = new THREE.Matrix3( 0, 0, 0, 0, 0, 0, 0, 0, 0 ); + + //var c = new THREE.Matrix4( 0, 0, 0, 0, 0, 0, 0, 0, 0 ); + var c = new THREE.Matrix4( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ); + + ok( ! matrixEquals3( a, b ), "Passed!" ); + b.getInverse( a, false ); + ok( matrixEquals3( b, new THREE.Matrix3() ), "Passed!" ); + + try { + b.getInverse( c, true ); + ok( false, "Passed!" ); // should never get here. + } + catch( err ) { + ok( true, "Passed!" ); + } + + var testMatrices = [ + new THREE.Matrix4().makeRotationX( 0.3 ), + new THREE.Matrix4().makeRotationX( -0.3 ), + new THREE.Matrix4().makeRotationY( 0.3 ), + new THREE.Matrix4().makeRotationY( -0.3 ), + new THREE.Matrix4().makeRotationZ( 0.3 ), + new THREE.Matrix4().makeRotationZ( -0.3 ), + new THREE.Matrix4().makeScale( 1, 2, 3 ), + new THREE.Matrix4().makeScale( 1/8, 1/2, 1/3 ) + ]; + + for( var i = 0, il = testMatrices.length; i < il; i ++ ) { + var m = testMatrices[i]; + var mInverse3 = new THREE.Matrix3().getInverse( m ); + + var mInverse = toMatrix4( mInverse3 ); + + // the determinant of the inverse should be the reciprocal + ok( Math.abs( m.determinant() * mInverse3.determinant() - 1 ) < 0.0001, "Passed!" ); + ok( Math.abs( m.determinant() * mInverse.determinant() - 1 ) < 0.0001, "Passed!" ); + + var mProduct = new THREE.Matrix4().multiplyMatrices( m, mInverse ); + ok( Math.abs( mProduct.determinant() - 1 ) < 0.0001, "Passed!" ); + ok( matrixEquals3( mProduct, identity ), "Passed!" ); + } + }); + + test( "transpose", function() { + var a = new THREE.Matrix3(); + var b = a.clone().transpose(); + ok( matrixEquals3( a, b ), "Passed!" ); + + b = new THREE.Matrix3( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); + var c = b.clone().transpose(); + ok( ! matrixEquals3( b, c ), "Passed!" ); + c.transpose(); + ok( matrixEquals3( b, c ), "Passed!" ); + }); + + test( "clone", function() { + var a = new THREE.Matrix3( 0, 1, 2, 3, 4, 5, 6, 7, 8 ); + var b = a.clone(); + + ok( matrixEquals3( a, b ), "Passed!" ); + + // ensure that it is a true copy + a.elements[0] = 2; + ok( ! matrixEquals3( a, b ), "Passed!" ); + }); + + var matrixEquals4 = function( a, b, tolerance? ) { + tolerance = tolerance || 0.0001; + if( a.elements.length != b.elements.length ) { + return false; + } + for( var i = 0, il = a.elements.length; i < il; i ++ ) { + var delta = a.elements[i] - b.elements[i]; + if( delta > tolerance ) { + return false; + } + } + return true; + }; + + test( "constructor", function() { + var a = new THREE.Matrix4(); + ok( a.determinant() == 1, "Passed!" ); + + var b = new THREE.Matrix4( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); + ok( b.elements[0] == 0 ); + ok( b.elements[1] == 4 ); + ok( b.elements[2] == 8 ); + ok( b.elements[3] == 12 ); + ok( b.elements[4] == 1 ); + ok( b.elements[5] == 5 ); + ok( b.elements[6] == 9 ); + ok( b.elements[7] == 13 ); + ok( b.elements[8] == 2 ); + ok( b.elements[9] == 6 ); + ok( b.elements[10] == 10 ); + ok( b.elements[11] == 14 ); + ok( b.elements[12] == 3 ); + ok( b.elements[13] == 7 ); + ok( b.elements[14] == 11 ); + ok( b.elements[15] == 15 ); + + ok( ! matrixEquals4( a, b ), "Passed!" ); + }); + + test( "copy", function() { + var a = new THREE.Matrix4( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); + var b = new THREE.Matrix4().copy( a ); + + ok( matrixEquals4( a, b ), "Passed!" ); + + // ensure that it is a true copy + a.elements[0] = 2; + ok( ! matrixEquals4( a, b ), "Passed!" ); + }); + + test( "set", function() { + var b = new THREE.Matrix4(); + ok( b.determinant() == 1, "Passed!" ); + + b.set( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); + ok( b.elements[0] == 0 ); + ok( b.elements[1] == 4 ); + ok( b.elements[2] == 8 ); + ok( b.elements[3] == 12 ); + ok( b.elements[4] == 1 ); + ok( b.elements[5] == 5 ); + ok( b.elements[6] == 9 ); + ok( b.elements[7] == 13 ); + ok( b.elements[8] == 2 ); + ok( b.elements[9] == 6 ); + ok( b.elements[10] == 10 ); + ok( b.elements[11] == 14 ); + ok( b.elements[12] == 3 ); + ok( b.elements[13] == 7 ); + ok( b.elements[14] == 11 ); + ok( b.elements[15] == 15 ); + }); + + test( "identity", function() { + var b = new THREE.Matrix4( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); + ok( b.elements[0] == 0 ); + ok( b.elements[1] == 4 ); + ok( b.elements[2] == 8 ); + ok( b.elements[3] == 12 ); + ok( b.elements[4] == 1 ); + ok( b.elements[5] == 5 ); + ok( b.elements[6] == 9 ); + ok( b.elements[7] == 13 ); + ok( b.elements[8] == 2 ); + ok( b.elements[9] == 6 ); + ok( b.elements[10] == 10 ); + ok( b.elements[11] == 14 ); + ok( b.elements[12] == 3 ); + ok( b.elements[13] == 7 ); + ok( b.elements[14] == 11 ); + ok( b.elements[15] == 15 ); + + var a = new THREE.Matrix4(); + ok( ! matrixEquals4( a, b ), "Passed!" ); + + b.identity(); + ok( matrixEquals4( a, b ), "Passed!" ); + }); + + test( "multiplyScalar", function() { + var b = new THREE.Matrix4( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); + ok( b.elements[0] == 0 ); + ok( b.elements[1] == 4 ); + ok( b.elements[2] == 8 ); + ok( b.elements[3] == 12 ); + ok( b.elements[4] == 1 ); + ok( b.elements[5] == 5 ); + ok( b.elements[6] == 9 ); + ok( b.elements[7] == 13 ); + ok( b.elements[8] == 2 ); + ok( b.elements[9] == 6 ); + ok( b.elements[10] == 10 ); + ok( b.elements[11] == 14 ); + ok( b.elements[12] == 3 ); + ok( b.elements[13] == 7 ); + ok( b.elements[14] == 11 ); + ok( b.elements[15] == 15 ); + + b.multiplyScalar( 2 ); + ok( b.elements[0] == 0*2 ); + ok( b.elements[1] == 4*2 ); + ok( b.elements[2] == 8*2 ); + ok( b.elements[3] == 12*2 ); + ok( b.elements[4] == 1*2 ); + ok( b.elements[5] == 5*2 ); + ok( b.elements[6] == 9*2 ); + ok( b.elements[7] == 13*2 ); + ok( b.elements[8] == 2*2 ); + ok( b.elements[9] == 6*2 ); + ok( b.elements[10] == 10*2 ); + ok( b.elements[11] == 14*2 ); + ok( b.elements[12] == 3*2 ); + ok( b.elements[13] == 7*2 ); + ok( b.elements[14] == 11*2 ); + ok( b.elements[15] == 15*2 ); + }); + + test( "determinant", function() { + var a = new THREE.Matrix4(); + ok( a.determinant() == 1, "Passed!" ); + + a.elements[0] = 2; + ok( a.determinant() == 2, "Passed!" ); + + a.elements[0] = 0; + ok( a.determinant() == 0, "Passed!" ); + + // calculated via http://www.euclideanspace.com/maths/algebra/matrix/functions/determinant/fourD/index.htm + a.set( 2, 3, 4, 5, -1, -21, -3, -4, 6, 7, 8, 10, -8, -9, -10, -12 ); + ok( a.determinant() == 76, "Passed!" ); + }); + + test( "getInverse", function() { + var identity = new THREE.Matrix4(); + + var a = new THREE.Matrix4(); + var b = new THREE.Matrix4( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ); + var c = new THREE.Matrix4( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ); + + ok( ! matrixEquals4( a, b ), "Passed!" ); + b.getInverse( a, false ); + ok( matrixEquals4( b, new THREE.Matrix4() ), "Passed!" ); + + try { + b.getInverse( c, true ); + ok( false, "Passed!" ); // should never get here. + } + catch( err ) { + ok( true, "Passed!" ); + } + + var testMatrices = [ + new THREE.Matrix4().makeRotationX( 0.3 ), + new THREE.Matrix4().makeRotationX( -0.3 ), + new THREE.Matrix4().makeRotationY( 0.3 ), + new THREE.Matrix4().makeRotationY( -0.3 ), + new THREE.Matrix4().makeRotationZ( 0.3 ), + new THREE.Matrix4().makeRotationZ( -0.3 ), + new THREE.Matrix4().makeScale( 1, 2, 3 ), + new THREE.Matrix4().makeScale( 1/8, 1/2, 1/3 ), + new THREE.Matrix4().makeFrustum( -1, 1, -1, 1, 1, 1000 ), + new THREE.Matrix4().makeFrustum( -16, 16, -9, 9, 0.1, 10000 ), + new THREE.Matrix4().makeTranslation( 1, 2, 3 ) + ]; + + for( var i = 0, il = testMatrices.length; i < il; i ++ ) { + var m = testMatrices[i]; + + var mInverse = new THREE.Matrix4().getInverse( m ); + + // the determinant of the inverse should be the reciprocal + ok( Math.abs( m.determinant() * mInverse.determinant() - 1 ) < 0.0001, "Passed!" ); + + var mProduct = new THREE.Matrix4().multiplyMatrices( m, mInverse ); + + // the determinant of the identity matrix is 1 + ok( Math.abs( mProduct.determinant() - 1 ) < 0.0001, "Passed!" ); + ok( matrixEquals4( mProduct, identity ), "Passed!" ); + } + }); + + test( "transpose", function() { + var a = new THREE.Matrix4(); + var b = a.clone().transpose(); + ok( matrixEquals4( a, b ), "Passed!" ); + + b = new THREE.Matrix4( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); + var c = b.clone().transpose(); + ok( ! matrixEquals4( b, c ), "Passed!" ); + c.transpose(); + ok( matrixEquals4( b, c ), "Passed!" ); + }); + + test( "clone", function() { + var a = new THREE.Matrix4( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ); + var b = a.clone(); + + ok( matrixEquals4( a, b ), "Passed!" ); + + // ensure that it is a true copy + a.elements[0] = 2; + ok( ! matrixEquals4( a, b ), "Passed!" ); + }); + + + var comparePlane = function ( a, b, threshold? ) { + threshold = threshold || 0.0001; + return ( a.normal.distanceTo( b.normal ) < threshold && + Math.abs( a.constant - b.constant ) < threshold ); + }; + + + test( "constructor", function() { + var a = new THREE.Plane(); + ok( a.normal.x == 1, "Passed!" ); + ok( a.normal.y == 0, "Passed!" ); + ok( a.normal.z == 0, "Passed!" ); + ok( a.constant == 0, "Passed!" ); + + a = new THREE.Plane( one3.clone(), 0 ); + ok( a.normal.x == 1, "Passed!" ); + ok( a.normal.y == 1, "Passed!" ); + ok( a.normal.z == 1, "Passed!" ); + ok( a.constant == 0, "Passed!" ); + + a = new THREE.Plane( one3.clone(), 1 ); + ok( a.normal.x == 1, "Passed!" ); + ok( a.normal.y == 1, "Passed!" ); + ok( a.normal.z == 1, "Passed!" ); + ok( a.constant == 1, "Passed!" ); + }); + + test( "copy", function() { + var a = new THREE.Plane( new THREE.Vector3( x, y, z ), w ); + var b = new THREE.Plane().copy( a ); + ok( b.normal.x == x, "Passed!" ); + ok( b.normal.y == y, "Passed!" ); + ok( b.normal.z == z, "Passed!" ); + ok( b.constant == w, "Passed!" ); + + // ensure that it is a true copy + a.normal.x = 0; + a.normal.y = -1; + a.normal.z = -2; + a.constant = -3; + ok( b.normal.x == x, "Passed!" ); + ok( b.normal.y == y, "Passed!" ); + ok( b.normal.z == z, "Passed!" ); + ok( b.constant == w, "Passed!" ); + }); + + test( "set", function() { + var a = new THREE.Plane(); + ok( a.normal.x == 1, "Passed!" ); + ok( a.normal.y == 0, "Passed!" ); + ok( a.normal.z == 0, "Passed!" ); + ok( a.constant == 0, "Passed!" ); + + var b = a.clone().set( new THREE.Vector3( x, y, z ), w ); + ok( b.normal.x == x, "Passed!" ); + ok( b.normal.y == y, "Passed!" ); + ok( b.normal.z == z, "Passed!" ); + ok( b.constant == w, "Passed!" ); + }); + + test( "setComponents", function() { + var a = new THREE.Plane(); + ok( a.normal.x == 1, "Passed!" ); + ok( a.normal.y == 0, "Passed!" ); + ok( a.normal.z == 0, "Passed!" ); + ok( a.constant == 0, "Passed!" ); + + var b = a.clone().setComponents( x, y, z , w ); + ok( b.normal.x == x, "Passed!" ); + ok( b.normal.y == y, "Passed!" ); + ok( b.normal.z == z, "Passed!" ); + ok( b.constant == w, "Passed!" ); + }); + + test( "setFromNormalAndCoplanarPoint", function() { + var normal = one3.clone().normalize(); + var a = new THREE.Plane().setFromNormalAndCoplanarPoint( normal, zero3 ); + + ok( a.normal.equals( normal ), "Passed!" ); + ok( a.constant == 0, "Passed!" ); + }); + + test( "normalize", function() { + var a = new THREE.Plane( new THREE.Vector3( 2, 0, 0 ), 2 ); + + a.normalize(); + ok( a.normal.length() == 1, "Passed!" ); + ok( a.normal.equals( new THREE.Vector3( 1, 0, 0 ) ), "Passed!" ); + ok( a.constant == 1, "Passed!" ); + }); + + test( "negate/distanceToPoint", function() { + var a = new THREE.Plane( new THREE.Vector3( 2, 0, 0 ), -2 ); + + a.normalize(); + ok( a.distanceToPoint( new THREE.Vector3( 4, 0, 0 ) ) === 3, "Passed!" ); + ok( a.distanceToPoint( new THREE.Vector3( 1, 0, 0 ) ) === 0, "Passed!" ); + + a.negate(); + ok( a.distanceToPoint( new THREE.Vector3( 4, 0, 0 ) ) === -3, "Passed!" ); + ok( a.distanceToPoint( new THREE.Vector3( 1, 0, 0 ) ) === 0, "Passed!" ); + }); + + test( "distanceToPoint", function() { + var a = new THREE.Plane( new THREE.Vector3( 2, 0, 0 ), -2 ); + + a.normalize(); + ok( a.distanceToPoint( a.projectPoint( zero3.clone() ) ) === 0, "Passed!" ); + ok( a.distanceToPoint( new THREE.Vector3( 4, 0, 0 ) ) === 3, "Passed!" ); + }); + + test( "distanceToSphere", function() { + var a = new THREE.Plane( new THREE.Vector3( 1, 0, 0 ), 0 ); + + var b = new THREE.Sphere( new THREE.Vector3( 2, 0, 0 ), 1 ); + + ok( a.distanceToSphere( b ) === 1, "Passed!" ); + + a.set( new THREE.Vector3( 1, 0, 0 ), 2 ); + ok( a.distanceToSphere( b ) === 3, "Passed!" ); + a.set( new THREE.Vector3( 1, 0, 0 ), -2 ); + ok( a.distanceToSphere( b ) === -1, "Passed!" ); + }); + + test( "isInterestionLine/intersectLine", function() { + var a = new THREE.Plane( new THREE.Vector3( 1, 0, 0 ), 0 ); + + var l1 = new THREE.Line3( new THREE.Vector3( -10, 0, 0 ), new THREE.Vector3( 10, 0, 0 ) ); + ok( a.isIntersectionLine( l1 ), "Passed!" ); + ok( a.intersectLine( l1 ).equals( new THREE.Vector3( 0, 0, 0 ) ), "Passed!" ); + + a = new THREE.Plane( new THREE.Vector3( 1, 0, 0 ), -3 ); + + ok( a.isIntersectionLine( l1 ), "Passed!" ); + ok( a.intersectLine( l1 ).equals( new THREE.Vector3( 3, 0, 0 ) ), "Passed!" ); + + + a = new THREE.Plane( new THREE.Vector3( 1, 0, 0 ), -11 ); + + ok( ! a.isIntersectionLine( l1 ), "Passed!" ); + ok( a.intersectLine( l1 ) === undefined, "Passed!" ); + + a = new THREE.Plane( new THREE.Vector3( 1, 0, 0 ), 11 ); + + ok( ! a.isIntersectionLine( l1 ), "Passed!" ); + ok( a.intersectLine( l1 ) === undefined, "Passed!" ); + + }); + + test( "projectPoint", function() { + var a = new THREE.Plane( new THREE.Vector3( 1, 0, 0 ), 0 ); + + ok( a.projectPoint( new THREE.Vector3( 10, 0, 0 ) ).equals( zero3 ), "Passed!" ); + ok( a.projectPoint( new THREE.Vector3( -10, 0, 0 ) ).equals( zero3 ), "Passed!" ); + + a = new THREE.Plane( new THREE.Vector3( 0, 1, 0 ), -1 ); + ok( a.projectPoint( new THREE.Vector3( 0, 0, 0 ) ).equals( new THREE.Vector3( 0, 1, 0 ) ), "Passed!" ); + ok( a.projectPoint( new THREE.Vector3( 0, 1, 0 ) ).equals( new THREE.Vector3( 0, 1, 0 ) ), "Passed!" ); + + }); + + test( "orthoPoint", function() { + var a = new THREE.Plane( new THREE.Vector3( 1, 0, 0 ), 0 ); + + ok( a.orthoPoint( new THREE.Vector3( 10, 0, 0 ) ).equals( new THREE.Vector3( 10, 0, 0 ) ), "Passed!" ); + ok( a.orthoPoint( new THREE.Vector3( -10, 0, 0 ) ).equals( new THREE.Vector3( -10, 0, 0 ) ), "Passed!" ); + }); + + test( "coplanarPoint", function() { + var a = new THREE.Plane( new THREE.Vector3( 1, 0, 0 ), 0 ); + ok( a.distanceToPoint( a.coplanarPoint() ) === 0, "Passed!" ); + + a = new THREE.Plane( new THREE.Vector3( 0, 1, 0 ), -1 ); + ok( a.distanceToPoint( a.coplanarPoint() ) === 0, "Passed!" ); + }); + + test( "applyMatrix4/translate", function() { + + var a = new THREE.Plane( new THREE.Vector3( 1, 0, 0 ), 0 ); + + var m = new THREE.Matrix4(); + m.makeRotationZ( Math.PI * 0.5 ); + + ok( comparePlane( a.clone().applyMatrix4( m ), new THREE.Plane( new THREE.Vector3( 0, 1, 0 ), 0 ) ), "Passed!" ); + + a = new THREE.Plane( new THREE.Vector3( 0, 1, 0 ), -1 ); + ok( comparePlane( a.clone().applyMatrix4( m ), new THREE.Plane( new THREE.Vector3( -1, 0, 0 ), -1 ) ), "Passed!" ); + + m.makeTranslation( 1, 1, 1 ); + ok( comparePlane( a.clone().applyMatrix4( m ), a.clone().translate( new THREE.Vector3( 1, 1, 1 ) ) ), "Passed!" ); + }); + + var orders = [ 'XYZ', 'YXZ', 'ZXY', 'ZYX', 'YZX', 'XZY' ]; + var eulerAngles = new THREE.Vector3( 0.1, -0.3, 0.25 ); + + + + var qSub = function ( a, b ) { + var result = new THREE.Quaternion(); + result.copy( a ); + + result.x -= b.x; + result.y -= b.y; + result.z -= b.z; + result.w -= b.w; + + return result; + + }; + + test( "constructor", function() { + var a = new THREE.Quaternion(); + ok( a.x == 0, "Passed!" ); + ok( a.y == 0, "Passed!" ); + ok( a.z == 0, "Passed!" ); + ok( a.w == 1, "Passed!" ); + + a = new THREE.Quaternion( x, y, z, w ); + ok( a.x === x, "Passed!" ); + ok( a.y === y, "Passed!" ); + ok( a.z === z, "Passed!" ); + ok( a.w === w, "Passed!" ); + }); + + test( "copy", function() { + var a = new THREE.Quaternion( x, y, z, w ); + var b = new THREE.Quaternion().copy( a ); + ok( b.x == x, "Passed!" ); + ok( b.y == y, "Passed!" ); + ok( b.z == z, "Passed!" ); + ok( b.w == w, "Passed!" ); + + // ensure that it is a true copy + a.x = 0; + a.y = -1; + a.z = 0; + a.w = -1; + ok( b.x == x, "Passed!" ); + ok( b.y == y, "Passed!" ); + }); + + test( "set", function() { + var a = new THREE.Quaternion(); + ok( a.x == 0, "Passed!" ); + ok( a.y == 0, "Passed!" ); + ok( a.z == 0, "Passed!" ); + ok( a.w == 1, "Passed!" ); + + a.set( x, y, z, w ); + ok( a.x == x, "Passed!" ); + ok( a.y == y, "Passed!" ); + ok( a.z === z, "Passed!" ); + ok( a.w === w, "Passed!" ); + }); + + test( "setFromAxisAngle", function() { + + // TODO: find cases to validate. + ok( true, "Passed!" ); + + var zero = new THREE.Quaternion(); + + var a = new THREE.Quaternion().setFromAxisAngle( new THREE.Vector3( 1, 0, 0 ), 0 ); + ok( a.equals( zero ), "Passed!" ); + a = new THREE.Quaternion().setFromAxisAngle( new THREE.Vector3( 0, 1, 0 ), 0 ); + ok( a.equals( zero ), "Passed!" ); + a = new THREE.Quaternion().setFromAxisAngle( new THREE.Vector3( 0, 0, 1 ), 0 ); + ok( a.equals( zero ), "Passed!" ); + + var b1 = new THREE.Quaternion().setFromAxisAngle( new THREE.Vector3( 1, 0, 0 ), Math.PI ); + ok( ! a.equals( b1 ), "Passed!" ); + var b2 = new THREE.Quaternion().setFromAxisAngle( new THREE.Vector3( 1, 0, 0 ), -Math.PI ); + ok( ! a.equals( b2 ), "Passed!" ); + + b1.multiply( b2 ); + ok( a.equals( b1 ), "Passed!" ); + }); + + + test( "setFromEuler/setEulerFromQuaternion", function() { + + var angles = [ new THREE.Vector3( 1, 0, 0 ), new THREE.Vector3( 0, 1, 0 ), new THREE.Vector3( 0, 0, 1 ) ]; + + // ensure euler conversion to/from Quaternion matches. + for( var i = 0; i < orders.length; i ++ ) { + for( var j = 0; j < angles.length; j ++ ) { + var eulers2 = new THREE.Vector3().setEulerFromQuaternion( new THREE.Quaternion().setFromEuler( angles[j], orders[i] ), orders[i] ); + + ok( eulers2.distanceTo( angles[j] ) < 0.001, "Passed!" ); + } + } + + }); + + test( "setFromEuler/setFromRotationMatrix", function() { + + // ensure euler conversion for Quaternion matches that of Matrix4 + for( var i = 0; i < orders.length; i ++ ) { + var q = new THREE.Quaternion().setFromEuler( eulerAngles, orders[i] ); + var m = new THREE.Matrix4().setRotationFromEuler( eulerAngles, orders[i] ); + var q2 = new THREE.Quaternion().setFromRotationMatrix( m ); + + ok( qSub( q, q2 ).length() < 0.001, "Passed!" ); + } + + }); + + test( "normalize/length/lengthSq", function() { + var a = new THREE.Quaternion( x, y, z, w ); + var b = new THREE.Quaternion( -x, -y, -z, -w ); + + ok( a.length() != 1, "Passed!"); + ok( a.lengthSq() != 1, "Passed!"); + a.normalize(); + ok( a.length() == 1, "Passed!"); + ok( a.lengthSq() == 1, "Passed!"); + + a.set( 0, 0, 0, 0 ); + ok( a.lengthSq() == 0, "Passed!"); + ok( a.length() == 0, "Passed!"); + a.normalize(); + ok( a.lengthSq() == 1, "Passed!"); + ok( a.length() == 1, "Passed!"); + }); + + test( "inverse/conjugate", function() { + var a = new THREE.Quaternion( x, y, z, w ); + + // TODO: add better validation here. + + var b = a.clone().conjugate(); + + ok( a.x == -b.x, "Passed!" ); + ok( a.y == -b.y, "Passed!" ); + ok( a.z == -b.z, "Passed!" ); + ok( a.w == b.w, "Passed!" ); + }); + + + test( "multiplyQuaternions/multiply", function() { + + var angles = [ new THREE.Vector3( 1, 0, 0 ), new THREE.Vector3( 0, 1, 0 ), new THREE.Vector3( 0, 0, 1 ) ]; + + var q1 = new THREE.Quaternion().setFromEuler( angles[0], "XYZ" ); + var q2 = new THREE.Quaternion().setFromEuler( angles[1], "XYZ" ); + var q3 = new THREE.Quaternion().setFromEuler( angles[2], "XYZ" ); + + var q = new THREE.Quaternion().multiplyQuaternions( q1, q2 ).multiply( q3 ); + + var m1 = new THREE.Matrix4().setRotationFromEuler( angles[0], "XYZ" ); + var m2 = new THREE.Matrix4().setRotationFromEuler( angles[1], "XYZ" ); + var m3 = new THREE.Matrix4().setRotationFromEuler( angles[2], "XYZ" ); + + var m = new THREE.Matrix4().multiplyMatrices( m1, m2 ).multiply( m3 ); + + var qFromM = new THREE.Quaternion().setFromRotationMatrix( m ); + + ok( qSub( q, qFromM ).length() < 0.001, "Passed!" ); + }); + + test( "multiplyVector3", function() { + + var angles = [ new THREE.Vector3( 1, 0, 0 ), new THREE.Vector3( 0, 1, 0 ), new THREE.Vector3( 0, 0, 1 ) ]; + + // ensure euler conversion for Quaternion matches that of Matrix4 + for( var i = 0; i < orders.length; i ++ ) { + for( var j = 0; j < angles.length; j ++ ) { + var q = new THREE.Quaternion().setFromEuler( angles[j], orders[i] ); + var m = new THREE.Matrix4().setRotationFromEuler( angles[j], orders[i] ); + + var v0 = new THREE.Vector3(1, 0, 0); + var qv = v0.clone().applyQuaternion( q ); + var mv = v0.clone().applyMatrix4( m ); + + ok( qv.distanceTo( mv ) < 0.001, "Passed!" ); + } + } + + }); + + test( "equals", function() { + var a = new THREE.Quaternion( x, y, z, w ); + var b = new THREE.Quaternion( -x, -y, -z, -w ); + + ok( a.x != b.x, "Passed!" ); + ok( a.y != b.y, "Passed!" ); + + ok( ! a.equals( b ), "Passed!" ); + ok( ! b.equals( a ), "Passed!" ); + + a.copy( b ); + ok( a.x == b.x, "Passed!" ); + ok( a.y == b.y, "Passed!" ); + + ok( a.equals( b ), "Passed!" ); + ok( b.equals( a ), "Passed!" ); + }); + + + test( "constructor/equals", function() { + var a = new THREE.Ray(); + ok( a.origin.equals( zero3 ), "Passed!" ); + ok( a.direction.equals( zero3 ), "Passed!" ); + + a = new THREE.Ray( two3.clone(), one3.clone() ); + ok( a.origin.equals( two3 ), "Passed!" ); + ok( a.direction.equals( one3 ), "Passed!" ); + }); + + test( "copy/equals", function() { + var a = new THREE.Ray( zero3.clone(), one3.clone() ); + var b = new THREE.Ray().copy( a ); + ok( b.origin.equals( zero3 ), "Passed!" ); + ok( b.direction.equals( one3 ), "Passed!" ); + + // ensure that it is a true copy + a.origin = zero3; + a.direction = one3; + ok( b.origin.equals( zero3 ), "Passed!" ); + ok( b.direction.equals( one3 ), "Passed!" ); + }); + + test( "set", function() { + var a = new THREE.Ray(); + + a.set( one3, one3 ); + ok( a.origin.equals( one3 ), "Passed!" ); + ok( a.direction.equals( one3 ), "Passed!" ); + }); + + test( "at", function() { + var a = new THREE.Ray( one3.clone(), new THREE.Vector3( 0, 0, 1 ) ); + + ok( a.at( 0 ).equals( one3 ), "Passed!" ); + ok( a.at( -1 ).equals( new THREE.Vector3( 1, 1, 0 ) ), "Passed!" ); + ok( a.at( 1 ).equals( new THREE.Vector3( 1, 1, 2 ) ), "Passed!" ); + }); + + test( "recast/clone", function() { + var a = new THREE.Ray( one3.clone(), new THREE.Vector3( 0, 0, 1 ) ); + + ok( a.recast( 0 ).equals( a ), "Passed!" ); + + var b = a.clone(); + ok( b.recast( -1 ).equals( new THREE.Ray( new THREE.Vector3( 1, 1, 0 ), new THREE.Vector3( 0, 0, 1 ) ) ), "Passed!" ); + + var c = a.clone(); + ok( c.recast( 1 ).equals( new THREE.Ray( new THREE.Vector3( 1, 1, 2 ), new THREE.Vector3( 0, 0, 1 ) ) ), "Passed!" ); + + var d = a.clone(); + var e = d.clone().recast( 1 ); + ok( d.equals( a ), "Passed!" ); + ok( ! e.equals( d ), "Passed!" ); + ok( e.equals( c ), "Passed!" ); + }); + + test( "closestPointToPoint", function() { + var a = new THREE.Ray( one3.clone(), new THREE.Vector3( 0, 0, 1 ) ); + + // nearby the ray + var b = a.closestPointToPoint( zero3 ); + ok( b.equals( new THREE.Vector3( 1, 1, 0 ) ), "Passed!" ); + + // exactly on the ray + var c = a.closestPointToPoint( one3 ); + ok( c.equals( one3 ), "Passed!" ); + }); + + test( "distanceToPoint", function() { + var a = new THREE.Ray( one3.clone(), new THREE.Vector3( 0, 0, 1 ) ); + + // nearby the ray + var b = a.distanceToPoint( zero3 ); + ok( b == Math.sqrt( 2 ), "Passed!" ); + + // exactly on the ray + var c = a.distanceToPoint( one3 ); + ok( c == 0, "Passed!" ); + }); + + test( "isIntersectionSphere", function() { + var a = new THREE.Ray( one3.clone(), new THREE.Vector3( 0, 0, 1 ) ); + var b = new THREE.Sphere( zero3, 0.5 ); + var c = new THREE.Sphere( zero3, 1.5 ); + var d = new THREE.Sphere( one3, 0.1 ); + var e = new THREE.Sphere( two3, 0.1 ); + var f = new THREE.Sphere( two3, 1 ); + + ok( ! a.isIntersectionSphere( b ), "Passed!" ); + ok( a.isIntersectionSphere( c ), "Passed!" ); + ok( a.isIntersectionSphere( d ), "Passed!" ); + ok( ! a.isIntersectionSphere( e ), "Passed!" ); + ok( ! a.isIntersectionSphere( f ), "Passed!" ); + }); + + test( "isIntersectionPlane", function() { + var a = new THREE.Ray( one3.clone(), new THREE.Vector3( 0, 0, 1 ) ); + + // parallel plane behind + var b = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3( 0, 0, 1 ), one3.clone().sub( new THREE.Vector3( 0, 0, -1 ) ) ); + ok( a.isIntersectionPlane( b ), "Passed!" ); + + // parallel plane coincident with origin + var c = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3( 0, 0, 1 ), one3.clone().sub( new THREE.Vector3( 0, 0, 0 ) ) ); + ok( a.isIntersectionPlane( c ), "Passed!" ); + + // parallel plane infront + var d = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3( 0, 0, 1 ), one3.clone().sub( new THREE.Vector3( 0, 0, 1 ) ) ); + ok( a.isIntersectionPlane( d ), "Passed!" ); + + // perpendical ray that overlaps exactly + var e = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3( 1, 0, 0 ), one3 ); + ok( a.isIntersectionPlane( e ), "Passed!" ); + + // perpendical ray that doesn't overlap + var f = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3( 1, 0, 0 ), zero3 ); + ok( ! a.isIntersectionPlane( f ), "Passed!" ); + }); + + test( "intersectPlane", function() { + var a = new THREE.Ray( one3.clone(), new THREE.Vector3( 0, 0, 1 ) ); + + // parallel plane behind + var b = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3( 0, 0, 1 ), new THREE.Vector3( 1, 1, -1 ) ); + ok( a.intersectPlane( b ).equals( new THREE.Vector3( 1, 1, -1 ) ), "Passed!" ); + + // parallel plane coincident with origin + var c = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3( 0, 0, 1 ), new THREE.Vector3( 1, 1, 0 ) ); + ok( a.intersectPlane( c ).equals( new THREE.Vector3( 1, 1, 0 ) ), "Passed!" ); + + // parallel plane infront + var d = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3( 0, 0, 1 ), new THREE.Vector3( 1, 1, 1 ) ); + ok( a.intersectPlane( d ).equals( new THREE.Vector3( 1, 1, 1 ) ), "Passed!" ); + + // perpendical ray that overlaps exactly + var e = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3( 1, 0, 0 ), one3 ); + ok( a.intersectPlane( e ).equals( a.origin ), "Passed!" ); + + // perpendical ray that doesn't overlap + var f = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3( 1, 0, 0 ), zero3 ); + ok( a.intersectPlane( f ) === undefined, "Passed!" ); + }); + + + test( "applyMatrix4", function() { + var a = new THREE.Ray( one3.clone(), new THREE.Vector3( 0, 0, 1 ) ); + var m = new THREE.Matrix4().identity(); + + ok( a.clone().applyMatrix4( m ).equals( a ), "Passed!" ); + + a = new THREE.Ray( zero3.clone(), new THREE.Vector3( 0, 0, 1 ) ); + m.rotateByAxis( new THREE.Vector3( 0, 0, 1 ), Math.PI ); + ok( a.clone().applyMatrix4( m ).equals( a ), "Passed!" ); + + m.identity().rotateX( Math.PI ); + var b = a.clone(); + b.direction.negate(); + var a2 = a.clone().applyMatrix4( m ); + ok( a2.origin.distanceTo( b.origin ) < 0.0001, "Passed!" ); + ok( a2.direction.distanceTo( b.direction ) < 0.0001, "Passed!" ); + + a.origin = new THREE.Vector3( 0, 0, 1 ); + b.origin = new THREE.Vector3( 0, 0, -1 ); + var a2 = a.clone().applyMatrix4( m ); + ok( a2.origin.distanceTo( b.origin ) < 0.0001, "Passed!" ); + ok( a2.direction.distanceTo( b.direction ) < 0.0001, "Passed!" ); + }); + + + test( "constructor", function() { + var a = new THREE.Sphere(); + ok( a.center.equals( zero3 ), "Passed!" ); + ok( a.radius == 0, "Passed!" ); + + a = new THREE.Sphere( one3.clone(), 1 ); + ok( a.center.equals( one3 ), "Passed!" ); + ok( a.radius == 1, "Passed!" ); + }); + + test( "copy", function() { + var a = new THREE.Sphere( one3.clone(), 1 ); + var b = new THREE.Sphere().copy( a ); + + ok( b.center.equals( one3 ), "Passed!" ); + ok( b.radius == 1, "Passed!" ); + + // ensure that it is a true copy + a.center = zero3; + a.radius = 0; + ok( b.center.equals( one3 ), "Passed!" ); + ok( b.radius == 1, "Passed!" ); + }); + + test( "set", function() { + var a = new THREE.Sphere(); + ok( a.center.equals( zero3 ), "Passed!" ); + ok( a.radius == 0, "Passed!" ); + + a.set( one3, 1 ); + ok( a.center.equals( one3 ), "Passed!" ); + ok( a.radius == 1, "Passed!" ); + }); + + test( "empty", function() { + var a = new THREE.Sphere(); + ok( a.empty(), "Passed!" ); + + a.set( one3, 1 ); + ok( ! a.empty(), "Passed!" ); + }); + + test( "containsPoint", function() { + var a = new THREE.Sphere( one3.clone(), 1 ); + + ok( ! a.containsPoint( zero3 ), "Passed!" ); + ok( a.containsPoint( one3 ), "Passed!" ); + }); + + test( "distanceToPoint", function() { + var a = new THREE.Sphere( one3.clone(), 1 ); + + ok( ( a.distanceToPoint( zero3 ) - 0.7320 ) < 0.001, "Passed!" ); + ok( a.distanceToPoint( one3 ) === -1, "Passed!" ); + }); + + test( "intersectsSphere", function() { + var a = new THREE.Sphere( one3.clone(), 1 ); + var b = new THREE.Sphere( zero3.clone(), 1 ); + var c = new THREE.Sphere( zero3.clone(), 0.25 ); + + ok( a.intersectsSphere( b ) , "Passed!" ); + ok( ! a.intersectsSphere( c ) , "Passed!" ); + }); + + test( "clampPoint", function() { + var a = new THREE.Sphere( one3.clone(), 1 ); + + ok( a.clampPoint( new THREE.Vector3( 1, 1, 3 ) ).equals( new THREE.Vector3( 1, 1, 2 ) ), "Passed!" ); + ok( a.clampPoint( new THREE.Vector3( 1, 1, -3 ) ).equals( new THREE.Vector3( 1, 1, 0 ) ), "Passed!" ); + }); + + test( "getBoundingBox", function() { + var a = new THREE.Sphere( one3.clone(), 1 ); + + ok( a.getBoundingBox().equals( new THREE.Box3( zero3, two3 ) ), "Passed!" ); + + a.set( zero3, 0 ) + ok( a.getBoundingBox().equals( new THREE.Box3( zero3, zero3 ) ), "Passed!" ); + }); + + test( "applyMatrix4", function() { + var a = new THREE.Sphere( one3.clone(), 1 ); + + var m = new THREE.Matrix4().makeTranslation( 1, -2, 1 ); + + ok( a.clone().applyMatrix4( m ).getBoundingBox().equals( a.getBoundingBox().applyMatrix4( m ) ), "Passed!" ); + }); + + test( "translate", function() { + var a = new THREE.Sphere( one3.clone(), 1 ); + + a.translate( one3.clone().negate() ); + ok( a.center.equals( zero3 ), "Passed!" ); + }); + + test( "constructor", function() { + var a = new THREE.Triangle(); + ok( a.a.equals( zero3 ), "Passed!" ); + ok( a.b.equals( zero3 ), "Passed!" ); + ok( a.c.equals( zero3 ), "Passed!" ); + + a = new THREE.Triangle( one3.clone().negate(), one3.clone(), two3.clone() ); + ok( a.a.equals( one3.clone().negate() ), "Passed!" ); + ok( a.b.equals( one3 ), "Passed!" ); + ok( a.c.equals( two3 ), "Passed!" ); + }); + + test( "copy", function() { + var a = new THREE.Triangle( one3.clone().negate(), one3.clone(), two3.clone() ); + var b = new THREE.Triangle().copy( a ); + ok( b.a.equals( one3.clone().negate() ), "Passed!" ); + ok( b.b.equals( one3 ), "Passed!" ); + ok( b.c.equals( two3 ), "Passed!" ); + + // ensure that it is a true copy + a.a = one3; + a.b = zero3; + a.c = zero3; + ok( b.a.equals( one3.clone().negate() ), "Passed!" ); + ok( b.b.equals( one3 ), "Passed!" ); + ok( b.c.equals( two3 ), "Passed!" ); + }); + + test( "setFromPointsAndIndices", function() { + var a = new THREE.Triangle(); + + var points = [ one3, one3.clone().negate(), two3 ]; + a.setFromPointsAndIndices( points, 1, 0, 2 ); + ok( a.a.equals( one3.clone().negate() ), "Passed!" ); + ok( a.b.equals( one3 ), "Passed!" ); + ok( a.c.equals( two3 ), "Passed!" ); + + }); + + test( "set", function() { + var a = new THREE.Triangle(); + + a.set( one3.clone().negate(), one3, two3 ); + ok( a.a.equals( one3.clone().negate() ), "Passed!" ); + ok( a.b.equals( one3 ), "Passed!" ); + ok( a.c.equals( two3 ), "Passed!" ); + + }); + + test( "area", function() { + var a = new THREE.Triangle(); + + ok( a.area() == 0, "Passed!" ); + + a = new THREE.Triangle( new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 1, 0, 0 ), new THREE.Vector3( 0, 1, 0 ) ); + ok( a.area() == 0.5, "Passed!" ); + + a = new THREE.Triangle( new THREE.Vector3( 2, 0, 0 ), new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 0, 0, 2 ) ); + ok( a.area() == 2, "Passed!" ); + + // colinear triangle. + a = new THREE.Triangle( new THREE.Vector3( 2, 0, 0 ), new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 3, 0, 0 ) ); + ok( a.area() == 0, "Passed!" ); + }); + + test( "midpoint", function() { + var a = new THREE.Triangle(); + + ok( a.midpoint().equals( new THREE.Vector3( 0, 0, 0 ) ), "Passed!" ); + + a = new THREE.Triangle( new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 1, 0, 0 ), new THREE.Vector3( 0, 1, 0 ) ); + ok( a.midpoint().equals( new THREE.Vector3( 1/3, 1/3, 0 ) ), "Passed!" ); + + a = new THREE.Triangle( new THREE.Vector3( 2, 0, 0 ), new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 0, 0, 2 ) ); + ok( a.midpoint().equals( new THREE.Vector3( 2/3, 0, 2/3 ) ), "Passed!" ); + }); + + test( "normal", function() { + var a = new THREE.Triangle(); + + ok( a.normal().equals( new THREE.Vector3( 0, 0, 0 ) ), "Passed!" ); + + a = new THREE.Triangle( new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 1, 0, 0 ), new THREE.Vector3( 0, 1, 0 ) ); + ok( a.normal().equals( new THREE.Vector3( 0, 0, 1 ) ), "Passed!" ); + + a = new THREE.Triangle( new THREE.Vector3( 2, 0, 0 ), new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 0, 0, 2 ) ); + ok( a.normal().equals( new THREE.Vector3( 0, 1, 0 ) ), "Passed!" ); + }); + + test( "plane", function() { + var a = new THREE.Triangle(); + + // artificial normal is created in this case. + ok( a.plane().distanceToPoint( a.a ) == 0, "Passed!" ); + ok( a.plane().distanceToPoint( a.b ) == 0, "Passed!" ); + ok( a.plane().distanceToPoint( a.c ) == 0, "Passed!" ); + ok( a.plane().normal.equals( a.normal() ), "Passed!" ); + + a = new THREE.Triangle( new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 1, 0, 0 ), new THREE.Vector3( 0, 1, 0 ) ); + ok( a.plane().distanceToPoint( a.a ) == 0, "Passed!" ); + ok( a.plane().distanceToPoint( a.b ) == 0, "Passed!" ); + ok( a.plane().distanceToPoint( a.c ) == 0, "Passed!" ); + ok( a.plane().normal.equals( a.normal() ), "Passed!" ); + + a = new THREE.Triangle( new THREE.Vector3( 2, 0, 0 ), new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 0, 0, 2 ) ); + ok( a.plane().distanceToPoint( a.a ) == 0, "Passed!" ); + ok( a.plane().distanceToPoint( a.b ) == 0, "Passed!" ); + ok( a.plane().distanceToPoint( a.c ) == 0, "Passed!" ); + ok( a.plane().normal.clone().normalize().equals( a.normal() ), "Passed!" ); + }); + + test( "barycoordFromPoint", function() { + var a = new THREE.Triangle(); + + var bad = new THREE.Vector3( -2, -1, -1 ); + + ok( a.barycoordFromPoint( a.a ).equals( bad ), "Passed!" ); + ok( a.barycoordFromPoint( a.b ).equals( bad ), "Passed!" ); + ok( a.barycoordFromPoint( a.c ).equals( bad ), "Passed!" ); + + a = new THREE.Triangle( new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 1, 0, 0 ), new THREE.Vector3( 0, 1, 0 ) ); + ok( a.barycoordFromPoint( a.a ).equals( new THREE.Vector3( 1, 0, 0 ) ), "Passed!" ); + ok( a.barycoordFromPoint( a.b ).equals( new THREE.Vector3( 0, 1, 0 ) ), "Passed!" ); + ok( a.barycoordFromPoint( a.c ).equals( new THREE.Vector3( 0, 0, 1 ) ), "Passed!" ); + ok( a.barycoordFromPoint( a.midpoint() ).distanceTo( new THREE.Vector3( 1/3, 1/3, 1/3 ) ) < 0.0001, "Passed!" ); + + a = new THREE.Triangle( new THREE.Vector3( 2, 0, 0 ), new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 0, 0, 2 ) ); + ok( a.barycoordFromPoint( a.a ).equals( new THREE.Vector3( 1, 0, 0 ) ), "Passed!" ); + ok( a.barycoordFromPoint( a.b ).equals( new THREE.Vector3( 0, 1, 0 ) ), "Passed!" ); + ok( a.barycoordFromPoint( a.c ).equals( new THREE.Vector3( 0, 0, 1 ) ), "Passed!" ); + ok( a.barycoordFromPoint( a.midpoint() ).distanceTo( new THREE.Vector3( 1/3, 1/3, 1/3 ) ) < 0.0001, "Passed!" ); + }); + + test( "containsPoint", function() { + var a = new THREE.Triangle(); + + ok( ! a.containsPoint( a.a ), "Passed!" ); + ok( ! a.containsPoint( a.b ), "Passed!" ); + ok( ! a.containsPoint( a.c ), "Passed!" ); + + a = new THREE.Triangle( new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 1, 0, 0 ), new THREE.Vector3( 0, 1, 0 ) ); + ok( a.containsPoint( a.a ), "Passed!" ); + ok( a.containsPoint( a.b ), "Passed!" ); + ok( a.containsPoint( a.c ), "Passed!" ); + ok( a.containsPoint( a.midpoint() ), "Passed!" ); + ok( ! a.containsPoint( new THREE.Vector3( -1, -1, -1 ) ), "Passed!" ); + + a = new THREE.Triangle( new THREE.Vector3( 2, 0, 0 ), new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 0, 0, 2 ) ); + ok( a.containsPoint( a.a ), "Passed!" ); + ok( a.containsPoint( a.b ), "Passed!" ); + ok( a.containsPoint( a.c ), "Passed!" ); + ok( a.containsPoint( a.midpoint() ), "Passed!" ); + ok( ! a.containsPoint( new THREE.Vector3( -1, -1, -1 ) ), "Passed!" ); + }); + + + test( "constructor", function() { + var a = new THREE.Vector2(); + ok( a.x == 0, "Passed!" ); + ok( a.y == 0, "Passed!" ); + + a = new THREE.Vector2( x, y ); + ok( a.x === x, "Passed!" ); + ok( a.y === y, "Passed!" ); + }); + + test( "copy", function() { + var a = new THREE.Vector2( x, y ); + var b = new THREE.Vector2().copy( a ); + ok( b.x == x, "Passed!" ); + ok( b.y == y, "Passed!" ); + + // ensure that it is a true copy + a.x = 0; + a.y = -1; + ok( b.x == x, "Passed!" ); + ok( b.y == y, "Passed!" ); + }); + + test( "set", function() { + var a = new THREE.Vector2(); + ok( a.x == 0, "Passed!" ); + ok( a.y == 0, "Passed!" ); + + a.set( x, y ); + ok( a.x == x, "Passed!" ); + ok( a.y == y, "Passed!" ); + }); + + test( "setX,setY", function() { + var a = new THREE.Vector2(); + ok( a.x == 0, "Passed!" ); + ok( a.y == 0, "Passed!" ); + + a.setX( x ); + a.setY( y ); + ok( a.x == x, "Passed!" ); + ok( a.y == y, "Passed!" ); + }); + + test( "setComponent,getComponent", function() { + var a = new THREE.Vector2(); + ok( a.x == 0, "Passed!" ); + ok( a.y == 0, "Passed!" ); + + a.setComponent( 0, 1 ); + a.setComponent( 1, 2 ); + ok( a.getComponent( 0 ) == 1, "Passed!" ); + ok( a.getComponent( 1 ) == 2, "Passed!" ); + }); + + test( "add", function() { + var a = new THREE.Vector2( x, y ); + var b = new THREE.Vector2( -x, -y ); + + a.add( b ); + ok( a.x == 0, "Passed!" ); + ok( a.y == 0, "Passed!" ); + + var c = new THREE.Vector2().addVectors( b, b ); + ok( c.x == -2*x, "Passed!" ); + ok( c.y == -2*y, "Passed!" ); + }); + + test( "sub", function() { + var a = new THREE.Vector2( x, y ); + var b = new THREE.Vector2( -x, -y ); + + a.sub( b ); + ok( a.x == 2*x, "Passed!" ); + ok( a.y == 2*y, "Passed!" ); + + var c = new THREE.Vector2().subVectors( a, a ); + ok( c.x == 0, "Passed!" ); + ok( c.y == 0, "Passed!" ); + }); + + test( "multiply/divide", function() { + var a = new THREE.Vector2( x, y ); + var b = new THREE.Vector2( -x, -y ); + + a.multiplyScalar( -2 ); + ok( a.x == x*-2, "Passed!" ); + ok( a.y == y*-2, "Passed!" ); + + b.multiplyScalar( -2 ); + ok( b.x == 2*x, "Passed!" ); + ok( b.y == 2*y, "Passed!" ); + + a.divideScalar( -2 ); + ok( a.x == x, "Passed!" ); + ok( a.y == y, "Passed!" ); + + b.divideScalar( -2 ); + ok( b.x == -x, "Passed!" ); + ok( b.y == -y, "Passed!" ); + }); + + + test( "min/max/clamp", function() { + var a = new THREE.Vector2( x, y ); + var b = new THREE.Vector2( -x, -y ); + var c = new THREE.Vector2(); + + c.copy( a ).min( b ); + ok( c.x == -x, "Passed!" ); + ok( c.y == -y, "Passed!" ); + + c.copy( a ).max( b ); + ok( c.x == x, "Passed!" ); + ok( c.y == y, "Passed!" ); + + c.set( -2*x, 2*y ); + c.clamp( b, a ); + ok( c.x == -x, "Passed!" ); + ok( c.y == y, "Passed!" ); + }); + + test( "negate", function() { + var a = new THREE.Vector2( x, y ); + + a.negate(); + ok( a.x == -x, "Passed!" ); + ok( a.y == -y, "Passed!" ); + }); + + test( "dot", function() { + var a = new THREE.Vector2( x, y ); + var b = new THREE.Vector2( -x, -y ); + var c = new THREE.Vector2(); + + var result = a.dot( b ); + ok( result == (-x*x-y*y), "Passed!" ); + + result = a.dot( c ); + ok( result == 0, "Passed!" ); + }); + + test( "length/lengthSq", function() { + var a = new THREE.Vector2( x, 0 ); + var b = new THREE.Vector2( 0, -y ); + var c = new THREE.Vector2(); + + ok( a.length() == x, "Passed!" ); + ok( a.lengthSq() == x*x, "Passed!" ); + ok( b.length() == y, "Passed!" ); + ok( b.lengthSq() == y*y, "Passed!" ); + ok( c.length() == 0, "Passed!" ); + ok( c.lengthSq() == 0, "Passed!" ); + + a.set( x, y ); + ok( a.length() == Math.sqrt( x*x + y*y ), "Passed!" ); + ok( a.lengthSq() == ( x*x + y*y ), "Passed!" ); + }); + + test( "normalize", function() { + var a = new THREE.Vector2( x, 0 ); + var b = new THREE.Vector2( 0, -y ); + var c = new THREE.Vector2(); + + a.normalize(); + ok( a.length() == 1, "Passed!" ); + ok( a.x == 1, "Passed!" ); + + b.normalize(); + ok( b.length() == 1, "Passed!" ); + ok( b.y == -1, "Passed!" ); + }); + + test( "distanceTo/distanceToSquared", function() { + var a = new THREE.Vector2( x, 0 ); + var b = new THREE.Vector2( 0, -y ); + var c = new THREE.Vector2(); + + ok( a.distanceTo( c ) == x, "Passed!" ); + ok( a.distanceToSquared( c ) == x*x, "Passed!" ); + + ok( b.distanceTo( c ) == y, "Passed!" ); + ok( b.distanceToSquared( c ) == y*y, "Passed!" ); + }); + + test( "setLength", function() { + var a = new THREE.Vector2( x, 0 ); + + ok( a.length() == x, "Passed!" ); + a.setLength( y ); + ok( a.length() == y, "Passed!" ); + + a = new THREE.Vector2( 0, 0 ); + ok( a.length() == 0, "Passed!" ); + a.setLength( y ); + ok( a.length() == 0, "Passed!" ); + }); + + test( "lerp/clone", function() { + var a = new THREE.Vector2( x, 0 ); + var b = new THREE.Vector2( 0, -y ); + + ok( a.lerp( a, 0 ).equals( a.lerp( a, 0.5 ) ), "Passed!" ); + ok( a.lerp( a, 0 ).equals( a.lerp( a, 1 ) ), "Passed!" ); + + ok( a.clone().lerp( b, 0 ).equals( a ), "Passed!" ); + + ok( a.clone().lerp( b, 0.5 ).x == x*0.5, "Passed!" ); + ok( a.clone().lerp( b, 0.5 ).y == -y*0.5, "Passed!" ); + + ok( a.clone().lerp( b, 1 ).equals( b ), "Passed!" ); + }); + + test( "equals", function() { + var a = new THREE.Vector2( x, 0 ); + var b = new THREE.Vector2( 0, -y ); + + ok( a.x != b.x, "Passed!" ); + ok( a.y != b.y, "Passed!" ); + + ok( ! a.equals( b ), "Passed!" ); + ok( ! b.equals( a ), "Passed!" ); + + a.copy( b ); + ok( a.x == b.x, "Passed!" ); + ok( a.y == b.y, "Passed!" ); + + ok( a.equals( b ), "Passed!" ); + ok( b.equals( a ), "Passed!" ); + }); + + + test( "constructor", function() { + var a = new THREE.Vector3(); + ok( a.x == 0, "Passed!" ); + ok( a.y == 0, "Passed!" ); + ok( a.z == 0, "Passed!" ); + + a = new THREE.Vector3( x, y, z ); + ok( a.x === x, "Passed!" ); + ok( a.y === y, "Passed!" ); + ok( a.z === z, "Passed!" ); + }); + + test( "copy", function() { + var a = new THREE.Vector3( x, y, z ); + var b = new THREE.Vector3().copy( a ); + ok( b.x == x, "Passed!" ); + ok( b.y == y, "Passed!" ); + ok( b.z == z, "Passed!" ); + + // ensure that it is a true copy + a.x = 0; + a.y = -1; + a.z = -2; + ok( b.x == x, "Passed!" ); + ok( b.y == y, "Passed!" ); + ok( b.z == z, "Passed!" ); + }); + + test( "set", function() { + var a = new THREE.Vector3(); + ok( a.x == 0, "Passed!" ); + ok( a.y == 0, "Passed!" ); + ok( a.z == 0, "Passed!" ); + + a.set( x, y, z ); + ok( a.x == x, "Passed!" ); + ok( a.y == y, "Passed!" ); + ok( a.z == z, "Passed!" ); + }); + + test( "setX,setY,setZ", function() { + var a = new THREE.Vector3(); + ok( a.x == 0, "Passed!" ); + ok( a.y == 0, "Passed!" ); + ok( a.z == 0, "Passed!" ); + + a.setX( x ); + a.setY( y ); + a.setZ( z ); + + ok( a.x == x, "Passed!" ); + ok( a.y == y, "Passed!" ); + ok( a.z == z, "Passed!" ); + }); + + test( "setComponent,getComponent", function() { + var a = new THREE.Vector3(); + ok( a.x == 0, "Passed!" ); + ok( a.y == 0, "Passed!" ); + ok( a.z == 0, "Passed!" ); + + a.setComponent( 0, 1 ); + a.setComponent( 1, 2 ); + a.setComponent( 2, 3 ); + ok( a.getComponent( 0 ) == 1, "Passed!" ); + ok( a.getComponent( 1 ) == 2, "Passed!" ); + ok( a.getComponent( 2 ) == 3, "Passed!" ); + }); + + test( "add", function() { + var a = new THREE.Vector3( x, y, z ); + var b = new THREE.Vector3( -x, -y, -z ); + + a.add( b ); + ok( a.x == 0, "Passed!" ); + ok( a.y == 0, "Passed!" ); + ok( a.z == 0, "Passed!" ); + + var c = new THREE.Vector3().addVectors( b, b ); + ok( c.x == -2*x, "Passed!" ); + ok( c.y == -2*y, "Passed!" ); + ok( c.z == -2*z, "Passed!" ); + }); + + test( "sub", function() { + var a = new THREE.Vector3( x, y, z ); + var b = new THREE.Vector3( -x, -y, -z ); + + a.sub( b ); + ok( a.x == 2*x, "Passed!" ); + ok( a.y == 2*y, "Passed!" ); + ok( a.z == 2*z, "Passed!" ); + + var c = new THREE.Vector3().subVectors( a, a ); + ok( c.x == 0, "Passed!" ); + ok( c.y == 0, "Passed!" ); + ok( c.z == 0, "Passed!" ); + }); + + test( "multiply/divide", function() { + var a = new THREE.Vector3( x, y, z ); + var b = new THREE.Vector3( -x, -y, -z ); + + a.multiplyScalar( -2 ); + ok( a.x == x*-2, "Passed!" ); + ok( a.y == y*-2, "Passed!" ); + ok( a.z == z*-2, "Passed!" ); + + b.multiplyScalar( -2 ); + ok( b.x == 2*x, "Passed!" ); + ok( b.y == 2*y, "Passed!" ); + ok( b.z == 2*z, "Passed!" ); + + a.divideScalar( -2 ); + ok( a.x == x, "Passed!" ); + ok( a.y == y, "Passed!" ); + ok( a.z == z, "Passed!" ); + + b.divideScalar( -2 ); + ok( b.x == -x, "Passed!" ); + ok( b.y == -y, "Passed!" ); + ok( b.z == -z, "Passed!" ); + }); + + test( "min/max/clamp", function() { + var a = new THREE.Vector3( x, y, z ); + var b = new THREE.Vector3( -x, -y, -z ); + var c = new THREE.Vector3(); + + c.copy( a ).min( b ); + ok( c.x == -x, "Passed!" ); + ok( c.y == -y, "Passed!" ); + ok( c.z == -z, "Passed!" ); + + c.copy( a ).max( b ); + ok( c.x == x, "Passed!" ); + ok( c.y == y, "Passed!" ); + ok( c.z == z, "Passed!" ); + + c.set( -2*x, 2*y, -2*z ); + c.clamp( b, a ); + ok( c.x == -x, "Passed!" ); + ok( c.y == y, "Passed!" ); + ok( c.z == -z, "Passed!" ); + }); + + test( "negate", function() { + var a = new THREE.Vector3( x, y, z ); + + a.negate(); + ok( a.x == -x, "Passed!" ); + ok( a.y == -y, "Passed!" ); + ok( a.z == -z, "Passed!" ); + }); + + test( "dot", function() { + var a = new THREE.Vector3( x, y, z ); + var b = new THREE.Vector3( -x, -y, -z ); + var c = new THREE.Vector3(); + + var result = a.dot( b ); + ok( result == (-x*x-y*y-z*z), "Passed!" ); + + result = a.dot( c ); + ok( result == 0, "Passed!" ); + }); + + test( "length/lengthSq", function() { + var a = new THREE.Vector3( x, 0, 0 ); + var b = new THREE.Vector3( 0, -y, 0 ); + var c = new THREE.Vector3( 0, 0, z ); + var d = new THREE.Vector3(); + + ok( a.length() == x, "Passed!" ); + ok( a.lengthSq() == x*x, "Passed!" ); + ok( b.length() == y, "Passed!" ); + ok( b.lengthSq() == y*y, "Passed!" ); + ok( c.length() == z, "Passed!" ); + ok( c.lengthSq() == z*z, "Passed!" ); + ok( d.length() == 0, "Passed!" ); + ok( d.lengthSq() == 0, "Passed!" ); + + a.set( x, y, z ); + ok( a.length() == Math.sqrt( x*x + y*y + z*z ), "Passed!" ); + ok( a.lengthSq() == ( x*x + y*y + z*z ), "Passed!" ); + }); + + test( "normalize", function() { + var a = new THREE.Vector3( x, 0, 0 ); + var b = new THREE.Vector3( 0, -y, 0 ); + var c = new THREE.Vector3( 0, 0, z ); + + a.normalize(); + ok( a.length() == 1, "Passed!" ); + ok( a.x == 1, "Passed!" ); + + b.normalize(); + ok( b.length() == 1, "Passed!" ); + ok( b.y == -1, "Passed!" ); + + c.normalize(); + ok( c.length() == 1, "Passed!" ); + ok( c.z == 1, "Passed!" ); + }); + + test( "distanceTo/distanceToSquared", function() { + var a = new THREE.Vector3( x, 0, 0 ); + var b = new THREE.Vector3( 0, -y, 0 ); + var c = new THREE.Vector3( 0, 0, z ); + var d = new THREE.Vector3(); + + ok( a.distanceTo( d ) == x, "Passed!" ); + ok( a.distanceToSquared( d ) == x*x, "Passed!" ); + + ok( b.distanceTo( d ) == y, "Passed!" ); + ok( b.distanceToSquared( d ) == y*y, "Passed!" ); + + ok( c.distanceTo( d ) == z, "Passed!" ); + ok( c.distanceToSquared( d ) == z*z, "Passed!" ); + }); + + test( "setLength", function() { + var a = new THREE.Vector3( x, 0, 0 ); + + ok( a.length() == x, "Passed!" ); + a.setLength( y ); + ok( a.length() == y, "Passed!" ); + + a = new THREE.Vector3( 0, 0, 0 ); + ok( a.length() == 0, "Passed!" ); + a.setLength( y ); + ok( a.length() == 0, "Passed!" ); + + }); + + test( "projectOnVector", function() { + var a = new THREE.Vector3( 1, 0, 0 ); + var b = new THREE.Vector3(); + var normal = new THREE.Vector3( 10, 0, 0 ); + + ok( b.copy( a ).projectOnVector( normal ).equals( new THREE.Vector3( 1, 0, 0 ) ), "Passed!" ); + + a.set( 0, 1, 0 ); + ok( b.copy( a ).projectOnVector( normal ).equals( new THREE.Vector3( 0, 0, 0 ) ), "Passed!" ); + + a.set( 0, 0, -1 ); + ok( b.copy( a ).projectOnVector( normal ).equals( new THREE.Vector3( 0, 0, 0 ) ), "Passed!" ); + + a.set( -1, 0, 0 ); + ok( b.copy( a ).projectOnVector( normal ).equals( new THREE.Vector3( -1, 0, 0 ) ), "Passed!" ); + + }); + + test( "projectOnPlane", function() { + var a = new THREE.Vector3( 1, 0, 0 ); + var b = new THREE.Vector3(); + var normal = new THREE.Vector3( 1, 0, 0 ); + + ok( b.copy( a ).projectOnPlane( normal ).equals( new THREE.Vector3( 0, 0, 0 ) ), "Passed!" ); + + a.set( 0, 1, 0 ); + ok( b.copy( a ).projectOnPlane( normal ).equals( new THREE.Vector3( 0, 1, 0 ) ), "Passed!" ); + + a.set( 0, 0, -1 ); + ok( b.copy( a ).projectOnPlane( normal ).equals( new THREE.Vector3( 0, 0, -1 ) ), "Passed!" ); + + a.set( -1, 0, 0 ); + ok( b.copy( a ).projectOnPlane( normal ).equals( new THREE.Vector3( 0, 0, 0 ) ), "Passed!" ); + + }); + + test( "reflect", function() { + var a = new THREE.Vector3( 1, 0, 0 ); + var normal = new THREE.Vector3( 1, 0, 0 ); + var b = new THREE.Vector3( 0, 0, 0 ); + + ok( b.copy( a ).reflect( normal ).equals( new THREE.Vector3( 1, 0, 0 ) ), "Passed!" ); + + a.set( 1, -1, 0 ); + ok( b.copy( a ).reflect( normal ).equals( new THREE.Vector3( 1, 1, 0 ) ), "Passed!" ); + + a.set( 1, -1, 0 ); + normal.set( 0, -1, 0 ); + ok( b.copy( a ).reflect( normal ).equals( new THREE.Vector3( -1, -1, 0 ) ), "Passed!" ); + }); + + test( "angleTo", function() { + var a = new THREE.Vector3( 0, -0.18851655680720186, 0.9820700116639124 ); + var b = new THREE.Vector3( 0, 0.18851655680720186, -0.9820700116639124 ); + + equal( a.angleTo( a ), 0 ); + equal( a.angleTo( b ), Math.PI ); + + var x = new THREE.Vector3( 1, 0, 0 ); + var y = new THREE.Vector3( 0, 1, 0 ); + var z = new THREE.Vector3( 0, 0, 1 ); + + equal( x.angleTo( y ), Math.PI / 2 ); + equal( x.angleTo( z ), Math.PI / 2 ); + equal( z.angleTo( x ), Math.PI / 2 ); + + ok( Math.abs( x.angleTo( new THREE.Vector3( 1, 1, 0 ) ) - ( Math.PI / 4 ) ) < 0.0000001 ); + }); + + test( "lerp/clone", function() { + var a = new THREE.Vector3( x, 0, z ); + var b = new THREE.Vector3( 0, -y, 0 ); + + ok( a.lerp( a, 0 ).equals( a.lerp( a, 0.5 ) ), "Passed!" ); + ok( a.lerp( a, 0 ).equals( a.lerp( a, 1 ) ), "Passed!" ); + + ok( a.clone().lerp( b, 0 ).equals( a ), "Passed!" ); + + ok( a.clone().lerp( b, 0.5 ).x == x*0.5, "Passed!" ); + ok( a.clone().lerp( b, 0.5 ).y == -y*0.5, "Passed!" ); + ok( a.clone().lerp( b, 0.5 ).z == z*0.5, "Passed!" ); + + ok( a.clone().lerp( b, 1 ).equals( b ), "Passed!" ); + }); + + test( "equals", function() { + var a = new THREE.Vector3( x, 0, z ); + var b = new THREE.Vector3( 0, -y, 0 ); + + ok( a.x != b.x, "Passed!" ); + ok( a.y != b.y, "Passed!" ); + ok( a.z != b.z, "Passed!" ); + + ok( ! a.equals( b ), "Passed!" ); + ok( ! b.equals( a ), "Passed!" ); + + a.copy( b ); + ok( a.x == b.x, "Passed!" ); + ok( a.y == b.y, "Passed!" ); + ok( a.z == b.z, "Passed!" ); + + ok( a.equals( b ), "Passed!" ); + ok( b.equals( a ), "Passed!" ); + }); + + + test( "constructor", function() { + var a = new THREE.Vector4(); + ok( a.x == 0, "Passed!" ); + ok( a.y == 0, "Passed!" ); + ok( a.z == 0, "Passed!" ); + ok( a.w == 1, "Passed!" ); + + a = new THREE.Vector4( x, y, z, w ); + ok( a.x === x, "Passed!" ); + ok( a.y === y, "Passed!" ); + ok( a.z === z, "Passed!" ); + ok( a.w === w, "Passed!" ); + }); + + test( "copy", function() { + var a = new THREE.Vector4( x, y, z, w ); + var b = new THREE.Vector4().copy( a ); + ok( b.x == x, "Passed!" ); + ok( b.y == y, "Passed!" ); + ok( b.z == z, "Passed!" ); + ok( b.w == w, "Passed!" ); + + // ensure that it is a true copy + a.x = 0; + a.y = -1; + a.z = -2; + a.w = -3; + ok( b.x == x, "Passed!" ); + ok( b.y == y, "Passed!" ); + ok( b.z == z, "Passed!" ); + ok( b.w == w, "Passed!" ); + }); + + test( "set", function() { + var a = new THREE.Vector4(); + ok( a.x == 0, "Passed!" ); + ok( a.y == 0, "Passed!" ); + ok( a.z == 0, "Passed!" ); + ok( a.w == 1, "Passed!" ); + + a.set( x, y, z, w ); + ok( a.x == x, "Passed!" ); + ok( a.y == y, "Passed!" ); + ok( a.z == z, "Passed!" ); + ok( a.w == w, "Passed!" ); + }); + + test( "setX,setY,setZ,setW", function() { + var a = new THREE.Vector4(); + ok( a.x == 0, "Passed!" ); + ok( a.y == 0, "Passed!" ); + ok( a.z == 0, "Passed!" ); + ok( a.w == 1, "Passed!" ); + + a.setX( x ); + a.setY( y ); + a.setZ( z ); + a.setW( w ); + + ok( a.x == x, "Passed!" ); + ok( a.y == y, "Passed!" ); + ok( a.z == z, "Passed!" ); + ok( a.w == w, "Passed!" ); + }); + + test( "setComponent,getComponent", function() { + var a = new THREE.Vector4(); + ok( a.x == 0, "Passed!" ); + ok( a.y == 0, "Passed!" ); + ok( a.z == 0, "Passed!" ); + ok( a.w == 1, "Passed!" ); + + a.setComponent( 0, 1 ); + a.setComponent( 1, 2 ); + a.setComponent( 2, 3 ); + a.setComponent( 3, 4 ); + ok( a.getComponent( 0 ) == 1, "Passed!" ); + ok( a.getComponent( 1 ) == 2, "Passed!" ); + ok( a.getComponent( 2 ) == 3, "Passed!" ); + ok( a.getComponent( 3 ) == 4, "Passed!" ); + }); + + test( "add", function() { + var a = new THREE.Vector4( x, y, z, w ); + var b = new THREE.Vector4( -x, -y, -z, -w ); + + a.add( b ); + ok( a.x == 0, "Passed!" ); + ok( a.y == 0, "Passed!" ); + ok( a.z == 0, "Passed!" ); + ok( a.w == 0, "Passed!" ); + + var c = new THREE.Vector4().addVectors( b, b ); + ok( c.x == -2*x, "Passed!" ); + ok( c.y == -2*y, "Passed!" ); + ok( c.z == -2*z, "Passed!" ); + ok( c.w == -2*w, "Passed!" ); + }); + + test( "sub", function() { + var a = new THREE.Vector4( x, y, z, w ); + var b = new THREE.Vector4( -x, -y, -z, -w ); + + a.sub( b ); + ok( a.x == 2*x, "Passed!" ); + ok( a.y == 2*y, "Passed!" ); + ok( a.z == 2*z, "Passed!" ); + ok( a.w == 2*w, "Passed!" ); + + var c = new THREE.Vector4().subVectors( a, a ); + ok( c.x == 0, "Passed!" ); + ok( c.y == 0, "Passed!" ); + ok( c.z == 0, "Passed!" ); + ok( c.w == 0, "Passed!" ); + }); + + test( "multiply/divide", function() { + var a = new THREE.Vector4( x, y, z, w ); + var b = new THREE.Vector4( -x, -y, -z, -w ); + + a.multiplyScalar( -2 ); + ok( a.x == x*-2, "Passed!" ); + ok( a.y == y*-2, "Passed!" ); + ok( a.z == z*-2, "Passed!" ); + ok( a.w == w*-2, "Passed!" ); + + b.multiplyScalar( -2 ); + ok( b.x == 2*x, "Passed!" ); + ok( b.y == 2*y, "Passed!" ); + ok( b.z == 2*z, "Passed!" ); + ok( b.w == 2*w, "Passed!" ); + + a.divideScalar( -2 ); + ok( a.x == x, "Passed!" ); + ok( a.y == y, "Passed!" ); + ok( a.z == z, "Passed!" ); + ok( a.w == w, "Passed!" ); + + b.divideScalar( -2 ); + ok( b.x == -x, "Passed!" ); + ok( b.y == -y, "Passed!" ); + ok( b.z == -z, "Passed!" ); + ok( b.w == -w, "Passed!" ); + }); + + test( "min/max/clamp", function() { + var a = new THREE.Vector4( x, y, z, w ); + var b = new THREE.Vector4( -x, -y, -z, -w ); + var c = new THREE.Vector4(); + + c.copy( a ).min( b ); + ok( c.x == -x, "Passed!" ); + ok( c.y == -y, "Passed!" ); + ok( c.z == -z, "Passed!" ); + ok( c.w == -w, "Passed!" ); + + c.copy( a ).max( b ); + ok( c.x == x, "Passed!" ); + ok( c.y == y, "Passed!" ); + ok( c.z == z, "Passed!" ); + ok( c.w == w, "Passed!" ); + + c.set( -2*x, 2*y, -2*z, 2*w ); + c.clamp( b, a ); + ok( c.x == -x, "Passed!" ); + ok( c.y == y, "Passed!" ); + ok( c.z == -z, "Passed!" ); + ok( c.w == w, "Passed!" ); + }); + + test( "negate", function() { + var a = new THREE.Vector4( x, y, z, w ); + + a.negate(); + ok( a.x == -x, "Passed!" ); + ok( a.y == -y, "Passed!" ); + ok( a.z == -z, "Passed!" ); + ok( a.w == -w, "Passed!" ); + }); + + test( "dot", function() { + var a = new THREE.Vector4( x, y, z, w ); + var b = new THREE.Vector4( -x, -y, -z, -w ); + var c = new THREE.Vector4( 0, 0, 0, 0 ); + + var result = a.dot( b ); + ok( result == (-x*x-y*y-z*z-w*w), "Passed!" ); + + result = a.dot( c ); + ok( result == 0, "Passed!" ); + }); + + test( "length/lengthSq", function() { + var a = new THREE.Vector4( x, 0, 0, 0 ); + var b = new THREE.Vector4( 0, -y, 0, 0 ); + var c = new THREE.Vector4( 0, 0, z, 0 ); + var d = new THREE.Vector4( 0, 0, 0, w ); + var e = new THREE.Vector4( 0, 0, 0, 0 ); + + ok( a.length() == x, "Passed!" ); + ok( a.lengthSq() == x*x, "Passed!" ); + ok( b.length() == y, "Passed!" ); + ok( b.lengthSq() == y*y, "Passed!" ); + ok( c.length() == z, "Passed!" ); + ok( c.lengthSq() == z*z, "Passed!" ); + ok( d.length() == w, "Passed!" ); + ok( d.lengthSq() == w*w, "Passed!" ); + ok( e.length() == 0, "Passed!" ); + ok( e.lengthSq() == 0, "Passed!" ); + + a.set( x, y, z, w ); + ok( a.length() == Math.sqrt( x*x + y*y + z*z + w*w ), "Passed!" ); + ok( a.lengthSq() == ( x*x + y*y + z*z + w*w ), "Passed!" ); + }); + + test( "normalize", function() { + var a = new THREE.Vector4( x, 0, 0, 0 ); + var b = new THREE.Vector4( 0, -y, 0, 0 ); + var c = new THREE.Vector4( 0, 0, z, 0 ); + var d = new THREE.Vector4( 0, 0, 0, -w ); + + a.normalize(); + ok( a.length() == 1, "Passed!" ); + ok( a.x == 1, "Passed!" ); + + b.normalize(); + ok( b.length() == 1, "Passed!" ); + ok( b.y == -1, "Passed!" ); + + c.normalize(); + ok( c.length() == 1, "Passed!" ); + ok( c.z == 1, "Passed!" ); + + d.normalize(); + ok( d.length() == 1, "Passed!" ); + ok( d.w == -1, "Passed!" ); + }); + + /* + test( "distanceTo/distanceToSquared", function() { + var a = new THREE.Vector4( x, 0, 0, 0 ); + var b = new THREE.Vector4( 0, -y, 0, 0 ); + var c = new THREE.Vector4( 0, 0, z, 0 ); + var d = new THREE.Vector4( 0, 0, 0, -w ); + var e = new THREE.Vector4(); + + ok( a.distanceTo( e ) == x, "Passed!" ); + ok( a.distanceToSquared( e ) == x*x, "Passed!" ); + + ok( b.distanceTo( e ) == y, "Passed!" ); + ok( b.distanceToSquared( e ) == y*y, "Passed!" ); + + ok( c.distanceTo( e ) == z, "Passed!" ); + ok( c.distanceToSquared( e ) == z*z, "Passed!" ); + + ok( d.distanceTo( e ) == w, "Passed!" ); + ok( d.distanceToSquared( e ) == w*w, "Passed!" ); + }); + */ + + + test( "setLength", function() { + var a = new THREE.Vector4( x, 0, 0, 0 ); + + ok( a.length() == x, "Passed!" ); + a.setLength( y ); + ok( a.length() == y, "Passed!" ); + + a = new THREE.Vector4( 0, 0, 0, 0 ); + ok( a.length() == 0, "Passed!" ); + a.setLength( y ); + ok( a.length() == 0, "Passed!" ); + }); + + test( "lerp/clone", function() { + var a = new THREE.Vector4( x, 0, z, 0 ); + var b = new THREE.Vector4( 0, -y, 0, -w ); + + ok( a.lerp( a, 0 ).equals( a.lerp( a, 0.5 ) ), "Passed!" ); + ok( a.lerp( a, 0 ).equals( a.lerp( a, 1 ) ), "Passed!" ); + + ok( a.clone().lerp( b, 0 ).equals( a ), "Passed!" ); + + ok( a.clone().lerp( b, 0.5 ).x == x*0.5, "Passed!" ); + ok( a.clone().lerp( b, 0.5 ).y == -y*0.5, "Passed!" ); + ok( a.clone().lerp( b, 0.5 ).z == z*0.5, "Passed!" ); + ok( a.clone().lerp( b, 0.5 ).w == -w*0.5, "Passed!" ); + + ok( a.clone().lerp( b, 1 ).equals( b ), "Passed!" ); + }); + + test( "equals", function() { + var a = new THREE.Vector4( x, 0, z, 0 ); + var b = new THREE.Vector4( 0, -y, 0, -w ); + + ok( a.x != b.x, "Passed!" ); + ok( a.y != b.y, "Passed!" ); + ok( a.z != b.z, "Passed!" ); + ok( a.w != b.w, "Passed!" ); + + ok( ! a.equals( b ), "Passed!" ); + ok( ! b.equals( a ), "Passed!" ); + + a.copy( b ); + ok( a.x == b.x, "Passed!" ); + ok( a.y == b.y, "Passed!" ); + ok( a.z == b.z, "Passed!" ); + ok( a.w == b.w, "Passed!" ); + + ok( a.equals( b ), "Passed!" ); + ok( b.equals( a ), "Passed!" ); + }); +}; + +///////////////////////////////////////////////////////////// +// https://github.com/mrdoob/three.js/tree/master/examples +////////////////////////////////////////////////////////////// + + +declare var Stats: any; +declare var TWEEN: any; +declare var Detector: any; +declare var Qrcode: any; + +declare module THREE{ + var PDBLoader: any; + var CSS3Renderer: any; + var CSS3DSprite: any; + var CSS3DRenderer: any; + var CSS3DObject: any; + var TrackballControls: any; + var FlyControls: any; + var RenderPass: any; + var FilmPass: any; + var EffectComposer: any; + var OrbitControls: any; + var PathControls: any; + var PointerLockControls: any; + var RollControls: any; + var FirstPersonControls: any; + var SVGRenderer: any; + var SoftwareRenderer: any; + var UVsDebug: any; + var UVsUtils: any; +} + +interface CSS3Properties{ + WebkitFilter: string; +} + +interface HTMLDocument{ + pointerLockElement: any; + mozPointerLockElement: any; + webkitPointerLockElement: any; + fullscreenElement: any; + mozFullscreenElement: any; + mozFullScreenElement: any; + webkitFullscreenElement: any; +} +interface HTMLElement{ + requestPointerLock: any; + mozRequestPointerLock: any; + webkitRequestPointerLock: any; + requestFullScreen: any; + requestFullscreen: any; + mozRequestFullScreen: any; + mozRequestFullscreen: any; + webkitRequestFullscreen: any; +} + + +// https://github.com/mrdoob/three.js/blob/master/examples/canvas_camera_orthographic.html + +()=>{ + var container, stats; + var camera, scene, renderer; + + 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 - orthographic view'; + container.appendChild( info ); + + camera = new THREE.OrthographicCamera( window.innerWidth / - 2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / - 2, - 500, 1000 ); + camera.position.x = 200; + camera.position.y = 100; + camera.position.z = 200; + + scene = new THREE.Scene(); + + // Grid + + var size = 500, step = 50; + + var geometry = new THREE.Geometry(); + + for ( var i = - size; i <= size; i += step ) { + + geometry.vertices.push( new THREE.Vector3( - size, 0, i ) ); + geometry.vertices.push( new THREE.Vector3( size, 0, i ) ); + + geometry.vertices.push( new THREE.Vector3( i, 0, - size ) ); + geometry.vertices.push( new THREE.Vector3( i, 0, size ) ); + + } + + var materialLine = new THREE.LineBasicMaterial( { color: 0x000000, opacity: 0.2 } ); + + var line = new THREE.Line( geometry, materialLine ); + line.type = THREE.LinePieces; + scene.add( line ); + + // Cubes + + var geometry = new THREE.CubeGeometry( 50, 50, 50 ); + var materialCube = new THREE.MeshLambertMaterial( { color: 0xffffff, shading: THREE.FlatShading, overdraw: true } ); + + for ( var i = 0; i < 100; i ++ ) { + + var cube = new THREE.Mesh( geometry, materialCube ); + + cube.scale.y = Math.floor( Math.random() * 2 + 1 ); + + cube.position.x = Math.floor( ( Math.random() * 1000 - 500 ) / 50 ) * 50 + 25; + cube.position.y = ( cube.scale.y * 50 ) / 2; + cube.position.z = Math.floor( ( Math.random() * 1000 - 500 ) / 50 ) * 50 + 25; + + scene.add( cube ); + + } + + // Lights + + var ambientLight = new THREE.AmbientLight( Math.random() * 0x10 ); + scene.add( ambientLight ); + + var directionalLight = new THREE.DirectionalLight( Math.random() * 0xffffff ); + directionalLight.position.x = Math.random() - 0.5; + directionalLight.position.y = Math.random() - 0.5; + directionalLight.position.z = Math.random() - 0.5; + directionalLight.position.normalize(); + scene.add( directionalLight ); + + var directionalLight = new THREE.DirectionalLight( Math.random() * 0xffffff ); + directionalLight.position.x = Math.random() - 0.5; + directionalLight.position.y = Math.random() - 0.5; + directionalLight.position.z = Math.random() - 0.5; + directionalLight.position.normalize(); + scene.add( directionalLight ); + + renderer = new THREE.CanvasRenderer(); + 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 ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + camera.left = window.innerWidth / - 2; + camera.right = window.innerWidth / 2; + camera.top = window.innerHeight / 2; + camera.bottom = window.innerHeight / - 2; + + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + var timer = Date.now() * 0.0001; + + camera.position.x = Math.cos( timer ) * 200; + camera.position.z = Math.sin( timer ) * 200; + camera.lookAt( scene.position ); + + renderer.render( scene, camera ); + + } + +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/canvas_geometry_cube.html + +()=>{ + + var container, stats; + + var camera, scene, renderer; + + var cube, plane; + + var targetRotation = 0; + var targetRotationOnMouseDown = 0; + + var mouseX = 0; + var mouseXOnMouseDown = 0; + + var windowHalfX = window.innerWidth / 2; + var windowHalfY = window.innerHeight / 2; + + 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 = 'Drag to spin the cube'; + container.appendChild( info ); + + camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 ); + camera.position.y = 150; + camera.position.z = 500; + + scene = new THREE.Scene(); + + // Cube + + var geometryCube = new THREE.CubeGeometry( 200, 200, 200 ); + + for ( var i = 0; i < geometryCube.faces.length; i ++ ) { + + geometryCube.faces[ i ].color.setHex( Math.random() * 0xffffff ); + + } + + var material = new THREE.MeshBasicMaterial( { vertexColors: THREE.FaceColors } ); + + cube = new THREE.Mesh( geometryCube, material ); + cube.position.y = 150; + scene.add( cube ); + + // Plane + + var geometryPlane = new THREE.PlaneGeometry( 200, 200 ); + geometryPlane.applyMatrix( new THREE.Matrix4().makeRotationX( - Math.PI / 2 ) ); + + var material = new THREE.MeshBasicMaterial( { color: 0xe0e0e0 } ); + + plane = new THREE.Mesh( geometryPlane, material ); + scene.add( plane ); + + renderer = new THREE.CanvasRenderer(); + 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 ); + + } + + // + + function onDocumentMouseDown( event ) { + + event.preventDefault(); + + document.addEventListener( 'mousemove', onDocumentMouseMove, false ); + document.addEventListener( 'mouseup', onDocumentMouseUp, false ); + document.addEventListener( 'mouseout', onDocumentMouseOut, false ); + + mouseXOnMouseDown = event.clientX - windowHalfX; + targetRotationOnMouseDown = targetRotation; + + } + + function onDocumentMouseMove( event ) { + + mouseX = event.clientX - windowHalfX; + + targetRotation = targetRotationOnMouseDown + ( mouseX - mouseXOnMouseDown ) * 0.02; + + } + + function onDocumentMouseUp( event ) { + + document.removeEventListener( 'mousemove', onDocumentMouseMove, false ); + document.removeEventListener( 'mouseup', onDocumentMouseUp, false ); + document.removeEventListener( 'mouseout', onDocumentMouseOut, false ); + + } + + function onDocumentMouseOut( event ) { + + document.removeEventListener( 'mousemove', onDocumentMouseMove, false ); + document.removeEventListener( 'mouseup', onDocumentMouseUp, false ); + document.removeEventListener( 'mouseout', onDocumentMouseOut, false ); + + } + + 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() { + + plane.rotation.y = cube.rotation.y += ( targetRotation - cube.rotation.y ) * 0.05; + renderer.render( scene, camera ); + + } +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/canvas_geometry_hierarchy.html + +()=>{ + var container, stats; + + var camera, scene, renderer; + + var geometry, group; + + var mouseX = 0, mouseY = 0; + + var windowHalfX = window.innerWidth / 2; + var windowHalfY = window.innerHeight / 2; + + document.addEventListener( 'mousemove', onDocumentMouseMove, false ); + + init(); + animate(); + + function init() { + + container = document.createElement( 'div' ); + document.body.appendChild( container ); + + camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 10000 ); + camera.position.z = 500; + + scene = new THREE.Scene(); + + var geometry = new THREE.CubeGeometry( 100, 100, 100 ); + var material = new THREE.MeshNormalMaterial(); + + group = new THREE.Object3D(); + + for ( var i = 0; i < 200; i ++ ) { + + var mesh = new THREE.Mesh( geometry, material ); + mesh.position.x = Math.random() * 2000 - 1000; + mesh.position.y = Math.random() * 2000 - 1000; + mesh.position.z = Math.random() * 2000 - 1000; + mesh.rotation.x = Math.random() * 2 * Math.PI; + mesh.rotation.y = Math.random() * 2 * Math.PI; + mesh.matrixAutoUpdate = false; + mesh.updateMatrix(); + group.add( mesh ); + + } + + scene.add( group ); + + renderer = new THREE.CanvasRenderer(); + renderer.setSize( window.innerWidth, window.innerHeight ); + renderer.sortObjects = false; + container.appendChild( renderer.domElement ); + + stats = new Stats(); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.top = '0px'; + stats.domElement.style.zIndex = 100; + container.appendChild( stats.domElement ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + windowHalfX = window.innerWidth / 2; + windowHalfY = window.innerHeight / 2; + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + } + + function onDocumentMouseMove(event) { + + mouseX = ( event.clientX - windowHalfX ) * 10; + mouseY = ( event.clientY - windowHalfY ) * 10; + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + camera.position.x += ( mouseX - camera.position.x ) * .05; + camera.position.y += ( - mouseY - camera.position.y ) * .05; + camera.lookAt( scene.position ); + + var currentSeconds = Date.now(); + group.rotation.x = Math.sin( currentSeconds * 0.0007 ) * 0.5; + group.rotation.y = Math.sin( currentSeconds * 0.0003 ) * 0.5; + group.rotation.z = Math.sin( currentSeconds * 0.0002 ) * 0.5; + + renderer.render( scene, camera ); + + } + +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/canvas_geometry_panorama.html + +()=>{ + var camera, scene, renderer; + + var texture_placeholder, + isUserInteracting = false, + onPointerDownPointerX = 0, onPointerDownPointerY = 0, + lon = 90, onPointerDownLon = 0, + lat = 0, onPointerDownLat = 0, + phi = 0, theta = 0, + target = new THREE.Vector3(); + + init(); + + function init() { + + var container, mesh; + + container = document.getElementById( 'container' ); + + camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 1100 ); + + scene = new THREE.Scene(); + + texture_placeholder = document.createElement( 'canvas' ); + texture_placeholder.width = 128; + texture_placeholder.height = 128; + + var context = texture_placeholder.getContext( '2d' ); + context.fillStyle = 'rgb( 200, 200, 200 )'; + context.fillRect( 0, 0, texture_placeholder.width, texture_placeholder.height ); + + var materials = [ + + loadTexture( 'textures/cube/skybox/px.jpg' ), // right + loadTexture( 'textures/cube/skybox/nx.jpg' ), // left + loadTexture( 'textures/cube/skybox/py.jpg' ), // top + loadTexture( 'textures/cube/skybox/ny.jpg' ), // bottom + loadTexture( 'textures/cube/skybox/pz.jpg' ), // back + loadTexture( 'textures/cube/skybox/nz.jpg' ) // front + + ]; + + mesh = new THREE.Mesh( new THREE.CubeGeometry( 300, 300, 300, 7, 7, 7 ), new THREE.MeshFaceMaterial( materials ) ); + mesh.scale.x = - 1; + scene.add( mesh ); + + renderer = new THREE.CanvasRenderer(); + renderer.setSize( window.innerWidth, window.innerHeight ); + + container.appendChild( renderer.domElement ); + + document.addEventListener( 'mousedown', onDocumentMouseDown, false ); + document.addEventListener( 'mousemove', onDocumentMouseMove, false ); + document.addEventListener( 'mouseup', onDocumentMouseUp, false ); + document.addEventListener( 'mousewheel', onDocumentMouseWheel, false ); + + document.addEventListener( 'touchstart', onDocumentTouchStart, false ); + document.addEventListener( 'touchmove', onDocumentTouchMove, false ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + render(); + + } + + function loadTexture( path ) { + + var texture = new THREE.Texture( texture_placeholder ); + var material = new THREE.MeshBasicMaterial( { map: texture, overdraw: true } ); + + var image = new Image(); + image.onload = function () { + + texture.needsUpdate = true; + material.map.image = this; + + render(); + + }; + image.src = path; + + return material; + + } + + function onDocumentMouseDown( event ) { + + event.preventDefault(); + + isUserInteracting = true; + + onPointerDownPointerX = event.clientX; + onPointerDownPointerY = event.clientY; + + onPointerDownLon = lon; + onPointerDownLat = lat; + + } + + function onDocumentMouseMove( event ) { + + if ( isUserInteracting ) { + + lon = ( onPointerDownPointerX - event.clientX ) * 0.1 + onPointerDownLon; + lat = ( event.clientY - onPointerDownPointerY ) * 0.1 + onPointerDownLat; + render(); + + } + + } + + function onDocumentMouseUp( event ) { + + isUserInteracting = false; + render(); + + } + + function onDocumentMouseWheel( event ) { + + camera.fov -= event.wheelDeltaY * 0.05; + camera.updateProjectionMatrix(); + + render(); + + } + + + function onDocumentTouchStart( event ) { + + if ( event.touches.length == 1 ) { + + event.preventDefault(); + + onPointerDownPointerX = event.touches[ 0 ].pageX; + onPointerDownPointerY = event.touches[ 0 ].pageY; + + onPointerDownLon = lon; + onPointerDownLat = lat; + + } + + } + + function onDocumentTouchMove( event ) { + + if ( event.touches.length == 1 ) { + + event.preventDefault(); + + lon = ( onPointerDownPointerX - event.touches[0].pageX ) * 0.1 + onPointerDownLon; + lat = ( event.touches[0].pageY - onPointerDownPointerY ) * 0.1 + onPointerDownLat; + + render(); + + } + + } + + function render() { + + lat = Math.max( - 85, Math.min( 85, lat ) ); + phi = THREE.Math.degToRad( 90 - lat ); + theta = THREE.Math.degToRad( lon ); + + target.x = 500 * Math.sin( phi ) * Math.cos( theta ); + target.y = 500 * Math.cos( phi ); + target.z = 500 * Math.sin( phi ) * Math.sin( theta ); + + camera.lookAt( target ); + + renderer.render( scene, camera ); + + } + +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/canvas_geometry_panorama_fisheye.html + +()=>{ + var camera, scene, renderer; + + var texture_placeholder, + isUserInteracting = false, + onPointerDownPointerX = 0, onPointerDownPointerY = 0, + lon = 90, onPointerDownLon = 0, + lat = 0, onPointerDownLat = 0, + phi = 0, theta = 0, + target = new THREE.Vector3(); + + init(); + + function init() { + + var container, mesh; + + container = document.getElementById( 'container' ); + + camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 1100 ); + + scene = new THREE.Scene(); + + texture_placeholder = document.createElement( 'canvas' ); + texture_placeholder.width = 128; + texture_placeholder.height = 128; + + var context = texture_placeholder.getContext( '2d' ); + context.fillStyle = 'rgb( 200, 200, 200 )'; + context.fillRect( 0, 0, texture_placeholder.width, texture_placeholder.height ); + + var materials = [ + + loadTexture( 'textures/cube/skybox/px.jpg' ), // right + loadTexture( 'textures/cube/skybox/nx.jpg' ), // left + loadTexture( 'textures/cube/skybox/py.jpg' ), // top + loadTexture( 'textures/cube/skybox/ny.jpg' ), // bottom + loadTexture( 'textures/cube/skybox/pz.jpg' ), // back + loadTexture( 'textures/cube/skybox/nz.jpg' ) // front + + ]; + + mesh = new THREE.Mesh( new THREE.CubeGeometry( 300, 300, 300, 7, 7, 7 ), new THREE.MeshFaceMaterial( materials ) ); + mesh.scale.x = - 1; + scene.add( mesh ); + + for ( var i = 0, l = mesh.geometry.vertices.length; i < l; i ++ ) { + + var vertex = mesh.geometry.vertices[ i ]; + + vertex.normalize(); + vertex.multiplyScalar( 550 ); + + } + + renderer = new THREE.CanvasRenderer(); + renderer.setSize( window.innerWidth, window.innerHeight ); + + container.appendChild( renderer.domElement ); + + document.addEventListener( 'mousedown', onDocumentMouseDown, false ); + document.addEventListener( 'mousemove', onDocumentMouseMove, false ); + document.addEventListener( 'mouseup', onDocumentMouseUp, false ); + document.addEventListener( 'mousewheel', onDocumentMouseWheel, false ); + document.addEventListener( 'DOMMouseScroll', onDocumentMouseWheel, false); + + document.addEventListener( 'touchstart', onDocumentTouchStart, false ); + document.addEventListener( 'touchmove', onDocumentTouchMove, false ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + render(); + + } + + function loadTexture( path ) { + + var texture = new THREE.Texture( texture_placeholder ); + var material = new THREE.MeshBasicMaterial( { map: texture, overdraw: true } ); + + var image = new Image(); + image.onload = function () { + + texture.needsUpdate = true; + material.map.image = this; + + render(); + + }; + image.src = path; + + return material; + + } + + function onDocumentMouseDown( event ) { + + event.preventDefault(); + + isUserInteracting = true; + + onPointerDownPointerX = event.clientX; + onPointerDownPointerY = event.clientY; + + onPointerDownLon = lon; + onPointerDownLat = lat; + + } + + function onDocumentMouseMove( event ) { + + if ( isUserInteracting ) { + + lon = ( onPointerDownPointerX - event.clientX ) * 0.1 + onPointerDownLon; + lat = ( event.clientY - onPointerDownPointerY ) * 0.1 + onPointerDownLat; + render(); + + } + } + + function onDocumentMouseUp( event ) { + + isUserInteracting = false; + render(); + + } + + function onDocumentMouseWheel( event ) { + + // WebKit + + if ( event.wheelDeltaY ) { + + camera.fov -= event.wheelDeltaY * 0.05; + + // Opera / Explorer 9 + + } else if ( event.wheelDelta ) { + + camera.fov -= event.wheelDelta * 0.05; + + // Firefox + + } else if ( event.detail ) { + + camera.fov -= event.detail * 0.05; + + } + + camera.updateProjectionMatrix(); + + render(); + + } + + + function onDocumentTouchStart( event ) { + + if ( event.touches.length == 1 ) { + + event.preventDefault(); + + onPointerDownPointerX = event.touches[ 0 ].pageX; + onPointerDownPointerY = event.touches[ 0 ].pageY; + + onPointerDownLon = lon; + onPointerDownLat = lat; + + } + + } + + function onDocumentTouchMove( event ) { + + if ( event.touches.length == 1 ) { + + event.preventDefault(); + + lon = ( onPointerDownPointerX - event.touches[0].pageX ) * 0.1 + onPointerDownLon; + lat = ( event.touches[0].pageY - onPointerDownPointerY ) * 0.1 + onPointerDownLat; + + render(); + + } + + } + + function render() { + + lat = Math.max( - 85, Math.min( 85, lat ) ); + phi = THREE.Math.degToRad( 90 - lat ); + theta = THREE.Math.degToRad( lon ); + + target.x = 500 * Math.sin( phi ) * Math.cos( theta ); + target.y = 500 * Math.cos( phi ); + target.z = 500 * Math.sin( phi ) * Math.sin( theta ); + + camera.position.x = - target.x; + camera.position.y = - target.y; + camera.position.z = - target.z; + camera.lookAt( target ); + + renderer.render( scene, camera ); + + } + +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/canvas_geometry_shapes.html + +()=>{ +var container, stats; + + var camera, scene, renderer; + + var 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 parent; + + init(); + animate(); + + function init() { + + container = document.createElement( 'div' ); + document.body.appendChild( container ); + + camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 1000 ); + camera.position.set( 0, 150, 500 ); + + scene = new THREE.Scene(); + + parent = new THREE.Object3D(); + parent.position.y = 50; + scene.add( parent ); + + function addShape( shape, color, x, y, z, rx, ry, rz, s ) { + + // flat shape + + var geometry = new THREE.ShapeGeometry( shape ); + var materialMesh = new THREE.MeshBasicMaterial( { color: color, overdraw: true } ); + + var mesh = new THREE.Mesh( geometry, materialMesh ); + mesh.position.set( x, y, z ); + mesh.rotation.set( rx, ry, rz ); + mesh.scale.set( s, s, s ); + parent.add( mesh ); + + // line + + var geometry = shape.createPointsGeometry(); + var materialLine = new THREE.LineBasicMaterial( { linewidth: 10, color: 0x333333, transparent: true } ); + + var line = new THREE.Line( geometry, materialLine ); + line.position.set( x, y, z ); + line.rotation.set( rx, ry, rz ); + line.scale.set( s, s, s ); + parent.add( line ); + + } + + + // California + + var californiaPts = []; + + californiaPts.push( new THREE.Vector2 ( 610, 320 ) ); + californiaPts.push( new THREE.Vector2 ( 450, 300 ) ); + californiaPts.push( new THREE.Vector2 ( 392, 392 ) ); + californiaPts.push( new THREE.Vector2 ( 266, 438 ) ); + californiaPts.push( new THREE.Vector2 ( 190, 570 ) ); + californiaPts.push( new THREE.Vector2 ( 190, 600 ) ); + californiaPts.push( new THREE.Vector2 ( 160, 620 ) ); + californiaPts.push( new THREE.Vector2 ( 160, 650 ) ); + californiaPts.push( new THREE.Vector2 ( 180, 640 ) ); + californiaPts.push( new THREE.Vector2 ( 165, 680 ) ); + californiaPts.push( new THREE.Vector2 ( 150, 670 ) ); + californiaPts.push( new THREE.Vector2 ( 90, 737 ) ); + californiaPts.push( new THREE.Vector2 ( 80, 795 ) ); + californiaPts.push( new THREE.Vector2 ( 50, 835 ) ); + californiaPts.push( new THREE.Vector2 ( 64, 870 ) ); + californiaPts.push( new THREE.Vector2 ( 60, 945 ) ); + californiaPts.push( new THREE.Vector2 ( 300, 945 ) ); + californiaPts.push( new THREE.Vector2 ( 300, 743 ) ); + californiaPts.push( new THREE.Vector2 ( 600, 473 ) ); + californiaPts.push( new THREE.Vector2 ( 626, 425 ) ); + californiaPts.push( new THREE.Vector2 ( 600, 370 ) ); + californiaPts.push( new THREE.Vector2 ( 610, 320 ) ); + + var californiaShape = new THREE.Shape( californiaPts ); + + + // Triangle + + var triangleShape = new THREE.Shape(); + triangleShape.moveTo( 80, 20 ); + triangleShape.lineTo( 40, 80 ); + triangleShape.lineTo( 120, 80 ); + triangleShape.lineTo( 80, 20 ); // close path + + + // Heart + + var x = 0, y = 0; + + var heartShape = new THREE.Shape(); // From http://blog.burlock.org/html5/130-paths + + 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 ); + + + // Square + + var sqLength = 80; + + var squareShape = new THREE.Shape(); + squareShape.moveTo( 0,0 ); + squareShape.lineTo( 0, sqLength ); + squareShape.lineTo( sqLength, sqLength ); + squareShape.lineTo( sqLength, 0 ); + squareShape.lineTo( 0, 0 ); + + + // Rectangle + + var rectLength = 120, rectWidth = 40; + + var rectShape = new THREE.Shape(); + rectShape.moveTo( 0,0 ); + rectShape.lineTo( 0, rectWidth ); + rectShape.lineTo( rectLength, rectWidth ); + rectShape.lineTo( rectLength, 0 ); + rectShape.lineTo( 0, 0 ); + + + // Rounded rectangle + + var roundedRectShape = new THREE.Shape(); + + ( function roundedRect( ctx, x, y, width, height, radius ){ + + ctx.moveTo( x, y + radius ); + ctx.lineTo( x, y + height - radius ); + ctx.quadraticCurveTo( x, y + height, x + radius, y + height ); + ctx.lineTo( x + width - radius, y + height) ; + ctx.quadraticCurveTo( x + width, y + height, x + width, y + height - radius ); + ctx.lineTo( x + width, y + radius ); + ctx.quadraticCurveTo( x + width, y, x + width - radius, y ); + ctx.lineTo( x + radius, y ); + ctx.quadraticCurveTo( x, y, x, y + radius ); + + } )( roundedRectShape, 0, 0, 50, 50, 20 ); + + + // Circle + + var circleRadius = 40; + var circleShape = new THREE.Shape(); + circleShape.moveTo( 0, circleRadius ); + circleShape.quadraticCurveTo( circleRadius, circleRadius, circleRadius, 0 ); + circleShape.quadraticCurveTo( circleRadius, -circleRadius, 0, -circleRadius ); + circleShape.quadraticCurveTo( -circleRadius, -circleRadius, -circleRadius, 0 ); + circleShape.quadraticCurveTo( -circleRadius, circleRadius, 0, circleRadius ); + + + // Fish + + x = y = 0; + + var fishShape = new THREE.Shape(); + + fishShape.moveTo(x,y); + fishShape.quadraticCurveTo(x + 50, y - 80, x + 90, y - 10); + fishShape.quadraticCurveTo(x + 100, y - 10, x + 115, y - 40); + fishShape.quadraticCurveTo(x + 115, y, x + 115, y + 40); + fishShape.quadraticCurveTo(x + 100, y + 10, x + 90, y + 10); + fishShape.quadraticCurveTo(x + 50, y + 80, x, y); + + + // Arc circle + + var arcShape = new THREE.Shape(); + arcShape.moveTo( 50, 10 ); + arcShape.absarc( 10, 10, 40, 0, Math.PI*2, false ); + + var holePath = new THREE.Path(); + holePath.moveTo( 20, 10 ); + holePath.absarc( 10, 10, 10, 0, Math.PI*2, true ); + arcShape.holes.push( holePath ); + + + // Smiley + + var smileyShape = new THREE.Shape(); + smileyShape.moveTo( 80, 40 ); + smileyShape.absarc( 40, 40, 40, 0, Math.PI*2, false ); + + var smileyEye1Path = new THREE.Path(); + smileyEye1Path.moveTo( 35, 20 ); + // smileyEye1Path.absarc( 25, 20, 10, 0, Math.PI*2, true ); + smileyEye1Path.absellipse( 25, 20, 10, 10, 0, Math.PI*2, true ); + + smileyShape.holes.push( smileyEye1Path ); + + var smileyEye2Path = new THREE.Path(); + smileyEye2Path.moveTo( 65, 20 ); + smileyEye2Path.absarc( 55, 20, 10, 0, Math.PI*2, true ); + smileyShape.holes.push( smileyEye2Path ); + + var smileyMouthPath = new THREE.Path(); + // ugly box mouth + // smileyMouthPath.moveTo( 20, 40 ); + // smileyMouthPath.lineTo( 60, 40 ); + // smileyMouthPath.lineTo( 60, 60 ); + // smileyMouthPath.lineTo( 20, 60 ); + // smileyMouthPath.lineTo( 20, 40 ); + + smileyMouthPath.moveTo( 20, 40 ); + smileyMouthPath.quadraticCurveTo( 40, 60, 60, 40 ); + smileyMouthPath.bezierCurveTo( 70, 45, 70, 50, 60, 60 ); + smileyMouthPath.quadraticCurveTo( 40, 80, 20, 60 ); + smileyMouthPath.quadraticCurveTo( 5, 50, 20, 40 ); + + smileyShape.holes.push( smileyMouthPath ); + + + // Spline shape + path extrusion + + var splinepts = []; + splinepts.push( new THREE.Vector2 ( 350, 100 ) ); + splinepts.push( new THREE.Vector2 ( 400, 450 ) ); + splinepts.push( new THREE.Vector2 ( -140, 350 ) ); + splinepts.push( new THREE.Vector2 ( 0, 0 ) ); + + var splineShape = new THREE.Shape( ); + splineShape.moveTo( 0, 0 ); + splineShape.splineThru( splinepts ); + + + // addShape( shape, color, x, y, z, rx, ry,rz, s ); + + addShape( californiaShape, 0xffaa00, -300, -100, 0, 0, 0, 0, 0.25 ); + addShape( triangleShape, 0xffee00, -180, 0, 0, 0, 0, 0, 1 ); + addShape( roundedRectShape, 0x005500, -150, 150, 0, 0, 0, 0, 1 ); + addShape( squareShape, 0x0055ff, 150, 100, 0, 0, 0, 0, 1 ); + addShape( heartShape, 0xff1100, 60, 100, 0, 0, 0, Math.PI, 1 ); + addShape( circleShape, 0x00ff11, 120, 250, 0, 0, 0, 0, 1 ); + addShape( fishShape, 0x222222, -60, 200, 0, 0, 0, 0, 1 ); + addShape( smileyShape, 0xee00ff, -200, 250, 0, 0, 0, Math.PI, 1 ); + addShape( arcShape, 0xbb4422, 150, 0, 0, 0, 0, 0, 1 ); + addShape( splineShape, 0x888888, -50, -100, 0, 0, 0, 0, 0.2 ); + + // + + renderer = new THREE.CanvasRenderer( { antialias: true } ); + renderer.setSize( window.innerWidth, window.innerHeight ); + renderer.sortObjects = false; + renderer.sortElements = false; + 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 ); + + } + + // + + function onDocumentMouseDown( event ) { + + event.preventDefault(); + + document.addEventListener( 'mousemove', onDocumentMouseMove, false ); + document.addEventListener( 'mouseup', onDocumentMouseUp, false ); + document.addEventListener( 'mouseout', onDocumentMouseOut, false ); + + mouseXOnMouseDown = event.clientX - windowHalfX; + targetRotationOnMouseDown = targetRotation; + + } + + function onDocumentMouseMove( event ) { + + mouseX = event.clientX - windowHalfX; + + targetRotation = targetRotationOnMouseDown + ( mouseX - mouseXOnMouseDown ) * 0.02; + + } + + function onDocumentMouseUp( event ) { + + document.removeEventListener( 'mousemove', onDocumentMouseMove, false ); + document.removeEventListener( 'mouseup', onDocumentMouseUp, false ); + document.removeEventListener( 'mouseout', onDocumentMouseOut, false ); + + } + + function onDocumentMouseOut( event ) { + + document.removeEventListener( 'mousemove', onDocumentMouseMove, false ); + document.removeEventListener( 'mouseup', onDocumentMouseUp, false ); + document.removeEventListener( 'mouseout', onDocumentMouseOut, false ); + + } + + 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() { + + parent.rotation.y += ( targetRotation - parent.rotation.y ) * 0.05; + renderer.render( scene, camera ); + + } + +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/canvas_interactive_cubes.html + +()=>{ + var container, stats; + var camera, scene, projector, renderer; + var particleMaterial; + + var objects = []; + + 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 - clickable objects'; + container.appendChild( info ); + + camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 10000 ); + camera.position.set( 0, 300, 500 ); + + scene = new THREE.Scene(); + + var geometry = new THREE.CubeGeometry( 100, 100, 100 ); + + for ( var i = 0; i < 10; i ++ ) { + + var object = new THREE.Mesh( geometry, new THREE.MeshBasicMaterial( { color: Math.random() * 0xffffff, opacity: 0.5 } ) ); + object.position.x = Math.random() * 800 - 400; + object.position.y = Math.random() * 800 - 400; + object.position.z = Math.random() * 800 - 400; + + object.scale.x = Math.random() * 2 + 1; + object.scale.y = Math.random() * 2 + 1; + object.scale.z = Math.random() * 2 + 1; + + object.rotation.x = Math.random() * 2 * Math.PI; + object.rotation.y = Math.random() * 2 * Math.PI; + object.rotation.z = Math.random() * 2 * Math.PI; + + scene.add( object ); + + objects.push( object ); + + } + + var PI2 = Math.PI * 2; + particleMaterial = new THREE.ParticleCanvasMaterial( { + + color: 0x000000, + program: function ( context ) { + + context.beginPath(); + context.arc( 0, 0, 1, 0, PI2, true ); + context.closePath(); + context.fill(); + + } + + } ); + + projector = new THREE.Projector(); + + renderer = new THREE.CanvasRenderer(); + 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 ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + } + + function onDocumentMouseDown( event ) { + + event.preventDefault(); + + var vector = new THREE.Vector3( ( event.clientX / window.innerWidth ) * 2 - 1, - ( event.clientY / window.innerHeight ) * 2 + 1, 0.5 ); + projector.unprojectVector( vector, camera ); + + var raycaster = new THREE.Raycaster( camera.position, vector.sub( camera.position ).normalize() ); + + var intersects = raycaster.intersectObjects( objects ); + + if ( intersects.length > 0 ) { + + var mesh = intersects[ 0 ].object; + var mat = mesh.material; + mat.color.setHex( Math.random() * 0xffffff ); + + var particle = new THREE.Particle( particleMaterial ); + particle.position = intersects[ 0 ].point; + particle.scale.x = particle.scale.y = 8; + scene.add( particle ); + + } + + /* + // Parse all the faces + for ( var i in intersects ) { + + intersects[ i ].face.material[ 0 ].color.setHex( Math.random() * 0xffffff | 0x80000000 ); + + } + */ + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + var radius = 600; + var theta = 0; + + function render() { + + theta += 0.1; + + camera.position.x = radius * Math.sin( THREE.Math.degToRad( theta ) ); + camera.position.y = radius * Math.sin( THREE.Math.degToRad( theta ) ); + camera.position.z = radius * Math.cos( THREE.Math.degToRad( theta ) ); + camera.lookAt( scene.position ); + + renderer.render( scene, camera ); + + } +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/canvas_interactive_particles.html + +()=>{ + var container, stats; + var camera, scene, projector, renderer; + + var PI2 = Math.PI * 2; + + var programFill = function ( context ) { + + context.beginPath(); + context.arc( 0, 0, 1, 0, PI2, true ); + context.closePath(); + context.fill(); + + } + + var programStroke = function ( context ) { + + context.lineWidth = 0.05; + context.beginPath(); + context.arc( 0, 0, 1, 0, PI2, true ); + context.closePath(); + context.stroke(); + + } + + var mouse = { x: 0, y: 0 }, INTERSECTED; + + 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 canvas - interactive particles'; + container.appendChild( info ); + + camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 10000 ); + camera.position.set( 0, 300, 500 ); + + scene = new THREE.Scene(); + + for ( var i = 0; i < 100; i ++ ) { + + var particle = new THREE.Particle( new THREE.ParticleCanvasMaterial( { color: Math.random() * 0x808080 + 0x808080, program: programStroke } ) ); + particle.position.x = Math.random() * 800 - 400; + particle.position.y = Math.random() * 800 - 400; + particle.position.z = Math.random() * 800 - 400; + particle.scale.x = particle.scale.y = Math.random() * 10 + 10; + scene.add( particle ); + + } + + projector = new THREE.Projector(); + + renderer = new THREE.CanvasRenderer(); + 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( 'mousemove', onDocumentMouseMove, false ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + } + + function onDocumentMouseMove( event ) { + + event.preventDefault(); + + mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1; + mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1; + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + var radius = 600; + var theta = 0; + + function render() { + + // rotate camera + + theta += 0.1; + + camera.position.x = radius * Math.sin( THREE.Math.degToRad( theta ) ); + camera.position.y = radius * Math.sin( THREE.Math.degToRad( theta ) ); + camera.position.z = radius * Math.cos( THREE.Math.degToRad( theta ) ); + camera.lookAt( scene.position ); + + // find intersections + + camera.updateMatrixWorld(); + + var vector = new THREE.Vector3( mouse.x, mouse.y, 0.5 ); + projector.unprojectVector( vector, camera ); + + var raycaster = new THREE.Raycaster( camera.position, vector.sub( camera.position ).normalize() ); + + var intersects = raycaster.intersectObjects( scene.children ); + + if ( intersects.length > 0 ) { + + if ( INTERSECTED != intersects[ 0 ].object ) { + + if ( INTERSECTED ) INTERSECTED.material.program = programStroke; + + INTERSECTED = intersects[ 0 ].object; + INTERSECTED.material.program = programFill; + + } + + } else { + + if ( INTERSECTED ) INTERSECTED.material.program = programStroke; + + INTERSECTED = null; + + } + + renderer.render( scene, camera ); + + } +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/canvas_camera_orthographic.html + +()=>{ + var container, stats; + var camera, scene, renderer; + + 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 - orthographic view'; + container.appendChild( info ); + + camera = new THREE.OrthographicCamera( window.innerWidth / - 2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / - 2, - 500, 1000 ); + camera.position.x = 200; + camera.position.y = 100; + camera.position.z = 200; + + scene = new THREE.Scene(); + + // Grid + + var size = 500, step = 50; + + var geometry = new THREE.Geometry(); + + for ( var i = - size; i <= size; i += step ) { + + geometry.vertices.push( new THREE.Vector3( - size, 0, i ) ); + geometry.vertices.push( new THREE.Vector3( size, 0, i ) ); + + geometry.vertices.push( new THREE.Vector3( i, 0, - size ) ); + geometry.vertices.push( new THREE.Vector3( i, 0, size ) ); + + } + + var lineMaterial = new THREE.LineBasicMaterial( { color: 0x000000, opacity: 0.2 } ); + + var line = new THREE.Line( geometry, lineMaterial ); + line.type = THREE.LinePieces; + scene.add( line ); + + // Cubes + + var geometry = new THREE.CubeGeometry( 50, 50, 50 ); + var cubeMaterial = new THREE.MeshLambertMaterial( { color: 0xffffff, shading: THREE.FlatShading, overdraw: true } ); + + for ( var i = 0; i < 100; i ++ ) { + + var cube = new THREE.Mesh( geometry, cubeMaterial ); + + cube.scale.y = Math.floor( Math.random() * 2 + 1 ); + + cube.position.x = Math.floor( ( Math.random() * 1000 - 500 ) / 50 ) * 50 + 25; + cube.position.y = ( cube.scale.y * 50 ) / 2; + cube.position.z = Math.floor( ( Math.random() * 1000 - 500 ) / 50 ) * 50 + 25; + + scene.add( cube ); + + } + + // Lights + + var ambientLight = new THREE.AmbientLight( Math.random() * 0x10 ); + scene.add( ambientLight ); + + var directionalLight = new THREE.DirectionalLight( Math.random() * 0xffffff ); + directionalLight.position.x = Math.random() - 0.5; + directionalLight.position.y = Math.random() - 0.5; + directionalLight.position.z = Math.random() - 0.5; + directionalLight.position.normalize(); + scene.add( directionalLight ); + + var directionalLight = new THREE.DirectionalLight( Math.random() * 0xffffff ); + directionalLight.position.x = Math.random() - 0.5; + directionalLight.position.y = Math.random() - 0.5; + directionalLight.position.z = Math.random() - 0.5; + directionalLight.position.normalize(); + scene.add( directionalLight ); + + renderer = new THREE.CanvasRenderer(); + 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 ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + camera.left = window.innerWidth / - 2; + camera.right = window.innerWidth / 2; + camera.top = window.innerHeight / 2; + camera.bottom = window.innerHeight / - 2; + + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + var timer = Date.now() * 0.0001; + + camera.position.x = Math.cos( timer ) * 200; + camera.position.z = Math.sin( timer ) * 200; + camera.lookAt( scene.position ); + + renderer.render( scene, camera ); + + } + +}; + + +// https://github.com/mrdoob/three.js/blob/master/examples/canvas_interactive_voxelpainter.html + +()=>{ + var container, stats; + var camera, scene, renderer; + var projector, plane; + var mouse2D, mouse3D, raycaster, theta = 45, + isShiftDown = false, isCtrlDown = false, + target = new THREE.Vector3( 0, 200, 0 ); + var ROLLOVERED; + + 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 - voxel painter
click: add voxel, control + click: remove voxel, shift: rotate, save .png'; + container.appendChild( info ); + + camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 10000 ); + camera.position.y = 800; + + scene = new THREE.Scene(); + + // Grid + + var size = 500, step = 50; + + var geometry = new THREE.Geometry(); + + for ( var i = - size; i <= size; i += step ) { + + geometry.vertices.push( new THREE.Vector3( - size, 0, i ) ); + geometry.vertices.push( new THREE.Vector3( size, 0, i ) ); + + geometry.vertices.push( new THREE.Vector3( i, 0, - size ) ); + geometry.vertices.push( new THREE.Vector3( i, 0, size ) ); + + } + + var material = new THREE.LineBasicMaterial( { color: 0x000000, opacity: 0.2 } ); + + var line = new THREE.Line( geometry, material ); + line.type = THREE.LinePieces; + scene.add( line ); + + // + + projector = new THREE.Projector(); + + plane = new THREE.Mesh( new THREE.PlaneGeometry( 1000, 1000 ), new THREE.MeshBasicMaterial() ); + plane.rotation.x = - Math.PI / 2; + plane.visible = false; + scene.add( plane ); + + mouse2D = new THREE.Vector3( 0, 10000, 0.5 ); + + // Lights + + var ambientLight = new THREE.AmbientLight( 0x606060 ); + scene.add( ambientLight ); + + var directionalLight = new THREE.DirectionalLight( 0xffffff ); + directionalLight.position.x = Math.random() - 0.5; + directionalLight.position.y = Math.random() - 0.5; + directionalLight.position.z = Math.random() - 0.5; + directionalLight.position.normalize(); + scene.add( directionalLight ); + + var directionalLight = new THREE.DirectionalLight( 0x808080 ); + directionalLight.position.x = Math.random() - 0.5; + directionalLight.position.y = Math.random() - 0.5; + directionalLight.position.z = Math.random() - 0.5; + directionalLight.position.normalize(); + scene.add( directionalLight ); + + renderer = new THREE.CanvasRenderer(); + 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( 'mousemove', onDocumentMouseMove, false ); + document.addEventListener( 'mousedown', onDocumentMouseDown, false ); + document.addEventListener( 'keydown', onDocumentKeyDown, false ); + document.addEventListener( 'keyup', onDocumentKeyUp, false ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + } + + function onDocumentMouseMove( event ) { + + event.preventDefault(); + + mouse2D.x = ( event.clientX / window.innerWidth ) * 2 - 1; + mouse2D.y = - ( event.clientY / window.innerHeight ) * 2 + 1; + + var intersects = raycaster.intersectObjects( scene.children ); + + if ( intersects.length > 0 ) { + + if ( ROLLOVERED ) ROLLOVERED.color.setHex( 0x00ff80 ); + + ROLLOVERED = intersects[ 0 ].face; + ROLLOVERED.color.setHex( 0xff8000 ) + + } + + } + + function onDocumentMouseDown( event ) { + + event.preventDefault(); + + var intersects = raycaster.intersectObjects( scene.children ); + + if ( intersects.length > 0 ) { + + var interect = intersects[ 0 ]; + + if ( isCtrlDown ) { + + if ( interect.object != plane ) { + + scene.remove( interect.object ); + + } + + } else { + + var normal = interect.face.normal.clone(); + normal.applyMatrix4( interect.object.matrixRotationWorld ); + + var position = new THREE.Vector3().addVectors( interect.point, normal ); + + var geometry = new THREE.CubeGeometry( 50, 50, 50 ); + + for ( var i = 0; i < geometry.faces.length; i ++ ) { + + geometry.faces[ i ].color.setHex( 0x00ff80 ); + + } + + var material = new THREE.MeshLambertMaterial( { vertexColors: THREE.FaceColors } ); + + var voxel = new THREE.Mesh( geometry, material ); + voxel.position.x = Math.floor( position.x / 50 ) * 50 + 25; + voxel.position.y = Math.floor( position.y / 50 ) * 50 + 25; + voxel.position.z = Math.floor( position.z / 50 ) * 50 + 25; + voxel.matrixAutoUpdate = false; + voxel.updateMatrix(); + scene.add( voxel ); + + } + + } + } + + function onDocumentKeyDown( event ) { + + switch( event.keyCode ) { + + case 16: isShiftDown = true; break; + case 17: isCtrlDown = true; break; + + } + + } + + function onDocumentKeyUp( event ) { + + switch( event.keyCode ) { + + case 16: isShiftDown = false; break; + case 17: isCtrlDown = false; break; + + } + } + + function save() { + + window.open( renderer.domElement.toDataURL('image/png'), 'mywindow' ); + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + if ( isShiftDown ) { + + theta += mouse2D.x * 3; + + } + + camera.position.x = 1400 * Math.sin( theta * Math.PI / 360 ); + camera.position.z = 1400 * Math.cos( theta * Math.PI / 360 ); + camera.lookAt( target ); + + raycaster = projector.pickingRay( mouse2D.clone(), camera ); + + renderer.render( scene, camera ); + + } +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/canvas_lights_pointlights.html + +()=>{ + var camera, scene, renderer, + particle1, particle2, particle3, + light1, light2, light3, + loader, mesh; + + init(); + animate(); + + function init() { + + var container = document.getElementById( 'container' ); + + camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 1000 ); + camera.position.set( 0, - 6, 100 ); + + scene = new THREE.Scene(); + + scene.add( new THREE.AmbientLight( 0x00020 ) ); + + light1 = new THREE.PointLight( 0xff0040, 1, 50 ); + scene.add( light1 ); + + light2 = new THREE.PointLight( 0x0040ff, 1, 50 ); + scene.add( light2 ); + + light3 = new THREE.PointLight( 0x80ff80, 1, 50 ); + scene.add( light3 ); + + var PI2 = Math.PI * 2; + var program = function ( context ) { + + context.beginPath(); + context.arc( 0, 0, 1, 0, PI2, true ); + context.fill(); + + } + + particle1 = new THREE.Particle( new THREE.ParticleCanvasMaterial( { color: 0xff0040, program: program } ) ); + particle1.scale.x = particle1.scale.y = particle1.scale.z = 0.5; + scene.add( particle1 ); + + particle2 = new THREE.Particle( new THREE.ParticleCanvasMaterial( { color: 0x0040ff, program: program } ) ); + particle2.scale.x = particle2.scale.y = particle2.scale.z = 0.5; + scene.add( particle2 ); + + particle3 = new THREE.Particle( new THREE.ParticleCanvasMaterial( { color: 0x80ff80, program: program } ) ); + particle3.scale.x = particle3.scale.y = particle3.scale.z = 0.5; + scene.add( particle3 ); + + loader = new THREE.JSONLoader(); + loader.load( 'obj/WaltHeadLo.js', function ( geometry ) { + + mesh = new THREE.Mesh( geometry, new THREE.MeshLambertMaterial( { color: 0xffffff, shading: THREE.FlatShading, overdraw: true } ) ); + scene.add( mesh ); + + } ); + + renderer = new THREE.CanvasRenderer(); + renderer.setSize( window.innerWidth, window.innerHeight ); + container.appendChild( renderer.domElement ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + render(); + + } + + function render() { + + var time = Date.now() * 0.0005; + + if ( mesh ) mesh.rotation.y -= 0.01; + + particle1.position.x = Math.sin( time * 0.7 ) * 30; + particle1.position.y = Math.cos( time * 0.5 ) * 40; + particle1.position.z = Math.cos( time * 0.3 ) * 30; + + light1.position.x = particle1.position.x; + light1.position.y = particle1.position.y; + light1.position.z = particle1.position.z; + + particle2.position.x = Math.cos( time * 0.3 ) * 30; + particle2.position.y = Math.sin( time * 0.5 ) * 40; + particle2.position.z = Math.sin( time * 0.7 ) * 30; + + light2.position.x = particle2.position.x; + light2.position.y = particle2.position.y; + light2.position.z = particle2.position.z; + + particle3.position.x = Math.sin( time * 0.7 ) * 30; + particle3.position.y = Math.cos( time * 0.3 ) * 40; + particle3.position.z = Math.sin( time * 0.5 ) * 30; + + light3.position.x = particle3.position.x; + light3.position.y = particle3.position.y; + light3.position.z = particle3.position.z; + + renderer.render( scene, camera ); + + } +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/canvas_lights_pointlights_smooth.html + +()=>{ + var camera, scene, renderer, + particle1, particle2, particle3, + light1, light2, light3, + loader, mesh; + + init(); + animate(); + + function init() { + + var container = document.getElementById( 'container' ); + + camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 1000 ); + camera.position.set( 0, - 6, 100 ); + + scene = new THREE.Scene(); + + scene.add( new THREE.AmbientLight( 0x00020 ) ); + + light1 = new THREE.PointLight( 0xff0040, 1, 50 ); + scene.add( light1 ); + + light2 = new THREE.PointLight( 0x0040ff, 1, 50 ); + scene.add( light2 ); + + light3 = new THREE.PointLight( 0x80ff80, 1, 50 ); + scene.add( light3 ); + + var PI2 = Math.PI * 2; + var program = function ( context ) { + + context.beginPath(); + context.arc( 0, 0, 1, 0, PI2, true ); + context.fill(); + + } + + particle1 = new THREE.Particle( new THREE.ParticleCanvasMaterial( { color: 0xff0040, program: program } ) ); + particle1.scale.x = particle1.scale.y = particle1.scale.z = 0.5; + scene.add( particle1 ); + + particle2 = new THREE.Particle( new THREE.ParticleCanvasMaterial( { color: 0x0040ff, program: program } ) ); + particle2.scale.x = particle2.scale.y = particle2.scale.z = 0.5; + scene.add( particle2 ); + + particle3 = new THREE.Particle( new THREE.ParticleCanvasMaterial( { color: 0x80ff80, program: program } ) ); + particle3.scale.x = particle3.scale.y = particle3.scale.z = 0.5; + scene.add( particle3 ); + + loader = new THREE.JSONLoader(); + loader.load( 'obj/WaltHeadLo.js', function ( geometry ) { + + geometry.computeVertexNormals(); + + mesh = new THREE.Mesh( geometry, new THREE.MeshLambertMaterial( { color: 0xffffff, overdraw: true } ) ); + scene.add( mesh ); + + } ); + + renderer = new THREE.CanvasRenderer(); + renderer.setSize( window.innerWidth, window.innerHeight ); + container.appendChild( renderer.domElement ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + + } + + function render() { + + var time = Date.now() * 0.0005; + + if ( mesh ) mesh.rotation.y -= 0.01; + + particle1.position.x = Math.sin( time * 0.7 ) * 30; + particle1.position.y = Math.cos( time * 0.5 ) * 40; + particle1.position.z = Math.cos( time * 0.3 ) * 30; + + light1.position.x = particle1.position.x; + light1.position.y = particle1.position.y; + light1.position.z = particle1.position.z; + + particle2.position.x = Math.cos( time * 0.3 ) * 30; + particle2.position.y = Math.sin( time * 0.5 ) * 40; + particle2.position.z = Math.sin( time * 0.7 ) * 30; + + light2.position.x = particle2.position.x; + light2.position.y = particle2.position.y; + light2.position.z = particle2.position.z; + + particle3.position.x = Math.sin( time * 0.7 ) * 30; + particle3.position.y = Math.cos( time * 0.3 ) * 40; + particle3.position.z = Math.sin( time * 0.5 ) * 30; + + light3.position.x = particle3.position.x; + light3.position.y = particle3.position.y; + light3.position.z = particle3.position.z; + + renderer.render( scene, camera ); + + } +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/canvas_lines.html + +()=>{ + + var mouseX = 0, mouseY = 0, + + windowHalfX = window.innerWidth / 2, + windowHalfY = window.innerHeight / 2, + + SEPARATION = 200, + AMOUNTX = 10, + AMOUNTY = 10, + + camera, scene, renderer; + + init(); + animate(); + + function init() { + + var container, separation = 100, amountX = 50, amountY = 50, + particles, particle; + + container = document.createElement('div'); + document.body.appendChild(container); + + camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 10000 ); + camera.position.z = 100; + + scene = new THREE.Scene(); + + renderer = new THREE.CanvasRenderer(); + renderer.setSize( window.innerWidth, window.innerHeight ); + container.appendChild( renderer.domElement ); + + // particles + + var PI2 = Math.PI * 2; + var material = new THREE.ParticleCanvasMaterial( { + + color: 0xffffff, + program: function ( context ) { + + context.beginPath(); + context.arc( 0, 0, 1, 0, PI2, true ); + context.closePath(); + context.fill(); + + } + + } ); + + var geometry = new THREE.Geometry(); + + for ( var i = 0; i < 100; i ++ ) { + + particle = new THREE.Particle( material ); + particle.position.x = Math.random() * 2 - 1; + particle.position.y = Math.random() * 2 - 1; + particle.position.z = Math.random() * 2 - 1; + particle.position.normalize(); + particle.position.multiplyScalar( Math.random() * 10 + 450 ); + particle.scale.x = particle.scale.y = 5; + scene.add( particle ); + + geometry.vertices.push( particle.position ); + + } + + // lines + + var line = new THREE.Line( geometry, new THREE.LineBasicMaterial( { color: 0xffffff, opacity: 0.5 } ) ); + scene.add( line ); + + document.addEventListener( 'mousemove', onDocumentMouseMove, 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 ); + + } + + // + + function onDocumentMouseMove(event) { + + mouseX = event.clientX - windowHalfX; + mouseY = event.clientY - windowHalfY; + + } + + function onDocumentTouchStart( event ) { + + if ( event.touches.length > 1 ) { + + event.preventDefault(); + + mouseX = event.touches[ 0 ].pageX - windowHalfX; + mouseY = event.touches[ 0 ].pageY - windowHalfY; + + } + + } + + function onDocumentTouchMove( event ) { + + if ( event.touches.length == 1 ) { + + event.preventDefault(); + + mouseX = event.touches[ 0 ].pageX - windowHalfX; + mouseY = event.touches[ 0 ].pageY - windowHalfY; + + } + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + + } + + function render() { + + camera.position.x += ( mouseX - camera.position.x ) * .05; + camera.position.y += ( - mouseY + 200 - camera.position.y ) * .05; + camera.lookAt( scene.position ); + + renderer.render( scene, camera ); + + } +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/canvas_lines_sphere.html + +()=>{ + + var SCREEN_WIDTH = window.innerWidth, + SCREEN_HEIGHT = window.innerHeight, + + mouseX = 0, mouseY = 0, + + windowHalfX = window.innerWidth / 2, + windowHalfY = window.innerHeight / 2, + + SEPARATION = 200, + AMOUNTX = 10, + AMOUNTY = 10, + + camera, scene, renderer; + + init(); + animate(); + + function init() { + + var container, separation = 100, amountX = 50, amountY = 50, + particles, particle; + + container = document.createElement('div'); + document.body.appendChild(container); + + camera = new THREE.PerspectiveCamera( 75, SCREEN_WIDTH / SCREEN_HEIGHT, 1, 10000 ); + camera.position.z = 1000; + + scene = new THREE.Scene(); + + renderer = new THREE.CanvasRenderer(); + renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT ); + container.appendChild( renderer.domElement ); + + // particles + + var PI2 = Math.PI * 2; + var material = new THREE.ParticleCanvasMaterial( { + + color: 0xffffff, + program: function ( context ) { + + context.beginPath(); + context.arc( 0, 0, 1, 0, PI2, true ); + context.closePath(); + context.fill(); + + } + + } ); + + for ( var i = 0; i < 1000; i ++ ) { + + particle = new THREE.Particle( material ); + particle.position.x = Math.random() * 2 - 1; + particle.position.y = Math.random() * 2 - 1; + particle.position.z = Math.random() * 2 - 1; + particle.position.normalize(); + particle.position.multiplyScalar( Math.random() * 10 + 450 ); + scene.add( particle ); + + } + + // lines + + for (var i = 0; i < 300; i++) { + + var geometry = new THREE.Geometry(); + + var vertex = new THREE.Vector3( Math.random() * 2 - 1, Math.random() * 2 - 1, Math.random() * 2 - 1 ); + vertex.normalize(); + vertex.multiplyScalar( 450 ); + + geometry.vertices.push( vertex ); + + var vertex2 = vertex.clone(); + vertex2.multiplyScalar( Math.random() * 0.3 + 1 ); + + geometry.vertices.push( vertex2 ); + + var line = new THREE.Line( geometry, new THREE.LineBasicMaterial( { color: 0xffffff, opacity: Math.random() } ) ); + scene.add( line ); + } + + document.addEventListener( 'mousemove', onDocumentMouseMove, 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 ); + + } + + // + + function onDocumentMouseMove(event) { + + mouseX = event.clientX - windowHalfX; + mouseY = event.clientY - windowHalfY; + } + + function onDocumentTouchStart( event ) { + + if ( event.touches.length > 1 ) { + + event.preventDefault(); + + mouseX = event.touches[ 0 ].pageX - windowHalfX; + mouseY = event.touches[ 0 ].pageY - windowHalfY; + + } + + } + + function onDocumentTouchMove( event ) { + + if ( event.touches.length == 1 ) { + + event.preventDefault(); + + mouseX = event.touches[ 0 ].pageX - windowHalfX; + mouseY = event.touches[ 0 ].pageY - windowHalfY; + + } + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + + } + + function render() { + + camera.position.x += ( mouseX - camera.position.x ) * .05; + camera.position.y += ( - mouseY + 200 - camera.position.y ) * .05; + camera.lookAt( scene.position ); + + renderer.render( scene, camera ); + + } +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/canvas_materials.html + +()=>{ + + var container, stats; + + var camera, scene, renderer, objects; + var particleLight, pointLight; + + init(); + animate(); + + function init() { + + container = document.createElement('div'); + document.body.appendChild(container); + + camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2000 ); + camera.position.set( 0, 200, 800 ); + + scene = new THREE.Scene(); + + // Grid + + var size = 500, step = 100; + + var geometry = new THREE.Geometry(); + + for ( var i = - size; i <= size; i += step ) { + + geometry.vertices.push( new THREE.Vector3( - size, - 120, i ) ); + geometry.vertices.push( new THREE.Vector3( size, - 120, i ) ); + + geometry.vertices.push( new THREE.Vector3( i, - 120, - size ) ); + geometry.vertices.push( new THREE.Vector3( i, - 120, size ) ); + + } + + var material = new THREE.LineBasicMaterial( { color: 0xffffff, opacity: 0.2 } ); + + var line = new THREE.Line( geometry, material ); + line.type = THREE.LinePieces; + scene.add( line ); + + // Spheres + + var geometry = new THREE.SphereGeometry( 100, 14, 7 ); + + var materials:THREE.Material[] = [ + + new THREE.MeshBasicMaterial( { color: 0x00ffff, wireframe: true, side: THREE.DoubleSide } ), + new THREE.MeshBasicMaterial( { color: 0xff0000, blending: THREE.AdditiveBlending, side: THREE.DoubleSide } ), + new THREE.MeshLambertMaterial( { color: 0xffffff, shading: THREE.FlatShading, side: THREE.DoubleSide, overdraw: true } ), + new THREE.MeshLambertMaterial( { color: 0xffffff, shading: THREE.SmoothShading, overdraw: true } ), + new THREE.MeshDepthMaterial( { overdraw: true } ), + new THREE.MeshNormalMaterial( { overdraw: true } ), + new THREE.MeshNormalMaterial( { shading: THREE.SmoothShading, overdraw: true } ), + new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture( 'textures/land_ocean_ice_cloud_2048.jpg' ) } ), + new THREE.MeshBasicMaterial( { envMap: THREE.ImageUtils.loadTexture( 'textures/envmap.png', new THREE.SphericalReflectionMapping() ) } ) + + ]; + + 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 ++ ) { + + var sphere = new THREE.Mesh( geometry, materials[ i ] ); + + sphere.position.x = ( i % 5 ) * 200 - 400; + sphere.position.z = Math.floor( i / 5 ) * 200 - 200; + + sphere.rotation.x = Math.random() * 200 - 100; + sphere.rotation.y = Math.random() * 200 - 100; + sphere.rotation.z = Math.random() * 200 - 100; + + objects.push( sphere ); + + scene.add( sphere ); + + } + + var PI2 = Math.PI * 2; + var program = function ( context ) { + + context.beginPath(); + context.arc( 0, 0, 1, 0, PI2, true ); + context.closePath(); + context.fill(); + + } + + particleLight = new THREE.Particle( new THREE.ParticleCanvasMaterial( { color: 0xffffff, program: program } ) ); + particleLight.scale.x = particleLight.scale.y = particleLight.scale.z = 4; + scene.add( particleLight ); + + // Lights + + scene.add( new THREE.AmbientLight( Math.random() * 0x202020 ) ); + + var directionalLight = new THREE.DirectionalLight( Math.random() * 0xffffff ); + directionalLight.position.x = Math.random() - 0.5; + directionalLight.position.y = Math.random() - 0.5; + directionalLight.position.z = Math.random() - 0.5; + directionalLight.position.normalize(); + scene.add( directionalLight ); + + pointLight = new THREE.PointLight( 0xffffff, 1 ); + scene.add( pointLight ); + + renderer = new THREE.CanvasRenderer(); + renderer.setSize( window.innerWidth, window.innerHeight ); + container.appendChild( renderer.domElement ); + + var debugCanvas:HTMLCanvasElement = document.createElement( 'canvas' ); + debugCanvas.width = 512; + debugCanvas.height = 512; + debugCanvas.style.position = 'absolute'; + debugCanvas.style.top = '0px'; + debugCanvas.style.left = '0px'; + + container.appendChild( debugCanvas ); + + var debugContext = debugCanvas.getContext( '2d' ); + debugContext.setTransform( 1, 0, 0, 1, 256, 256 ); + debugContext.strokeStyle = '#000000'; + + stats = new Stats(); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.top = '0px'; + container.appendChild(stats.domElement); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + } + + function loadImage( path ) { + + var image:HTMLImageElement = document.createElement( 'img' ); + var texture = new THREE.Texture( image, THREE.UVMapping ) + + image.onload = function () { texture.needsUpdate = true; }; + image.src = path; + + return texture; + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + var timer = Date.now() * 0.0001; + + camera.position.x = Math.cos( timer ) * 1000; + camera.position.z = Math.sin( timer ) * 1000; + camera.lookAt( scene.position ); + + for ( var i = 0, l = objects.length; i < l; i++ ) { + + var object = objects[ i ]; + + object.rotation.x += 0.01; + object.rotation.y += 0.005; + + } + + particleLight.position.x = Math.sin( timer * 7 ) * 300; + particleLight.position.y = Math.cos( timer * 5 ) * 400; + particleLight.position.z = Math.cos( timer * 3 ) * 300; + + pointLight.position.x = particleLight.position.x; + pointLight.position.y = particleLight.position.y; + pointLight.position.z = particleLight.position.z; + + renderer.render( scene, camera ); + + } + +}; + + +// https://github.com/mrdoob/three.js/blob/master/examples/canvas_materials_depth.html + +()=>{ + var container, stats; + + var camera, scene, renderer; + + var cube, plane, objects = []; + + var targetRotation = 0; + var targetRotationOnMouseDown = 0; + + var mouseX = 0; + var mouseXOnMouseDown = 0; + + var moveForward = false; + var moveBackwards = false; + var moveLeft = false; + var moveRight = false; + var moveUp = false; + var moveDown = false; + + var targetMoveLeft = false; + var targetMoveRight = false; + + var debugContext; + + init(); + animate(); + + function init() { + + container = document.createElement( 'div' ); + document.body.appendChild( container ); + + camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2000 ); + camera.position.set( 1000, 1000, 1000 ); + camera.target = new THREE.Vector3( 0, 150, 0 ); + + scene = new THREE.Scene(); + + // Plane + + var material = new THREE.MeshDepthMaterial( { side: THREE.DoubleSide, overdraw: true } ); + + plane = new THREE.Mesh( new THREE.PlaneGeometry( 1000, 1000, 10, 10 ), material ); + plane.position.y = - 100; + plane.rotation.x = - Math.PI / 2; + scene.add( plane ); + + // Cubes + + var geometry = new THREE.CubeGeometry( 100, 100, 100 ); + material = new THREE.MeshDepthMaterial( { overdraw: true } ); + + for ( var i = 0; i < 20; i ++ ) { + + cube = new THREE.Mesh( geometry, material ); + + cube.position.x = ( i % 5 ) * 200 - 400; + cube.position.z = Math.floor( i / 5 ) * 200 - 350; + + cube.rotation.x = Math.random() * 200 - 100; + cube.rotation.y = Math.random() * 200 - 100; + cube.rotation.z = Math.random() * 200 - 100; + + scene.add( cube ); + + objects.push( cube ); + + } + + renderer = new THREE.CanvasRenderer(); + renderer.setSize( window.innerWidth, window.innerHeight ); + + container.appendChild( renderer.domElement ); + + var debugCanvas = document.createElement( 'canvas' ); + debugCanvas.width = 512; + debugCanvas.height = 512; + debugCanvas.style.position = 'absolute'; + debugCanvas.style.top = '0px'; + debugCanvas.style.left = '0px'; + + container.appendChild( debugCanvas ); + + debugContext = debugCanvas.getContext( '2d' ); + debugContext.setTransform( 1, 0, 0, 1, 256, 256 ); + debugContext.strokeStyle = '#808080'; + + stats = new Stats(); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.top = '0px'; + container.appendChild(stats.domElement); + + document.addEventListener( 'keydown', onDocumentKeyDown, false ); + document.addEventListener( 'keyup', onDocumentKeyUp, false ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + } + + function onDocumentKeyDown( event ) { + + switch ( event.keyCode ) { + + case 38: moveForward = true; break; // up + case 40: moveBackwards = true; break; // down + case 37: moveLeft = true; break; // left + case 39: moveRight = true; break; // right + case 87: moveUp = true; break; // w + case 83: moveDown = true; break; // s + case 65: targetMoveLeft = true; break; // a + case 68: targetMoveRight = true; break; // d + + } + + } + + function onDocumentKeyUp( event ) { + + switch ( event.keyCode ) { + + case 38: moveForward = false; break; // up + case 40: moveBackwards = false; break; // down + case 37: moveLeft = false; break; // left + case 39: moveRight = false; break; // right + case 87: moveUp = false; break; // w + case 83: moveDown = false; break; // s + case 65: targetMoveLeft = false; break; // a + case 68: targetMoveRight = false; break; // d + + } + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + if ( moveForward ) camera.position.z -= 10; + if ( moveBackwards ) camera.position.z += 10; + + if ( moveLeft ) camera.position.x -= 10; + if ( moveRight ) camera.position.x += 10; + + if ( moveUp ) camera.position.y += 10; + if ( moveDown ) camera.position.y -= 10; + + if ( targetMoveLeft ) camera.target.x -= 10; + if ( targetMoveRight ) camera.target.x += 10; + + camera.lookAt( camera.target ); + + debugContext.clearRect( - 256, - 256, 512, 512 ); + + debugContext.beginPath(); + + // center + debugContext.moveTo( - 10, 0 ); + debugContext.lineTo( 10, 0 ); + debugContext.moveTo( 0, - 10 ); + debugContext.lineTo( 0, 10 ); + + // camera + + debugContext.moveTo( camera.position.x * 0.1, camera.position.z * 0.1 ); + debugContext.lineTo( camera.target.x * 0.1, camera.target.z * 0.1 ); + debugContext.rect( camera.position.x * 0.1 - 5, camera.position.z * 0.1 - 5, 10, 10 ); + debugContext.rect( camera.target.x * 0.1 - 5, camera.target.z * 0.1 - 5, 10, 10 ); + debugContext.rect( - 50, - 50, 100, 100 ); + + for ( var i = 0; i < objects.length; i++ ) { + + var object = objects[ i ]; + + object.rotation.x += 0.01; + object.rotation.y += 0.005; + object.position.y = Math.sin( object.rotation.x ) * 200 + 200; + + debugContext.rect( object.position.x * 0.1 - 5, object.position.z * 0.1 - 5, 10, 10 ); + + } + + debugContext.closePath(); + debugContext.stroke(); + + renderer.render( scene, camera ); + + } + +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/canvas_materials_normal.html + +()=>{ + var camera, scene, renderer, + loader, mesh; + + init(); + animate(); + + function init() { + + var container = document.getElementById( 'container' ); + + camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 2000 ); + camera.position.set( 0, - 6, 100 ); + + scene = new THREE.Scene(); + + loader = new THREE.JSONLoader(); + loader.load( 'obj/WaltHeadLo.js', function ( geometry ) { + + mesh = new THREE.Mesh( geometry, new THREE.MeshNormalMaterial( { overdraw: true } ) ); + scene.add( mesh ); + + } ); + + renderer = new THREE.CanvasRenderer(); + renderer.setSize( window.innerWidth, window.innerHeight ); + container.appendChild( renderer.domElement ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + render(); + + } + + function render() { + + var time = Date.now() * 0.0005; + + if ( mesh ) { + + mesh.rotation.x -= 0.005; + mesh.rotation.y -= 0.01; + + } + + renderer.render( scene, camera ); + + } +}; + + +// https://github.com/mrdoob/three.js/blob/master/examples/canvas_materials_reflection.html + +()=>{ + + var camera, scene, renderer, + particle1, particle2, particle2, + light1, light2, light3, + loader, mesh; + + init(); + animate(); + + function init() { + + var container = document.getElementById( 'container' ); + + camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 1000 ); + camera.position.set( 0, - 6, 100 ); + + scene = new THREE.Scene(); + + loader = new THREE.JSONLoader(); + loader.load( 'obj/WaltHeadLo.js', function ( geometry ) { + + geometry.computeVertexNormals(); + + mesh = new THREE.Mesh( geometry, new THREE.MeshBasicMaterial( { envMap: THREE.ImageUtils.loadTexture( 'textures/metal.jpg', new THREE.SphericalReflectionMapping() ), overdraw: true } ) ); + scene.add( mesh ); + + } ); + + renderer = new THREE.CanvasRenderer(); + renderer.setSize( window.innerWidth, window.innerHeight ); + container.appendChild( renderer.domElement ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + + } + + function render() { + + var time = Date.now() * 0.0005; + + if ( mesh ) mesh.rotation.y -= 0.01; + + renderer.render( scene, camera ); + + } +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/canvas_materials_video.html + +()=>{ + var AMOUNT = 100; + + var container, stats; + + var camera, scene, renderer; + + var video, image, imageContext, + imageReflection, imageReflectionContext, imageReflectionGradient, + texture, textureReflection; + + var mesh; + + var mouseX = 0; + var mouseY = 0; + + var windowHalfX = window.innerWidth / 2; + var windowHalfY = window.innerHeight / 2; + + 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 - video demo. playing sintel trailer'; + container.appendChild( info ); + + camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 10000 ); + camera.position.z = 1000; + + scene = new THREE.Scene(); + + video = document.getElementById( 'video' ); + + // + + image = document.createElement( 'canvas' ); + image.width = 480; + image.height = 204; + + imageContext = image.getContext( '2d' ); + imageContext.fillStyle = '#000000'; + imageContext.fillRect( 0, 0, 480, 204 ); + + texture = new THREE.Texture( image ); + texture.minFilter = THREE.LinearFilter; + texture.magFilter = THREE.LinearFilter; + + var material = new THREE.MeshBasicMaterial( { map: texture, overdraw: true } ); + + imageReflection = document.createElement( 'canvas' ); + imageReflection.width = 480; + imageReflection.height = 204; + + imageReflectionContext = imageReflection.getContext( '2d' ); + imageReflectionContext.fillStyle = '#000000'; + imageReflectionContext.fillRect( 0, 0, 480, 204 ); + + imageReflectionGradient = imageReflectionContext.createLinearGradient( 0, 0, 0, 204 ); + imageReflectionGradient.addColorStop( 0.2, 'rgba(240, 240, 240, 1)' ); + imageReflectionGradient.addColorStop( 1, 'rgba(240, 240, 240, 0.8)' ); + + textureReflection = new THREE.Texture( imageReflection ); + textureReflection.minFilter = THREE.LinearFilter; + textureReflection.magFilter = THREE.LinearFilter; + + var materialReflection = new THREE.MeshBasicMaterial( { map: textureReflection, side: THREE.BackSide, overdraw: true } ); + + // + + var plane = new THREE.PlaneGeometry( 480, 204, 4, 4 ); + + mesh = new THREE.Mesh( plane, material ); + mesh.scale.x = mesh.scale.y = mesh.scale.z = 1.5; + scene.add(mesh); + + mesh = new THREE.Mesh( plane, materialReflection ); + mesh.position.y = -306; + mesh.rotation.x = - Math.PI; + mesh.scale.x = mesh.scale.y = mesh.scale.z = 1.5; + scene.add( mesh ); + + // + + var separation = 150; + var amountx = 10; + var amounty = 10; + + var PI2 = Math.PI * 2; + var materialParticle = new THREE.ParticleCanvasMaterial( { + + color: 0x0808080, + program: function ( context ) { + + context.beginPath(); + context.arc( 0, 0, 1, 0, PI2, true ); + context.closePath(); + context.fill(); + + } + + } ); + + for ( var ix = 0; ix < amountx; ix++ ) { + + for ( var iy = 0; iy < amounty; iy++ ) { + + var particle = new THREE.Particle( materialParticle ); + particle.position.x = ix * separation - ( ( amountx * separation ) / 2 ); + particle.position.y = -153 + particle.position.z = iy * separation - ( ( amounty * separation ) / 2 ); + scene.add( particle ); + + } + + } + + renderer = new THREE.CanvasRenderer(); + 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( 'mousemove', onDocumentMouseMove, 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 ); + + } + + function onDocumentMouseMove( event ) { + + mouseX = ( event.clientX - windowHalfX ); + mouseY = ( event.clientY - windowHalfY ) * 0.2; + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + camera.position.x += ( mouseX - camera.position.x ) * 0.05; + camera.position.y += ( - mouseY - camera.position.y ) * 0.05; + camera.lookAt( scene.position ); + + if ( video.readyState === video.HAVE_ENOUGH_DATA ) { + + imageContext.drawImage( video, 0, 0 ); + + if ( texture ) texture.needsUpdate = true; + if ( textureReflection ) textureReflection.needsUpdate = true; + + } + + imageReflectionContext.drawImage( image, 0, 0 ); + imageReflectionContext.fillStyle = imageReflectionGradient; + imageReflectionContext.fillRect( 0, 0, 480, 204 ); + + renderer.render( scene, camera ); + + } + +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/canvas_particles_floor.html + +()=>{ + var SEPARATION = 100; + var AMOUNTX = 50; + var AMOUNTY = 50; + + var container, stats; + var camera, scene, renderer, particle; + var mouseX = 0, mouseY = 0; + + var windowHalfX = window.innerWidth / 2; + var windowHalfY = window.innerHeight / 2; + + init(); + animate(); + + function init() { + + container = document.createElement( 'div' ); + document.body.appendChild( container ); + + camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 10000 ); + camera.position.z = 1000; + + scene = new THREE.Scene(); + + var material = new THREE.ParticleBasicMaterial(); + + for ( var ix = 0; ix < AMOUNTX; ix++ ) { + + for ( var iy = 0; iy < AMOUNTY; iy++ ) { + + particle = new THREE.Particle( material ); + particle.scale.y = 4; + particle.position.x = ix * SEPARATION - ( ( AMOUNTX * SEPARATION ) / 2 ); + particle.position.z = iy * SEPARATION - ( ( AMOUNTY * SEPARATION ) / 2 ); + scene.add( particle ); + } + } + + renderer = new THREE.CanvasRenderer(); + 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( 'mousemove', onDocumentMouseMove, 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 ); + + } + + // + + function onDocumentMouseMove( event ) { + + mouseX = event.clientX - windowHalfX; + mouseY = event.clientY - windowHalfY; + } + + function onDocumentTouchStart( event ) { + + if ( event.touches.length > 1 ) { + + event.preventDefault(); + + mouseX = event.touches[ 0 ].pageX - windowHalfX; + mouseY = event.touches[ 0 ].pageY - windowHalfY; + } + } + + function onDocumentTouchMove( event ) { + + if ( event.touches.length == 1 ) { + + event.preventDefault(); + + mouseX = event.touches[ 0 ].pageX - windowHalfX; + mouseY = event.touches[ 0 ].pageY - windowHalfY; + } + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + camera.position.x += ( mouseX - camera.position.x ) * .05; + camera.position.y += ( - mouseY - camera.position.y ) * .05; + camera.lookAt( scene.position ); + + renderer.render( scene, camera ); + + } +}; + + +// https://github.com/mrdoob/three.js/blob/master/examples/canvas_particles_random.html + +()=>{ + var container, stats; + var camera, scene, renderer, group, particle; + var mouseX = 0, mouseY = 0; + + var windowHalfX = window.innerWidth / 2; + var windowHalfY = window.innerHeight / 2; + + init(); + animate(); + + function init() { + + container = document.createElement( 'div' ); + document.body.appendChild( container ); + + camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 3000 ); + camera.position.z = 1000; + + scene = new THREE.Scene(); + + var PI2 = Math.PI * 2; + var program = function ( context ) { + + context.beginPath(); + context.arc( 0, 0, 1, 0, PI2, true ); + context.closePath(); + context.fill(); + + } + + group = new THREE.Object3D(); + scene.add( group ); + + for ( var i = 0; i < 1000; i++ ) { + + particle = new THREE.Particle( new THREE.ParticleCanvasMaterial( { color: Math.random() * 0x808008 + 0x808080, program: program } ) ); + particle.position.x = Math.random() * 2000 - 1000; + particle.position.y = Math.random() * 2000 - 1000; + particle.position.z = Math.random() * 2000 - 1000; + particle.scale.x = particle.scale.y = Math.random() * 10 + 5; + group.add( particle ); + } + + renderer = new THREE.CanvasRenderer(); + 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( 'mousemove', onDocumentMouseMove, 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 ); + + } + + // + + function onDocumentMouseMove( event ) { + + mouseX = event.clientX - windowHalfX; + mouseY = event.clientY - windowHalfY; + } + + function onDocumentTouchStart( event ) { + + if ( event.touches.length === 1 ) { + + event.preventDefault(); + + mouseX = event.touches[ 0 ].pageX - windowHalfX; + mouseY = event.touches[ 0 ].pageY - windowHalfY; + + } + + } + + function onDocumentTouchMove( event ) { + + if ( event.touches.length === 1 ) { + + event.preventDefault(); + + mouseX = event.touches[ 0 ].pageX - windowHalfX; + mouseY = event.touches[ 0 ].pageY - windowHalfY; + + } + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + camera.position.x += ( mouseX - camera.position.x ) * 0.05; + camera.position.y += ( - mouseY - camera.position.y ) * 0.05; + camera.lookAt( scene.position ); + + group.rotation.x += 0.01; + group.rotation.y += 0.02; + + renderer.render( scene, camera ); + + } +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/canvas_particles_sprites.html + +()=>{ + var container, stats; + var camera, scene, renderer, particle; + var mouseX = 0, mouseY = 0; + + var windowHalfX = window.innerWidth / 2; + var windowHalfY = window.innerHeight / 2; + + init(); + animate(); + + function init() { + + container = document.createElement( 'div' ); + document.body.appendChild( container ); + + camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 5000 ); + camera.position.z = 1000; + + scene = new THREE.Scene(); + + var material = new THREE.ParticleBasicMaterial( { map: new THREE.Texture( generateSprite() ), blending: THREE.AdditiveBlending } ); + + for ( var i = 0; i < 1000; i++ ) { + + particle = new THREE.Particle( material ); + + initParticle( particle, i * 10 ); + + scene.add( particle ); + } + + renderer = new THREE.CanvasRenderer(); + renderer.setSize( window.innerWidth, window.innerHeight ); + renderer.sortElements = false; + renderer.setClearColorHex( 0x0000ff, 0.25 ); + container.appendChild( renderer.domElement ); + + stats = new Stats(); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.top = '0px'; + container.appendChild( stats.domElement ); + + document.addEventListener( 'mousemove', onDocumentMouseMove, 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 ); + + } + + function generateSprite() { + + var canvas = document.createElement( 'canvas' ); + canvas.width = 16; + canvas.height = 16; + + var context = canvas.getContext( '2d' ); + var gradient = context.createRadialGradient( canvas.width / 2, canvas.height / 2, 0, canvas.width / 2, canvas.height / 2, canvas.width / 2 ); + gradient.addColorStop( 0, 'rgba(255,255,255,1)' ); + gradient.addColorStop( 0.2, 'rgba(0,255,255,1)' ); + gradient.addColorStop( 0.4, 'rgba(0,0,64,1)' ); + gradient.addColorStop( 1, 'rgba(0,0,0,1)' ); + + context.fillStyle = gradient; + context.fillRect( 0, 0, canvas.width, canvas.height ); + + return canvas; + + } + + function initParticle( particle, delay ) { + + var particle = this instanceof THREE.Particle ? this : particle; + var delay = delay !== undefined ? delay : 0; + + particle.position.x = 0; + particle.position.y = 0; + particle.position.z = 0; + particle.scale.x = particle.scale.y = Math.random() * 3 + 1; + + new TWEEN.Tween( particle ) + .delay( delay ) + .to( {}, 10000 ) + .onComplete( initParticle ) + .start(); + + new TWEEN.Tween( particle.position ) + .delay( delay ) + .to( { x: Math.random() * 4000 - 2000, y: Math.random() * 1000 - 500, z: Math.random() * 4000 - 2000 }, 10000 ) + .start(); + + new TWEEN.Tween( particle.scale ) + .delay( delay ) + .to( { x: 0, y: 0 }, 10000 ) + .start(); + + } + + // + + function onDocumentMouseMove( event ) { + + mouseX = event.clientX - windowHalfX; + mouseY = event.clientY - windowHalfY; + } + + function onDocumentTouchStart( event ) { + + if ( event.touches.length == 1 ) { + + event.preventDefault(); + + mouseX = event.touches[ 0 ].pageX - windowHalfX; + mouseY = event.touches[ 0 ].pageY - windowHalfY; + + } + + } + + function onDocumentTouchMove( event ) { + + if ( event.touches.length == 1 ) { + + event.preventDefault(); + + mouseX = event.touches[ 0 ].pageX - windowHalfX; + mouseY = event.touches[ 0 ].pageY - windowHalfY; + + } + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + TWEEN.update(); + + camera.position.x += ( mouseX - camera.position.x ) * 0.05; + camera.position.y += ( - mouseY - camera.position.y ) * 0.05; + camera.lookAt( scene.position ); + + renderer.render( scene, camera ); + + } +var container, stats; + var camera, scene, renderer, particle; + var mouseX = 0, mouseY = 0; + + var windowHalfX = window.innerWidth / 2; + var windowHalfY = window.innerHeight / 2; + + init(); + animate(); + + function init() { + + container = document.createElement( 'div' ); + document.body.appendChild( container ); + + camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 5000 ); + camera.position.z = 1000; + + scene = new THREE.Scene(); + + var material = new THREE.ParticleBasicMaterial( { map: new THREE.Texture( generateSprite() ), blending: THREE.AdditiveBlending } ); + + for ( var i = 0; i < 1000; i++ ) { + + particle = new THREE.Particle( material ); + + initParticle( particle, i * 10 ); + + scene.add( particle ); + } + + renderer = new THREE.CanvasRenderer(); + renderer.setSize( window.innerWidth, window.innerHeight ); + renderer.sortElements = false; + renderer.setClearColorHex( 0x0000ff, 0.25 ); + container.appendChild( renderer.domElement ); + + stats = new Stats(); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.top = '0px'; + container.appendChild( stats.domElement ); + + document.addEventListener( 'mousemove', onDocumentMouseMove, 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 ); + + } + + function generateSprite() { + + var canvas = document.createElement( 'canvas' ); + canvas.width = 16; + canvas.height = 16; + + var context = canvas.getContext( '2d' ); + var gradient = context.createRadialGradient( canvas.width / 2, canvas.height / 2, 0, canvas.width / 2, canvas.height / 2, canvas.width / 2 ); + gradient.addColorStop( 0, 'rgba(255,255,255,1)' ); + gradient.addColorStop( 0.2, 'rgba(0,255,255,1)' ); + gradient.addColorStop( 0.4, 'rgba(0,0,64,1)' ); + gradient.addColorStop( 1, 'rgba(0,0,0,1)' ); + + context.fillStyle = gradient; + context.fillRect( 0, 0, canvas.width, canvas.height ); + + return canvas; + + } + + function initParticle( particle, delay ) { + + var particle = this instanceof THREE.Particle ? this : particle; + var delay = delay !== undefined ? delay : 0; + + particle.position.x = 0; + particle.position.y = 0; + particle.position.z = 0; + particle.scale.x = particle.scale.y = Math.random() * 3 + 1; + + new TWEEN.Tween( particle ) + .delay( delay ) + .to( {}, 10000 ) + .onComplete( initParticle ) + .start(); + + new TWEEN.Tween( particle.position ) + .delay( delay ) + .to( { x: Math.random() * 4000 - 2000, y: Math.random() * 1000 - 500, z: Math.random() * 4000 - 2000 }, 10000 ) + .start(); + + new TWEEN.Tween( particle.scale ) + .delay( delay ) + .to( { x: 0, y: 0 }, 10000 ) + .start(); + + } + + // + + function onDocumentMouseMove( event ) { + + mouseX = event.clientX - windowHalfX; + mouseY = event.clientY - windowHalfY; + } + + function onDocumentTouchStart( event ) { + + if ( event.touches.length == 1 ) { + + event.preventDefault(); + + mouseX = event.touches[ 0 ].pageX - windowHalfX; + mouseY = event.touches[ 0 ].pageY - windowHalfY; + + } + + } + + function onDocumentTouchMove( event ) { + + if ( event.touches.length == 1 ) { + + event.preventDefault(); + + mouseX = event.touches[ 0 ].pageX - windowHalfX; + mouseY = event.touches[ 0 ].pageY - windowHalfY; + + } + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + TWEEN.update(); + + camera.position.x += ( mouseX - camera.position.x ) * 0.05; + camera.position.y += ( - mouseY - camera.position.y ) * 0.05; + camera.lookAt( scene.position ); + + renderer.render( scene, camera ); + + } + +}; + + +// https://github.com/mrdoob/three.js/blob/master/examples/canvas_particles_waves.html + +()=>{ + var SEPARATION = 100, AMOUNTX = 50, AMOUNTY = 50; + + var container, stats; + var camera, scene, renderer; + + var particles, particle, count = 0; + + var mouseX = 0, mouseY = 0; + + var windowHalfX = window.innerWidth / 2; + var windowHalfY = window.innerHeight / 2; + + init(); + animate(); + + function init() { + + container = document.createElement( 'div' ); + document.body.appendChild( container ); + + camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 10000 ); + camera.position.z = 1000; + + scene = new THREE.Scene(); + + particles = new Array(); + + var PI2 = Math.PI * 2; + var material = new THREE.ParticleCanvasMaterial( { + + color: 0xffffff, + program: function ( context ) { + + context.beginPath(); + context.arc( 0, 0, 1, 0, PI2, true ); + context.fill(); + + } + + } ); + + var i = 0; + + for ( var ix = 0; ix < AMOUNTX; ix ++ ) { + + for ( var iy = 0; iy < AMOUNTY; iy ++ ) { + + particle = particles[ i ++ ] = new THREE.Particle( material ); + particle.position.x = ix * SEPARATION - ( ( AMOUNTX * SEPARATION ) / 2 ); + particle.position.z = iy * SEPARATION - ( ( AMOUNTY * SEPARATION ) / 2 ); + scene.add( particle ); + + } + + } + + renderer = new THREE.CanvasRenderer(); + 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( 'mousemove', onDocumentMouseMove, 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 ); + + } + + // + + function onDocumentMouseMove( event ) { + + mouseX = event.clientX - windowHalfX; + mouseY = event.clientY - windowHalfY; + + } + + function onDocumentTouchStart( event ) { + + if ( event.touches.length === 1 ) { + + event.preventDefault(); + + mouseX = event.touches[ 0 ].pageX - windowHalfX; + mouseY = event.touches[ 0 ].pageY - windowHalfY; + + } + + } + + function onDocumentTouchMove( event ) { + + if ( event.touches.length === 1 ) { + + event.preventDefault(); + + mouseX = event.touches[ 0 ].pageX - windowHalfX; + mouseY = event.touches[ 0 ].pageY - windowHalfY; + + } + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + camera.position.x += ( mouseX - camera.position.x ) * .05; + camera.position.y += ( - mouseY - camera.position.y ) * .05; + camera.lookAt( scene.position ); + + var i = 0; + + for ( var ix = 0; ix < AMOUNTX; ix ++ ) { + + for ( var iy = 0; iy < AMOUNTY; iy ++ ) { + + particle = particles[ i++ ]; + particle.position.y = ( Math.sin( ( ix + count ) * 0.3 ) * 50 ) + ( Math.sin( ( iy + count ) * 0.5 ) * 50 ); + particle.scale.x = particle.scale.y = ( Math.sin( ( ix + count ) * 0.3 ) + 1 ) * 2 + ( Math.sin( ( iy + count ) * 0.5 ) + 1 ) * 2; + + } + + } + + renderer.render( scene, camera ); + + count += 0.1; + + } +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/canvas_performance.html + +()=>{ + var container, stats; + + var camera, scene, renderer; + + var sphere, plane; + + init(); + animate(); + + function init() { + + container = document.createElement( 'div' ); + document.body.appendChild( container ); + + camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 10000 ); + camera.position.set( 0, 1000, 1000 ); + + scene = new THREE.Scene(); + + // Grid + + var size = 500, step = 100; + + var geometry = new THREE.Geometry(); + + for ( var i = - size; i <= size; i += step ) { + + geometry.vertices.push( new THREE.Vector3( - size, 0, i ) ); + geometry.vertices.push( new THREE.Vector3( size, 0, i ) ); + + geometry.vertices.push( new THREE.Vector3( i, 0, - size ) ); + geometry.vertices.push( new THREE.Vector3( i, 0, size ) ); + + } + + var material = new THREE.LineBasicMaterial( { color: 0x000000, opacity: 0.5 } ); + + var line = new THREE.Line( geometry, material ); + line.type = THREE.LinePieces; + scene.add( line ); + + // Spheres + + geometry = new THREE.SphereGeometry( 100, 26, 18 ); + var materialLambert = new THREE.MeshLambertMaterial( { color: 0xffffff, shading: THREE.FlatShading, overdraw: true } ); + + for ( var i = 0; i < 20; i ++ ) { + + sphere = new THREE.Mesh( geometry, materialLambert ); + + sphere.position.x = ( i % 5 ) * 200 - 400; + sphere.position.z = Math.floor( i / 5 ) * 200 - 400; + + scene.add( sphere ); + + } + + // Lights + + var ambientLight = new THREE.AmbientLight( Math.random() * 0x202020 ); + scene.add( ambientLight ); + + var directionalLight = new THREE.DirectionalLight( Math.random() * 0xffffff ); + directionalLight.position.set( 0, 1, 0 ); + scene.add( directionalLight ); + + var pointLight = new THREE.PointLight( 0xff0000, 1, 500 ); + scene.add( pointLight ); + + renderer = new THREE.CanvasRenderer(); + 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); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + camera.lookAt( scene.position ); + + renderer.render( scene, camera ); + + } +}; + + +// https://github.com/mrdoob/three.js/blob/master/examples/canvas_sandbox.html + +()=>{ + var container, stats; + + var camera, scene, renderer, objects; + var pointLight; + + var sphere; + + var targetRotation = 0; + var targetRotationOnMouseDown = 0; + + var mouseX = 0; + var mouseXOnMouseDown = 0; + + var windowHalfX = window.innerWidth / 2; + var windowHalfY = window.innerHeight / 2; + + var moveForward = false; + var moveBackwards = false; + var moveLeft = false; + var moveRight = false; + var moveUp = false; + var moveDown = false; + + var targetMoveLeft = false; + var targetMoveRight = false; + + var debugContext; + + init(); + animate(); + + function init() { + + container = document.createElement( 'div' ); + document.body.appendChild( container ); + + camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 10000 ); + camera.position.set( 0, 150, 400 ); + camera.target = new THREE.Vector3( 0, 150, 0 ); + + scene = new THREE.Scene(); + + + // Grid + + var size = 500, step = 100; + + var geometry = new THREE.Geometry(); + + for ( var i = - size; i <= size; i += step ) { + + geometry.vertices.push( new THREE.Vector3( - size, 0, i ) ); + geometry.vertices.push( new THREE.Vector3( size, 0, i ) ); + + geometry.vertices.push( new THREE.Vector3( i, 0, - size ) ); + geometry.vertices.push( new THREE.Vector3( i, 0, size ) ); + + } + + var material = new THREE.LineBasicMaterial( { color: 0x000000, opacity: 0.5 } ); + + var line = new THREE.Line( geometry, material ); + line.type = THREE.LinePieces; + scene.add( line ); + + // Spheres + + objects = []; + + geometry = new THREE.IcosahedronGeometry( 100, 1 ); + + var materialBasic = new THREE.MeshBasicMaterial( { envMap: THREE.ImageUtils.loadTexture( 'textures/metal.jpg', new THREE.SphericalReflectionMapping() ), overdraw: true } ); + + for ( var i = 0; i < 10; i ++ ) { + + sphere = new THREE.Mesh( geometry, materialBasic ); + + sphere.position.x = Math.random() * 1000 - 500; + sphere.position.y = Math.random() * 1000 - 500; + sphere.position.z = Math.random() * 1000 - 500; + + sphere.rotation.x = Math.random() * 200 - 100; + sphere.rotation.y = Math.random() * 200 - 100; + sphere.rotation.z = Math.random() * 200 - 100; + + sphere.scale.x = sphere.scale.y = sphere.scale.z = Math.random() + 0.5; + + objects.push( sphere ); + + scene.add( sphere ); + + } + + // Lights + + var ambientLight = new THREE.AmbientLight( Math.random() * 0x202020 ); + scene.add( ambientLight ); + + var directionalLight = new THREE.DirectionalLight( Math.random() * 0xffffff ); + directionalLight.position.x = Math.random() - 0.5; + directionalLight.position.y = Math.random() - 0.5; + directionalLight.position.z = Math.random() - 0.5; + directionalLight.position.normalize(); + scene.add( directionalLight ); + + pointLight = new THREE.PointLight( 0xff0000, 1 ); + scene.add( pointLight ); + + renderer = new THREE.CanvasRenderer(); + renderer.setSize( window.innerWidth, window.innerHeight ); + + container.appendChild( renderer.domElement ); + + var debugCanvas = document.createElement( 'canvas' ); + debugCanvas.width = 512; + debugCanvas.height = 512; + debugCanvas.style.position = 'absolute'; + debugCanvas.style.top = '0px'; + debugCanvas.style.left = '0px'; + + container.appendChild( debugCanvas ); + + debugContext = debugCanvas.getContext( '2d' ); + debugContext.setTransform( 1, 0, 0, 1, 256, 256 ); + debugContext.strokeStyle = '#000000'; + + stats = new Stats(); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.top = '0px'; + container.appendChild(stats.domElement); + + document.addEventListener( 'keydown', onDocumentKeyDown, false ); + document.addEventListener( 'keyup', onDocumentKeyUp, 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 ); + + } + + function onDocumentKeyDown( event ) { + + switch ( event.keyCode ) { + + case 38: moveForward = true; break; // up + case 40: moveBackwards = true; break; // down + case 37: moveLeft = true; break; // left + case 39: moveRight = true; break; // right + case 87: moveUp = true; break; // w + case 83: moveDown = true; break; // s + case 65: targetMoveLeft = true; break; // a + case 68: targetMoveRight = true; break; // d + + } + + } + + function onDocumentKeyUp( event ) { + + switch ( event.keyCode ) { + + case 38: moveForward = false; break; // up + case 40: moveBackwards = false; break; // down + case 37: moveLeft = false; break; // left + case 39: moveRight = false; break; // right + case 87: moveUp = false; break; // w + case 83: moveDown = false; break; // s + case 65: targetMoveLeft = false; break; // a + case 68: targetMoveRight = false; break; // d + + } + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + if ( moveForward ) camera.position.z -= 10; + if ( moveBackwards ) camera.position.z += 10; + + if ( moveLeft ) camera.position.x -= 10; + if ( moveRight ) camera.position.x += 10; + + if ( moveUp ) camera.position.y += 10; + if ( moveDown ) camera.position.y -= 10; + + if ( targetMoveLeft ) camera.target.x -= 10; + if ( targetMoveRight ) camera.target.x += 10; + + camera.lookAt( camera.target ); + + debugContext.clearRect( -256, -256, 512, 512 ); + + debugContext.beginPath(); + + // center + debugContext.moveTo( -10, 0 ); + debugContext.lineTo( 10, 0 ); + debugContext.moveTo( 0, -10 ); + debugContext.lineTo( 0, 10 ); + + // camera + + debugContext.moveTo( camera.position.x * 0.1, camera.position.z * 0.1 ); + debugContext.lineTo( camera.target.x * 0.1, camera.target.z * 0.1 ); + debugContext.rect( camera.position.x * 0.1 - 5, camera.position.z * 0.1 - 5, 10, 10 ); + debugContext.rect( camera.target.x * 0.1 - 5, camera.target.z * 0.1 - 5, 10, 10 ); + debugContext.rect( - 50, - 50, 100, 100 ); + + for ( var i = 0, l = objects.length; i < l; i++ ) { + + var object = objects[ i ]; + + object.rotation.x += 0.01; + object.rotation.y += 0.005; + object.position.y = Math.sin( object.rotation.x ) * 200; + + debugContext.rect( object.position.x * 0.1 - 5, object.position.z * 0.1 - 5, 10, 10 ); + + } + + + debugContext.closePath(); + debugContext.stroke(); + + renderer.render( scene, camera ); + + } + +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/css3d_molecules.html + +()=>{ + var camera, scene, renderer; + var controls; + var root; + + var objects = []; + var tmpVec1 = new THREE.Vector3(); + var tmpVec2 = new THREE.Vector3(); + var tmpVec3 = new THREE.Vector3(); + var tmpVec4 = new THREE.Vector3(); + + var visualizationType = 2; + + var MOLECULES = { + "Ethanol" :"ethanol.pdb", + "Aspirin" :"aspirin.pdb", + "Caffeine" :"caffeine.pdb", + "Nicotine" :"nicotine.pdb", + "LSD" :"lsd.pdb", + "Cocaine" :"cocaine.pdb", + "Cholesterol" :"cholesterol.pdb", + "Lycopene" :"lycopene.pdb", + "Glucose" : "glucose.pdb", + "Aluminium oxide":"Al2O3.pdb", + "Cubane" :"cubane.pdb", + "Copper" :"cu.pdb", + "Fluorite" :"caf2.pdb", + "Salt" :"nacl.pdb", + "YBCO superconductor":"ybco.pdb", + "Buckyball" : "buckyball.pdb", + //"Diamond" :"diamond.pdb", + "Graphite" :"graphite.pdb" + }; + + var loader = new THREE.PDBLoader(); + var colorSpriteMap = {}; + var baseSprite = document.createElement( 'img' ); + + var menu = document.getElementById( "menu" ); + + init(); + animate(); + + function init() { + + camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 5000 ); + camera.position.z = 1500; + + scene = new THREE.Scene(); + + root = new THREE.Object3D(); + scene.add( root ); + + // + + renderer = new THREE.CSS3DRenderer(); + renderer.setSize( window.innerWidth, window.innerHeight ); + document.getElementById( 'container' ).appendChild( renderer.domElement ); + + // + + controls = new THREE.TrackballControls( camera, renderer.domElement ); + controls.rotateSpeed = 0.5; + controls.addEventListener( 'change', render ); + + // + + baseSprite.onload = function () { + + loadMolecule( "models/molecules/caffeine.pdb" ); + createMenu(); + + }; + + baseSprite.src = 'textures/sprites/ball.png'; + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + // + + function generateButtonCallback( url ) { + + return function ( event ) { + + loadMolecule( url ); + + } + + } + + function createMenu() { + + for ( var m in MOLECULES ) { + + var button = document.createElement( 'button' ); + button.innerHTML = m; + menu.appendChild( button ); + + var url = "models/molecules/" + MOLECULES[ m ]; + + button.addEventListener( 'click', generateButtonCallback( url ), false ); + + } + + var b_a = document.getElementById( "b_a" ); + var b_b = document.getElementById( "b_b" ); + var b_ab = document.getElementById( "b_ab" ); + + b_a.addEventListener( 'click', function() { visualizationType = 0; showAtoms() } ); + b_b.addEventListener( 'click', function() { visualizationType = 1; showBonds() } ); + b_ab.addEventListener( 'click', function() { visualizationType = 2; showAtomsBonds() } ); + + } + + // + + function showAtoms() { + + for ( var i = 0; i < objects.length; i ++ ) { + + var object = objects[ i ]; + + if ( object instanceof THREE.CSS3DSprite ) { + + object.element.style.display = ""; + object.visible = true; + + } else { + + object.element.style.display = "none"; + object.visible = false; + + } + + } + + } + + function showBonds() { + + for ( var i = 0; i < objects.length; i ++ ) { + + var object = objects[ i ]; + + if ( object instanceof THREE.CSS3DSprite ) { + + object.element.style.display = "none"; + object.visible = false; + + } else { + + object.element.style.display = ""; + object.element.style.height = object.properties.bondLengthFull; + object.visible = true; + + } + + } + + } + + function showAtomsBonds() { + + for ( var i = 0; i < objects.length; i ++ ) { + + var object = objects[ i ]; + + object.element.style.display = ""; + object.visible = true; + + if ( ! ( object instanceof THREE.CSS3DSprite ) ) { + + object.element.style.height = object.properties.bondLengthShort; + + } + + } + + } + + // + + function colorify( ctx, width, height, color, a ) { + + var r = color.r; + var g = color.g; + var b = color.b; + + var imageData = ctx.getImageData( 0, 0, width, height ); + var data = imageData.data; + + for ( var y = 0; y < height; y ++ ) { + + for ( var x = 0; x < width; x ++ ) { + + var index = ( y * width + x ) * 4; + + data[ index ] *= r; + data[ index + 1 ] *= g; + data[ index + 2 ] *= b; + data[ index + 3 ] *= a; + + } + + } + + ctx.putImageData( imageData, 0, 0 ); + + } + + function imageToCanvas( image ) { + + var width = image.width; + var height = image.height; + + var canvas = document.createElement( 'canvas' ); + + canvas.width = width; + canvas.height = height; + + var context = canvas.getContext( '2d' ); + context.drawImage( image, 0, 0, width, height ); + + return canvas; + + } + + // + + function loadMolecule( url ) { + + for ( var i = 0; i < objects.length; i ++ ) { + + var object = objects[ i ]; + + object.parent.remove( object ); + + if ( object.element.parentNode === renderer.cameraElement ) { + + renderer.cameraElement.removeChild( object.element ); + + } + + if ( object.properties.joint ) { + + object.properties.joint.parent.remove( object.properties.joint ); + + } + + } + + objects = []; + + loader.load( url, function ( geometry, geometryBonds ) { + + var offset = THREE.GeometryUtils.center( geometry ); + geometryBonds.applyMatrix( new THREE.Matrix4().makeTranslation( offset.x, offset.y, offset.z ) ); + + for ( var i = 0; i < geometry.vertices.length; i ++ ) { + + var position = geometry.vertices[ i ]; + var color = geometry.colors[ i ]; + var element = geometry.elements[ i ]; + + if ( ! colorSpriteMap[ element ] ) { + + var canvas = imageToCanvas( baseSprite ); + var context = canvas.getContext( '2d' ); + + colorify( context, canvas.width, canvas.height, color, 1 ); + + var dataUrl = canvas.toDataURL(); + + colorSpriteMap[ element ] = dataUrl; + + } + + var colorSprite = colorSpriteMap[ element ]; + + var atom = document.createElement( 'img' ); + atom.src = colorSprite; + + var object = new THREE.CSS3DSprite( atom ); + object.position.copy( position ); + object.position.multiplyScalar( 75 ); + object.billboard = true; + + object.matrixAutoUpdate = false; + object.updateMatrix(); + + root.add( object ); + + objects.push( object ); + + } + + for ( var i = 0; i < geometryBonds.vertices.length; i += 2 ) { + + var start = geometryBonds.vertices[ i ]; + var end = geometryBonds.vertices[ i + 1 ]; + + start.multiplyScalar( 75 ); + end.multiplyScalar( 75 ); + + tmpVec1.subVectors( end, start ); + var bondLength = tmpVec1.length() - 50; + + + // + + var bond = document.createElement( 'div' ); + bond.className = "bond"; + bond.style.height = bondLength + "px"; + + var object = new THREE.CSS3DObject( bond ); + object.position.copy( start ); + object.position.lerp( end, 0.5 ); + + object.properties.bondLengthShort = bondLength + "px"; + object.properties.bondLengthFull = ( bondLength + 55 ) + "px"; + + // + + var axis = tmpVec2.set( 0, 1, 0 ).cross( tmpVec1 ); + var radians = Math.acos( tmpVec3.set( 0, 1, 0 ).dot( tmpVec4.copy( tmpVec1 ).normalize() ) ); + + var objMatrix = new THREE.Matrix4().makeRotationAxis( axis.normalize(), radians ); + object.matrix = objMatrix; + object.rotation.setEulerFromRotationMatrix( object.matrix, object.eulerOrder ); + + object.matrixAutoUpdate = false; + object.updateMatrix(); + + root.add( object ); + + objects.push( object ); + + // + + var bond = document.createElement( 'div' ); + bond.className = "bond"; + bond.style.height = bondLength + "px"; + + + // three-tests/ts: + // var joint = new THREE.Object3D( bond ); + // It seems a parameter "bond" is not used by Object3D. + var joint = new THREE.Object3D(); + + + joint.position.copy( start ); + joint.position.lerp( end, 0.5 ); + + joint.matrix.copy( objMatrix ); + joint.rotation.setEulerFromRotationMatrix( joint.matrix, joint.eulerOrder ); + + joint.matrixAutoUpdate = false; + joint.updateMatrix(); + + var object = new THREE.CSS3DObject( bond ); + object.rotation.y = Math.PI/2; + + object.matrixAutoUpdate = false; + object.updateMatrix(); + + object.properties.bondLengthShort = bondLength + "px"; + object.properties.bondLengthFull = ( bondLength + 55 ) + "px"; + + object.properties.joint = joint; + + joint.add( object ); + root.add( joint ); + + objects.push( object ); + + } + + //console.log( "CSS3DObjects:", objects.length ); + + switch ( visualizationType ) { + + case 0: showAtoms(); break; + case 1: showBonds(); break; + case 2: showAtomsBonds(); break; + + } + + render(); + + } ); + + + } + + // + + function onWindowResize() { + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + render(); + + } + + function animate() { + + requestAnimationFrame( animate ); + controls.update(); + + var time = Date.now() * 0.0004; + + root.rotation.x = time; + root.rotation.y = time * 0.7; + + render(); + + } + + function render() { + + renderer.render( scene, camera ); + + } + +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/css3d_panorama.html + +()=>{ + var camera, scene, renderer; + var geometry, material, mesh; + var target = new THREE.Vector3(); + + var lon = 90, lat = 0; + var phi = 0, theta = 0; + + var touchX, touchY; + + init(); + animate(); + + function init() { + + camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 1000 ); + + scene = new THREE.Scene(); + + var sides = [ + { + url: 'textures/cube/Bridge2/posx.jpg', + position: new THREE.Vector3( -512, 0, 0 ), + rotation: new THREE.Vector3( 0, Math.PI / 2, 0 ) + }, + { + url: 'textures/cube/Bridge2/negx.jpg', + position: new THREE.Vector3( 512, 0, 0 ), + rotation: new THREE.Vector3( 0, -Math.PI / 2, 0 ) + }, + { + url: 'textures/cube/Bridge2/posy.jpg', + position: new THREE.Vector3( 0, 512, 0 ), + rotation: new THREE.Vector3( Math.PI / 2, 0, Math.PI ) + }, + { + url: 'textures/cube/Bridge2/negy.jpg', + position: new THREE.Vector3( 0, -512, 0 ), + rotation: new THREE.Vector3( - Math.PI / 2, 0, Math.PI ) + }, + { + url: 'textures/cube/Bridge2/posz.jpg', + position: new THREE.Vector3( 0, 0, 512 ), + rotation: new THREE.Vector3( 0, Math.PI, 0 ) + }, + { + url: 'textures/cube/Bridge2/negz.jpg', + position: new THREE.Vector3( 0, 0, -512 ), + rotation: new THREE.Vector3( 0, 0, 0 ) + } + ]; + + for ( var i = 0; i < sides.length; i ++ ) { + + var side = sides[ i ]; + + var element = document.createElement( 'img' ); + element.width = 1026; // 2 pixels extra to close the gap. + element.src = side.url; + + var object = new THREE.CSS3DObject( element ); + object.position = side.position; + object.rotation = side.rotation; + scene.add( object ); + + } + + renderer = new THREE.CSS3DRenderer(); + renderer.setSize( window.innerWidth, window.innerHeight ); + document.body.appendChild( renderer.domElement ); + + // + + document.addEventListener( 'mousedown', onDocumentMouseDown, false ); + document.addEventListener( 'mousewheel', onDocumentMouseWheel, false ); + + document.addEventListener( 'touchstart', onDocumentTouchStart, false ); + document.addEventListener( 'touchmove', onDocumentTouchMove, false ); + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + } + + function onDocumentMouseDown( event ) { + + event.preventDefault(); + + document.addEventListener( 'mousemove', onDocumentMouseMove, false ); + document.addEventListener( 'mouseup', onDocumentMouseUp, false ); + + } + + function onDocumentMouseMove( event ) { + + var movementX = event.movementX || event.mozMovementX || event.webkitMovementX || 0; + var movementY = event.movementY || event.mozMovementY || event.webkitMovementY || 0; + + lon -= movementX * 0.1; + lat += movementY * 0.1; + + } + + function onDocumentMouseUp( event ) { + + document.removeEventListener( 'mousemove', onDocumentMouseMove ); + document.removeEventListener( 'mouseup', onDocumentMouseUp ); + + } + + function onDocumentMouseWheel( event ) { + + camera.fov -= event.wheelDeltaY * 0.05; + camera.updateProjectionMatrix(); + + } + + function onDocumentTouchStart( event ) { + + event.preventDefault(); + + var touch = event.touches[ 0 ]; + + touchX = touch.screenX; + touchY = touch.screenY; + + } + + function onDocumentTouchMove( event ) { + + event.preventDefault(); + + var touch = event.touches[ 0 ]; + + lon -= ( touch.screenX - touchX ) * 0.1; + lat += ( touch.screenY - touchY ) * 0.1; + + touchX = touch.screenX; + touchY = touch.screenY; + + } + + function animate() { + + requestAnimationFrame( animate ); + + lon += 0.1; + lat = Math.max( - 85, Math.min( 85, lat ) ); + phi = THREE.Math.degToRad( 90 - lat ); + theta = THREE.Math.degToRad( lon ); + + target.x = Math.sin( phi ) * Math.cos( theta ); + target.y = Math.cos( phi ); + target.z = Math.sin( phi ) * Math.sin( theta ); + + camera.lookAt( target ); + + renderer.render( scene, camera ); + + } +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/css3d_periodictable.html + +()=>{ + + var table: any[][] = [ + [ "H", "Hydrogen", "1.00794", 1, 1 ], + [ "He", "Helium", "4.002602", 18, 1 ], + [ "Li", "Lithium", "6.941", 1, 2 ], + [ "Be", "Beryllium", "9.012182", 2, 2 ], + [ "B", "Boron", "10.811", 13, 2 ], + [ "C", "Carbon", "12.0107", 14, 2 ], + [ "N", "Nitrogen", "14.0067", 15, 2 ], + [ "O", "Oxygen", "15.9994", 16, 2 ], + [ "F", "Fluorine", "18.9984032", 17, 2 ], + [ "Ne", "Neon", "20.1797", 18, 2 ], + [ "Na", "Sodium", "22.98976...", 1, 3 ], + [ "Mg", "Magnesium", "24.305", 2, 3 ], + [ "Al", "Aluminium", "26.9815386", 13, 3 ], + [ "Si", "Silicon", "28.0855", 14, 3 ], + [ "P", "Phosphorus", "30.973762", 15, 3 ], + [ "S", "Sulfur", "32.065", 16, 3 ], + [ "Cl", "Chlorine", "35.453", 17, 3 ], + [ "Ar", "Argon", "39.948", 18, 3 ], + [ "K", "Potassium", "39.948", 1, 4 ], + [ "Ca", "Calcium", "40.078", 2, 4 ], + [ "Sc", "Scandium", "44.955912", 3, 4 ], + [ "Ti", "Titanium", "47.867", 4, 4 ], + [ "V", "Vanadium", "50.9415", 5, 4 ], + [ "Cr", "Chromium", "51.9961", 6, 4 ], + [ "Mn", "Manganese", "54.938045", 7, 4 ], + [ "Fe", "Iron", "55.845", 8, 4 ], + [ "Co", "Cobalt", "58.933195", 9, 4 ], + [ "Ni", "Nickel", "58.6934", 10, 4 ], + [ "Cu", "Copper", "63.546", 11, 4 ], + [ "Zn", "Zinc", "65.38", 12, 4 ], + [ "Ga", "Gallium", "69.723", 13, 4 ], + [ "Ge", "Germanium", "72.63", 14, 4 ], + [ "As", "Arsenic", "74.9216", 15, 4 ], + [ "Se", "Selenium", "78.96", 16, 4 ], + [ "Br", "Bromine", "79.904", 17, 4 ], + [ "Kr", "Krypton", "83.798", 18, 4 ], + [ "Rb", "Rubidium", "85.4678", 1, 5 ], + [ "Sr", "Strontium", "87.62", 2, 5 ], + [ "Y", "Yttrium", "88.90585", 3, 5 ], + [ "Zr", "Zirconium", "91.224", 4, 5 ], + [ "Nb", "Niobium", "92.90628", 5, 5 ], + [ "Mo", "Molybdenum", "95.96", 6, 5 ], + [ "Tc", "Technetium", "(98)", 7, 5 ], + [ "Ru", "Ruthenium", "101.07", 8, 5 ], + [ "Rh", "Rhodium", "102.9055", 9, 5 ], + [ "Pd", "Palladium", "106.42", 10, 5 ], + [ "Ag", "Silver", "107.8682", 11, 5 ], + [ "Cd", "Cadmium", "112.411", 12, 5 ], + [ "In", "Indium", "114.818", 13, 5 ], + [ "Sn", "Tin", "118.71", 14, 5 ], + [ "Sb", "Antimony", "121.76", 15, 5 ], + [ "Te", "Tellurium", "127.6", 16, 5 ], + [ "I", "Iodine", "126.90447", 17, 5 ], + [ "Xe", "Xenon", "131.293", 18, 5 ], + [ "Cs", "Caesium", "132.9054", 1, 6 ], + [ "Ba", "Barium", "132.9054", 2, 6 ], + [ "La", "Lanthanum", "138.90547", 4, 9 ], + [ "Ce", "Cerium", "140.116", 5, 9 ], + [ "Pr", "Praseodymium", "140.90765", 6, 9 ], + [ "Nd", "Neodymium", "144.242", 7, 9 ], + [ "Pm", "Promethium", "(145)", 8, 9 ], + [ "Sm", "Samarium", "150.36", 9, 9 ], + [ "Eu", "Europium", "151.964", 10, 9 ], + [ "Gd", "Gadolinium", "157.25", 11, 9 ], + [ "Tb", "Terbium", "158.92535", 12, 9 ], + [ "Dy", "Dysprosium", "162.5", 13, 9 ], + [ "Ho", "Holmium", "164.93032", 14, 9 ], + [ "Er", "Erbium", "167.259", 15, 9 ], + [ "Tm", "Thulium", "168.93421", 16, 9 ], + [ "Yb", "Ytterbium", "173.054", 17, 9 ], + [ "Lu", "Lutetium", "174.9668", 18, 9 ], + [ "Hf", "Hafnium", "178.49", 4, 6 ], + [ "Ta", "Tantalum", "180.94788", 5, 6 ], + [ "W", "Tungsten", "183.84", 6, 6 ], + [ "Re", "Rhenium", "186.207", 7, 6 ], + [ "Os", "Osmium", "190.23", 8, 6 ], + [ "Ir", "Iridium", "192.217", 9, 6 ], + [ "Pt", "Platinum", "195.084", 10, 6 ], + [ "Au", "Gold", "196.966569", 11, 6 ], + [ "Hg", "Mercury", "200.59", 12, 6 ], + [ "Tl", "Thallium", "204.3833", 13, 6 ], + [ "Pb", "Lead", "207.2", 14, 6 ], + [ "Bi", "Bismuth", "208.9804", 15, 6 ], + [ "Po", "Polonium", "(209)", 16, 6 ], + [ "At", "Astatine", "(210)", 17, 6 ], + [ "Rn", "Radon", "(222)", 18, 6 ], + [ "Fr", "Francium", "(223)", 1, 7 ], + [ "Ra", "Radium", "(226)", 2, 7 ], + [ "Ac", "Actinium", "(227)", 4, 10 ], + [ "Th", "Thorium", "232.03806", 5, 10 ], + [ "Pa", "Protactinium", "231.0588", 6, 10 ], + [ "U", "Uranium", "238.02891", 7, 10 ], + [ "Np", "Neptunium", "(237)", 8, 10 ], + [ "Pu", "Plutonium", "(244)", 9, 10 ], + [ "Am", "Americium", "(243)", 10, 10 ], + [ "Cm", "Curium", "(247)", 11, 10 ], + [ "Bk", "Berkelium", "(247)", 12, 10 ], + [ "Cf", "Californium", "(251)", 13, 10 ], + [ "Es", "Einstenium", "(252)", 14, 10 ], + [ "Fm", "Fermium", "(257)", 15, 10 ], + [ "Md", "Mendelevium", "(258)", 16, 10 ], + [ "No", "Nobelium", "(259)", 17, 10 ], + [ "Lr", "Lawrencium", "(262)", 18, 10 ], + [ "Rf", "Rutherfordium", "(267)", 4, 7 ], + [ "Db", "Dubnium", "(268)", 5, 7 ], + [ "Sg", "Seaborgium", "(271)", 6, 7 ], + [ "Bh", "Bohrium", "(272)", 7, 7 ], + [ "Hs", "Hassium", "(270)", 8, 7 ], + [ "Mt", "Meitnerium", "(276)", 9, 7 ], + [ "Ds", "Darmstadium", "(281)", 10, 7 ], + [ "Rg", "Roentgenium", "(280)", 11, 7 ], + [ "Cn", "Copernicium", "(285)", 12, 7 ], + [ "Uut", "Unutrium", "(284)", 13, 7 ], + [ "Fl", "Flerovium", "(289)", 14, 7 ], + [ "Uup", "Ununpentium", "(288)", 15, 7 ], + [ "Lv", "Livermorium", "(293)", 16, 7 ], + [ "Uus", "Ununseptium", "(294)", 17, 7 ], + [ "Uuo", "Ununoctium", "(294)", 18, 7 ] + ]; + + var camera, scene, renderer; + var controls; + + var objects = []; + var targets = { table: [], sphere: [], helix: [], grid: [] }; + + init(); + animate(); + + function init() { + + camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 5000 ); + camera.position.z = 1800; + + scene = new THREE.Scene(); + + for ( var i = 0; i < table.length; i ++ ) { + + var item = table[ i ]; + + var element = document.createElement( 'div' ); + element.className = 'element'; + element.style.backgroundColor = 'rgba(0,127,127,' + ( Math.random() * 0.5 + 0.25 ) + ')'; + + var number = document.createElement( 'div' ); + number.className = 'number'; + number.textContent = (i + 1).toString(); + element.appendChild( number ); + + var symbol = document.createElement( 'div' ); + symbol.className = 'symbol'; + symbol.textContent = item[ 0 ]; + element.appendChild( symbol ); + + var details = document.createElement( 'div' ); + details.className = 'details'; + details.innerHTML = item[ 1 ] + '
' + item[ 2 ]; + element.appendChild( details ); + + var object = new THREE.CSS3DObject( element ); + object.position.x = Math.random() * 4000 - 2000; + object.position.y = Math.random() * 4000 - 2000; + object.position.z = Math.random() * 4000 - 2000; + scene.add( object ); + + objects.push( object ); + + } + + // table + + for ( var i = 0; i < objects.length; i ++ ) { + + var item = table[ i ]; + + var object = new THREE.Object3D(); + object.position.x = ( item[ 3 ] * 160 ) - 1540; + object.position.y = - ( item[ 4 ] * 200 ) + 1100; + + targets.table.push( object ); + + } + + // sphere + + var vector = new THREE.Vector3(); + + for ( var i = 0, l = objects.length; i < l; i ++ ) { + + var phi = Math.acos( -1 + ( 2 * i ) / l ); + var theta = Math.sqrt( l * Math.PI ) * phi; + + var object = new THREE.Object3D(); + + object.position.x = 1000 * Math.cos( theta ) * Math.sin( phi ); + object.position.y = 1000 * Math.sin( theta ) * Math.sin( phi ); + object.position.z = 1000 * Math.cos( phi ); + + vector.copy( object.position ).multiplyScalar( 2 ); + + object.lookAt( vector ); + + targets.sphere.push( object ); + + } + + // helix + + var vector = new THREE.Vector3(); + + for ( var i = 0, l = objects.length; i < l; i ++ ) { + + var phi = i * 0.175 + Math.PI; + + var object = new THREE.Object3D(); + + object.position.x = 1100 * Math.sin( phi ); + object.position.y = - ( i * 8 ) + 450; + object.position.z = 1100 * Math.cos( phi ); + + vector.copy( object.position ); + vector.x *= 2; + vector.z *= 2; + + object.lookAt( vector ); + + targets.helix.push( object ); + + } + + // grid + + for ( var i = 0; i < objects.length; i ++ ) { + + var object = new THREE.Object3D(); + + object.position.x = ( ( i % 5 ) * 400 ) - 800; + object.position.y = ( - ( Math.floor( i / 5 ) % 5 ) * 400 ) + 800; + object.position.z = ( Math.floor( i / 25 ) ) * 1000 - 2000; + + targets.grid.push( object ); + + } + + // + + renderer = new THREE.CSS3DRenderer(); + renderer.setSize( window.innerWidth, window.innerHeight ); + renderer.domElement.style.position = 'absolute'; + document.getElementById( 'container' ).appendChild( renderer.domElement ); + + // + + controls = new THREE.TrackballControls( camera, renderer.domElement ); + controls.rotateSpeed = 0.5; + controls.addEventListener( 'change', render ); + + var button = document.getElementById( 'table' ); + button.addEventListener( 'click', function ( event ) { + + transform( targets.table, 2000 ); + + }, false ); + + var button = document.getElementById( 'sphere' ); + button.addEventListener( 'click', function ( event ) { + + transform( targets.sphere, 2000 ); + + }, false ); + + var button = document.getElementById( 'helix' ); + button.addEventListener( 'click', function ( event ) { + + transform( targets.helix, 2000 ); + + }, false ); + + var button = document.getElementById( 'grid' ); + button.addEventListener( 'click', function ( event ) { + + transform( targets.grid, 2000 ); + + }, false ); + + transform( targets.table, 5000 ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function transform( targets, duration ) { + + TWEEN.removeAll(); + + for ( var i = 0; i < objects.length; i ++ ) { + + var object = objects[ i ]; + var target = targets[ i ]; + + new TWEEN.Tween( object.position ) + .to( { x: target.position.x, y: target.position.y, z: target.position.z }, Math.random() * duration + duration ) + .easing( TWEEN.Easing.Exponential.InOut ) + .start(); + + new TWEEN.Tween( object.rotation ) + .to( { x: target.rotation.x, y: target.rotation.y, z: target.rotation.z }, Math.random() * duration + duration ) + .easing( TWEEN.Easing.Exponential.InOut ) + .start(); + + } + + new TWEEN.Tween( this ) + .to( {}, duration * 2 ) + .onUpdate( render ) + .start(); + + } + + function onWindowResize() { + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + } + + function animate() { + + requestAnimationFrame( animate ); + + TWEEN.update(); + controls.update(); + + } + + function render() { + + renderer.render( scene, camera ); + + } +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/css3d_sandbox.html + +()=>{ + var camera, scene, renderer; + var geometry, material, mesh; + + var scene2, renderer2; + + var controls; + + init(); + animate(); + + function init() { + + camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 1000 ); + camera.position.set( 200, 200, 200 ); + + controls = new THREE.TrackballControls( camera ); + + controls.rotateSpeed = 1.0; + controls.zoomSpeed = 1.2; + controls.panSpeed = 0.8; + + controls.noZoom = false; + controls.noPan = false; + + controls.staticMoving = false; + controls.dynamicDampingFactor = 0.3; + + controls.keys = [ 65, 83, 68 ]; + + scene = new THREE.Scene(); + + geometry = new THREE.CubeGeometry( 200, 200, 200 ); + material = new THREE.MeshBasicMaterial( { color: 0x000000, wireframe: true, wireframeLinewidth: 1 } ); + + mesh = new THREE.Mesh( geometry, material ); + scene.add( mesh ); + + renderer = new THREE.CanvasRenderer(); + renderer.setSize( window.innerWidth, window.innerHeight ); + document.body.appendChild( renderer.domElement ); + + // + + scene2 = new THREE.Scene(); + + for ( var i = 0; i < 20; i ++ ) { + + var element = document.createElement( 'div' ); + element.style.width = '100px'; + element.style.height = '100px'; + element.style.background = new THREE.Color( Math.random() * 0xffffff ).getStyle(); + + var object = new THREE.CSS3DObject( element ); + object.position.x = Math.random() * 200 - 100; + object.position.y = Math.random() * 200 - 100; + object.position.z = Math.random() * 200 - 100; + object.scale.x = Math.random() + 0.5; + object.scale.y = Math.random() + 0.5; + scene2.add( object ); + + } + + // + + renderer2 = new THREE.CSS3DRenderer(); + renderer2.setSize( window.innerWidth, window.innerHeight ); + renderer2.domElement.style.position = 'absolute'; + renderer2.domElement.style.top = 0; + document.body.appendChild( renderer2.domElement ); + + } + + function animate() { + + requestAnimationFrame( animate ); + + controls.update(); + + renderer.render( scene, camera ); + renderer2.render( scene2, camera ); + + } +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/css3d_youtube.html + +()=>{ + var camera, scene, renderer; + var objects = [], player; + + var auto = true; + + init(); + animate(); + + function init() { + + camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 5000 ); + camera.position.y = - 25; + + scene = new THREE.Scene(); + + renderer = new THREE.CSS3DRenderer(); + renderer.setSize( window.innerWidth, window.innerHeight ); + renderer.domElement.style.position = 'absolute'; + renderer.domElement.style.top = 0; + document.getElementById( 'container' ).appendChild( renderer.domElement ); + + // + + var query = document.getElementById( 'query' ); + query.addEventListener( 'keyup', function ( event:KeyboardEvent ) { + + if ( event.keyCode === 13 ) { + + search( query.value ); + + } + + }, false ); + + var button = document.getElementById( 'button' ); + button.addEventListener( 'click', function ( event ) { + + search( query.value ); + + }, false ); + + if ( window.location.hash.length > 0 ) { + + query.value = window.location.hash.substr( 1 ); + + } + + search( query.value ); + + document.body.addEventListener( 'mousewheel', onMouseWheel, false ); + + document.body.addEventListener( 'click', function ( event ) { + + auto = true; + + if ( player !== undefined ) { + + player.parentNode.removeChild( player ); + player = undefined; + + } + + new TWEEN.Tween( camera.position ) + .to( { x: 0, y: - 25 }, 1500 ) + .easing( TWEEN.Easing.Exponential.Out ) + .start(); + + }, false ); + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function search( query ) { + + window.location.hash = query; + + for ( var i = 0, l = objects.length; i < l; i ++ ) { + + var object = objects[ i ]; + var delay = Math.random() * 1000; + + new TWEEN.Tween( object.position ) + .to( { y: - 3000 }, 1000 ) + .delay( delay ) + .easing( TWEEN.Easing.Exponential.In ) + .start(); + + new TWEEN.Tween( object ) + .to( {}, 2000 ) + .delay( delay ) + .onComplete( function () { + + scene.remove( this ); + renderer.cameraElement.removeChild( this.element ); + + var index = objects.indexOf( this ); + objects.splice( index, 1 ); + + } ) + .start(); + + } + + var request = new XMLHttpRequest(); + request.addEventListener( 'load', onData, false ); + request.open( 'GET', 'https://gdata.youtube.com/feeds/api/videos?v=2&alt=json&max-results=50&q=' + query, true ); + request.send( null ); + + } + + function onData( event ) { + + var data = JSON.parse( event.target.responseText ); + var entries = data.feed.entry; + + // console.log( entries ); + + for ( var i = 0; i < entries.length; i ++ ) { + + var entry = entries[ i ]; + + var element = document.createElement( 'div' ); + element.style.width = '480px'; + element.style.height = '360px'; + + var image = document.createElement( 'img' ); + image.addEventListener( 'load', function ( event ) { + + var object = this.properties.object; + var button = this.properties.button; + + button.style.visibility = 'visible'; + + new TWEEN.Tween( object.position ) + .to( { y: Math.random() * 2000 - 1000 }, 2000 ) + .easing( TWEEN.Easing.Exponential.Out ) + .start(); + + }, false ); + image.style.position = 'absolute'; + image.style.width = '480px'; + image.style.height = '360px'; + image.src = entry.media$group.media$thumbnail[ 2 ].url; + element.appendChild( image ); + + var button = document.createElement( 'img' ); + button.style.position = 'absolute'; + button.style.left = ( ( 480 - 86 ) / 2 ) + 'px'; + button.style.top = ( ( 360 - 61 ) / 2 ) + 'px'; + button.style.visibility = 'hidden'; + button.style.WebkitFilter = 'grayscale()'; + button.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFYAAAA9CAYAAAA3ZZ5uAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9wLBQ0uMbsnLZIAAAbXSURBVHja7ZxvbBvlHcc/z/maf4PGg9FtbaZeS2I1iUgP1q7QEmFpmxB7AYxXk/aCvETaC/Zy2qSpk7apL/YCTbCyoU0uUAGdRv8uVCorzsQGSRu4tFoahbYxpEkKayvHaRInvnt+e5HEzb92cez4bHRfyS/ufPbd8/H3vs/vZ99Zkac+erB5OxhhAG1oS4myZp5RYVFi5/PeSpSFwrrd84I4QDLH93RAksusjwM89PH5DgoglcvGZ+ymp8RQTytRliCWUsriyywhCTiiJKFQCaUmXtjRfXk0b7Bnv7211vUq2xSqDaVsAoGII0jMDE3F7gT5tmA/tJue0qiYgnBAczkzkzSQtoed3qMrBvt+y7ZnlTJiAb6VGFi3PXqu78D/Bft+y7ZnhQBqbhPVUrgLwP6rsXGza+IEp3/usWC62HsuXPh0bp05f4NMSGKgwhKwylXhTIgXgB8ucezp5sh2MJyAUR7O1cr67qxrs471kDZF4NW8slbpNuBXC8CKNmxRAZz8LKuiS8BqJBoYNm9FF2Rs+7b6x8CIB1wKIR39Qd/FDnOmyFU2gV0LlbQ2MAPW02Ip5UPAVlXB44/Dxk0zy8NDcOYMDA+XcScmVjZjtWD7URFU79zJzp//gtraWgBGR0cZGBhgsLMT3nyjLAGLYGfBimhbKL5jv7FnTxYqQG1tLbZtE4lE6N+1i5Hjx5n+x7vlBVjkFlitlC8t7Ncbm5ZdX1NTg23bNDc30//MM3wWj5P+66HyADzLUv1ty5bN2lAJP46h9bXXuW/XrhVt29/fT197O96Rw0iJAza0WKYnYkkZdAaRSIRIJMLlJ5+k7+23mTx+vGQBi4hlagiL+FNqrWavW7du5VvPP0//E0+QaG9n4sQJZGiotNIAwqaA7RNXRITVfKimadLU1IRlWfRGowydepfMyZPo0gFsm54mjPKLbH4vr6mpYceOHTQ0NHDu0T1cO3aMqXdOwuSkz1lA2NQitn/7L8wHWltbS2trK4OWRX80SrL9Habicf8AC7apfexkRaCQ+V5XV0ddXR399fVc2rObsTcPkTl/3pcz0dRI2D+wwlpMnA0NDWzatIlPGhsZPHWK1FuH0DduFHNoYVOD7df3L3qNwAJUV1fT0tJCfX09Zx94gKuxA0x1dhVv8tIiPkaBRkSv7fcR1VW0fv97DNTfz5lf/5Z0vKMoYzNmcs6vhxTtYVkWj+z9JcbGjUUZm6+O1SLoIs6eVckUjKYoxph9joK1y9jFutrZyennfkJmbKwo+/O53JI1z9jpVIre2Ks4v3+pqGPzNwq0Rmu9hi7tous3+7hxoa/oYzO1f4ZFa1kTsDevDOG8+AcuHj7q29jMSddzKkOGL22tlsI69ubQEM6L+30FCjDlacesMFTSrzSYiQKvAECHuXj4GD0vvVwSX21VGCo5O3mJj2BX79jp1Bi9rx2k99WDZMZuUkoytXgOGNFyAjudGuOz0+/Rte93JQcUIK11whStkn79MuNpjed5OQG9ePQEPfv/VJJA51SJSpifuy5fM82Sj4Le19+gZ/8rJQ10TtdcF/MejLhfTYKnPTzPvb1Dx8YYfO+f9Lz8Z8aHr1Iuugcjbn7iprnfqPblAEa6urnvwe1LZ/nhET4/+zHn/vgXxkfKB+icLrlpzEtpN7Glwp8D+M/BQ3yzdTdfjTRkgQ78/STnX4lRzrqUdhMK4Gd33SvrlH/XFmx4aMa1X3zUQ7krI8K+m9eVCTCudXK9EfLtJ5qr3eUPdE7jWidh7opuEUeLRAmUv0ScLNgJTydqlBFAKYAmPJ3Igp0UHB1c0F0QTQq3HDuQmXY2hkIBlQJoIDPtwLwb6H687m7ZYJgBmTx0Q3scyKTUrckLmBKJC8EElo9S4mXv7MyC/UJ7RzaoUNRUwV10q9V1rbOdjXGr/pqMXRMvoLNK/Vd7uFqOLAHbDaMj4sZcCcqDXOWKcEUysX+T/nQJWADPY29Cu8kAVW5KaDfpeeydv25BjTWIO3qvClVVoKJfCRqGFemyznAd77kPJN1xW7AAV8TtuAvDAuz1Adw7nv4JcbkmXtuHXnrJf8Is2xVcEffoelQ4KfrhdUpRHQBeAPS6aC5LJpny3B91ytRby213x9rqEaoekxB7K1DRShTzHVyBolIpalB8mUu0lGjGZi+DSolmAo0nxDI6/dNuyP1/t+ZrN1WbBSwxmN9AWCgsEbGVUuEaFKFF8AHuXrTsd7xMiTA1+3P/hGjmF5jjs8sewgQCQgJFQkQchUoqTXyatHMnoDmBXYm+w7rtIULhRfBBsbibK5nuTkQcpVQSIQEkAARJGlo5ChLzy6dc9T9S8wu+HzDbBQAAAABJRU5ErkJggg=='; + element.appendChild( button ); + + var blocker = document.createElement( 'div' ); + blocker.style.position = 'absolute'; + blocker.style.width = '480px'; + blocker.style.height = '360px'; + blocker.style.background = 'rgba(0,0,0,0.5)'; + blocker.style.cursor = 'pointer'; + element.appendChild( blocker ); + + var object = new THREE.CSS3DObject( element ); + object.position.x = Math.random() * 4000 - 2000; + // object.position.y = Math.random() * 2000 - 1000; + object.position.y = 3000; + object.position.z = Math.random() * - 5000; + scene.add( object ); + + objects.push( object ); + + // + + var properties = { data: entry, blocker: blocker, button: button, object: object } + + element["properties"] = properties; + image["properties"] = properties; + + element.addEventListener( 'mouseover', function () { + + this.properties.button.style.WebkitFilter = ''; + this.properties.blocker.style.background = 'rgba(0,0,0,0)'; + + }, false ); + + element.addEventListener( 'mouseout', function () { + + this.properties.button.style.WebkitFilter = 'grayscale()'; + this.properties.blocker.style.background = 'rgba(0,0,0,0.75)'; + + }, false ); + + element.addEventListener( 'click', function ( event ) { + + event.stopPropagation(); + + var data = this.properties.data; + var object = this.properties.object; + + auto = false; + + if ( player !== undefined ) { + + player.parentNode.removeChild( player ); + player = undefined; + + } + + player = document.createElement( 'iframe' ); + player.style.position = 'absolute'; + player.style.width = '480px'; + player.style.height = '360px'; + player.style.border = '0px'; + player.src = 'http://www.youtube.com/embed/' + data.id.$t.split( ':' ).pop() + '?rel=0&autoplay=1&controls=1&showinfo=0'; + this.appendChild( player ); + + // + + var prev = object.position.z + 400; + + new TWEEN.Tween( camera.position ) + .to( { x: object.position.x, y: object.position.y - 25 }, 1500 ) + .easing( TWEEN.Easing.Exponential.Out ) + .start(); + + new TWEEN.Tween( { value: prev } ) + .to( { value: 0 }, 2000 ) + .onUpdate( function () { + + move( this.value - prev ); + prev = this.value; + + } ) + .easing( TWEEN.Easing.Exponential.Out ) + .start(); + + }, false ); + + } + + } + + function move( delta ) { + + for ( var i = 0; i < objects.length; i ++ ) { + + var object = objects[ i ]; + + object.position.z += delta; + + if ( object.position.z > 0 ) { + + object.position.z -= 5000; + + } else if ( object.position.z < - 5000 ) { + + object.position.z += 5000; + + } + + } + + } + + function onMouseWheel( event ) { + + move( event.wheelDelta ); + + } + + function onWindowResize() { + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + } + + function animate() { + + requestAnimationFrame( animate ); + + TWEEN.update(); + + if ( auto === true ) { + + move( 1 ); + + } + + renderer.render( scene, camera ); + + } +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/misc_controls_fly.html + +()=>{ + if ( ! Detector.webgl ) Detector.addGetWebGLMessage(); + + var radius = 6371; + var tilt = 0.41; + var rotationSpeed = 0.02; + + var cloudsScale = 1.005; + var moonScale = 0.23; + + var MARGIN = 0; + var SCREEN_HEIGHT = window.innerHeight - MARGIN * 2; + var SCREEN_WIDTH = window.innerWidth; + + var container, stats; + var camera, controls, scene, sceneCube, renderer; + var geometry, meshPlanet, meshClouds, meshMoon; + var dirLight, pointLight, ambientLight; + + var d, dPlanet, dMoon, dMoonVec = new THREE.Vector3(); + + var clock = new THREE.Clock(); + + var composer; + + init(); + animate(); + + function init() { + + container = document.createElement( 'div' ); + document.body.appendChild( container ); + + camera = new THREE.PerspectiveCamera( 25, SCREEN_WIDTH / SCREEN_HEIGHT, 50, 1e7 ); + camera.position.z = radius * 5; + + scene = new THREE.Scene(); + scene.fog = new THREE.FogExp2( 0x000000, 0.00000025 ); + + controls = new THREE.FlyControls( camera ); + + controls.movementSpeed = 1000; + controls.domElement = container; + controls.rollSpeed = Math.PI / 24; + controls.autoForward = false; + controls.dragToLook = false; + + dirLight = new THREE.DirectionalLight( 0xffffff ); + dirLight.position.set( -1, 0, 1 ).normalize(); + scene.add( dirLight ); + + ambientLight = new THREE.AmbientLight( 0x000000 ); + scene.add( ambientLight ); + + var planetTexture = THREE.ImageUtils.loadTexture( "textures/planets/earth_atmos_2048.jpg" ); + var cloudsTexture = THREE.ImageUtils.loadTexture( "textures/planets/earth_clouds_1024.png" ); + var normalTexture = THREE.ImageUtils.loadTexture( "textures/planets/earth_normal_2048.jpg" ); + var specularTexture = THREE.ImageUtils.loadTexture( "textures/planets/earth_specular_2048.jpg" ); + + var moonTexture = THREE.ImageUtils.loadTexture( "textures/planets/moon_1024.jpg" ); + + var shader = THREE.ShaderLib[ "normalmap" ]; + var uniforms = THREE.UniformsUtils.clone( shader.uniforms ); + + uniforms[ "tNormal" ].value = normalTexture; + uniforms[ "uNormalScale" ].value.set( 0.85, 0.85 ); + + uniforms[ "tDiffuse" ].value = planetTexture; + uniforms[ "tSpecular" ].value = specularTexture; + + uniforms[ "enableAO" ].value = false; + uniforms[ "enableDiffuse" ].value = true; + uniforms[ "enableSpecular" ].value = true; + + uniforms[ "uDiffuseColor" ].value.setHex( 0xffffff ); + uniforms[ "uSpecularColor" ].value.setHex( 0x333333 ); + uniforms[ "uAmbientColor" ].value.setHex( 0x000000 ); + + uniforms[ "uShininess" ].value = 15; + + var parameters = { + + fragmentShader: shader.fragmentShader, + vertexShader: shader.vertexShader, + uniforms: uniforms, + lights: true, + fog: true + + }; + + var materialNormalMap = new THREE.ShaderMaterial( parameters ); + + // planet + + geometry = new THREE.SphereGeometry( radius, 100, 50 ); + geometry.computeTangents(); + + meshPlanet = new THREE.Mesh( geometry, materialNormalMap ); + meshPlanet.rotation.y = 0; + meshPlanet.rotation.z = tilt; + scene.add( meshPlanet ); + + // clouds + + var materialClouds = new THREE.MeshLambertMaterial( { color: 0xffffff, map: cloudsTexture, transparent: true } ); + + meshClouds = new THREE.Mesh( geometry, materialClouds ); + meshClouds.scale.set( cloudsScale, cloudsScale, cloudsScale ); + meshClouds.rotation.z = tilt; + scene.add( meshClouds ); + + // moon + + var materialMoon = new THREE.MeshPhongMaterial( { color: 0xffffff, map: moonTexture } ); + + meshMoon = new THREE.Mesh( geometry, materialMoon ); + meshMoon.position.set( radius * 5, 0, 0 ); + meshMoon.scale.set( moonScale, moonScale, moonScale ); + scene.add( meshMoon ); + + // stars + + var i, r = radius, starsGeometry = [ new THREE.Geometry(), new THREE.Geometry() ]; + + for ( i = 0; i < 250; i ++ ) { + + var vertex = new THREE.Vector3(); + vertex.x = Math.random() * 2 - 1; + vertex.y = Math.random() * 2 - 1; + vertex.z = Math.random() * 2 - 1; + vertex.multiplyScalar( r ); + + starsGeometry[ 0 ].vertices.push( vertex ); + + } + + for ( i = 0; i < 1500; i ++ ) { + + var vertex = new THREE.Vector3(); + vertex.x = Math.random() * 2 - 1; + vertex.y = Math.random() * 2 - 1; + vertex.z = Math.random() * 2 - 1; + vertex.multiplyScalar( r ); + + starsGeometry[ 1 ].vertices.push( vertex ); + + } + + var stars; + var starsMaterials = [ + new THREE.ParticleBasicMaterial( { color: 0x555555, size: 2, sizeAttenuation: false } ), + new THREE.ParticleBasicMaterial( { color: 0x555555, size: 1, sizeAttenuation: false } ), + new THREE.ParticleBasicMaterial( { color: 0x333333, size: 2, sizeAttenuation: false } ), + new THREE.ParticleBasicMaterial( { color: 0x3a3a3a, size: 1, sizeAttenuation: false } ), + new THREE.ParticleBasicMaterial( { color: 0x1a1a1a, size: 2, sizeAttenuation: false } ), + new THREE.ParticleBasicMaterial( { color: 0x1a1a1a, size: 1, sizeAttenuation: false } ) + ]; + + for ( i = 10; i < 30; i ++ ) { + + stars = new THREE.ParticleSystem( starsGeometry[ i % 2 ], starsMaterials[ i % 6 ] ); + + stars.rotation.x = Math.random() * 6; + stars.rotation.y = Math.random() * 6; + stars.rotation.z = Math.random() * 6; + + var s = i * 10; + stars.scale.set( s, s, s ); + + stars.matrixAutoUpdate = false; + stars.updateMatrix(); + + scene.add( stars ); + + } + + renderer = new THREE.WebGLRenderer( { clearColor: 0x000000, clearAlpha: 1 } ); + renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT ); + renderer.sortObjects = false; + + renderer.autoClear = false; + + container.appendChild( renderer.domElement ); + + stats = new Stats(); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.top = '0px'; + stats.domElement.style.zIndex = 100; + container.appendChild( stats.domElement ); + + window.addEventListener( 'resize', onWindowResize, false ); + + // postprocessing + + var renderModel = new THREE.RenderPass( scene, camera ); + var effectFilm = new THREE.FilmPass( 0.35, 0.75, 2048, false ); + + effectFilm.renderToScreen = true; + + composer = new THREE.EffectComposer( renderer ); + + composer.addPass( renderModel ); + composer.addPass( effectFilm ); + + }; + + function onWindowResize( event ) { + + SCREEN_HEIGHT = window.innerHeight; + SCREEN_WIDTH = window.innerWidth; + + renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT ); + + camera.aspect = SCREEN_WIDTH / SCREEN_HEIGHT; + camera.updateProjectionMatrix(); + + composer.reset(); + + }; + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + }; + + function render() { + + // rotate the planet and clouds + + var delta = clock.getDelta(); + + meshPlanet.rotation.y += rotationSpeed * delta; + meshClouds.rotation.y += 1.25 * rotationSpeed * delta; + + // slow down as we approach the surface + + dPlanet = camera.position.length(); + + dMoonVec.subVectors( camera.position, meshMoon.position ); + dMoon = dMoonVec.length(); + + if ( dMoon < dPlanet ) { + + d = ( dMoon - radius * moonScale * 1.01 ); + + } else { + + d = ( dPlanet - radius * 1.01 ); + + } + + controls.movementSpeed = 0.33 * d; + controls.update( delta ); + + renderer.clear(); + composer.render( delta ); + + }; +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/misc_controls_orbit.html + +()=>{ + if ( ! Detector.webgl ) Detector.addGetWebGLMessage(); + + var container, stats; + + var camera, controls, scene, renderer; + + var cross; + + init(); + animate(); + + function init() { + + camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 1000 ); + camera.position.z = 500; + + controls = new THREE.OrbitControls( camera ); + controls.addEventListener( 'change', render ); + + scene = new THREE.Scene(); + scene.fog = new THREE.FogExp2( 0xcccccc, 0.002 ); + + // world + + var geometry = new THREE.CylinderGeometry( 0, 10, 30, 4, 1 ); + var material = new THREE.MeshLambertMaterial( { color:0xffffff, shading: THREE.FlatShading } ); + + for ( var i = 0; i < 500; i ++ ) { + + var mesh = new THREE.Mesh( geometry, material ); + mesh.position.x = ( Math.random() - 0.5 ) * 1000; + mesh.position.y = ( Math.random() - 0.5 ) * 1000; + mesh.position.z = ( Math.random() - 0.5 ) * 1000; + mesh.updateMatrix(); + mesh.matrixAutoUpdate = false; + scene.add( mesh ); + + } + + + // lights + + var light = new THREE.DirectionalLight( 0xffffff ); + light.position.set( 1, 1, 1 ); + scene.add( light ); + + light = new THREE.DirectionalLight( 0x002288 ); + light.position.set( -1, -1, -1 ); + scene.add( light ); + + var lightAmbient = new THREE.AmbientLight( 0x222222 ); + scene.add( lightAmbient ); + + + // renderer + + renderer = new THREE.WebGLRenderer( { antialias: false } ); + renderer.setClearColor( scene.fog.color, 1 ); + renderer.setSize( window.innerWidth, window.innerHeight ); + + container = document.getElementById( 'container' ); + container.appendChild( renderer.domElement ); + + stats = new Stats(); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.top = '0px'; + stats.domElement.style.zIndex = 100; + container.appendChild( stats.domElement ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + render(); + + } + + function animate() { + + requestAnimationFrame( animate ); + controls.update(); + + } + + function render() { + + renderer.render( scene, camera ); + stats.update(); + + } + +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/misc_controls_path.html + +()=>{ + if ( ! Detector.webgl ) Detector.addGetWebGLMessage(); + + var container, stats; + + var camera, controls, scene, renderer; + + var cross; + + var clock = new THREE.Clock(); + + init(); + animate(); + + function init() { + + camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 1000 ); + + controls = new THREE.PathControls( camera ); + + controls.waypoints = [ [ -500, 0, 0 ], [ 0, 200, 0 ], [ 500, 0, 0 ] ]; + controls.duration = 28 + controls.useConstantSpeed = true; + //controls.createDebugPath = true; + //controls.createDebugDummy = true; + controls.lookSpeed = 0.06; + controls.lookVertical = true; + controls.lookHorizontal = true; + controls.verticalAngleMap = { srcRange: [ 0, 2 * Math.PI ], dstRange: [ 1.1, 3.8 ] }; + controls.horizontalAngleMap = { srcRange: [ 0, 2 * Math.PI ], dstRange: [ 0.3, Math.PI - 0.3 ] }; + controls.lon = 180; + + controls.init(); + + // world + + scene = new THREE.Scene(); + scene.fog = new THREE.FogExp2( 0xcccccc, 0.002 ); + + scene.add( controls.animationParent ); + + var geometry = new THREE.CylinderGeometry( 0, 10, 30, 4, 1 ); + var material = new THREE.MeshLambertMaterial( { color:0xffffff, shading: THREE.FlatShading } ); + + for ( var i = 0; i < 500; i ++ ) { + + var mesh = new THREE.Mesh( geometry, material ); + mesh.position.x = ( Math.random() - 0.5 ) * 1000; + mesh.position.y = ( Math.random() - 0.5 ) * 1000; + mesh.position.z = ( Math.random() - 0.5 ) * 1000; + mesh.updateMatrix(); + mesh.matrixAutoUpdate = false; + scene.add( mesh ); + + } + + // lights + + var light = new THREE.DirectionalLight( 0xffffff ); + light.position.set( 1, 1, 1 ); + scene.add( light ); + + light = new THREE.DirectionalLight( 0x002288 ); + light.position.set( -1, -1, -1 ); + scene.add( light ); + + var lightAmbient = new THREE.AmbientLight( 0x222222 ); + scene.add( lightAmbient ); + + + // renderer + + renderer = new THREE.WebGLRenderer( { antialias: false } ); + renderer.setClearColor( scene.fog.color, 1 ); + renderer.setSize( window.innerWidth, window.innerHeight ); + + container = document.getElementById( 'container' ); + container.appendChild( renderer.domElement ); + + // stats + + stats = new Stats(); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.top = '0px'; + stats.domElement.style.zIndex = 100; + container.appendChild( stats.domElement ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + // start animation + + controls.animation.play( true, 0 ); + + } + + function onWindowResize() { + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + controls.handleResize(); + + } + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + var delta = clock.getDelta(); + + THREE.AnimationHandler.update( delta ); + + controls.update( delta ); + renderer.render( scene, camera ); + + } +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/misc_controls_pointerlock.html + +()=>{ + var camera, scene, renderer; + var geometry, material, mesh; + var controls,time = Date.now(); + + var objects = []; + + var ray; + + var blocker = document.getElementById( 'blocker' ); + var instructions = document.getElementById( 'instructions' ); + + // http://www.html5rocks.com/en/tutorials/pointerlock/intro/ + + var havePointerLock = 'pointerLockElement' in document || 'mozPointerLockElement' in document || 'webkitPointerLockElement' in document; + + if ( havePointerLock ) { + + var element = document.body; + + var pointerlockchange = function ( event ) { + + if ( document.pointerLockElement === element || document.mozPointerLockElement === element || document.webkitPointerLockElement === element ) { + + controls.enabled = true; + + blocker.style.display = 'none'; + + } else { + + controls.enabled = false; + + blocker.style.display = '-webkit-box'; + blocker.style.display = '-moz-box'; + blocker.style.display = 'box'; + + instructions.style.display = ''; + + } + + } + + var pointerlockerror = function ( event ) { + + instructions.style.display = ''; + + } + + // Hook pointer lock state change events + document.addEventListener( 'pointerlockchange', pointerlockchange, false ); + document.addEventListener( 'mozpointerlockchange', pointerlockchange, false ); + document.addEventListener( 'webkitpointerlockchange', pointerlockchange, false ); + + document.addEventListener( 'pointerlockerror', pointerlockerror, false ); + document.addEventListener( 'mozpointerlockerror', pointerlockerror, false ); + document.addEventListener( 'webkitpointerlockerror', pointerlockerror, false ); + + instructions.addEventListener( 'click', function ( event ) { + + instructions.style.display = 'none'; + + // Ask the browser to lock the pointer + element.requestPointerLock = element.requestPointerLock || element.mozRequestPointerLock || element.webkitRequestPointerLock; + + if ( /Firefox/i.test( navigator.userAgent ) ) { + + var fullscreenchange = function ( event ) { + + if ( document.fullscreenElement === element || document.mozFullscreenElement === element || document.mozFullScreenElement === element ) { + + document.removeEventListener( 'fullscreenchange', fullscreenchange ); + document.removeEventListener( 'mozfullscreenchange', fullscreenchange ); + + element.requestPointerLock(); + } + + } + + document.addEventListener( 'fullscreenchange', fullscreenchange, false ); + document.addEventListener( 'mozfullscreenchange', fullscreenchange, false ); + + element.requestFullscreen = element.requestFullscreen || element.mozRequestFullscreen || element.mozRequestFullScreen || element.webkitRequestFullscreen; + + element.requestFullscreen(); + + } else { + + element.requestPointerLock(); + + } + + }, false ); + + } else { + + instructions.innerHTML = 'Your browser doesn\'t seem to support Pointer Lock API'; + + } + + init(); + animate(); + + function init() { + + camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 1000 ); + + scene = new THREE.Scene(); + scene.fog = new THREE.Fog( 0xffffff, 0, 750 ); + + var light = new THREE.DirectionalLight( 0xffffff, 1.5 ); + light.position.set( 1, 1, 1 ); + scene.add( light ); + + var light = new THREE.DirectionalLight( 0xffffff, 0.75 ); + light.position.set( -1, - 0.5, -1 ); + scene.add( light ); + + controls = new THREE.PointerLockControls( camera ); + scene.add( controls.getObject() ); + + ray = new THREE.Raycaster(); + ray.ray.direction.set( 0, -1, 0 ); + + // floor + + geometry = new THREE.PlaneGeometry( 2000, 2000, 100, 100 ); + geometry.applyMatrix( new THREE.Matrix4().makeRotationX( - Math.PI / 2 ) ); + + for ( var i = 0, l = geometry.vertices.length; i < l; i ++ ) { + + var vertex = geometry.vertices[ i ]; + vertex.x += Math.random() * 20 - 10; + vertex.y += Math.random() * 2; + vertex.z += Math.random() * 20 - 10; + + } + + for ( var i = 0, l = geometry.faces.length; i < l; i ++ ) { + + var face = geometry.faces[ i ]; + face.vertexColors[ 0 ] = new THREE.Color().setHSL( Math.random() * 0.2 + 0.5, 0.75, Math.random() * 0.25 + 0.75 ); + face.vertexColors[ 1 ] = new THREE.Color().setHSL( Math.random() * 0.2 + 0.5, 0.75, Math.random() * 0.25 + 0.75 ); + face.vertexColors[ 2 ] = new THREE.Color().setHSL( Math.random() * 0.2 + 0.5, 0.75, Math.random() * 0.25 + 0.75 ); + face.vertexColors[ 3 ] = new THREE.Color().setHSL( Math.random() * 0.2 + 0.5, 0.75, Math.random() * 0.25 + 0.75 ); + + } + + material = new THREE.MeshBasicMaterial( { vertexColors: THREE.VertexColors } ); + + mesh = new THREE.Mesh( geometry, material ); + scene.add( mesh ); + + // objects + + geometry = new THREE.CubeGeometry( 20, 20, 20 ); + + for ( var i = 0, l = geometry.faces.length; i < l; i ++ ) { + + var face = geometry.faces[ i ]; + face.vertexColors[ 0 ] = new THREE.Color().setHSL( Math.random() * 0.2 + 0.5, 0.75, Math.random() * 0.25 + 0.75 ); + face.vertexColors[ 1 ] = new THREE.Color().setHSL( Math.random() * 0.2 + 0.5, 0.75, Math.random() * 0.25 + 0.75 ); + face.vertexColors[ 2 ] = new THREE.Color().setHSL( Math.random() * 0.2 + 0.5, 0.75, Math.random() * 0.25 + 0.75 ); + face.vertexColors[ 3 ] = new THREE.Color().setHSL( Math.random() * 0.2 + 0.5, 0.75, Math.random() * 0.25 + 0.75 ); + + } + + for ( var i = 0; i < 500; i ++ ) { + + material = new THREE.MeshPhongMaterial( { specular: 0xffffff, shading: THREE.FlatShading, vertexColors: THREE.VertexColors } ); + + var mesh = new THREE.Mesh( geometry, material ); + mesh.position.x = Math.floor( Math.random() * 20 - 10 ) * 20; + mesh.position.y = Math.floor( Math.random() * 20 ) * 20 + 10; + mesh.position.z = Math.floor( Math.random() * 20 - 10 ) * 20; + scene.add( mesh ); + + material.color.setHSL( Math.random() * 0.2 + 0.5, 0.75, Math.random() * 0.25 + 0.75 ); + + objects.push( mesh ); + + } + + // + + renderer = new THREE.WebGLRenderer(); + renderer.setSize( window.innerWidth, window.innerHeight ); + + document.body.appendChild( renderer.domElement ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + } + + function animate() { + + requestAnimationFrame( animate ); + + // + + controls.isOnObject( false ); + + ray.ray.origin.copy( controls.getObject().position ); + ray.ray.origin.y -= 10; + + var intersections = ray.intersectObjects( objects ); + + if ( intersections.length > 0 ) { + + var distance = intersections[ 0 ].distance; + + if ( distance > 0 && distance < 10 ) { + + controls.isOnObject( true ); + + } + + } + + controls.update( Date.now() - time ); + + renderer.render( scene, camera ); + + time = Date.now(); + + } +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/misc_controls_roll.html + +()=>{ + + if ( ! Detector.webgl ) Detector.addGetWebGLMessage(); + + var container, stats; + + var camera, controls, scene, renderer; + + var cross; + + var clock = new THREE.Clock(); + + init(); + animate(); + + function init() { + + camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 1000 ); + + controls = new THREE.RollControls( camera ); + + controls.movementSpeed = 100; + controls.lookSpeed = 3; + controls.constrainVertical = [ -0.5, 0.5 ]; + //controls.autoForward = true; + + // world + + scene = new THREE.Scene(); + scene.fog = new THREE.FogExp2( 0xcccccc, 0.002 ); + + var geometry = new THREE.CylinderGeometry( 0, 10, 30, 4, 1 ); + var material = new THREE.MeshLambertMaterial( { color:0xffffff, shading: THREE.FlatShading } ); + + for ( var i = 0; i < 500; i ++ ) { + + var mesh = new THREE.Mesh( geometry, material ); + mesh.position.x = ( Math.random() - 0.5 ) * 1000; + mesh.position.y = ( Math.random() - 0.5 ) * 1000; + mesh.position.z = ( Math.random() - 0.5 ) * 1000; + mesh.updateMatrix(); + mesh.matrixAutoUpdate = false; + scene.add( mesh ); + + } + + // lights + + var light = new THREE.DirectionalLight( 0xffffff ); + light.position.set( 1, 1, 1 ); + scene.add( light ); + + light = new THREE.DirectionalLight( 0x002288 ); + light.position.set( -1, -1, -1 ); + scene.add( light ); + + var lightAmbient = new THREE.AmbientLight( 0x555555 ); + scene.add( lightAmbient ); + + + // renderer + + renderer = new THREE.WebGLRenderer( { antialias: false } ); + renderer.setClearColor( scene.fog.color, 1 ); + renderer.setSize( window.innerWidth, window.innerHeight ); + + container = document.getElementById( 'container' ); + container.appendChild( renderer.domElement ); + + stats = new Stats(); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.top = '0px'; + stats.domElement.style.zIndex = 100; + container.appendChild( stats.domElement ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + controls.handleResize(); + + } + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + controls.update( clock.getDelta() ); + renderer.render( scene, camera ); + + } +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/misc_controls_trackball.html + +()=>{ + + if ( ! Detector.webgl ) Detector.addGetWebGLMessage(); + + var container, stats; + + var camera, controls, scene, renderer; + + var cross; + + init(); + animate(); + + function init() { + + camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 1000 ); + camera.position.z = 500; + + controls = new THREE.TrackballControls( camera ); + + controls.rotateSpeed = 1.0; + controls.zoomSpeed = 1.2; + controls.panSpeed = 0.8; + + controls.noZoom = false; + controls.noPan = false; + + controls.staticMoving = true; + controls.dynamicDampingFactor = 0.3; + + controls.keys = [ 65, 83, 68 ]; + + controls.addEventListener( 'change', render ); + + // world + + scene = new THREE.Scene(); + scene.fog = new THREE.FogExp2( 0xcccccc, 0.002 ); + + var geometry = new THREE.CylinderGeometry( 0, 10, 30, 4, 1 ); + var material = new THREE.MeshLambertMaterial( { color:0xffffff, shading: THREE.FlatShading } ); + + for ( var i = 0; i < 500; i ++ ) { + + var mesh = new THREE.Mesh( geometry, material ); + mesh.position.x = ( Math.random() - 0.5 ) * 1000; + mesh.position.y = ( Math.random() - 0.5 ) * 1000; + mesh.position.z = ( Math.random() - 0.5 ) * 1000; + mesh.updateMatrix(); + mesh.matrixAutoUpdate = false; + scene.add( mesh ); + + } + + + // lights + + var light = new THREE.DirectionalLight( 0xffffff ); + light.position.set( 1, 1, 1 ); + scene.add( light ); + + light = new THREE.DirectionalLight( 0x002288 ); + light.position.set( -1, -1, -1 ); + scene.add( light ); + + var lightAmbient = new THREE.AmbientLight( 0x222222 ); + scene.add( lightAmbient ); + + + // renderer + + renderer = new THREE.WebGLRenderer( { antialias: false } ); + renderer.setClearColor( scene.fog.color, 1 ); + renderer.setSize( window.innerWidth, window.innerHeight ); + + container = document.getElementById( 'container' ); + container.appendChild( renderer.domElement ); + + stats = new Stats(); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.top = '0px'; + stats.domElement.style.zIndex = 100; + container.appendChild( stats.domElement ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + controls.handleResize(); + + render(); + + } + + function animate() { + + requestAnimationFrame( animate ); + controls.update(); + + } + + function render() { + + renderer.render( scene, camera ); + stats.update(); + + } +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/misc_lights_test.html + +()=>{ + var SCREEN_WIDTH = window.innerWidth / 2; + var SCREEN_HEIGHT = window.innerHeight; + var FLOOR = -250; + + var container, stats; + + var camera, scene, canvasRenderer, webglRenderer; + + var mesh, zmesh, lightMesh, geometry; + var materialSpheres, materialTorus; + + var directionalLight, pointLight; + + var mouseX = 0, mouseY = 0; + + var windowHalfX = window.innerWidth / 2; + var windowHalfY = window.innerHeight / 2; + + var render_canvas = true, render_gl = true; + var has_gl = 0; + + var lightAdded = false; + + var clock = new THREE.Clock(); + + var bcanvas = document.getElementById( 'rcanvas' ); + var bwebgl = document.getElementById( 'rwebgl' ); + + document.addEventListener( 'mousemove', onDocumentMouseMove, false ); + + init(); + animate(); + + //render_canvas = !has_gl; + bwebgl.style.display = has_gl ? 'inline' : 'none'; + bcanvas.className = render_canvas ? 'button' : 'button inactive'; + + function init() { + + container = document.createElement('div'); + document.body.appendChild(container); + + camera = new THREE.PerspectiveCamera( 75, SCREEN_WIDTH / SCREEN_HEIGHT, 1, 100000 ); + camera.position.z = 500; + + scene = new THREE.Scene(); + + // Spheres + + var geometry = new THREE.SphereGeometry( 100, 16, 8 ); + materialSpheres = new THREE.MeshLambertMaterial( { color: 0xffffff, shading: THREE.FlatShading, overdraw: true } ); + + for ( var i = 0; i < 30; i ++ ) { + + mesh = new THREE.Mesh( geometry, materialSpheres ); + mesh.position.x = 500 * ( Math.random() - 0.5 ); + mesh.position.y = 500 * ( Math.random() - 0.5 ); + mesh.position.z = 500 * ( Math.random() - 0.5 ); + mesh.scale.x = mesh.scale.y = mesh.scale.z = 0.25 * ( Math.random() + 0.5 ); + scene.add( mesh ); + + } + + // Torus + + materialTorus = new THREE.MeshLambertMaterial( { color: 0xffffff, overdraw: true } ); + mesh = new THREE.Mesh( new THREE.TorusGeometry( 100, 25, 15, 30 ), materialTorus ); + scene.add( mesh ); + + // Lights + + var ambient = new THREE.AmbientLight( 0x101010 ); + scene.add( ambient ); + + directionalLight = new THREE.DirectionalLight( 0xffffff ); + directionalLight.position.set( 0, -70, 100 ).normalize(); + //scene.add( directionalLight ); + + pointLight = new THREE.PointLight( 0xffaa00 ); + scene.add( pointLight ); + + lightMesh = new THREE.Mesh( geometry, new THREE.MeshBasicMaterial( { color: 0xffaa00 } ) ); + lightMesh.scale.x = lightMesh.scale.y = lightMesh.scale.z = 0.05; + lightMesh.position = pointLight.position; + scene.add( lightMesh ); + + + if ( render_canvas ) { + + canvasRenderer = new THREE.CanvasRenderer(); + canvasRenderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT ); + container.appendChild( canvasRenderer.domElement ); + + } + + if ( render_gl ) { + + try { + + webglRenderer = new THREE.WebGLRenderer( { alpha: true } ); + webglRenderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT ); + webglRenderer.domElement.style.position = "relative"; + container.appendChild( webglRenderer.domElement ); + + has_gl = 1; + + } catch (e) { + + } + + } + + stats = new Stats(); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.top = '0px'; + stats.domElement.style.zIndex = 100; + container.appendChild( stats.domElement ); + + bcanvas.addEventListener("click", toggleCanvas, false); + bwebgl.addEventListener("click", toggleWebGL, false); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + SCREEN_WIDTH = window.innerWidth / 2; + SCREEN_HEIGHT = window.innerHeight; + + camera.aspect = SCREEN_WIDTH / SCREEN_HEIGHT; + camera.updateProjectionMatrix(); + + if ( canvasRenderer ) canvasRenderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT ); + if ( webglRenderer ) webglRenderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT ); + + } + + function onDocumentMouseMove( event ) { + + mouseX = ( event.clientX - windowHalfX ); + mouseY = ( event.clientY - windowHalfY ); + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + var delta = clock.getDelta(); + var r = clock.getElapsedTime(); + + if ( ! lightAdded && r >= 3.0 ) { + + scene.add( directionalLight ); + + materialTorus.needsUpdate = true; + materialSpheres.needsUpdate = true; + + lightAdded = true; + + } + + camera.position.x += ( mouseX - camera.position.x ) * 0.05; + camera.position.y += ( - mouseY - camera.position.y ) * 0.05; + + camera.lookAt( scene.position ); + + for ( var i = 0, l = scene.children.length; i < l; i ++ ) { + + var object = scene.children[ i ]; + + if ( object instanceof THREE.Mesh ) { + + if ( i % 3 == 1 ) + + object.rotation.z += 1.5 * delta; + + else if ( i % 3 == 2 ) + + object.rotation.y += 1.5 * delta; + + else if ( i % 3 == 0 ) + + object.rotation.x += 1.5 * delta; + + } + + } + + + lightMesh.position.x = 200 * Math.cos( r ); + lightMesh.position.z = 200 * Math.sin( r ); + + if ( render_canvas ) canvasRenderer.render( scene, camera ); + if ( render_gl && has_gl ) webglRenderer.render( scene, camera ); + + } + + function toggleCanvas() { + + render_canvas = !render_canvas; + bcanvas.className = render_canvas ? "button" : "button inactive"; + + render_gl = !render_canvas; + bwebgl.className = render_gl ? "button" : "button inactive"; + + if( has_gl ) + webglRenderer.domElement.style.display = render_gl ? "block" : "none"; + + canvasRenderer.domElement.style.display = render_canvas ? "block" : "none"; + + } + + function toggleWebGL() { + + render_gl = !render_gl; + bwebgl.className = render_gl ? "button" : "button inactive"; + + render_canvas = !render_gl; + bcanvas.className = render_canvas ? "button" : "button inactive"; + + if( has_gl ) + webglRenderer.domElement.style.display = render_gl ? "block" : "none"; + + canvasRenderer.domElement.style.display = render_canvas ? "block" : "none"; + + } +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/misc_lookat.html + +()=>{ + + var container, stats; + + var camera, scene, renderer; + + var mesh, geometry, sphere; + + var mouseX = 0, mouseY = 0; + + var windowHalfX = window.innerWidth / 2; + var windowHalfY = window.innerHeight / 2; + + document.addEventListener( 'mousemove', onDocumentMouseMove, false ); + + init(); + animate(); + + + function init() { + + container = document.createElement( 'div' ); + document.body.appendChild( container ); + + camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 15000 ); + camera.position.z = 3200; + + scene = new THREE.Scene(); + + sphere = new THREE.Mesh( new THREE.SphereGeometry( 100, 20, 20 ), new THREE.MeshNormalMaterial( { shading: THREE.SmoothShading } ) ); + scene.add( sphere ); + + var geometry = new THREE.CylinderGeometry( 0, 10, 100, 3 ); + geometry.applyMatrix( new THREE.Matrix4().setRotationFromEuler( new THREE.Vector3( Math.PI / 2, Math.PI, 0 ) ) ); + + var material = new THREE.MeshNormalMaterial(); + + for ( var i = 0; i < 1000; i ++ ) { + + var mesh = new THREE.Mesh( geometry, material ); + mesh.position.x = Math.random() * 4000 - 2000; + mesh.position.y = Math.random() * 4000 - 2000; + mesh.position.z = Math.random() * 4000 - 2000; + mesh.scale.x = mesh.scale.y = mesh.scale.z = Math.random() * 4 + 2; + scene.add( mesh ); + + } + + scene.matrixAutoUpdate = false; + + renderer = new THREE.WebGLRenderer( { antialias: true } ); + renderer.setSize( window.innerWidth, window.innerHeight ); + renderer.sortObjects = false; + container.appendChild( renderer.domElement ); + + stats = new Stats(); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.top = '0px'; + stats.domElement.style.zIndex = 100; + container.appendChild( stats.domElement ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + windowHalfX = window.innerWidth / 2; + windowHalfY = window.innerHeight / 2; + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + } + + function onDocumentMouseMove(event) { + + mouseX = ( event.clientX - windowHalfX ) * 10; + mouseY = ( event.clientY - windowHalfY ) * 10; + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + var time = Date.now() * 0.0005; + + sphere.position.x = Math.sin( time * 0.7 ) * 2000; + sphere.position.y = Math.cos( time * 0.5 ) * 2000; + sphere.position.z = Math.cos( time * 0.3 ) * 2000; + + for ( var i = 1, l = scene.children.length; i < l; i ++ ) { + + scene.children[ i ].lookAt( sphere.position ); + + } + + camera.position.x += ( mouseX - camera.position.x ) * .05; + camera.position.y += ( - mouseY - camera.position.y ) * .05; + camera.lookAt( scene.position ); + + renderer.render( scene, camera ); + + } +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/misc_sound.html + +()=>{ + if ( ! Detector.webgl ) Detector.addGetWebGLMessage(); + + var container; + var camera, controls, scene, renderer; + var light, pointLight; + + var mesh; + var material_sphere1, material_sphere2; + + var sound1, sound2; + + var clock = new THREE.Clock(); + + var Sound = function ( sources, radius, volume ) { + + var audio = document.createElement( 'audio' ); + + for ( var i = 0; i < sources.length; i ++ ) { + + var source = document.createElement( 'source' ); + source.src = sources[ i ]; + + audio.appendChild( source ); + + } + + this.position = new THREE.Vector3(); + + this.play = function () { + + audio.play(); + + } + + this.update = function ( camera ) { + + var distance = this.position.distanceTo( camera.position ); + + if ( distance <= radius ) { + + audio.volume = volume * ( 1 - distance / radius ); + + } else { + + audio.volume = 0; + + } + + } + + } + + init(); + animate(); + + function init() { + + container = document.getElementById( 'container' ); + + camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 10000 ); + camera.position.set( 0, 25, 0 ); + + controls = new THREE.FirstPersonControls( camera ); + + controls.movementSpeed = 70; + controls.lookSpeed = 0.05; + controls.noFly = true; + controls.lookVertical = false; + + scene = new THREE.Scene(); + scene.fog = new THREE.FogExp2( 0x000000, 0.0035 ); + + light = new THREE.DirectionalLight( 0xffffff ); + light.position.set( 0, 0.5, 1 ).normalize(); + scene.add( light ); + + var sphere = new THREE.SphereGeometry( 20, 32, 16 ); + + material_sphere1 = new THREE.MeshLambertMaterial( { color: 0xffaa00, shading: THREE.FlatShading } ); + material_sphere2 = new THREE.MeshLambertMaterial( { color: 0xff2200, shading: THREE.FlatShading } ); + + // sound spheres + + var s = 1; + + var mesh1 = new THREE.Mesh( sphere, material_sphere1 ); + mesh1.position.set( -250, 30, 0 ); + mesh1.scale.set( s, s, s ); + scene.add( mesh1 ); + + sound1 = new Sound( [ 'sounds/358232_j_s_song.mp3', 'sounds/358232_j_s_song.ogg' ], 275, 1 ); + sound1.position.copy( mesh1.position ); + sound1.play(); + + // + + var mesh2 = new THREE.Mesh( sphere, material_sphere2 ); + mesh2.position.set( 250, 30, 0 ); + mesh2.scale.set( s, s, s ); + scene.add( mesh2 ); + + sound2 = new Sound( [ 'sounds/376737_Skullbeatz___Bad_Cat_Maste.mp3', 'sounds/376737_Skullbeatz___Bad_Cat_Maste.ogg' ], 275, 1 ); + sound2.position.copy( mesh2.position ); + sound2.play(); + + + // ground + + var material = new THREE.MeshLambertMaterial( { color: 0x7f7566, wireframe: true, wireframeLinewidth: 1 } ); + + mesh = new THREE.Mesh( new THREE.PlaneGeometry( 1000, 1000, 100, 100 ), material ); + mesh.position.y = 0.1; + mesh.rotation.x = - Math.PI / 2; + scene.add( mesh ); + + // + + renderer = new THREE.WebGLRenderer( { clearColor: 0x000000, clearAlpha: 1, antialias: true } ); + renderer.setSize( window.innerWidth, window.innerHeight ); + + container.innerHTML = ""; + container.appendChild( renderer.domElement ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + controls.handleResize(); + + } + + function animate() { + + requestAnimationFrame( animate ); + render(); + + } + + + function render() { + + var delta = clock.getDelta(), + time = clock.getElapsedTime() * 5; + + controls.update( delta ); + + material_sphere1.color.setHSL( 0.0, 0.3 + 0.7 * ( 1 + Math.cos( time ) ) / 2, 0.5 ); + material_sphere2.color.setHSL( 0.1, 0.3 + 0.7 * ( 1 + Math.sin( time ) ) / 2, 0.5 ); + + renderer.render( scene, camera ); + + sound1.update( camera ); + sound2.update( camera ); + + } + +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/misc_ubiquity_test.html + +()=>{ + var SCREEN_WIDTH = window.innerWidth / 2; + var SCREEN_HEIGHT = window.innerHeight / 2; + var AMOUNT = 100; + + var container, stats; + + var camera, scene; + var canvasRenderer, svgRenderer, softwareRenderer, webglRenderer; + + var mesh, group; + + var mouseX = 0, mouseY = 0; + + var windowHalfX = window.innerWidth / 2; + var windowHalfY = window.innerHeight / 2; + + init(); + animate(); + + function init() { + + container = document.createElement( 'div' ); + document.body.appendChild( container ); + + camera = new THREE.PerspectiveCamera( 75, SCREEN_WIDTH / SCREEN_HEIGHT, 1, 100000 ); + camera.position.z = 500; + + scene = new THREE.Scene(); + + // QRCODE + + mesh = new THREE.Mesh( new Qrcode(), new THREE.MeshLambertMaterial( { /*emissive: 0xff0000,*/ vertexColors: THREE.FaceColors } ) ); + mesh.scale.x = mesh.scale.y = mesh.scale.z = 2; + scene.add( mesh ); + + // CUBES + + var cube = new THREE.CubeGeometry( 100, 100, 100 ); + + mesh = new THREE.Mesh( cube, new THREE.MeshBasicMaterial( { color: 0x0000ff, opacity: 0.5, transparent: true } ) ); + mesh.position.x = 500; + mesh.rotation.x = Math.random(); + mesh.rotation.y = Math.random(); + mesh.scale.x = mesh.scale.y = mesh.scale.z = 2; + scene.add( mesh ); + + mesh = new THREE.Mesh( cube, new THREE.MeshBasicMaterial( { color: Math.random() * 0xffffff } ) ); + mesh.position.x = 500; + mesh.position.y = 500; + mesh.rotation.x = Math.random(); + mesh.rotation.y = Math.random(); + mesh.scale.x = mesh.scale.y = mesh.scale.z = 2; + scene.add( mesh ); + + // PLANE + + mesh = new THREE.Mesh( new THREE.PlaneGeometry( 100, 100 ), new THREE.MeshBasicMaterial( { color: Math.random() * 0xffffff, side: THREE.DoubleSide } ) ); + mesh.position.y = -500; + mesh.scale.x = mesh.scale.y = mesh.scale.z = 2; + scene.add( mesh ); + + // CYLINDER + + mesh = new THREE.Mesh( new THREE.CylinderGeometry( 20, 100, 200, 10 ), new THREE.MeshBasicMaterial( { color: Math.random() * 0xffffff } ) ); + mesh.position.x = -500; + mesh.rotation.x = - Math.PI / 2; + mesh.scale.x = mesh.scale.y = mesh.scale.z = 2; + scene.add( mesh ); + + // POLYFIELD + + var geometry = new THREE.Geometry(); + var materials = []; + + for ( var i = 0; i < 100; i ++ ) { + + var v = new THREE.Vector3( Math.random() * 1000 - 500, Math.random() * 1000 - 500, Math.random() * 1000 - 500 ); + + var v0 = new THREE.Vector3( Math.random() * 100 - 50, Math.random() * 100 - 50, Math.random() * 100 - 50 ); + var v1 = new THREE.Vector3( Math.random() * 100 - 50, Math.random() * 100 - 50, Math.random() * 100 - 50 ); + var v2 = new THREE.Vector3( Math.random() * 100 - 50, Math.random() * 100 - 50, Math.random() * 100 - 50 ); + + v0.add( v ); + v1.add( v ); + v2.add( v ); + + var face = new THREE.Face3( geometry.vertices.push( v0 ) - 1, geometry.vertices.push( v1 ) - 1, geometry.vertices.push( v2 ) - 1, null, null, i ); + + geometry.faces.push( face ); + + materials.push( new THREE.MeshBasicMaterial( { color: Math.random() * 0xffffff, side: THREE.DoubleSide } ) ); + + } + + geometry.computeFaceNormals(); + geometry.computeCentroids(); + + group = new THREE.Object3D(); + group.scale.x = group.scale.y = group.scale.z = 2; + scene.add( group ); + + mesh = new THREE.Mesh( geometry, new THREE.MeshFaceMaterial( materials ) ); + group.add( mesh ); + + // LIGHTS + + var ambient = new THREE.AmbientLight( 0x80ffff ); + scene.add( ambient ); + + var directional = new THREE.DirectionalLight( 0xffff00 ); + directional.position.set( - 1, 0.5, 0 ); + scene.add( directional ); + + canvasRenderer = new THREE.CanvasRenderer(); + canvasRenderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT ); + container.appendChild( canvasRenderer.domElement ); + + svgRenderer = new THREE.SVGRenderer(); + svgRenderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT ); + svgRenderer.setQuality( 'low' ); + container.appendChild( svgRenderer.domElement ); + + softwareRenderer = new THREE.SoftwareRenderer(); + softwareRenderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT ); + container.appendChild( softwareRenderer.domElement ); + + webglRenderer = new THREE.WebGLRenderer( { antialias: true } ); + webglRenderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT ); + container.appendChild( webglRenderer.domElement ); + + stats = new Stats(); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.top = '0px'; + container.appendChild( stats.domElement ); + + document.addEventListener( 'mousemove', onDocumentMouseMove, false ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + windowHalfX = window.innerWidth / 2; + windowHalfY = window.innerHeight / 2; + + SCREEN_WIDTH = window.innerWidth / 2; + SCREEN_HEIGHT = window.innerHeight / 2; + + camera.aspect = SCREEN_WIDTH / SCREEN_HEIGHT; + camera.updateProjectionMatrix(); + + canvasRenderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT ); + svgRenderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT ); + softwareRenderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT ); + webglRenderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT ); + + } + + function onDocumentMouseMove(event) { + + mouseX = ( event.clientX - windowHalfX ); + mouseY = ( event.clientY - windowHalfY ); + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + camera.position.x += ( mouseX - camera.position.x ) * .05; + camera.position.y += ( - mouseY - camera.position.y ) * .05; + camera.lookAt( scene.position ); + + group.rotation.y += 0.01; + + canvasRenderer.render( scene, camera ); + svgRenderer.render( scene, camera ); + softwareRenderer.render( scene, camera ); + webglRenderer.render( scene, camera ); + + } +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/misc_uv_tests.html + +()=>{ + /* + * This is to help debug UVs problems in geometry, + * as well as allow a new user to visualize what UVs are about. + */ + + + function test(name, geometry) { + + var d = document.createElement('div'); + d.innerHTML = '

' + name + '
'; + d.appendChild(THREE.UVsDebug(geometry)); + document.body.appendChild(d); + + } + + + test('new THREE.PlaneGeometry( 100, 100, 4, 4 )', new THREE.PlaneGeometry( 100, 100, 4, 4 )); + test('new THREE.SphereGeometry( 75, 12, 6 )', new THREE.SphereGeometry( 75, 12, 6 )); + + test('new THREE.IcosahedronGeometry( 30, 1 )', new THREE.IcosahedronGeometry( 30, 1 )); + test('new THREE.OctahedronGeometry( 30, 2 )', new THREE.OctahedronGeometry( 30, 2 )); + + test('new THREE.CylinderGeometry( 25, 75, 100, 10, 5 )', new THREE.CylinderGeometry( 25, 75, 100, 10, 5 )); + + test('new THREE.CubeGeometry( 100, 100, 100, 4, 4, 4 )', new THREE.CubeGeometry( 100, 100, 100, 4, 4, 4 )); + + var points = []; + + for ( var i = 0; i < 10; i ++ ) { + + points.push( new THREE.Vector3( Math.sin( i * 0.2 ) * 15 + 50, 0, ( i - 5 ) * 2 ) ); + + } + + + test('new THREE.LatheGeometry( points, 8 )', new THREE.LatheGeometry( points, 8 )); + test('new THREE.TorusGeometry( 50, 20, 8, 8 )', new THREE.TorusGeometry( 50, 20, 8, 8 )); + test('new THREE.TorusKnotGeometry( 50, 10, 12, 6 )', new THREE.TorusKnotGeometry( 50, 10, 12, 6 )); + + /* + Not sure how UVs for ExtrudeGeometry are done currently... + */ + + var pts = [], starPoints = 5, l; + for (i=0; i{ + var container, stats; + + var camera, controls, scene, renderer; + + var torus, cube; + + var start = Date.now(); + + 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 - software renderer
drag to change the point of view'; + container.appendChild( info ); + + camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 ); + camera.position.z = 600; + + controls = new THREE.TrackballControls( camera ); + + scene = new THREE.Scene(); + + torus = new THREE.Mesh( new THREE.TorusKnotGeometry( 150 ), new THREE.MeshBasicMaterial( { color: 0x0000ff } ) ); + scene.add( torus ); + + // Plane + + cube = new THREE.Mesh( new THREE.CubeGeometry( 200, 200, 200 ), new THREE.MeshBasicMaterial( { color: 0x00ff00 } ) ); + scene.add( cube ); + + renderer = new THREE.SoftwareRenderer(); + 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 ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + var timer = Date.now() - start; + + torus.position.y = Math.sin( timer * 0.002 ) * 150; + torus.rotation.x = timer * 0.0003; + torus.rotation.z = timer * 0.0002; + + cube.rotation.x = timer * 0.0002; + cube.rotation.z = timer * 0.0003; + + + controls.update(); + + renderer.render( scene, camera ); + + } +}; \ No newline at end of file diff --git a/threejs/three.d.ts b/threejs/three.d.ts index e3868af58d..e4a692f58b 100644 --- a/threejs/three.d.ts +++ b/threejs/three.d.ts @@ -88,7 +88,9 @@ module THREE { export var AddOperation: Combine; // Mapping modes - export enum Mapping { } + export interface Mapping { + new(): Mapping; + } export var UVMapping: Mapping; export var CubeReflectionMapping: Mapping; export var CubeRefractionMapping: Mapping; @@ -1250,6 +1252,10 @@ module THREE { * Returns -1 if x is less than 0, 1 if x is greater than 0, and 0 if x is zero. */ sign(x: number): number; + + degToRad(degrees: number): number; + + radToDeg(radians: number): number; }; /** @@ -1402,7 +1408,7 @@ module THREE { * * @param v Rotation vector. order — The order of rotations. Eg. "XYZ". */ - setRotationFromEuler(v: Vector3, order: string): Matrix4; + setRotationFromEuler(v: Vector3, order?: string): Matrix4; /** * Sets the rotation submatrix of this matrix to the rotation specified by q. @@ -3868,7 +3874,7 @@ module THREE { export interface Uniforms { - [name: string]: { type: string; value: Object; }; + [name: string]: { type: string; value: any; }; //[name:string]:{type:UniformType;value:Object;}; } @@ -3924,10 +3930,14 @@ module THREE { constructor(geometry?: Geometry, material?: ShaderMaterial, type?: number); geometry: Geometry; material: Material; - type: number; + type: LineType; clone(object?: Line): Line; } + enum LineType{} + var LineStrip: LineType; + var LinePieces: LineType; + export class LOD extends Object3D { constructor(); LODs: Object3D[]; @@ -4779,6 +4789,17 @@ module THREE { type?: TextureDataType, anisotropy?: number ); + constructor( + image: HTMLCanvasElement, + mapping?: Mapping, + wrapS?: Wrapping, + wrapT?: Wrapping, + magFilter?: TextureFilter, + minFilter?: TextureFilter, + format?: PixelFormat, + type?: TextureDataType, + anisotropy?: number + ); id: number; name: string; image: Object; // HTMLImageElement or ImageData ; @@ -5378,8 +5399,8 @@ module THREE { * Defines a 2d shape plane using paths. */ export class Shape extends Path { - constructor(); - holes: Vector2[][]; + constructor(points?: Vector2[]); + holes: Path[]; extrude(options?: any): ExtrudeGeometry; makeGeometry(options?: any): ShapeGeometry; getPointsHoles(divisions: number): Vector2[][]; @@ -5502,8 +5523,8 @@ module THREE { } export class ShapeGeometry extends Geometry { - constructor(shape: Shape, options: any); - constructor(shapes: Shape[], options: any); + constructor(shape: Shape, options?: any); + constructor(shapes: Shape[], options?: any); shapebb: BoundingBox; addShapeList(shapes: Shape[], options: any): ShapeGeometry; addShape(shape: Shape, options?: any): void; @@ -5766,7 +5787,7 @@ module THREE { export var UniformsUtils: { merge(uniforms: Object[]): Uniforms; merge(uniforms: Uniforms[]): Uniforms; - clone(uniforms_src: Object[][]): Object[][]; + clone(uniforms_src: Uniforms): Uniforms; }; export var UniformsLib: { From f34f352f9bc6eacf526ad231a3dfbd838c2fd770 Mon Sep 17 00:00:00 2001 From: Kon Date: Mon, 4 Mar 2013 07:44:48 +0900 Subject: [PATCH 2/3] Add more and more examples to three-tests.ts --- threejs/three-tests.ts | 5005 +++++++++++++++++++++++++++++++++++++++- threejs/three.d.ts | 77 +- 2 files changed, 5065 insertions(+), 17 deletions(-) diff --git a/threejs/three-tests.ts b/threejs/three-tests.ts index 2d59266c3b..f38cb99176 100644 --- a/threejs/three-tests.ts +++ b/threejs/three-tests.ts @@ -3110,6 +3110,7 @@ declare var Stats: any; declare var TWEEN: any; declare var Detector: any; declare var Qrcode: any; +declare var ImprovedNoise: any; declare module THREE{ var PDBLoader: any; @@ -3131,6 +3132,9 @@ declare module THREE{ var SoftwareRenderer: any; var UVsDebug: any; var UVsUtils: any; + var Curves: any; + var ParametricGeometries: any; + var BinaryLoader: any; } interface CSS3Properties{ @@ -5813,7 +5817,7 @@ var container, stats; function loadImage( path ) { var image:HTMLImageElement = document.createElement( 'img' ); - var texture = new THREE.Texture( image, THREE.UVMapping ) + var texture = new THREE.Texture( image, new THREE.UVMapping() ) image.onload = function () { texture.needsUpdate = true; }; image.src = path; @@ -10803,4 +10807,5003 @@ var container, stats; renderer.render( scene, camera ); } +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/webgl_animation_cloth.html + + +declare var cloth: any; +declare var clothFunction: any; +declare var ballSize: number; +declare var windStrength: number; +declare var windForce: THREE.Vector3; +declare function simulate(time: number); +declare var ballPosition: THREE.Vector3; +()=>{ + /* testing cloth simulation */ + + var pinsFormation = []; + var pins = [6]; + + pinsFormation.push( pins ); + + pins = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]; + pinsFormation.push( pins ); + + pins = [ 0 ]; + pinsFormation.push( pins ); + + pins = []; // cut the rope ;) + pinsFormation.push( pins ); + + pins = [ 0, cloth.w ]; // classic 2 pins + pinsFormation.push( pins ); + + pins = pinsFormation[ 1 ]; + + + function togglePins() { + + pins = pinsFormation[ ~~( Math.random() * pinsFormation.length ) ]; + + } + + if ( ! Detector.webgl ) Detector.addGetWebGLMessage(); + + var container, stats; + var camera, scene, renderer; + + var clothGeometry; + var sphere; + var object, arrow; + + var rotate = true; + + init(); + animate(); + + function init() { + + container = document.createElement( 'div' ); + document.body.appendChild( container ); + + // scene + + scene = new THREE.Scene(); + + scene.fog = new THREE.Fog( 0xcce0ff, 500, 10000 ); + + // camera + + camera = new THREE.PerspectiveCamera( 30, window.innerWidth / window.innerHeight, 1, 10000 ); + camera.position.y = 50; + camera.position.z = 1500; + scene.add( camera ); + + // lights + + var light, materials; + + scene.add( new THREE.AmbientLight( 0x666666 ) ); + + light = new THREE.DirectionalLight( 0xdfebff, 1.75 ); + light.position.set( 50, 200, 100 ); + light.position.multiplyScalar( 1.3 ); + + light.castShadow = true; + //light.shadowCameraVisible = true; + + light.shadowMapWidth = 2048; + light.shadowMapHeight = 2048; + + var d = 300; + + light.shadowCameraLeft = -d; + light.shadowCameraRight = d; + light.shadowCameraTop = d; + light.shadowCameraBottom = -d; + + light.shadowCameraFar = 1000; + light.shadowDarkness = 0.5; + + scene.add( light ); + + light = new THREE.DirectionalLight( 0x3dff0c, 0.35 ); + light.position.set( 0, -1, 0 ); + + scene.add( light ); + + // cloth material + + var clothTexture = THREE.ImageUtils.loadTexture( 'textures/patterns/circuit_pattern.png' ); + clothTexture.wrapS = clothTexture.wrapT = THREE.RepeatWrapping; + clothTexture.anisotropy = 16; + + var clothMaterial = new THREE.MeshPhongMaterial( { alphaTest: 0.5, ambient: 0xffffff, color: 0xffffff, specular: 0x030303, emissive: 0x111111, shiness: 10, map: clothTexture, side: THREE.DoubleSide } ); + + // cloth geometry + clothGeometry = new THREE.ParametricGeometry( clothFunction, cloth.w, cloth.h, true ); + clothGeometry.dynamic = true; + clothGeometry.computeFaceNormals(); + + var uniforms = { texture: { type: "t", value: clothTexture } }; + var vertexShader = document.getElementById( 'vertexShaderDepth' ).textContent; + var fragmentShader = document.getElementById( 'fragmentShaderDepth' ).textContent; + + // cloth mesh + + object = new THREE.Mesh( clothGeometry, clothMaterial ); + object.position.set( 0, 0, 0 ); + object.castShadow = true; + object.receiveShadow = true; + scene.add( object ); + + object.customDepthMaterial = new THREE.ShaderMaterial( { uniforms: uniforms, vertexShader: vertexShader, fragmentShader: fragmentShader } ); + + // sphere + + var ballGeo = new THREE.SphereGeometry( ballSize, 20, 20 ); + var ballMaterial = new THREE.MeshPhongMaterial( { color: 0xffffff } ); + + sphere = new THREE.Mesh( ballGeo, ballMaterial ); + sphere.castShadow = true; + sphere.receiveShadow = true; + scene.add( sphere ); + + // arrow + + arrow = new THREE.ArrowHelper( new THREE.Vector3( 0, 1, 0 ), new THREE.Vector3( 0, 0, 0 ), 50, 0xff0000 ); + arrow.position.set( -200, 0, -200 ); + // scene.add( arrow ); + + // ground + + var initColor = new THREE.Color( 0x497f13 ); + var initTexture = THREE.ImageUtils.generateDataTexture( 1, 1, initColor ); + + var groundMaterial = new THREE.MeshPhongMaterial( { color: 0xffffff, specular: 0x111111, map: initTexture } ); + + var groundTexture = THREE.ImageUtils.loadTexture( "textures/terrain/grasslight-big.jpg", undefined, function() { groundMaterial.map = groundTexture } ); + groundTexture.wrapS = groundTexture.wrapT = THREE.RepeatWrapping; + groundTexture.repeat.set( 25, 25 ); + groundTexture.anisotropy = 16; + + var mesh = new THREE.Mesh( new THREE.PlaneGeometry( 20000, 20000 ), groundMaterial ); + mesh.position.y = -250; + mesh.rotation.x = - Math.PI / 2; + mesh.receiveShadow = true; + scene.add( mesh ); + + // poles + + var poleGeo = new THREE.CubeGeometry( 5, 375, 5 ); + var poleMat = new THREE.MeshPhongMaterial( { color: 0xffffff, specular: 0x111111, shiness: 100 } ); + + var mesh = new THREE.Mesh( poleGeo, poleMat ); + mesh.position.x = -125; + mesh.position.y = -62; + mesh.receiveShadow = true; + mesh.castShadow = true; + scene.add( mesh ); + + var mesh = new THREE.Mesh( poleGeo, poleMat ); + mesh.position.x = 125; + mesh.position.y = -62; + mesh.receiveShadow = true; + mesh.castShadow = true; + scene.add( mesh ); + + var mesh = new THREE.Mesh( new THREE.CubeGeometry( 255, 5, 5 ), poleMat ); + mesh.position.y = -250 + 750/2; + mesh.position.x = 0; + mesh.receiveShadow = true; + mesh.castShadow = true; + scene.add( mesh ); + + var gg = new THREE.CubeGeometry( 10, 10, 10 ); + var mesh = new THREE.Mesh( gg, poleMat ); + mesh.position.y = -250; + mesh.position.x = 125; + mesh.receiveShadow = true; + mesh.castShadow = true; + scene.add( mesh ); + + var mesh = new THREE.Mesh( gg, poleMat ); + mesh.position.y = -250; + mesh.position.x = -125; + mesh.receiveShadow = true; + mesh.castShadow = true; + scene.add( mesh ); + + // + + renderer = new THREE.WebGLRenderer( { antialias: true } ); + renderer.setSize( window.innerWidth, window.innerHeight ); + renderer.setClearColor( scene.fog.color ); + + container.appendChild( renderer.domElement ); + + renderer.gammaInput = true; + renderer.gammaOutput = true; + renderer.physicallyBasedShading = true; + + renderer.shadowMapEnabled = true; + + // + + stats = new Stats(); + container.appendChild( stats.domElement ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + sphere.visible = !true + + } + + // + + function onWindowResize() { + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + var time = Date.now(); + + windStrength = Math.cos( time / 7000 ) * 20 + 40; + windForce.set( Math.sin( time / 2000 ), Math.cos( time / 3000 ), Math.sin( time / 1000 ) ).normalize().multiplyScalar( windStrength ); + arrow.setLength( windStrength ); + arrow.setDirection( windForce ); + + simulate(time); + render(); + stats.update(); + + } + + function render() { + + var timer = Date.now() * 0.0002; + + var p = cloth.particles; + + for ( var i = 0, il = p.length; i < il; i ++ ) { + + clothGeometry.vertices[ i ].copy( p[ i ].position ); + + } + + clothGeometry.computeFaceNormals(); + clothGeometry.computeVertexNormals(); + + clothGeometry.normalsNeedUpdate = true; + clothGeometry.verticesNeedUpdate = true; + + sphere.position.copy( ballPosition ); + + if ( rotate ) { + + camera.position.x = Math.cos( timer ) * 1500; + camera.position.z = Math.sin( timer ) * 1500; + + } + + camera.lookAt( scene.position ); + + renderer.render( scene, camera ); + + } + +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/webgl_animation_skinning.html + +()=>{ + + if ( ! Detector.webgl ) Detector.addGetWebGLMessage(); + + window.onload = init; + + var container, stats; + + var camera, scene, renderer; + + var mesh, light; + + var mouseX = 0, mouseY = 0; + + var windowHalfX = window.innerWidth / 2; + var windowHalfY = window.innerHeight / 2; + + var animations = []; + var buffalos = []; + var offset = []; + + var floor, dz = 0, dstep = -10, playback = false; + + var clock = new THREE.Clock(); + + function init() { + + container = document.getElementById( 'container' ); + + camera = new THREE.PerspectiveCamera( 25, window.innerWidth / window.innerHeight, 1, 10000 ); + camera.position.set( 0, 185, 2500 ); + + scene = new THREE.Scene(); + scene.fog = new THREE.FogExp2( 0xfff4e5, 0.0003 ); + + light = new THREE.DirectionalLight( 0xffffff, 1.5 ); + light.position.set( 0, 1, 1 ).normalize(); + scene.add( light ); + + var planeSimple = new THREE.PlaneGeometry( 200, 300 ); + var planeTesselated = new THREE.PlaneGeometry( 100, 300, 25, 40 ); + var matWire = new THREE.MeshBasicMaterial( { color: 0x110000, wireframe: true, wireframeLinewidth: 2 } ); + var matSolid = new THREE.MeshBasicMaterial( { color: 0xffb23f } ); + + floor = new THREE.Mesh( planeSimple, matSolid ); + floor.position.y = -10; + floor.rotation.x = - Math.PI / 2; + floor.scale.set( 25, 25, 25 ); + scene.add( floor ); + + floor = new THREE.Mesh( planeTesselated, matWire ); + floor.rotation.x = - Math.PI / 2; + floor.scale.set( 25, 25, 25 ); + scene.add( floor ); + + renderer = new THREE.WebGLRenderer( { clearColor: 0xffffff, clearAlpha: 1, antialias: true } ); + renderer.setSize( window.innerWidth, window.innerHeight ); + renderer.setClearColor( scene.fog.color, 1 ); + renderer.sortObjects = false; + + container.appendChild( renderer.domElement ); + + stats = new Stats(); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.top = '0px'; + container.appendChild( stats.domElement ); + + document.addEventListener( 'mousemove', onDocumentMouseMove, false ); + document.addEventListener( 'click', startAnimation, false ); + + var loader = new THREE.JSONLoader(); + loader.load( "obj/buffalo/buffalo.js", createScene ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + // + + loop(); + + } + + function onWindowResize() { + + windowHalfX = window.innerWidth / 2; + windowHalfY = window.innerHeight / 2; + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + } + + function createScene( geometry, materials ) { + + buffalos = []; + animations = []; + + var x, y, + buffalo, animation, + gridx = 25, gridz = 15, + sepx = 150, sepz = 300; + + var material = new THREE.MeshFaceMaterial( materials ); + + var originalMaterial = materials[ 0 ]; + + originalMaterial.skinning = true; + originalMaterial.transparent = true; + originalMaterial.alphaTest = 0.75; + + THREE.AnimationHandler.add( geometry.animation ); + + for(var x = 0; x < gridx; x ++ ) { + + for(var z = 0; z < gridz; z ++ ) { + + buffalo = new THREE.SkinnedMesh( geometry, material, false ); + + buffalo.position.x = - ( gridx - 1 ) * sepx * 0.5 + x * sepx + Math.random() * 0.5 * sepx; + buffalo.position.z = - ( gridz - 1 ) * sepz * 0.5 + z * sepz + Math.random() * 0.5 * sepz - 500; + + buffalo.position.y = buffalo.geometry.boundingSphere.radius * 0.5; + buffalo.rotation.y = 0.2 - Math.random() * 0.4; + + scene.add( buffalo ); + + buffalos.push( buffalo ); + + animation = new THREE.Animation( buffalo, "take_001" ); + animations.push( animation ); + + offset.push( Math.random() ); + + } + + } + + } + + function startAnimation() { + + for( var i = 0; i < animations.length; i ++ ) { + + animations[ i ].offset = 0.05 * Math.random(); + animations[ i ].play(); + + } + + dz = dstep; + playback = true; + + } + + + function onDocumentMouseMove( event ) { + + mouseX = ( event.clientX - windowHalfX ); + mouseY = ( event.clientY - windowHalfY ); + + } + + function loop() { + + requestAnimationFrame( loop ); + + var delta = clock.getDelta(); + + THREE.AnimationHandler.update( delta ); + + camera.position.x += ( mouseX - camera.position.x ) * 0.05; + camera.lookAt( scene.position ); + + if ( buffalos && playback ) { + + var elapsed = clock.getElapsedTime(); + + camera.position.z += 2 * Math.sin( elapsed ); + + for(var i = 0; i < buffalos.length; i++ ) { + + buffalos[ i ].position.z += 2 * Math.sin( elapsed + offset[ i ] ); + + } + + } + + floor.position.z += dz; + if( floor.position.z < -500 ) floor.position.z = 0; + + + renderer.render( scene, camera ); + + stats.update(); + + } +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/webgl_animation_skinning_morph.html + +()=>{ + var SCREEN_WIDTH = window.innerWidth; + var SCREEN_HEIGHT = window.innerHeight; + var FLOOR = -250; + + var container,stats; + + var camera, scene; + var renderer; + + var mesh; + + var mouseX = 0, mouseY = 0; + + var windowHalfX = window.innerWidth / 2; + var windowHalfY = window.innerHeight / 2; + + var clock = new THREE.Clock(); + + document.addEventListener( 'mousemove', onDocumentMouseMove, false ); + + init(); + animate(); + + function init() { + + container = document.getElementById( 'container' ); + + camera = new THREE.PerspectiveCamera( 30, SCREEN_WIDTH / SCREEN_HEIGHT, 1, 10000 ); + camera.position.z = 2200; + + scene = new THREE.Scene(); + + scene.fog = new THREE.Fog( 0xffffff, 2000, 10000 ); + + scene.add( camera ); + + // GROUND + + var groundMaterial = new THREE.MeshPhongMaterial( { emissive: 0xbbbbbb } ); + var planeGeometry = new THREE.PlaneGeometry( 16000, 16000 ); + + var ground = new THREE.Mesh( planeGeometry, groundMaterial ); + ground.position.set( 0, FLOOR, 0 ); + ground.rotation.x = -Math.PI/2; + scene.add( ground ); + + ground.receiveShadow = true; + + + // LIGHTS + + var ambient = new THREE.AmbientLight( 0x222222 ); + scene.add( ambient ); + + + var light = new THREE.DirectionalLight( 0xebf3ff, 1.6 ); + light.position.set( 0, 140, 500 ).multiplyScalar( 1.1 ); + scene.add( light ); + + light.castShadow = true; + + light.shadowMapWidth = 2048; + light.shadowMapHeight = 2048; + + var d = 390; + + light.shadowCameraLeft = -d * 2; + light.shadowCameraRight = d * 2; + light.shadowCameraTop = d * 1.5; + light.shadowCameraBottom = -d; + + light.shadowCameraFar = 3500; + //light.shadowCameraVisible = true; + + // + + var light = new THREE.DirectionalLight( 0x497f13, 1 ); + light.position.set( 0, -1, 0 ); + scene.add( light ); + + // RENDERER + + renderer = new THREE.WebGLRenderer( { antialias: true } ); + renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT ); + renderer.domElement.style.position = "relative"; + + renderer.setClearColor( scene.fog.color, 1 ); + + container.appendChild( renderer.domElement ); + + renderer.gammaInput = true; + renderer.gammaOutput = true; + renderer.physicallyBasedShading = true; + + renderer.shadowMapEnabled = true; + + + // STATS + + stats = new Stats(); + container.appendChild( stats.domElement ); + + // + + var loader = new THREE.JSONLoader(); + loader.load( "models/skinned/knight.js", function ( geometry, materials ) { createScene( geometry, materials, 0, FLOOR, -300, 60 ) } ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + windowHalfX = window.innerWidth / 2; + windowHalfY = window.innerHeight / 2; + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + } + + function ensureLoop( animation ) { + + for ( var i = 0; i < animation.hierarchy.length; i ++ ) { + + var bone = animation.hierarchy[ i ]; + + var first = bone.keys[ 0 ]; + var last = bone.keys[ bone.keys.length - 1 ]; + + last.pos = first.pos; + last.rot = first.rot; + last.scl = first.scl; + + } + + } + + function createScene( geometry, materials, x, y, z, s ) { + + ensureLoop( geometry.animation ); + + geometry.computeBoundingBox(); + var bb = geometry.boundingBox; + + THREE.AnimationHandler.add( geometry.animation ); + + var path = "textures/cube/Park2/"; + var format = '.jpg'; + var urls = [ + path + 'posx' + format, path + 'negx' + format, + path + 'posy' + format, path + 'negy' + format, + path + 'posz' + format, path + 'negz' + format + ]; + + + //var envMap = THREE.ImageUtils.loadTextureCube( urls ); + + //var map = THREE.ImageUtils.loadTexture( "textures/ash_uvgrid01.jpg" ); + + //var bumpMap = THREE.ImageUtils.generateDataTexture( 1, 1, new THREE.Color() ); + //var bumpMap = THREE.ImageUtils.loadTexture( "textures/water.jpg" ); + + for ( var i = 0; i < materials.length; i ++ ) { + + var m = materials[ i ]; + m.skinning = true; + m.morphTargets = true; + + m.specular.setHSL( 0, 0, 0.1 ); + + m.color.setHSL( 0.6, 0, 0.6 ); + m.ambient.copy( m.color ); + + //m.map = map; + //m.envMap = envMap; + //m.bumpMap = bumpMap; + //m.bumpScale = 2; + + //m.combine = THREE.MixOperation; + //m.reflectivity = 0.75; + + m.wrapAround = true; + + } + + mesh = new THREE.SkinnedMesh( geometry, new THREE.MeshFaceMaterial( materials ) ); + mesh.position.set( x, y - bb.min.y * s, z ); + mesh.scale.set( s, s, s ); + scene.add( mesh ); + + mesh.castShadow = true; + mesh.receiveShadow = true; + + var animation = new THREE.Animation( mesh, geometry.animation.name ); + animation.JITCompile = false; + animation.interpolationType = THREE.AnimationHandler.LINEAR; + + animation.play(); + + } + + function onDocumentMouseMove( event ) { + + mouseX = ( event.clientX - windowHalfX ); + mouseY = ( event.clientY - windowHalfY ); + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + var delta = 0.75 * clock.getDelta(); + + camera.position.x += ( mouseX - camera.position.x ) * .05; + camera.position.y = THREE.Math.clamp( camera.position.y + ( - mouseY - camera.position.y ) * .05, 0, 1000 ); + + camera.lookAt( scene.position ); + + // update skinning + + THREE.AnimationHandler.update( delta ); + + // update morphs + + if ( mesh ) { + + var time = Date.now() * 0.001; + + // mouth + + mesh.morphTargetInfluences[ 1 ] = ( 1 + Math.sin( 4 * time ) ) / 2; + + // frown ? + + mesh.morphTargetInfluences[ 2 ] = ( 1 + Math.sin( 2 * time ) ) / 2; + + // eyes + + mesh.morphTargetInfluences[ 3 ] = ( 1 + Math.cos( 4 * time ) ) / 2; + + } + + renderer.render( scene, camera ); + + } +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/webgl_buffergeometry.html + +()=>{ + if ( ! Detector.webgl ) Detector.addGetWebGLMessage(); + + var container, stats; + + var camera, scene, renderer; + + var mesh; + + init(); + animate(); + + function init() { + + container = document.getElementById( 'container' ); + + // + + camera = new THREE.PerspectiveCamera( 27, window.innerWidth / window.innerHeight, 1, 3500 ); + camera.position.z = 2750; + + scene = new THREE.Scene(); + scene.fog = new THREE.Fog( 0x050505, 2000, 3500 ); + + // + + scene.add( new THREE.AmbientLight( 0x444444 ) ); + + var light1 = new THREE.DirectionalLight( 0xffffff, 0.5 ); + light1.position.set( 1, 1, 1 ); + scene.add( light1 ); + + var light2 = new THREE.DirectionalLight( 0xffffff, 1.5 ); + light2.position.set( 0, -1, 0 ); + scene.add( light2 ); + + // + + var triangles = 160000; + + var geometry = new THREE.BufferGeometry(); + geometry.attributes = { + index: { + itemSize: 1, + array: new Uint16Array( triangles * 3 ), + numItems: triangles * 3 + }, + position: { + itemSize: 3, + array: new Float32Array( triangles * 3 * 3 ), + numItems: triangles * 3 * 3 + }, + normal: { + itemSize: 3, + array: new Float32Array( triangles * 3 * 3 ), + numItems: triangles * 3 * 3 + }, + color: { + itemSize: 3, + array: new Float32Array( triangles * 3 * 3 ), + numItems: triangles * 3 * 3 + } + } + + // break geometry into + // chunks of 21,845 triangles (3 unique vertices per triangle) + // for indices to fit into 16 bit integer number + // floor(2^16 / 3) = 21845 + + var chunkSize = 21845; + + var indices = geometry.attributes.index.array; + + for ( var i = 0; i < indices.length; i ++ ) { + + indices[ i ] = i % ( 3 * chunkSize ); + + } + + var positions = geometry.attributes.position.array; + var normals = geometry.attributes.normal.array; + var colors = geometry.attributes.color.array; + + var color = new THREE.Color(); + + var n = 800, n2 = n/2; // triangles spread in the cube + var d = 12, d2 = d/2; // individual triangle size + + var pA = new THREE.Vector3(); + var pB = new THREE.Vector3(); + var pC = new THREE.Vector3(); + + var cb = new THREE.Vector3(); + var ab = new THREE.Vector3(); + + for ( var i = 0; i < positions.length; i += 9 ) { + + // positions + + var x = Math.random() * n - n2; + var y = Math.random() * n - n2; + var z = Math.random() * n - n2; + + var ax = x + Math.random() * d - d2; + var ay = y + Math.random() * d - d2; + var az = z + Math.random() * d - d2; + + var bx = x + Math.random() * d - d2; + var by = y + Math.random() * d - d2; + var bz = z + Math.random() * d - d2; + + var cx = x + Math.random() * d - d2; + var cy = y + Math.random() * d - d2; + var cz = z + Math.random() * d - d2; + + positions[ i ] = ax; + positions[ i + 1 ] = ay; + positions[ i + 2 ] = az; + + positions[ i + 3 ] = bx; + positions[ i + 4 ] = by; + positions[ i + 5 ] = bz; + + positions[ i + 6 ] = cx; + positions[ i + 7 ] = cy; + positions[ i + 8 ] = cz; + + // flat face normals + + pA.set( ax, ay, az ); + pB.set( bx, by, bz ); + pC.set( cx, cy, cz ); + + cb.subVectors( pC, pB ); + ab.subVectors( pA, pB ); + cb.cross( ab ); + + cb.normalize(); + + var nx = cb.x; + var ny = cb.y; + var nz = cb.z; + + normals[ i ] = nx; + normals[ i + 1 ] = ny; + normals[ i + 2 ] = nz; + + normals[ i + 3 ] = nx; + normals[ i + 4 ] = ny; + normals[ i + 5 ] = nz; + + normals[ i + 6 ] = nx; + normals[ i + 7 ] = ny; + normals[ i + 8 ] = nz; + + // colors + + var vx = ( x / n ) + 0.5; + var vy = ( y / n ) + 0.5; + var vz = ( z / n ) + 0.5; + + //color.setHSV( 0.5 + 0.5 * vx, 0.25 + 0.75 * vy, 0.25 + 0.75 * vz ); + color.setRGB( vx, vy, vz ); + + colors[ i ] = color.r; + colors[ i + 1 ] = color.g; + colors[ i + 2 ] = color.b; + + colors[ i + 3 ] = color.r; + colors[ i + 4 ] = color.g; + colors[ i + 5 ] = color.b; + + colors[ i + 6 ] = color.r; + colors[ i + 7 ] = color.g; + colors[ i + 8 ] = color.b; + + } + + geometry.offsets = []; + + var offsets = triangles / chunkSize; + + for ( var i = 0; i < offsets; i ++ ) { + + var offset = { + start: i * chunkSize * 3, + index: i * chunkSize * 3, + count: Math.min( triangles - ( i * chunkSize ), chunkSize ) * 3 + }; + + geometry.offsets.push( offset ); + + } + + geometry.computeBoundingSphere(); + + var material = new THREE.MeshPhongMaterial( { + color: 0xaaaaaa, ambient: 0xaaaaaa, specular: 0xffffff, shininess: 250, + side: THREE.DoubleSide, vertexColors: THREE.VertexColors + } ); + + mesh = new THREE.Mesh( geometry, material ); + scene.add( mesh ); + + // + + renderer = new THREE.WebGLRenderer( { antialias: false, clearColor: 0x333333, clearAlpha: 1, alpha: false } ); + renderer.setSize( window.innerWidth, window.innerHeight ); + renderer.setClearColor( scene.fog.color, 1 ); + + renderer.gammaInput = true; + renderer.gammaOutput = true; + renderer.physicallyBasedShading = true; + + container.appendChild( renderer.domElement ); + + // + + stats = new Stats(); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.top = '0px'; + container.appendChild( stats.domElement ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + var time = Date.now() * 0.001; + + mesh.rotation.x = time * 0.25; + mesh.rotation.y = time * 0.5; + + renderer.render( scene, camera ); + + } +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/webgl_buffergeometry_lines.html + +()=>{ + + if ( ! Detector.webgl ) Detector.addGetWebGLMessage(); + + var container, stats; + + var camera, scene, renderer; + + var mesh; + + init(); + animate(); + + function init() { + + container = document.getElementById( 'container' ); + + // + + camera = new THREE.PerspectiveCamera( 27, window.innerWidth / window.innerHeight, 1, 4000 ); + camera.position.z = 2750; + + scene = new THREE.Scene(); + + + var segments = 10000; + + var geometry = new THREE.BufferGeometry(); + var material = new THREE.LineBasicMaterial({ vertexColors: true }); + + geometry.attributes = { + position: { + itemSize: 3, + array: new Float32Array(segments * 3), + numItems: segments * 3 + }, + color: { + itemSize: 3, + array: new Float32Array(segments * 3), + numItems: segments * 3 + } + }; + + var positions = geometry.attributes.position.array; + var colors = geometry.attributes.color.array; + + var r = 800; + + for ( var i = 0; i < segments; i ++ ) { + + var x = Math.random() * r - r / 2; + var y = Math.random() * r - r / 2; + var z = Math.random() * r - r / 2; + + // positions + + positions[ i * 3 ] = x; + positions[ i * 3 + 1 ] = y; + positions[ i * 3 + 2 ] = z; + + // colors + + colors[ i * 3 ] = ( x / r ) + 0.5; + colors[ i * 3 + 1 ] = ( y / r ) + 0.5; + colors[ i * 3 + 2 ] = ( z / r ) + 0.5; + + } + + geometry.computeBoundingSphere(); + + mesh = new THREE.Line( geometry, material ); + scene.add( mesh ); + + // + + renderer = new THREE.WebGLRenderer( { antialias: false, clearColor: 0x000000, clearAlpha: 0, alpha: true } ); + renderer.setSize( window.innerWidth, window.innerHeight ); + + renderer.gammaInput = true; + renderer.gammaOutput = true; + renderer.physicallyBasedShading = true; + + container.appendChild( renderer.domElement ); + + // + + stats = new Stats(); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.top = '0px'; + container.appendChild( stats.domElement ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + var time = Date.now() * 0.001; + + mesh.rotation.x = time * 0.25; + mesh.rotation.y = time * 0.5; + + renderer.render( scene, camera ); + + } +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/webgl_buffergeometry_particles.html + +()=>{ + if ( ! Detector.webgl ) Detector.addGetWebGLMessage(); + + var container, stats; + + var camera, scene, renderer; + + var mesh; + + var particleSystem; + + init(); + animate(); + + function init() { + + container = document.getElementById( 'container' ); + + // + + camera = new THREE.PerspectiveCamera( 27, window.innerWidth / window.innerHeight, 5, 3500 ); + camera.position.z = 2750; + + scene = new THREE.Scene(); + scene.fog = new THREE.Fog( 0x050505, 2000, 3500 ); + + // + + var particles = 500000; + + var geometry = new THREE.BufferGeometry(); + geometry.attributes = { + + position: { + itemSize: 3, + array: new Float32Array( particles * 3 ), + numItems: particles * 3 + }, + color: { + itemSize: 3, + array: new Float32Array( particles * 3 ), + numItems: particles * 3 + } + + } + + + var positions = geometry.attributes.position.array; + var colors = geometry.attributes.color.array; + + var color = new THREE.Color(); + + var n = 1000, n2 = n / 2; // particles spread in the cube + + for ( var i = 0; i < positions.length; i += 3 ) { + + // positions + + var x = Math.random() * n - n2; + var y = Math.random() * n - n2; + var z = Math.random() * n - n2; + + positions[ i ] = x; + positions[ i + 1 ] = y; + positions[ i + 2 ] = z; + + // colors + + var vx = ( x / n ) + 0.5; + var vy = ( y / n ) + 0.5; + var vz = ( z / n ) + 0.5; + + color.setRGB( vx, vy, vz ); + + colors[ i ] = color.r; + colors[ i + 1 ] = color.g; + colors[ i + 2 ] = color.b; + + } + + geometry.computeBoundingSphere(); + + // + + var material = new THREE.ParticleBasicMaterial( { size: 15, vertexColors: true } ); + + particleSystem = new THREE.ParticleSystem( geometry, material ); + scene.add( particleSystem ); + + // + + renderer = new THREE.WebGLRenderer( { antialias: false, clearColor: 0x333333, clearAlpha: 1, alpha: false } ); + renderer.setSize( window.innerWidth, window.innerHeight ); + renderer.setClearColor( scene.fog.color, 1 ); + + container.appendChild( renderer.domElement ); + + // + + stats = new Stats(); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.top = '0px'; + container.appendChild( stats.domElement ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + var windowHalfX = window.innerWidth / 2; + var windowHalfY = window.innerHeight / 2; + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + var time = Date.now() * 0.001; + + particleSystem.rotation.x = time * 0.25; + particleSystem.rotation.y = time * 0.5; + + renderer.render( scene, camera ); + + } +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/webgl_camera.html + +()=>{ + var SCREEN_WIDTH = window.innerWidth; + var SCREEN_HEIGHT = window.innerHeight; + + var container, stats; + var camera, scene, renderer, mesh; + var cameraRig, activeCamera, activeHelper; + var cameraPerspective, cameraOrtho; + var cameraPerspectiveHelper, cameraOrthoHelper; + + init(); + animate(); + + function init() { + + container = document.createElement( 'div' ); + document.body.appendChild( container ); + + scene = new THREE.Scene(); + + // + + camera = new THREE.PerspectiveCamera( 50, 0.5 * SCREEN_WIDTH / SCREEN_HEIGHT, 1, 10000 ); + camera.position.z = 2500; + + cameraPerspective = new THREE.PerspectiveCamera( 50, 0.5 * SCREEN_WIDTH / SCREEN_HEIGHT, 150, 1000 ); + + cameraPerspectiveHelper = new THREE.CameraHelper( cameraPerspective ); + scene.add( cameraPerspectiveHelper ); + + // + + cameraOrtho = new THREE.OrthographicCamera( 0.5 * SCREEN_WIDTH / - 2, 0.5 * SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, SCREEN_HEIGHT / - 2, 150, 1000 ); + + cameraOrthoHelper = new THREE.CameraHelper( cameraOrtho ); + scene.add( cameraOrthoHelper ); + + // + + activeCamera = cameraPerspective; + activeHelper = cameraPerspectiveHelper; + + + // counteract different front orientation of cameras vs rig + + cameraOrtho.rotation.y = Math.PI; + cameraPerspective.rotation.y = Math.PI; + + cameraRig = new THREE.Object3D(); + + cameraRig.add( cameraPerspective ); + cameraRig.add( cameraOrtho ); + + scene.add( cameraRig ); + + // + + mesh = new THREE.Mesh( new THREE.SphereGeometry( 100, 16, 8 ), new THREE.MeshBasicMaterial( { color: 0xffffff, wireframe: true } ) ); + scene.add( mesh ); + + var mesh2 = new THREE.Mesh( new THREE.SphereGeometry( 50, 16, 8 ), new THREE.MeshBasicMaterial( { color: 0x00ff00, wireframe: true } ) ); + mesh2.position.y = 150; + mesh.add( mesh2 ); + + var mesh3 = new THREE.Mesh( new THREE.SphereGeometry( 5, 16, 8 ), new THREE.MeshBasicMaterial( { color: 0x0000ff, wireframe: true } ) ); + mesh3.position.z = 150; + cameraRig.add( mesh3 ); + + // + + var geometry = new THREE.Geometry(); + + for ( var i = 0; i < 10000; i ++ ) { + + var vertex = new THREE.Vector3(); + vertex.x = THREE.Math.randFloatSpread( 2000 ); + vertex.y = THREE.Math.randFloatSpread( 2000 ); + vertex.z = THREE.Math.randFloatSpread( 2000 ); + + geometry.vertices.push( vertex ); + + } + + var particles = new THREE.ParticleSystem( geometry, new THREE.ParticleBasicMaterial( { color: 0x888888 } ) ); + scene.add( particles ); + + // + + + renderer = new THREE.WebGLRenderer( { antialias: true, clearColor: 0x000000, clearAlpha: 1 } ); + renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT ); + renderer.domElement.style.position = "relative"; + container.appendChild( renderer.domElement ); + + renderer.autoClear = false; + + // + + stats = new Stats(); + container.appendChild( stats.domElement ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + document.addEventListener( 'keydown', onKeyDown, false ); + + } + + // + + function onKeyDown ( event ) { + + switch( event.keyCode ) { + + case 79: /*O*/ + + activeCamera = cameraOrtho; + activeHelper = cameraOrthoHelper; + + break; + + case 80: /*P*/ + + activeCamera = cameraPerspective; + activeHelper = cameraPerspectiveHelper; + + break; + + } + + }; + + // + + function onWindowResize( event ) { + + SCREEN_WIDTH = window.innerWidth; + SCREEN_HEIGHT = window.innerHeight; + + renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT ); + + camera.aspect = 0.5 * SCREEN_WIDTH / SCREEN_HEIGHT; + camera.updateProjectionMatrix(); + + cameraPerspective.aspect = 0.5 * SCREEN_WIDTH / SCREEN_HEIGHT; + cameraPerspective.updateProjectionMatrix(); + + cameraOrtho.left = - 0.5 * SCREEN_WIDTH / 2; + cameraOrtho.right = 0.5 * SCREEN_WIDTH / 2; + cameraOrtho.top = SCREEN_HEIGHT / 2; + cameraOrtho.bottom = - SCREEN_HEIGHT / 2; + cameraOrtho.updateProjectionMatrix(); + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + + function render() { + + var r = Date.now() * 0.0005; + + mesh.position.x = 700 * Math.cos( r ); + mesh.position.z = 700 * Math.sin( r ); + mesh.position.y = 700 * Math.sin( r ); + + mesh.children[ 0 ].position.x = 70 * Math.cos( 2 * r ); + mesh.children[ 0 ].position.z = 70 * Math.sin( r ); + + if ( activeCamera === cameraPerspective ) { + + cameraPerspective.fov = 35 + 30 * Math.sin( 0.5 * r ); + cameraPerspective.far = mesh.position.length(); + cameraPerspective.updateProjectionMatrix(); + + cameraPerspectiveHelper.update(); + cameraPerspectiveHelper.visible = true; + + cameraOrthoHelper.visible = false; + + } else { + + cameraOrtho.far = mesh.position.length(); + cameraOrtho.updateProjectionMatrix(); + + cameraOrthoHelper.update(); + cameraOrthoHelper.visible = true; + + cameraPerspectiveHelper.visible = false; + + } + + cameraRig.lookAt( mesh.position ); + + renderer.clear(); + + activeHelper.visible = false; + + renderer.setViewport( 0, 0, SCREEN_WIDTH/2, SCREEN_HEIGHT ); + renderer.render( scene, activeCamera ); + + activeHelper.visible = true; + + renderer.setViewport( SCREEN_WIDTH/2, 0, SCREEN_WIDTH/2, SCREEN_HEIGHT ); + renderer.render( scene, camera ); + + } +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/webgl_custom_attributes.html + +()=>{ + if ( ! Detector.webgl ) Detector.addGetWebGLMessage(); + + var renderer, scene, camera, stats; + + var sphere, uniforms, attributes; + + var noise = []; + + var WIDTH = window.innerWidth, + HEIGHT = window.innerHeight; + + init(); + animate(); + + function init() { + + camera = new THREE.PerspectiveCamera( 30, WIDTH / HEIGHT, 1, 10000 ); + camera.position.z = 300; + + scene = new THREE.Scene(); + + attributes = { + + displacement: { type: 'f', value: [] } + + }; + + uniforms = { + + amplitude: { type: "f", value: 1.0 }, + color: { type: "c", value: new THREE.Color( 0xff2200 ) }, + texture: { type: "t", value: THREE.ImageUtils.loadTexture( "textures/water.jpg" ) }, + + }; + + uniforms.texture.value.wrapS = uniforms.texture.value.wrapT = THREE.RepeatWrapping; + + var shaderMaterial = new THREE.ShaderMaterial( { + + uniforms: uniforms, + attributes: attributes, + vertexShader: document.getElementById( 'vertexshader' ).textContent, + fragmentShader: document.getElementById( 'fragmentshader' ).textContent + + }); + + + var radius = 50, segments = 128, rings = 64; + var geometry = new THREE.SphereGeometry( radius, segments, rings ); + geometry.dynamic = true; + + sphere = new THREE.Mesh( geometry, shaderMaterial ); + + var vertices = sphere.geometry.vertices; + var values = attributes.displacement.value; + + for ( var v = 0; v < vertices.length; v++ ) { + + values[ v ] = 0; + noise[ v ] = Math.random() * 5; + + } + + scene.add( sphere ); + + renderer = new THREE.WebGLRenderer( { clearColor: 0x050505, clearAlpha: 1 } ); + renderer.setSize( WIDTH, HEIGHT ); + + var container = document.getElementById( 'container' ); + container.appendChild( renderer.domElement ); + + stats = new Stats(); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.top = '0px'; + container.appendChild( stats.domElement ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + } + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + var time = Date.now() * 0.01; + + sphere.rotation.y = sphere.rotation.z = 0.01 * time; + + uniforms.amplitude.value = 2.5 * Math.sin( sphere.rotation.y * 0.125 ); + uniforms.color.value.offsetHSL( 0.0005, 0, 0 ); + + for ( var i = 0; i < attributes.displacement.value.length; i ++ ) { + + attributes.displacement.value[ i ] = Math.sin( 0.1 * i + time ); + + noise[ i ] += 0.5 * ( 0.5 - Math.random() ); + noise[ i ] = THREE.Math.clamp( noise[ i ], -5, 5 ); + + attributes.displacement.value[ i ] += noise[ i ]; + + } + + attributes.displacement.needsUpdate = true; + + renderer.render( scene, camera ); + + } +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/webgl_custom_attributes_lines.html + +()=>{ + + if ( ! Detector.webgl ) Detector.addGetWebGLMessage(); + + var renderer, scene, camera, stats; + + var object, uniforms, attributes; + + var text = "three.js", + + height = 15, + size = 50, + + curveSegments = 10, + steps = 40, + + bevelThickness = 5, + bevelSize = 1.5, + bevelSegments = 10, + bevelEnabled = true, + + font = "helvetiker", // helvetiker, optimer, gentilis, droid sans, droid serif + weight = "bold", // normal bold + style = "normal"; // normal italic + + var WIDTH = window.innerWidth, + HEIGHT = window.innerHeight; + + init(); + animate(); + + function init() { + + camera = new THREE.PerspectiveCamera( 30, WIDTH / HEIGHT, 1, 10000 ); + camera.position.z = 400; + + scene = new THREE.Scene(); + + attributes = { + + displacement: { type: 'v3', value: [] }, + customColor: { type: 'c', value: [] } + + }; + + uniforms = { + + amplitude: { type: "f", value: 5.0 }, + opacity: { type: "f", value: 0.3 }, + color: { type: "c", value: new THREE.Color( 0xff0000 ) } + + }; + + var shaderMaterial = new THREE.ShaderMaterial( { + + uniforms: uniforms, + attributes: attributes, + vertexShader: document.getElementById( 'vertexshader' ).textContent, + fragmentShader: document.getElementById( 'fragmentshader' ).textContent, + blending: THREE.AdditiveBlending, + depthTest: false, + transparent: true + + }); + + (shaderMaterial).linewidth = 1; + + var geometry = new THREE.TextGeometry( text, { + + size: size, + height: height, + curveSegments: curveSegments, + + font: font, + weight: weight, + style: style, + + bevelThickness: bevelThickness, + bevelSize: bevelSize, + bevelEnabled: bevelEnabled, + bevelSegments: bevelSegments, + + steps: steps + + }); + + geometry.dynamic = true; + + THREE.GeometryUtils.center( geometry ); + + object = new THREE.Line( geometry, shaderMaterial, THREE.LineStrip ); + + var vertices = object.geometry.vertices; + + var displacement = attributes.displacement.value; + var color = attributes.customColor.value; + + for( var v = 0; v < vertices.length; v ++ ) { + + displacement[ v ] = new THREE.Vector3(); + + color[ v ] = new THREE.Color( 0xffffff ); + color[ v ].setHSL( v / vertices.length, 0.5, 0.5 ); + + } + + object.rotation.x = 0.2; + + scene.add( object ); + + renderer = new THREE.WebGLRenderer( { clearColor: 0x050505, clearAlpha: 1, antialias: true } ); + renderer.setSize( WIDTH, HEIGHT ); + + var container = document.getElementById( 'container' ); + container.appendChild( renderer.domElement ); + + stats = new Stats(); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.top = '0px'; + container.appendChild( stats.domElement ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + } + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + var time = Date.now() * 0.001; + + object.rotation.y = 0.25 * time; + + uniforms.amplitude.value = 0.5 * Math.sin( 0.5 * time ); + uniforms.color.value.offsetHSL( 0.0005, 0, 0 ); + + var nx, ny, nz, value; + + for( var i = 0, il = attributes.displacement.value.length; i < il; i ++ ) { + + nx = 0.3 * ( 0.5 - Math.random() ); + ny = 0.3 * ( 0.5 - Math.random() ); + nz = 0.3 * ( 0.5 - Math.random() ); + + value = attributes.displacement.value[ i ]; + + value.x += nx; + value.y += ny; + value.z += nz; + + } + + attributes.displacement.needsUpdate = true; + + renderer.render( scene, camera ); + + } +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/webgl_custom_attributes_particles.html + +()=>{ + if ( ! Detector.webgl ) Detector.addGetWebGLMessage(); + + var renderer, scene, camera, stats; + + var sphere, uniforms, attributes; + + var noise = []; + + var WIDTH = window.innerWidth; + var HEIGHT = window.innerHeight; + + init(); + animate(); + + function init() { + + camera = new THREE.PerspectiveCamera( 40, WIDTH / HEIGHT, 1, 10000 ); + camera.position.z = 300; + + scene = new THREE.Scene(); + + attributes = { + + size: { type: 'f', value: [] }, + customColor: { type: 'c', value: [] } + + }; + + uniforms = { + + amplitude: { type: "f", value: 1.0 }, + color: { type: "c", value: new THREE.Color( 0xffffff ) }, + texture: { type: "t", value: THREE.ImageUtils.loadTexture( "textures/sprites/spark1.png" ) }, + + }; + + var shaderMaterial = new THREE.ShaderMaterial( { + + uniforms: uniforms, + attributes: attributes, + vertexShader: document.getElementById( 'vertexshader' ).textContent, + fragmentShader: document.getElementById( 'fragmentshader' ).textContent, + + blending: THREE.AdditiveBlending, + depthTest: false, + transparent: true + + }); + + + var radius = 200; + var geometry = new THREE.Geometry(); + + for ( var i = 0; i < 100000; i++ ) { + + var vertex = new THREE.Vector3(); + vertex.x = Math.random() * 2 - 1; + vertex.y = Math.random() * 2 - 1; + vertex.z = Math.random() * 2 - 1; + vertex.multiplyScalar( radius ); + + geometry.vertices.push( vertex ); + + } + + sphere = new THREE.ParticleSystem( geometry, shaderMaterial ); + + sphere.dynamic = true; + //sphere.sortParticles = true; + + var vertices = sphere.geometry.vertices; + var values_size = attributes.size.value; + var values_color = attributes.customColor.value; + + + for( var v = 0; v < vertices.length; v++ ) { + + values_size[ v ] = 10; + values_color[ v ] = new THREE.Color( 0xffaa00 ); + + if ( vertices[ v ].x < 0 ) + values_color[ v ].setHSL( 0.5 + 0.1 * ( v / vertices.length ), 0.7, 0.9 ); + else + values_color[ v ].setHSL( 0.0 + 0.1 * ( v / vertices.length ), 0.9, 0.9 ); + + } + + scene.add( sphere ); + + renderer = new THREE.WebGLRenderer( { clearColor: 0x000000, clearAlpha: 1 } ); + renderer.setSize( WIDTH, HEIGHT ); + + var container = document.getElementById( 'container' ); + container.appendChild( renderer.domElement ); + + stats = new Stats(); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.top = '0px'; + container.appendChild( stats.domElement ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + } + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + var time = Date.now() * 0.005; + + sphere.rotation.z = 0.01 * time; + + for( var i = 0; i < attributes.size.value.length; i++ ) { + + attributes.size.value[ i ] = 14 + 13 * Math.sin( 0.1 * i + time ); + + + } + + attributes.size.needsUpdate = true; + + renderer.render( scene, camera ); + + } + +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/webgl_custom_attributes_particles2.html + +()=>{ + if ( ! Detector.webgl ) Detector.addGetWebGLMessage(); + + var renderer, scene, camera, stats; + + var sphere, uniforms, attributes; + + var vc1; + + var WIDTH = window.innerWidth; + var HEIGHT = window.innerHeight; + + init(); + animate(); + + function init() { + + camera = new THREE.PerspectiveCamera( 45, WIDTH / HEIGHT, 1, 10000 ); + camera.position.z = 300; + + scene = new THREE.Scene(); + + attributes = { + + size: { type: 'f', value: [] }, + ca: { type: 'c', value: [] } + + }; + + uniforms = { + + amplitude: { type: "f", value: 1.0 }, + color: { type: "c", value: new THREE.Color( 0xffffff ) }, + texture: { type: "t", value: THREE.ImageUtils.loadTexture( "textures/sprites/disc.png" ) }, + + }; + + uniforms.texture.value.wrapS = uniforms.texture.value.wrapT = THREE.RepeatWrapping; + + var shaderMaterial = new THREE.ShaderMaterial( { + + uniforms: uniforms, + attributes: attributes, + vertexShader: document.getElementById( 'vertexshader' ).textContent, + fragmentShader: document.getElementById( 'fragmentshader' ).textContent, + transparent: true + + }); + + + var radius = 100, segments = 68, rings = 38; + var geometry = new THREE.SphereGeometry( radius, segments, rings ); + + vc1 = geometry.vertices.length; + + var geometry2 = new THREE.CubeGeometry( 0.8 * radius, 0.8 * radius, 0.8 * radius, 10, 10, 10 ); + + THREE.GeometryUtils.merge( geometry, geometry2 ); + + sphere = new THREE.ParticleSystem( geometry, shaderMaterial ); + + sphere.dynamic = true; + sphere.sortParticles = true; + + var vertices = sphere.geometry.vertices; + var values_size = attributes.size.value; + var values_color = attributes.ca.value; + + for( var v = 0; v < vertices.length; v++ ) { + + values_size[ v ] = 10; + values_color[ v ] = new THREE.Color( 0xffffff ); + + if ( v < vc1 ) { + + values_color[ v ].setHSL( 0.01 + 0.1 * ( v / vc1 ), 0.99, ( vertices[ v ].y + radius ) / ( 2 *radius ) ); + + } else { + + values_size[ v ] = 40; + values_color[ v ].setHSL( 0.6, 0.75, 0.5 + vertices[ v ].y / ( 0.8 * radius ) ); + + } + + } + + scene.add( sphere ); + + renderer = new THREE.WebGLRenderer( { clearColor: 0x000000, clearAlpha: 1 } ); + renderer.setSize( WIDTH, HEIGHT ); + + var container = document.getElementById( 'container' ); + container.appendChild( renderer.domElement ); + + stats = new Stats(); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.top = '0px'; + container.appendChild( stats.domElement ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + } + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + var time = Date.now() * 0.005; + + sphere.rotation.y = 0.02 * time; + sphere.rotation.z = 0.02 * time; + + for( var i = 0; i < attributes.size.value.length; i ++ ) { + + if ( i < vc1 ) + attributes.size.value[ i ] = 16 + 12 * Math.sin( 0.1 * i + time ); + + + } + + attributes.size.needsUpdate = true; + + renderer.render( scene, camera ); + + } +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/webgl_custom_attributes_particles3.html + +()=>{ + if ( ! Detector.webgl ) Detector.addGetWebGLMessage(); + + var renderer, scene, camera, stats; + + var object, uniforms, attributes; + + var vc1; + + var WIDTH = window.innerWidth; + var HEIGHT = window.innerHeight; + + init(); + animate(); + + function init() { + + camera = new THREE.PerspectiveCamera( 40, WIDTH / HEIGHT, 1, 1000 ); + camera.position.z = 500; + + scene = new THREE.Scene(); + + attributes = { + + size: { type: 'f', value: [] }, + ca: { type: 'c', value: [] } + + }; + + uniforms = { + + amplitude: { type: "f", value: 1.0 }, + color: { type: "c", value: new THREE.Color( 0xffffff ) }, + texture: { type: "t", value: THREE.ImageUtils.loadTexture( "textures/sprites/ball.png" ) }, + + }; + + uniforms.texture.value.wrapS = uniforms.texture.value.wrapT = THREE.RepeatWrapping; + + var shaderMaterial = new THREE.ShaderMaterial( { + + uniforms: uniforms, + attributes: attributes, + vertexShader: document.getElementById( 'vertexshader' ).textContent, + fragmentShader: document.getElementById( 'fragmentshader' ).textContent + + }); + + + var radius = 100, inner = 0.6 * radius; + var geometry = new THREE.Geometry(); + + for ( var i = 0; i < 100000; i ++ ) { + + var vertex = new THREE.Vector3(); + vertex.x = Math.random() * 2 - 1; + vertex.y = Math.random() * 2 - 1; + vertex.z = Math.random() * 2 - 1; + vertex.multiplyScalar( radius ); + + if ( ( vertex.x > inner || vertex.x < -inner ) || + ( vertex.y > inner || vertex.y < -inner ) || + ( vertex.z > inner || vertex.z < -inner ) ) + + geometry.vertices.push( vertex ); + + } + + vc1 = geometry.vertices.length; + + var m, dummyMaterial = new THREE.MeshFaceMaterial(); + + radius = 200; + var geometry2 = new THREE.CubeGeometry( radius, 0.1 * radius, 0.1 * radius, 50, 5, 5 ); + + function addGeo( geo, x, y, z, ry ) { + + m = new THREE.Mesh( geo, dummyMaterial ); + m.position.set( x, y, z ); + m.rotation.y = ry; + + THREE.GeometryUtils.merge( geometry, m ); + + } + + // side 1 + + addGeo( geometry2, 0, 110, 110, 0 ); + addGeo( geometry2, 0, 110, -110, 0 ); + addGeo( geometry2, 0, -110, 110, 0 ); + addGeo( geometry2, 0, -110, -110, 0 ); + + // side 2 + + addGeo( geometry2, 110, 110, 0, Math.PI/2 ); + addGeo( geometry2, 110, -110, 0, Math.PI/2 ); + addGeo( geometry2, -110, 110, 0, Math.PI/2 ); + addGeo( geometry2, -110, -110, 0, Math.PI/2 ); + + // corner edges + + var geometry3 = new THREE.CubeGeometry( 0.1 * radius, radius * 1.2, 0.1 * radius, 5, 60, 5 ); + + addGeo( geometry3, 110, 0, 110, 0 ); + addGeo( geometry3, 110, 0, -110, 0 ); + addGeo( geometry3, -110, 0, 110, 0 ); + addGeo( geometry3, -110, 0, -110, 0 ); + + // particle system + + object = new THREE.ParticleSystem( geometry, shaderMaterial ); + object.dynamic = true; + + // custom attributes + + var vertices = object.geometry.vertices; + + var values_size = attributes.size.value; + var values_color = attributes.ca.value; + + for( var v = 0; v < vertices.length; v ++ ) { + + values_size[ v ] = 10; + values_color[ v ] = new THREE.Color( 0xffffff ); + + if ( v < vc1 ) { + + values_color[ v ].setHSL( 0.5 + 0.2 * ( v / vc1 ), 0.99, 1.0 ); + + } else { + + values_size[ v ] = 55; + values_color[ v ].setHSL( 0.1, 0.99, 1.0 ); + + } + + } + + //console.log( vertices.length ); + + scene.add( object ); + + renderer = new THREE.WebGLRenderer( { clearColor: 0x000000, clearAlpha: 1 } ); + renderer.setSize( WIDTH, HEIGHT ); + + var container = document.getElementById( 'container' ); + container.appendChild( renderer.domElement ); + + stats = new Stats(); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.top = '0px'; + container.appendChild( stats.domElement ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + } + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + var time = Date.now() * 0.01; + + object.rotation.y = object.rotation.z = 0.02 * time; + + for( var i = 0; i < attributes.size.value.length; i ++ ) { + + if ( i < vc1 ) + attributes.size.value[ i ] = Math.max(0, 26 + 32 * Math.sin( 0.1 * i + 0.6 * time )); + + + } + + attributes.size.needsUpdate = true; + + renderer.render( scene, camera ); + + } + +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/webgl_custom_attributes_ribbons.html + +()=>{ + if ( ! Detector.webgl ) Detector.addGetWebGLMessage(); + + var container, stats; + var camera, scene, renderer; + + var materials = []; + + var mouseX = 0, mouseY = 0; + + var windowHalfX = window.innerWidth / 2; + var windowHalfY = window.innerHeight / 2; + + init(); + animate(); + + function init() { + + container = document.createElement( 'div' ); + document.body.appendChild( container ); + + camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 3000 ); + camera.position.z = 1200; + + scene = new THREE.Scene(); + scene.fog = new THREE.FogExp2( 0x000000, 0.0016 ); + + // + + var vertexShader = document.getElementById( 'vertexShader' ).textContent; + var fragmentShader = document.getElementById( 'fragmentShader' ).textContent; + + var attributes = { customColor: { type: 'c', boundTo: 'vertices', value: [] }, + position2: { type: 'v3', boundTo: 'vertices', value: [] } + }; + + var uniforms = { ratio: { type: "f", value: 1.0 }, + color: { type: "c", value: new THREE.Color( 0xffffff ) } + }; + + var material = new THREE.ShaderMaterial( { uniforms: uniforms, attributes: attributes, vertexShader: vertexShader, fragmentShader: fragmentShader, side: THREE.DoubleSide } ); + + var position2 = attributes.position2.value; + var colors = attributes.customColor.value; + + // + + var geometry = new THREE.Geometry(); + + var i, i2; + var x1, y1, z1; + var x2, y2, z2; + var color; + + var n = 200; + + for ( i = -n; i < n; i ++ ) { + + i2 = i + n; + + x1 = 10 * i; + y1 = - 50 + ( i2 % 2 ) * 100 - Math.cos( 4 * Math.PI * i/n ) * 50; + z1 = 0; + + x2 = x1; + y2 = y1 + Math.cos( 4 * Math.PI * i/n ) * 100; + z2 = z1; + + var h = i2 % 2 ? 1 : 0.15; + if ( i2 % 4 <= 2 ) h -= 0.15; + + color = new THREE.Color( 0xffffff ); + color.setHSL( 0.1 * Math.random(), 0.15, h ); + + position2[ geometry.vertices.length ] = new THREE.Vector3( x2, y2, z2 ); + colors[ geometry.vertices.length ] = color; + + geometry.vertices.push( new THREE.Vector3( x1, y1, z1 ) ); + + } + + var ribbon = new THREE.Ribbon( geometry, material ); + scene.add( ribbon ); + + materials.push( ribbon.material ); + + var ribbon = new THREE.Ribbon( geometry, material.clone() ); + ribbon.position.y = 250; + ribbon.position.x = 250; + scene.add( ribbon ); + + var ribbonMaterial = ribbon.material; + + ribbonMaterial.uniforms.color.value.setHSL( 0, 0.75, 1 ); + materials.push( ribbon.material ); + + var ribbon = new THREE.Ribbon( geometry, material.clone() ); + ribbon.position.y = -250; + ribbon.position.x = 250; + scene.add( ribbon ); + + ribbonMaterial.uniforms.color.value.setHSL( 0.1, 0.75, 1 ); + materials.push( ribbon.material ); + + // + + renderer = new THREE.WebGLRenderer( { antialias: true } ); + renderer.setSize( window.innerWidth, window.innerHeight ); + renderer.setClearColor( scene.fog.color, 1 ); + + container.appendChild( renderer.domElement ); + + // + + stats = new Stats(); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.top = '0px'; + container.appendChild( stats.domElement ); + + // + + document.addEventListener( 'mousemove', onDocumentMouseMove, 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 ); + + } + + function onDocumentMouseMove( event ) { + + mouseX = event.clientX - windowHalfX; + mouseY = event.clientY - windowHalfY; + + } + + function onDocumentTouchStart( event ) { + + if ( event.touches.length === 1 ) { + + event.preventDefault(); + + mouseX = event.touches[ 0 ].pageX - windowHalfX; + mouseY = event.touches[ 0 ].pageY - windowHalfY; + + } + + } + + function onDocumentTouchMove( event ) { + + if ( event.touches.length === 1 ) { + + event.preventDefault(); + + mouseX = event.touches[ 0 ].pageX - windowHalfX; + mouseY = event.touches[ 0 ].pageY - windowHalfY; + + } + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + var time = Date.now() * 0.0025; + + //camera.position.x += ( mouseX - camera.position.x ) * 0.036; + //camera.position.y += ( - mouseY - camera.position.y ) * 0.036; + + camera.lookAt( scene.position ); + + for ( var i = 0; i < materials.length; i ++ ) { + + var uniforms = materials[ i ].uniforms; + uniforms.ratio.value = 0.5 * ( Math.sin( time ) + 1 ); + + } + + renderer.render( scene, camera ); + + } +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/webgl_geometries.html + +()=>{ + if ( ! Detector.webgl ) Detector.addGetWebGLMessage(); + + var container, stats; + + var camera, scene, renderer; + + init(); + animate(); + + function init() { + + container = document.createElement( 'div' ); + document.body.appendChild( container ); + + camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2000 ); + camera.position.y = 400; + + scene = new THREE.Scene(); + + var light, object, object2, materials: THREE.Material[]; + + scene.add( new THREE.AmbientLight( 0x404040 ) ); + + light = new THREE.DirectionalLight( 0xffffff ); + light.position.set( 0, 1, 0 ); + scene.add( light ); + + var map = THREE.ImageUtils.loadTexture( 'textures/ash_uvgrid01.jpg' ); + map.wrapS = map.wrapT = THREE.RepeatWrapping; + map.anisotropy = 16; + + materials = [ + new THREE.MeshLambertMaterial( { ambient: 0xbbbbbb, map: map, side: THREE.DoubleSide } ), + new THREE.MeshBasicMaterial( { color: 0xffffff, wireframe: true, transparent: true, opacity: 0.1, side: THREE.DoubleSide } ) + ]; + + object = THREE.SceneUtils.createMultiMaterialObject( new THREE.CubeGeometry( 100, 100, 100, 4, 4, 4 ), materials ); + object.position.set( -200, 0, 400 ); + scene.add( object ); + + object = THREE.SceneUtils.createMultiMaterialObject( new THREE.CylinderGeometry( 25, 75, 100, 40, 5 ), materials ); + object.position.set( 0, 0, 400 ); + scene.add( object ); + + object = THREE.SceneUtils.createMultiMaterialObject( new THREE.IcosahedronGeometry( 75, 1 ), materials ); + object.position.set( -200, 0, 200 ); + scene.add( object ); + + object = THREE.SceneUtils.createMultiMaterialObject( new THREE.OctahedronGeometry( 75, 2 ), materials ); + object.position.set( 0, 0, 200 ); + scene.add( object ); + + + object = THREE.SceneUtils.createMultiMaterialObject( new THREE.TetrahedronGeometry( 75, 0 ), materials ); + object.position.set( 200, 0, 200 ); + scene.add( object ); + + object = THREE.SceneUtils.createMultiMaterialObject( new THREE.PlaneGeometry( 100, 100, 4, 4 ), materials ); + object.position.set( -200, 0, 0 ); + scene.add( object ); + + object2 = THREE.SceneUtils.createMultiMaterialObject( new THREE.CircleGeometry( 50, 10, 0, Math.PI ), materials ); + object2.rotation.x = Math.PI/2; + object.add( object2 ); + + object = THREE.SceneUtils.createMultiMaterialObject( new THREE.SphereGeometry( 75, 20, 10 ), materials ); + object.position.set( 0, 0, 0 ); + scene.add( object ); + + var points = []; + + for ( var i = 0; i < 50; i ++ ) { + + points.push( new THREE.Vector3( Math.sin( i * 0.2 ) * 15 + 50, 0, ( i - 5 ) * 2 ) ); + + } + + object = THREE.SceneUtils.createMultiMaterialObject( new THREE.LatheGeometry( points, 20 ), materials ); + object.position.set( 200, 0, 0 ); + scene.add( object ); + + object = THREE.SceneUtils.createMultiMaterialObject( new THREE.TorusGeometry( 50, 20, 20, 20 ), materials ); + object.position.set( -200, 0, -200 ); + scene.add( object ); + + object = THREE.SceneUtils.createMultiMaterialObject( new THREE.TorusKnotGeometry( 50, 10, 50, 20 ), materials ); + object.position.set( 0, 0, -200 ); + scene.add( object ); + + object = new THREE.AxisHelper( 50 ); + object.position.set( 200, 0, -200 ); + scene.add( object ); + + object = new THREE.ArrowHelper( new THREE.Vector3( 0, 1, 0 ), new THREE.Vector3( 0, 0, 0 ), 50 ); + object.position.set( 200, 0, 400 ); + scene.add( object ); + + renderer = new THREE.WebGLRenderer( { antialias: true } ); + 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 ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + var timer = Date.now() * 0.0001; + + camera.position.x = Math.cos( timer ) * 800; + camera.position.z = Math.sin( timer ) * 800; + + camera.lookAt( scene.position ); + + for ( var i = 0, l = scene.children.length; i < l; i ++ ) { + + var object = scene.children[ i ]; + + object.rotation.x = timer * 5; + object.rotation.y = timer * 2.5; + + } + + renderer.render( scene, camera ); + + } +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/webgl_geometries2.html + +()=>{ + /* Testing the new Parametric Surfaces Geometries*/ + + + if ( ! Detector.webgl ) Detector.addGetWebGLMessage(); + + var container, stats; + + var camera, scene, renderer; + + init(); + animate(); + + function init() { + + container = document.createElement( 'div' ); + document.body.appendChild( container ); + + camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2000 ); + camera.position.y = 400; + + scene = new THREE.Scene(); + + var light, object, materials: THREE.Material[]; + + scene.add( new THREE.AmbientLight( 0x404040 ) ); + + light = new THREE.DirectionalLight( 0xffffff ); + light.position.set( 0, 0, 1 ); + scene.add( light ); + + var map = THREE.ImageUtils.loadTexture( 'textures/ash_uvgrid01.jpg' ); + map.wrapS = map.wrapT = THREE.RepeatWrapping; + map.anisotropy = 16; + + materials = [ + new THREE.MeshLambertMaterial( { ambient: 0xbbbbbb, map: map, side: THREE.DoubleSide } ), + new THREE.MeshBasicMaterial( { color: 0xffffff, wireframe: true, transparent: true, opacity: 0.1, side: THREE.DoubleSide } ) + ]; + + + var heightScale = 1; + var p = 2; + var q = 3; + var radius = 150, tube = 10, segmentsR = 50, segmentsT = 20; + + var GrannyKnot = new THREE.Curves.GrannyKnot(); + + var torus2 = new THREE.ParametricGeometries.TorusKnotGeometry( radius, tube, segmentsR, segmentsT, p , q, heightScale ); + var sphere2 = new THREE.ParametricGeometries.SphereGeometry( 75, 20, 10 ); + var tube2 = new THREE.ParametricGeometries.TubeGeometry( GrannyKnot, 150, 2, 8, true, false ); + + // var torus = new THREE.TorusKnotGeometry( radius, tube, segmentsR, segmentsT, p , q, heightScale ); + // var sphere = new THREE.SphereGeometry( 75, 20, 10 ); + // var tube = new THREE.TubeGeometry( GrannyKnot, 150, 2, 8, true, false ); + + + // var benchmarkCopies = 1000; + // var benchmarkObject = tube; + // var rand = function() { return (Math.random() - 0.5 ) * 600; }; + // for (var b=0;b{ + if ( ! Detector.webgl ) Detector.addGetWebGLMessage(); + + var container, stats; + + var camera, scene, renderer; + + var mesh, mesh2, mesh3, light; + + var mouseX = 0, mouseY = 0; + + var windowHalfX = window.innerWidth / 2; + var windowHalfY = window.innerHeight / 2; + + init(); + animate(); + + function init() { + + container = document.getElementById( 'container' ); + + camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 10000 ); + camera.position.z = 1800; + + scene = new THREE.Scene(); + + light = new THREE.DirectionalLight( 0xffffff ); + light.position.set( 0, 0, 1 ).normalize(); + scene.add( light ); + + var loader = new THREE.JSONLoader(); + + loader.load( "obj/cubecolors/cubecolors.js", createScene1 ); + loader.load( "obj/cubecolors/cube_fvc.js", createScene2 ); + + renderer = new THREE.WebGLRenderer( { antialias: true } ); + 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( 'mousemove', onDocumentMouseMove, 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 ); + + } + + function createScene1( geometry, materials ) { + + materials[ 0 ].shading = THREE.FlatShading; + + mesh = new THREE.Object3D(); + mesh.position.x = 400; + mesh.scale.x = mesh.scale.y = mesh.scale.z = 250; + scene.add( mesh ); + + var part1 = new THREE.Mesh( geometry, new THREE.MeshFaceMaterial( materials ) ); + mesh.add( part1 ); + + var part2 = new THREE.Mesh( geometry, new THREE.MeshLambertMaterial( { color: 0xffffff, opacity: 0.9, shading: THREE.FlatShading, wireframe: true, wireframeLinewidth: 2, transparent: true } ) ); + mesh.add( part2 ); + + } + + function createScene2( geometry, materials ) { + + materials[ 0 ].shading = THREE.FlatShading; + + mesh2 = new THREE.Mesh( geometry, new THREE.MeshFaceMaterial( materials ) ); + mesh2.position.x = - 400; + mesh2.scale.x = mesh2.scale.y = mesh2.scale.z = 250; + scene.add( mesh2 ); + + } + + function onDocumentMouseMove( event ) { + + mouseX = ( event.clientX - windowHalfX ); + mouseY = ( event.clientY - windowHalfY ); + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + camera.position.x += ( mouseX - camera.position.x ) * 0.05; + camera.position.y += ( - mouseY - camera.position.y ) * 0.05; + + camera.lookAt( scene.position ); + + if ( mesh ) { + + mesh.rotation.x += 0.01; + mesh.rotation.y += 0.01; + } + + if ( mesh2 ) { + + mesh2.rotation.x += 0.01; + mesh2.rotation.y += 0.01; + + } + + renderer.render( scene, camera ); + + } + +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/webgl_geometry_convex.html + +()=>{ + if ( ! Detector.webgl ) Detector.addGetWebGLMessage(); + + var container, stats; + + var camera, scene, renderer; + + init(); + animate(); + + function init() { + + container = document.createElement( 'div' ); + document.body.appendChild( container ); + + camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2000 ); + camera.position.y = 400; + + scene = new THREE.Scene(); + + var light, object, materials: THREE.Material[]; + + scene.add( new THREE.AmbientLight( 0x404040 ) ); + + light = new THREE.DirectionalLight( 0xffffff ); + light.position.set( 0, 1, 0 ); + scene.add( light ); + + var map = THREE.ImageUtils.loadTexture( 'textures/ash_uvgrid01.jpg' ); + map.wrapS = map.wrapT = THREE.RepeatWrapping; + map.anisotropy = 16; + + materials = [ + new THREE.MeshLambertMaterial( { ambient: 0xbbbbbb, map: map } ), + new THREE.MeshBasicMaterial( { color: 0xffffff, wireframe: true, transparent: true, opacity: 0.1 } ) + ]; + + + // tetrahedron + + var points = [ + new THREE.Vector3( 100, 0, 0 ), + new THREE.Vector3( 0, 100, 0 ), + new THREE.Vector3( 0, 0, 100 ), + new THREE.Vector3( 0, 0, 0 ) + ]; + + object = THREE.SceneUtils.createMultiMaterialObject( new THREE.ConvexGeometry( points ), materials ); + object.position.set( 0, 0, 0 ); + scene.add( object ); + + // cube + + var points = [ + new THREE.Vector3( 50, 50, 50 ), + new THREE.Vector3( 50, 50, -50 ), + new THREE.Vector3( -50, 50, -50 ), + new THREE.Vector3( -50, 50, 50 ), + new THREE.Vector3( 50, -50, 50 ), + new THREE.Vector3( 50, -50, -50 ), + new THREE.Vector3( -50, -50, -50 ), + new THREE.Vector3( -50, -50, 50 ), + ]; + + object = THREE.SceneUtils.createMultiMaterialObject( new THREE.ConvexGeometry( points ), materials ); + object.position.set( -200, 0, -200 ); + scene.add( object ); + + // random convex + + points = []; + for ( var i = 0; i < 30; i ++ ) { + + points.push( randomPointInSphere( 50 ) ); + + } + + object = THREE.SceneUtils.createMultiMaterialObject( new THREE.ConvexGeometry( points ), materials ); + object.position.set( -200, 0, 200 ); + scene.add( object ); + + + object = new THREE.AxisHelper( 50 ); + object.position.set( 200, 0, -200 ); + scene.add( object ); + + object = new THREE.ArrowHelper( new THREE.Vector3( 0, 1, 0 ), new THREE.Vector3( 0, 0, 0 ), 50 ); + object.position.set( 200, 0, 400 ); + scene.add( object ); + + renderer = new THREE.WebGLRenderer( { antialias: true } ); + 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 ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + } + + + function randomPointInSphere( radius ) { + + return new THREE.Vector3( + ( Math.random() - 0.5 ) * 2 * radius, + ( Math.random() - 0.5 ) * 2 * radius, + ( Math.random() - 0.5 ) * 2 * radius + ); + + } + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + var timer = Date.now() * 0.0001; + + camera.position.x = Math.cos( timer ) * 800; + camera.position.z = Math.sin( timer ) * 800; + + camera.lookAt( scene.position ); + + for ( var i = 0, l = scene.children.length; i < l; i ++ ) { + + var object = scene.children[ i ]; + + object.rotation.x = timer * 5; + object.rotation.y = timer * 2.5; + + } + + renderer.render( scene, camera ); + + } + +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/webgl_geometry_cube.html + +()=>{ + var camera, scene, renderer; + var mesh; + + init(); + animate(); + + function init() { + + renderer = new THREE.WebGLRenderer(); + renderer.setSize( window.innerWidth, window.innerHeight ); + document.body.appendChild( renderer.domElement ); + + // + + camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 ); + camera.position.z = 400; + + scene = new THREE.Scene(); + + var geometry = new THREE.CubeGeometry( 200, 200, 200 ); + + var texture = THREE.ImageUtils.loadTexture( 'textures/crate.gif' ); + texture.anisotropy = renderer.getMaxAnisotropy(); + + var material = new THREE.MeshBasicMaterial( { map: texture } ); + + mesh = new THREE.Mesh( geometry, material ); + scene.add( mesh ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + } + + function animate() { + + requestAnimationFrame( animate ); + + mesh.rotation.x += 0.005; + mesh.rotation.y += 0.01; + + renderer.render( scene, camera ); + + } + +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/webgl_geometry_dynamic.html + +()=>{ + if ( ! Detector.webgl ) { + + Detector.addGetWebGLMessage(); + document.getElementById( 'container' ).innerHTML = ""; + + } + + var container, stats; + + var camera, controls, scene, renderer; + + var mesh, texture, geometry, material; + + var worldWidth = 128, worldDepth = 128, + worldHalfWidth = worldWidth / 2, worldHalfDepth = worldDepth / 2; + + var clock = new THREE.Clock(); + + init(); + animate(); + + function init() { + + container = document.getElementById( 'container' ); + + camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 20000 ); + camera.position.y = 200; + + controls = new THREE.FirstPersonControls( camera ); + + controls.movementSpeed = 500; + controls.lookSpeed = 0.1 + + scene = new THREE.Scene(); + scene.fog = new THREE.FogExp2( 0xaaccff, 0.0007 ); + + geometry = new THREE.PlaneGeometry( 20000, 20000, worldWidth - 1, worldDepth - 1 ); + geometry.applyMatrix( new THREE.Matrix4().makeRotationX( - Math.PI / 2 ) ); + geometry.dynamic = true; + + var i, j, il, jl; + + for ( i = 0, il = geometry.vertices.length; i < il; i ++ ) { + + geometry.vertices[ i ].y = 35 * Math.sin( i/2 ); + + } + + + //console.log( "triangles: " + geometry.faces.length * 2 + " faces: " + geometry.faces.length + " vertices: " + geometry.vertices.length ); + + geometry.computeFaceNormals(); + geometry.computeVertexNormals(); + + var texture = THREE.ImageUtils.loadTexture( "textures/water.jpg" ); + texture.wrapS = texture.wrapT = THREE.RepeatWrapping; + texture.repeat.set( 5, 5 ); + + material = new THREE.MeshBasicMaterial( { color: 0x0044ff, map: texture } ); + + mesh = new THREE.Mesh( geometry, material ); + scene.add( mesh ); + + renderer = new THREE.WebGLRenderer( { clearColor: 0xaaccff, clearAlpha: 1 } ); + renderer.setSize( window.innerWidth, window.innerHeight ); + + container.innerHTML = ""; + + container.appendChild( renderer.domElement ); + + stats = new Stats(); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.top = '0px'; + container.appendChild( stats.domElement ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + controls.handleResize(); + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + var delta = clock.getDelta(), + time = clock.getElapsedTime() * 10; + + for ( var i = 0, l = geometry.vertices.length; i < l; i ++ ) { + + geometry.vertices[ i ].y = 35 * Math.sin( i / 5 + ( time + i ) / 7 ); + + } + + //geometry.computeFaceNormals(); + //geometry.computeVertexNormals(); + + mesh.geometry.verticesNeedUpdate = true; + //mesh.geometry.normalsNeedUpdate = true; + + controls.update( delta ); + renderer.render( scene, camera ); + + } + +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/webgl_geometry_extrude_shapes.html + +()=>{ + var container, stats; + + var camera, scene, renderer; + + var 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 parent; + + 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 = 'Shapes Extrusion via Spline path
Drag to spin'; + container.appendChild( info ); + + camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 1000 ); + camera.position.set( 0, 150, 500 ); + + scene = new THREE.Scene(); + + var light = new THREE.DirectionalLight( 0xffffff ); + light.position.set( 0, 0, 1 ); + scene.add( light ); + + parent = new THREE.Object3D(); + parent.position.y = 50; + scene.add( parent ); + + function addGeometry( geometry, color, x, y, z, rx, ry, rz, s ) { + + // 3d shape + + var mesh = THREE.SceneUtils.createMultiMaterialObject( geometry, [ new THREE.MeshLambertMaterial( { color: color, opacity: 0.2, transparent: true } ), new THREE.MeshBasicMaterial( { color: 0x000000, wireframe: true, opacity: 0.3 } ) ] ); + + mesh.position.set( x, y, z - 75 ); + // mesh.rotation.set( rx, ry, rz ); + mesh.scale.set( s, s, s ); + + if ( geometry.debug ) mesh.add( geometry.debug ); + + parent.add( mesh ); + + } + + var extrudeSettings: { amount: number; bevelEnabled: bool; bevelSegments: number; steps: number; extrudePath?: THREE.SplineCurve3; }; + extrudeSettings = { amount: 200, bevelEnabled: true, bevelSegments: 2, steps: 150 }; // bevelSegments: 2, steps: 2 , bevelSegments: 5, bevelSize: 8, bevelThickness:5, + + // var extrudePath = new THREE.Path(); + + // extrudePath.moveTo( 0, 0 ); + // extrudePath.lineTo( 10, 10 ); + // extrudePath.quadraticCurveTo( 80, 60, 160, 10 ); + // extrudePath.quadraticCurveTo( 240, -40, 320, 10 ); + + + extrudeSettings.bevelEnabled = false; + + var extrudeBend = new THREE.SplineCurve3( //Closed + [ + + new THREE.Vector3( 30, 12, 83), + new THREE.Vector3( 40, 20, 67), + new THREE.Vector3( 60, 40, 99), + new THREE.Vector3( 10, 60, 49), + new THREE.Vector3( 25, 80, 40) + + ]); + + var pipeSpline = new THREE.SplineCurve3([ + new THREE.Vector3(0, 10, -10), new THREE.Vector3(10, 0, -10), new THREE.Vector3(20, 0, 0), new THREE.Vector3(30, 0, 10), new THREE.Vector3(30, 0, 20), new THREE.Vector3(20, 0, 30), new THREE.Vector3(10, 0, 30), new THREE.Vector3(0, 0, 30), new THREE.Vector3(-10, 10, 30), new THREE.Vector3(-10, 20, 30), new THREE.Vector3(0, 30, 30), new THREE.Vector3(10, 30, 30), new THREE.Vector3(20, 30, 15), new THREE.Vector3(10, 30, 10), new THREE.Vector3(0, 30, 10), new THREE.Vector3(-10, 20, 10), new THREE.Vector3(-10, 10, 10), new THREE.Vector3(0, 0, 10), new THREE.Vector3(10, -10, 10), new THREE.Vector3(20, -15, 10), new THREE.Vector3(30, -15, 10), new THREE.Vector3(40, -15, 10), new THREE.Vector3(50, -15, 10), new THREE.Vector3(60, 0, 10), new THREE.Vector3(70, 0, 0), new THREE.Vector3(80, 0, 0), new THREE.Vector3(90, 0, 0), new THREE.Vector3(100, 0, 0)] + ); + + var sampleClosedSpline = new THREE.ClosedSplineCurve3([ + new THREE.Vector3(0, -40, -40), + new THREE.Vector3(0, 40, -40), + new THREE.Vector3(0, 140, -40), + new THREE.Vector3(0, 40, 40), + new THREE.Vector3(0, -40, 40), + ]); + + var randomPoints = []; + + for ( var i = 0; i < 10; i ++ ) { + + randomPoints.push( new THREE.Vector3(Math.random() * 200,Math.random() * 200,Math.random() * 200 ) ); + + } + + var randomSpline = new THREE.SplineCurve3( randomPoints ); + + extrudeSettings.extrudePath = randomSpline; // extrudeBend sampleClosedSpline pipeSpline randomSpline + + // Circle + + var circleRadius = 4; + var circleShape = new THREE.Shape(); + circleShape.moveTo( 0, circleRadius ); + circleShape.quadraticCurveTo( circleRadius, circleRadius, circleRadius, 0 ); + circleShape.quadraticCurveTo( circleRadius, -circleRadius, 0, -circleRadius ); + circleShape.quadraticCurveTo( -circleRadius, -circleRadius, -circleRadius, 0 ); + circleShape.quadraticCurveTo( -circleRadius, circleRadius, 0, circleRadius); + + var rectLength = 12, rectWidth = 4; + + var rectShape = new THREE.Shape(); + + rectShape.moveTo( -rectLength/2, -rectWidth/2 ); + rectShape.lineTo( -rectLength/2, rectWidth/2 ); + rectShape.lineTo( rectLength/2, rectWidth/2 ); + rectShape.lineTo( rectLength/2, -rectLength/2 ); + rectShape.lineTo( -rectLength/2, -rectLength/2 ); + + + var pts = [], starPoints = 5, l; + + for ( i = 0; i < starPoints * 2; i ++ ) { + + if ( i % 2 == 1 ) { + + l = 5; + + } else { + + l = 10; + + } + + var a = i / starPoints * Math.PI; + pts.push( new THREE.Vector2 ( Math.cos( a ) * l, Math.sin( a ) * l ) ); + + } + + var starShape = new THREE.Shape( pts ); + + // Smiley + + var smileyShape = new THREE.Shape(); + smileyShape.moveTo( 80, 40 ); + smileyShape.arc( 40, 40, 40, 0, Math.PI*2, false ); + + var smileyEye1Path = new THREE.Path(); + smileyEye1Path.moveTo( 35, 20 ); + smileyEye1Path.arc( 25, 20, 10, 0, Math.PI*2, true ); + smileyShape.holes.push( smileyEye1Path ); + + var smileyEye2Path = new THREE.Path(); + smileyEye2Path.moveTo( 65, 20 ); + smileyEye2Path.arc( 55, 20, 10, 0, Math.PI*2, true ); + smileyShape.holes.push( smileyEye2Path ); + + var smileyMouthPath = new THREE.Path(); + + smileyMouthPath.moveTo( 20, 40 ); + smileyMouthPath.quadraticCurveTo( 40, 60, 60, 40 ); + smileyMouthPath.bezierCurveTo( 70, 45, 70, 50, 60, 60 ); + smileyMouthPath.quadraticCurveTo( 40, 80, 20, 60 ); + smileyMouthPath.quadraticCurveTo( 5, 50, 20, 40 ); + + smileyShape.holes.push( smileyMouthPath ); + + var circle3d = starShape.extrude( extrudeSettings ); //circleShape rectShape smileyShape starShape + // var circle3d = new THREE.ExtrudeGeometry(circleShape, extrudeBend, extrudeSettings ); + + var tube = new THREE.TubeGeometry(extrudeSettings.extrudePath, 150, 4, 5, false, true); + // new THREE.TubeGeometry(extrudePath, segments, 2, radiusSegments, closed2, debug); + + + addGeometry( circle3d, 0xff1111, -100, 0, 0, 0, 0, 0, 1 ); + addGeometry( tube, 0x00ff11, 0, 0, 0, 0, 0, 0, 1 ); + console.log(tube); + + // + + renderer = new THREE.WebGLRenderer( { antialias: true } ); + 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 ); + +} + +// + +function onDocumentMouseDown( event ) { + + event.preventDefault(); + + document.addEventListener( 'mousemove', onDocumentMouseMove, false ); + document.addEventListener( 'mouseup', onDocumentMouseUp, false ); + document.addEventListener( 'mouseout', onDocumentMouseOut, false ); + + mouseXOnMouseDown = event.clientX - windowHalfX; + targetRotationOnMouseDown = targetRotation; + +} + +function onDocumentMouseMove( event ) { + + mouseX = event.clientX - windowHalfX; + + targetRotation = targetRotationOnMouseDown + ( mouseX - mouseXOnMouseDown ) * 0.02; + +} + +function onDocumentMouseUp( event ) { + + document.removeEventListener( 'mousemove', onDocumentMouseMove, false ); + document.removeEventListener( 'mouseup', onDocumentMouseUp, false ); + document.removeEventListener( 'mouseout', onDocumentMouseOut, false ); + +} + +function onDocumentMouseOut( event ) { + + document.removeEventListener( 'mousemove', onDocumentMouseMove, false ); + document.removeEventListener( 'mouseup', onDocumentMouseUp, false ); + document.removeEventListener( 'mouseout', onDocumentMouseOut, false ); + +} + +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() { + + parent.rotation.y += ( targetRotation - parent.rotation.y ) * 0.05; + renderer.render( scene, camera ); + +} +}; + + +// https://github.com/mrdoob/three.js/blob/master/examples/webgl_geometry_extrude_splines.html + +()=>{ + var container, stats; + + var camera, scene, renderer, splineCamera, cameraHelper, cameraEye; + + var 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 binormal = new THREE.Vector3(); + var normal = new THREE.Vector3(); + + + var pipeSpline = new THREE.SplineCurve3([ + new THREE.Vector3(0, 10, -10), new THREE.Vector3(10, 0, -10), new THREE.Vector3(20, 0, 0), new THREE.Vector3(30, 0, 10), new THREE.Vector3(30, 0, 20), new THREE.Vector3(20, 0, 30), new THREE.Vector3(10, 0, 30), new THREE.Vector3(0, 0, 30), new THREE.Vector3(-10, 10, 30), new THREE.Vector3(-10, 20, 30), new THREE.Vector3(0, 30, 30), new THREE.Vector3(10, 30, 30), new THREE.Vector3(20, 30, 15), new THREE.Vector3(10, 30, 10), new THREE.Vector3(0, 30, 10), new THREE.Vector3(-10, 20, 10), new THREE.Vector3(-10, 10, 10), new THREE.Vector3(0, 0, 10), new THREE.Vector3(10, -10, 10), new THREE.Vector3(20, -15, 10), new THREE.Vector3(30, -15, 10), new THREE.Vector3(40, -15, 10), new THREE.Vector3(50, -15, 10), new THREE.Vector3(60, 0, 10), new THREE.Vector3(70, 0, 0), new THREE.Vector3(80, 0, 0), new THREE.Vector3(90, 0, 0), new THREE.Vector3(100, 0, 0)]); + + var sampleClosedSpline = new THREE.ClosedSplineCurve3([ + new THREE.Vector3(0, -40, -40), + new THREE.Vector3(0, 40, -40), + new THREE.Vector3(0, 140, -40), + new THREE.Vector3(0, 40, 40), + new THREE.Vector3(0, -40, 40), + ]); + + // Keep a dictionary of Curve instances + var splines = { + GrannyKnot: new THREE.Curves.GrannyKnot(), + HeartCurve: new THREE.Curves.HeartCurve(3.5), + VivianiCurve: new THREE.Curves.VivianiCurve(70), + KnotCurve: new THREE.Curves.KnotCurve(), + HelixCurve: new THREE.Curves.HelixCurve(), + TrefoilKnot: new THREE.Curves.TrefoilKnot(), + TorusKnot: new THREE.Curves.TorusKnot(20), + CinquefoilKnot: new THREE.Curves.CinquefoilKnot(20), + TrefoilPolynomialKnot: new THREE.Curves.TrefoilPolynomialKnot(14), + FigureEightPolynomialKnot: new THREE.Curves.FigureEightPolynomialKnot(), + DecoratedTorusKnot4a: new THREE.Curves.DecoratedTorusKnot4a(), + DecoratedTorusKnot4b: new THREE.Curves.DecoratedTorusKnot4b(), + DecoratedTorusKnot5a: new THREE.Curves.DecoratedTorusKnot5a(), + DecoratedTorusKnot5c: new THREE.Curves.DecoratedTorusKnot5c(), + PipeSpline: pipeSpline, + SampleClosedSpline: sampleClosedSpline + }; + + + + + var extrudePath = new THREE.Curves.TrefoilKnot(); + + var dropdown = ''; + + var closed2 = true; + var debug = true; + var parent; + var tube, tubeMesh; + var animation = false, lookAhead = false; + var scale; + var showCameraHelper = false; + + function addTube() { + + var value = (document.getElementById('dropdown')).value; + + var segments = parseInt((document.getElementById('segments')).value); + closed2 = (document.getElementById('closed')).checked; + debug = (document.getElementById('debug')).checked; + + var radiusSegments = parseInt((document.getElementById('radiusSegments')).value); + + console.log('adding tube', value, closed2, debug, radiusSegments); + if (tubeMesh) parent.remove(tubeMesh); + + extrudePath = splines[value]; + + tube = new THREE.TubeGeometry(extrudePath, segments, 2, radiusSegments, closed2, debug); + + addGeometry(tube, 0xff00ff); + setScale(); + + } + + function setScale() { + + scale = parseInt( (document.getElementById('scale')).value ); + tubeMesh.scale.set( scale, scale, scale ); + + } + + + function addGeometry( geometry, color ) { + + // 3d shape + + tubeMesh = THREE.SceneUtils.createMultiMaterialObject( geometry, [ + new THREE.MeshLambertMaterial({ + color: color, + opacity: geometry.debug ? 0.2 : 0.8, + transparent: true + }), + new THREE.MeshBasicMaterial({ + color: 0x000000, + opacity: 0.5, + wireframe: true + })]); + + if ( geometry.debug ) tubeMesh.add( geometry.debug ); + + parent.add( tubeMesh ); + + } + + function animateCamera( toggle ) { + + if ( toggle ) { + + animation = animation === false; + (document.getElementById('animation')).value = 'Camera Spline Animation View: ' + (animation? 'ON': 'OFF'); + + } + + lookAhead = (document.getElementById('lookAhead')).checked; + + showCameraHelper = (document.getElementById('cameraHelper')).checked; + + cameraHelper.visible = showCameraHelper; + cameraEye.visible = showCameraHelper; + } + + + 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 = 'Spline Extrusion Examples by
zz85
Select spline:'; + + info.innerHTML += dropdown; + + info.innerHTML += '
Scale: '; + info.innerHTML += '
Extrusion Segments: '; + info.innerHTML += '
Radius Segments: '; + info.innerHTML += '
Debug normals: Closed:'; + + info.innerHTML += '


Look Ahead Camera Helper '; + + container.appendChild(info); + + // + + camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.01, 1000); + camera.position.set(0, 50, 500); + + scene = new THREE.Scene(); + + var light = new THREE.DirectionalLight( 0xffffff ); + light.position.set( 0, 0, 1 ); + scene.add( light ); + + parent = new THREE.Object3D(); + parent.position.y = 100; + scene.add( parent ); + + splineCamera = new THREE.PerspectiveCamera( 84, window.innerWidth / window.innerHeight, 0.01, 1000 ); + parent.add( splineCamera ); + + cameraHelper = new THREE.CameraHelper( splineCamera ); + scene.add( cameraHelper ); + + addTube(); + + // Debug point + + cameraEye = new THREE.Mesh( new THREE.SphereGeometry( 5 ), new THREE.MeshBasicMaterial( { color: 0xdddddd } ) ); + parent.add( cameraEye ); + + cameraHelper.visible = showCameraHelper; + cameraEye.visible = showCameraHelper; + + // + + renderer = new THREE.WebGLRenderer( { antialias: true } ); + 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 ); + + renderer.domElement.addEventListener( 'mousedown', onDocumentMouseDown, false ); + renderer.domElement.addEventListener( 'touchstart', onDocumentTouchStart, false ); + renderer.domElement.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 ); + + } + + // + + function onDocumentMouseDown(event) { + + event.preventDefault(); + + renderer.domElement.addEventListener( 'mousemove', onDocumentMouseMove, false ); + renderer.domElement.addEventListener( 'mouseup', onDocumentMouseUp, false ); + renderer.domElement.addEventListener( 'mouseout', onDocumentMouseOut, false ); + + mouseXOnMouseDown = event.clientX - windowHalfX; + targetRotationOnMouseDown = targetRotation; + + } + + function onDocumentMouseMove(event) { + + mouseX = event.clientX - windowHalfX; + + targetRotation = targetRotationOnMouseDown + (mouseX - mouseXOnMouseDown) * 0.02; + + } + + function onDocumentMouseUp(event) { + + renderer.domElement.removeEventListener( 'mousemove', onDocumentMouseMove, false ); + renderer.domElement.removeEventListener( 'mouseup', onDocumentMouseUp, false ); + renderer.domElement.removeEventListener( 'mouseout', onDocumentMouseOut, false ); + + } + + function onDocumentMouseOut(event) { + + renderer.domElement.removeEventListener( 'mousemove', onDocumentMouseMove, false ); + renderer.domElement.removeEventListener( 'mouseup', onDocumentMouseUp, false ); + renderer.domElement.removeEventListener( 'mouseout', onDocumentMouseOut, false ); + + } + + 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() { + + // Try Animate Camera Along Spline + var time = Date.now(); + var looptime = 20 * 1000; + var t = ( time % looptime ) / looptime; + + var pos = tube.path.getPointAt( t ); + pos.multiplyScalar( scale ); + + // interpolation + var segments = tube.tangents.length; + var pickt = t * segments; + var pick = Math.floor( pickt ); + var pickNext = ( pick + 1 ) % segments; + + binormal.subVectors( tube.binormals[ pickNext ], tube.binormals[ pick ] ); + binormal.multiplyScalar( pickt - pick ).add( tube.binormals[ pick ] ); + + + var dir = tube.path.getTangentAt( t ); + + var offset = 15; + + normal.copy( binormal ).cross( dir ); + + // We move on a offset on its binormal + pos.add( normal.clone().multiplyScalar( offset ) ); + + splineCamera.position = pos; + cameraEye.position = pos; + + + // Camera Orientation 1 - default look at + // splineCamera.lookAt( lookAt ); + + // Using arclength for stablization in look ahead. + var lookAt = tube.path.getPointAt( ( t + 30 / tube.path.getLength() ) % 1 ).multiplyScalar( scale ); + + // Camera Orientation 2 - up orientation via normal + if (!lookAhead) + lookAt.copy( pos ).add( dir ); + splineCamera.matrix.lookAt(splineCamera.position, lookAt, normal); + splineCamera.rotation.setEulerFromRotationMatrix( splineCamera.matrix, splineCamera.eulerOrder ); + + cameraHelper.update(); + + parent.rotation.y += ( targetRotation - parent.rotation.y ) * 0.05; + + renderer.render( scene, animation === true ? splineCamera : camera ); + + } +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/webgl_geometry_extrude_uvs2.html + +()=>{ + (function(){ + 'use strict'; + + var tex; + var testShape; + var holeShape; + var testMesh = null; + var WIDTH = 640; + var HEIGHT = 480; + var targetCanvas; + var uvGenerator; + + var scene, renderer, camera; + + var rX = 0; + var rY = 0; + + window["launch"] = function() { + + camera = new THREE.PerspectiveCamera(30, WIDTH / HEIGHT); + camera.position.z = 20; + + scene = new THREE.Scene(); + + /** Custom UV mapper **/ + uvGenerator = new THREE.UVsUtils.CylinderUVGenerator(); + testShape = setupShape(8, 3); + holeShape = setupShape(8, 2); + testShape.holes.push(holeShape); + + tex = setupTexture(TestTextureData); + renewMesh(); + + renderer = new THREE.WebGLRenderer(); + renderer.setSize(WIDTH, HEIGHT); + + // show canvas + targetCanvas = renderer.domElement; + targetCanvas.width = WIDTH; + targetCanvas.height = HEIGHT; + document.getElementById('canvas-container').appendChild(targetCanvas); + + setupAnimation(); + render(); + }; + + function setupAnimation(n?) { + new AnimationController( + document.getElementById('html-el'), + function(x, y) { + rX = x; + rY = y; + render(); + }); + } + + function updateRotation() { + rX = (rX + 3600) % 360; + rY = (rY + 3600) % 360; + testMesh.rotation.set( THREE.Math.degToRad( rY ), 0, THREE.Math.degToRad( rX ) ); + } + + function render() { + if (testMesh) { + var rx = pickRepeatSetting(); + if (uvGenerator.uRepeat != rx) { + uvGenerator.uRepeat = rx; + renewMesh(); + } + + updateRotation(); + renderer.render( scene, camera ); + } + } + + function pickRepeatSetting() { + var radios = (document.getElementById('repeat-setting'))["repeat"]; + for (var i = 0;i < 3;i++) { + if (radios[i].checked) { return radios[i].value - 0; } + } + + return 1; + } + + function setupShape(n, r) { + // Make shape + var sh = new THREE.Shape(); + for (var i = 0; i < n;i++) { + var method = i ? 'lineTo' : 'moveTo'; + var a = (i/n) * Math.PI * 2; + var x = Math.cos(a) * r; + var y = Math.sin(a) * r; + sh[method](x, y); + } + + return sh; + } + + function setupGeometry(shape) { + // Make extruded geometory + var exoption = { + bevelEnabled: true, + bevelSize: 1, + amount: 3, + extrudeMaterial: 0, + material: 1, + uvGenerator: uvGenerator + }; + + var geom = shape.extrude(exoption); + return geom; + } + + function setupTexture(dat) { + var img = new Image(); + var t = new THREE.Texture(img); + t.wrapS = THREE.RepeatWrapping; + + img.onload = function() { + t.needsUpdate = true; + render(); + }; + img.src = dat; + return t; + } + + function setupMesh(geom, side_texture) { + var materials = [ + new THREE.MeshBasicMaterial( { map: side_texture } ), + new THREE.MeshBasicMaterial( { color: 0x447766 } ) + ]; + var mesh = new THREE.Mesh(geom, new THREE.MeshFaceMaterial(materials)); + + scene.add(mesh); + return mesh; + } + + function renewMesh() { + if (testMesh) { + scene.remove(testMesh); + } + + testMesh = setupMesh( setupGeometry(testShape) , tex); + testMesh.position.set(0, 0, -30); + } + + function AnimationController(target, callback) { + var _this = this; + this.callback = callback; + target.addEventListener('mousemove', function(e) { + _this.onMouseMove(e); + }, false); + } + + AnimationController.prototype = { + onMouseMove: function(e) { + this.callback(e.clientX, e.clientY); + } + }; + + var TestTextureData = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEABAMAAACuXLVVAAAAAXNSR0IArs4c6QAAADBQTFRFB1B5B1iEA16QAGCPAGaWE2WXJHJMJntSLoJVKopbQX+fMJBgLZlnbZuyZaiGgrCY0v66KwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9wEEBE0NIvLSa4AAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAa7ElEQVR42u1cTWwbR5YuUuIlQAA2qb4YEMCm3JcBDEhyeBlgAdsJLwECsJus41xlEiImN0eCCeQmk2AjvlFssDDJZmcvAXS1SbAxvlHd6ELW1iQXAbzOTrDB+OZx4EC936tuyXIws4ct7M4uQEZ/MfsVu169+t73Xr1+jHNuchffnLt22TUlXl4UyEjOpSelz2sN2+U2XcXtht2UQ7wde5EcyHksA6krz0rczjsGzztV2zWNZiGaz6WI8CV8XCMPMQAv4pLSmlPLbZuV4KHsRmEvnHfkJJSDWFeemY5tuBBscLtpb3EzCvwIA0g1Siw9x2zwKjcd+so3axZmIGQsw/SKQOrKM6iuzHnTdHnN5S1egwJjucA7ePWkDBwokPO6w+0WtFjjcoIBIjnFN2bg+7ryrO6U87Q4Dq9atuHkQ188HR4FgyMx9vcjv920HbvSxDRMxzDdgisPw14UBsdyLAc0UV15LIGR54bLi5gG7IjT/QUR7o+0FAUCMtxyCzCihskd08X76WuSzlJXHksAC4WaylzpistfvHi9mQ6NSWCAZuBBMBr6shP2Ynkw15VnroO7y1VMwzEd03LWnspBqh7YcT+c9GBEJrRoWTCz4p2Cc9gLu7PT3hMxiXHFINaVZxbnVjPP+Y4Le951Csp28SOUx54fBUED1ovBoUIXmoYKSbt0hVR/SV15BgWWOCaBgRo2dCTTpUmXES+X0w5KgSSPhcTQAggyhh0DbwZSV57Z7obFC9jMHIZsWHYoBtHhOBZT+UT60wj7eIcGqNhmo2xiu8veKW1zH58TEJLpyjNOpoMb3M3gMr4yH4IJKRpQHRC2CZwhS+KkYZohrBkDTaSuPG6gvoF/51a95tg1bmfSUGE6lFN3ecE1W7SG/K7pRl4Y+EeYZufp4WjeiXXlmXW3lCsWGhsGLzVgyoWo3Q4fjuL2g6AtZscTr2FW3NyddcsxK2bFMCsTcQrVyXmQfZKuPEHx5Uspc3Eoo1R7Us4i6TUIQmmKmMmu2ufKuAjP8SViXXlWNWjx0gHqNrefSDWASJdJ9siK67jEhY2VXBsqPA0m43F7dv9YPBAHY115ZuRauUaOmxVm7hjrTmksx0960wEcdifqHE27MGBsHnu3srHNgSUlbOF4OFNmBI8vpa48U4TimhbVwij7ERHp0cEOJxRtYib2L6CWLtOVT29AbSNaQ8fOdpCcZV7DzQbgtkVo7/oAUAweYJMfjuXRXFeelXbcvJN3GDOMom0U8+N5ZxQcxQeDeBh1QJy2a0WeA4wX1w3ODF4MRAiI7UVyL8ZAB1JXXmkA27SmLKlE+xi7ZJaqCIDec+o7dOdV3DxN1FD2HQJNOsqKI115dQNw06kp1xSpjACUeDOIYEkC+MrT5bvHay2eA9ETk4UcjbsYP05JqY48s5v3gOSOZTqFOyUTWD4ajg59KcawYsBZt4EBNir1HHytW8BOkr1YpB+RvnTlWYrkXJEF+iu6slFB0+gR1SDaTQ6NmKeyMAU00Rz0U+rKwxeQI3fJn7bIisf0dqwYaywG0nOxsLR85FQwQDX2ppP+02AQe+OxP8YNaMqz0vZWubhmWTnD3rbMit2X+yOxF+0fgz12B1Fv2zTcXNE0ts0dByo0Qo+4HqaXgbmuPONKcUBKMhVoMcAigbtfEhapdrhCcks5VQnOfcnqMU5fV54BqM1sAOjIMYPYI8aK9Qtgo7HHifJyxTa4eZeXInEcDMbSB7kOaBq68sywiU06Vp18BQaII29B9tOfdSJvfLrfsPPwI2ZZbSeLIh81O8B4pKiFrjwjwyHOCFXW6AeAJFQzUIsUScW1HZpejf66JBwHMlh4I18MdOVBSkGYTacKI0WE42yIGPjVh+4yZ3KPxIt8AxN0TMzxNBj1xbHcpwhM4YCmPCKjZs3hDu0l011r5CUcNlTY34e5eqEIrHqxiAGwg5hbqzr2acYkKPYOVGSkJ69IqXPJZ8DhJe2TOCZEV/ze4beV6u4S94atUdwPK+4tuos9DzG4rjxDQLle4WyH4ocmjGj2VCzkfeKrwcgbh55BSAbjoTdL4HxhfDD3ZnIYBYuAYj9deYWEFs9h+RDnYxSfNirWx5Od8WQ8kSCbTs0gTmsSt7DDjPVmrEPqymek9JLWkRWnjO4yiM1I/9VLDTCW'+ + 'D+PJWPZjv68rz+wNp3YXN5hvYqO6OR5Q0NqJZTfynmIQAAnWDpzCIXdTctkjsTiY9ONuPPDJkua68swGQhZv5oHTds4xqnwciTDaj+fdcAgjirpuk6Je4hQGqCXFfuF1fyd15QmKyYrJoZl02VBxCZlu05BIJWKqe2/VLCn1FEsfbCNuj6O2rjyza0Qbqw7lkCiJIIgsDOMB9nAo+lIYfN25adwrFaFrG1hCQW03DD6LheJdQleemVWKbGGkjgPQdvmEcOxQDrGW00BEnpVyCV5qFYrV9UY9C/subUzqyjOyXPfKRltcKdC75PZEq2vNd3k/gL5PUX4Ud8bBRFcefKBSA5927DKvNW4a9mAq/RiEMYAxyYfwdkDR1lrD3P7AVpg3EgNiOvuhfKRIp648s0uV2g7RpuaHICxOvR/LR7Ib7g/DXoi19Ix7a266xHDpu00+IgvDHCnXitdQV56puP0amqgEGuBcJTCECr2U6po0ACYxloMYzhRXdOTkqRzoyjOedwCkZiMHzNwBlohTDypckDPFNWREnDwpb1QxwbxTCikB5tMMyOHiAzTlGd8FSpC3dNPQZv8U7oqgNAx8uR/LCs836muOvZNFH1kSShE+isF15VmK07ZzqcIgvQIoJjLCAcF1oGmduzV80TYPYMVHwaHfGY8PdOWZS2/yUsM2mohe7nLs0o58GLUnp14sJpEog2UQxADoHbPaMEfBOPb68aBPWSZsNV15ZgC9cjwHILFhqZX6w1OsUHchQNkAKZEogeryDXfDpk0OPcdyEgeTdI/TdteVZ8QWSsSsFWuscWXAKW0P6RaVZnOcb9VaLqV9Kcsu9gnOOlEXe0lXHjZg8Fw93zCLPG8Yxj1vEfixryJ4bJIw2ALLKGGAKt+hbEvpVE6iwIu8fhrcCF15ZuXp/kvg7q2yDc9GAUss/LAbgrsexLJEdDPNQbZoMmqC4HyU6hTRYKIrfz1Nx6+n2ymZp4CkZatkbwlu9TbczSkgdNAOsdAHsjd+J03335JnlbpTY4ov0KEK42IKpPBArkPMZF8OKL9bLTTsSqnkVDHRqZzHh0JeOTRdecZs8CVuVHGL8NZAsihG6BzNek/Ekzl2kkVHHtDeJeBOs6AzogMBbGpteZU9yMImohbB2xwaBRgSpNetEuXlNQdoaj+S/ZEcxw+PfTHCKnu68ozSZzCjpl0x63SZOA3mcBUzOOwnUS8UhmM2SiVrgw4byJ58yq6ouCYLvzXlmQrryUoQvFIWg/Zx1JUqjKc0V+tvGVk6zVPpTwJdeXVoBRW6tsqkVDj+WZIRXZJXJWXylsHrxfKOZYbzTtRvx96TuBvKIy/WlWc2MwDVdOrEK0VY8eFIHp52wz3xSI6EiGc5a227lrubY27OqBr3eH/qhYEEr6fpkbPRlGeEECY5bEyAMtuwTGwjxG2xxIaKhbFDh478KiWcWZhQSp7Iia48S9+6pDUuD2C7sVCptJBMRaUXCs3LJEzLJ7bvEeEbULJtqCvPLCLVDggFcLpRa/CH9LaHPXosj2HFwQ62D8WVao7A9AGpLqBTJy89MdGUZ+7l/YNZKiOKKZUrswgqBKtNVbfO1ZkT7fOQ+FYPWCcWk4muPJagRGefnKvowuDBQganFLlTggF6NCm5VnYdBOBFx3byg2C4GLbDtoiVHqWuPCsWii55s3yOks6W642ktxCDBZbx0fTh8axQMStb607VbJnKtU8UlbwMLaXUlVeREVeHeumpBu4qXSRiNuk+Thl16x1vB8jvYQbxga48bmCLl51aEf7CpHSWgBWr5MkozWgTpW8R7XLsYtls5P1wGE46YXc02w9xrdSVxy7IAUhgn0WYsrlDWO4vglnoPQWjOww9s2E27q1XKAen8jA+bWHvKvSTuvKXhKR2mei6dvI6J03CsFXQefMalkdpig0R9rSvK8927Y8osrvNyxTlVgnJgvAKRijy4VtuzeXsQ161imsuvFx45IXD4UKM5F4/1pVnRqHi5pzbzAFU5yuFxrAftQ+kfzQAZ4S7irHH8latQkUYCL24AwubZ4cOVI4ideUzQsILrZRR/KIEg86EKL9gXHpTRwiZESrayDOpK09AxNP6Bu5AU67CMVokBHcIr8ZUIXOXAo8iN8BqKmIYt5+KAVjvuJtuMz155rTW3fUdC+FLuQhYL/pU1xDiCoS5UFSfm9sEcq1qiZDcqNIeVicymRnryjMoiCC65qQqKstrZkw6VMUZ2aEc/U75zISSjZgg1lhTninVqS2kynBMVV8SUYYFHiseCleV6OQbtgPWAU1jesO+bMf9Pfkw9DtSV56BVG/Xq0auaOWLJVYunHpTuTce9o/EI39/sT8tlixuIO60CfIBdrITqvxCj4rmyBdoyjOHvBW37S0iDlZaYJC6iTFFkDJNxtdaWb7XlT06EFGHEYSkUl'+ + 'f+emjmwKXYaaFbShmoFIEyzXTmaZucSmG2ZfcUCEM5prBLyQZdeaYSiVaTwpciSMXGaTDATvL3qcbncDRpO3nDrCh31iyQW1PpF5X9SA1ZV55ZTTgxdbYNK23xWpxVFqgkkko0qveyYh2+C70GEwqq8OZTKFNXnrlNeGqjCaeNyNFQBYlyMiMY9dR9ko+nCiVcY9+pmkbYe4LYfhgGhws4vGGkK88chE5lY8egarNC0Sqcimk08GNvgYsOx2JALtYih4vxaQpZGZgyITp+0pVn6qTpbRkOfwsjqS076p8LCmzrnComSQxQ681g55NYV55R9Mq3VPhMHqMuo0MYiS+P04zzkM6DjEbBsfJ3bOaU2LR3JIaL7pPBfijHQghdeUZ1gFYe2jN2c2WEsDMYyL4fBfdlO/RGY7HDc9XiLs+wzq7J1OGHGdRKXXl2edj0yxSL'+ + 'zAIHnp77vfu+GoAOyT2pK8+4Q8kzB0NsUXRnwlFQ8Ij/PFXnsAXNNl1YUm7HLiO2mXoR2KxYyPZ45i0QHWvKM4PdZka+YuagSifn5I8HXuiDTI4ItMeyXUTcTQUgDmDEdGq1OFWhqpmkRJSuPLt26KeOVi9teBZ31dmTqoNUNqbovcJ6ygXCq6sYVFeebqDOFZ2E0+INDDAHn53KfgxF+WGvxXPNtGCyAfrHy6E3o9QCBbmBVKGZnjyzmG1U1orNnGMwnrO4PzoMZ+1ZCqSATQvjFygLs66KAPjboCqmeq25rjydG+b5ZRLNzKxUXKZxpCxBwzbVbRPe3OV2JOaUAzwMRX/WfhT4uvIshSmVaaZaMx4ovor1Cb1wcjCZFRxKqNfKQFy3VNzaONqfhd2ncSeU7ZlIYz8teWbCn7oI7Qzu5Iv8rj2Ieguf4uaFt5gM4wGnqJYqZeyrfUxkwrs6N9SUz+oJd7L0Aedp1C7TraKCSzXBumvuqlRD5sg9ORtIMY7buvIMQZvhbFi8VG0UuJtrerR7+weyfRSMo+HULzXg5SqmUSkZrm055qkQZMOIrQd08CZ05Zlpp1lGk/w2/uey7FpkBWfZmVvdrV+pME7fVnoMdOX/brr+qjrezWrVlI5dE+NO5YiOnidUnzrUlYcRshLVIJUqhumUjOL+6eQwnvRDj7CkM5vligVrhzXXKioZ7hRGAR3OXlXLSV15Zju1qiqCspyagyhOUq7XwxVPwCoRZtG5+BXc2i4CDy9OT1s8KtUa6MqzKyqTZRmUpxbKitUtAscV46ES9bLZMCOElbI97TwCv/ajyUBXntUct9Cwcm6JzjRaeRduYnxMBQ50+ipGAXAcwU8T/nSjYdec2tFVMV4KqLryjO80VSlkTcXxNr86+U9rgyWo9kdpAuZa3fBlzn0GI9OUv7YLSFM3nWHKJuMgO3dS+LLVRNRhursbFVvE4lgeRmBbh0eftQNfV56VqNYRsWU+V+RgJ8XO0aAdtu8fDw6OO4v+wM9vm2S9puHmGzU4lA6VHXTDICN1A115LMFtu2EbO7x+N4XKt08oqBkUHJ7V7HJ1+CSyCpBpyjs8XXnG7awY7W8ASTbAhzSyxW3Lrll1byGOhB8HPYnY8pEQuvKslndLKs9cxq26ue1gDMb0EHxmFPQjuR/R0zm80DB3Ff/f4r1Q0KN06txT7QJNeWiA6iFrdzhiWN5E9HqcZtBgoaoOQCXBMI3qL2cYCSpVkLryLFPgHXpWTW2jcfqISJpOwwBU+YFp5NybMOTKRzChvjyMhwOq3B3EA115littE2PcJqCCpTrykdwbi2Ho9UfdhXd8RDBCBcFm01Ql+nC3AxXgxz2FJbryTOW3XLMIVdYJrKWqyw2yMD+MeYmvKQN2a6pSQ0X2ILwy9OJxN/R15dUugJpqnLI8agD1KFz2KFZfUokMB6kzG3mLCmG6oTiIuiMxWYhTEUQTXXnWLDQMKr12mbGVr+Qqnf5M+H6bDp3apxNP7tLBMJUhudmxmwoq5FVVnq68MsL6WyNtpo5aXFpxVKcTCZNnD/NxOhmdU65TlaSB+OrKs7eOIgX0q5PdCV0jQtBdqpim0wirWd5pDo/lAT2a4IXBlFBVV54ZIJTlHW7QM2vFml2kBxEj4R+Lw7AznndDrGGJMISy0U3bdUUGpIE6HQ6lrjxrphUWW2ShZewTUo9K6WdwQSZEGE7pSDoWUo/0Dg4Ad5LOx/q68syBYEHlOGknmU3ZlkBT3GSkyKvvrLn5O2aF0uHMqua2geRDOpgEjvmEprryzOEVdeBHlae7O4BSjx4C6sTyCFqKJ8Ix3fRxRjoYwDzk27BPpEkoPXmWPSWmftWvsDq4uuz6g2yX'+ + '6fY4fWhTIBL3deWZRZXx2EZNYCaIsyWHkQc+EwWA82jela0CPR5QrdpuHdy74GJmiDvlFDAyj7HeuvKsxIsmjDNnwanmHLs687A5ov0wGC68Iy+IgOPYQdv0RCnV49GZj0dPTMtQVYbOdeVZSlTqGW0nFcaBevhBYYmUiOsBpPTcMj0qYTv+MOo9nXViSjMhupzpyqtitpTQbvFqnW9R+YEawIvVqYoagFgVPS0Fjq9Ou6R6jGEo1amZnjxb9R9Y9R9Y9R9Y9R9Y9R9Y9R9Y9R9Y9R9Y9R9Y9R9Y9R9Y9R9Y9R9Y9R9Y9R9Y9R9Y9R9Y9R9Y9R9Y9R9Y9R/4P99/oLj7v9J/oIpXaqZgEe/0D6jks/4BLdPaNf+L/gPVX/QfIHc/kTGIImJWGGq1hK8r+eH0nf4DLsPLVv0Djh+82z/g1lnWP8DK4Rrr7/cfyOSv+g882Q/jvdkePQmaKznqE67Jf3b4Tv8Bd4mXslX+6at3+wdsnqX9A7Yr7y2X35T+bv8BN5O/6j/w7I0fJfNkm+cbyzWnulymn5HJP3v9Tv8BdQOtrVaryR//NBdzGc/nEX7h9+aZebe5VufF9+iaFx+E84EM+rF3FByO2/3+we0STP/2huMuq1Vsw11ICeVpnr2RcRK8/Lq+8evzdc7TG7hbngEmJgfy81d+51r/AXdZgSEzVmKlT1/t3X/QfnB/7+nwgfCP9t4/W6sg8jSLJ+d3Nz5+Xnqwtzf3jvBTTj5r7w3GbI3fg263i0vGKrkiG7fl/fZ+1J48exNPktnj5+7aP31H/Qdat56bO0W25x0f7e35+Jj9a/0H3KVVteyTr6yTr5MkeZ38NvkpeTJMggcvk5OzfPFk+ZX5q2Ud9tS0HicXh/PfJsmfgxiX/fsXy3++Y723PM/dwvxuPT9ZfvpKjBPqP/DsTRgns9+d2/mTf1X9B26dtaxvlhcPj18myQAf8+Za/wF3SUb4yXc3l3V6R33PoMDPk2R5Zp1g7A9unLfcXevmDbz3aowfidemn8ny3LqB9//4G7oBfH9xEfzuIlA2gBuYf3tuV5cfqf4Dt17UcWXy+ovsI3661n/gnjKQ9eV7f7z3+FXQTy4GkbqBT18Hn7y4sfwwd/L15nc7DcbyJ3+dP774IvnzF8mPk+THb5MfP16yk/Pb753nl3Z+c/kv94aJ9/kb6j/w7M3TOJkGy93yMu0/sPm8evKd8ezi8V+HX/z58at3+g+kRlg+Ofk9f/xahonnh8l0AhuO5ftnm88Zw88z3oQRLvf29pIvL2L5+M0s8cJkaC0NUt+yurxZ3vyOc/Fy+PgH6j/w7M0xNCBPvr5xnvYfuHXWPIENQPqzfoxdcL3/gLukp/Favzq/yb9UxovvOb7wx62zTbq7s80/mg7dAKn901ehePzms6Q7SuawfmXf1SWtMoDo3354qThXugvkJy82v6ur/gObL3ZwXZJgCf40xjyv9x/AKNQ/4MaS1aGbftKDFsZYhWQyeP/F+zT+9zfO887uZnYD2MSPf54ksMOgsrTUDQAH7FtnjItnf01U/4Fnr2dhEgw2X7z/PO0/8P6LqrqB2bcvk/949tM7/QfcpYF1Mk5OvuKPsUGTXjRNHnyW+EmfbuB5qbpjfrw0dqubZ8u9yezoy9eT2eOfJrQEA7bEBqwytrUsGbfOgITfXlyo/gNfvj56lMTiV+cnX6f9B6CfpVEd9afjycs3z15NvWv9B9JdUD7/5Hnty4u9wwQ3l/zpt4CRv94/gRF+xW6cGcvzInv/xcmrB3uf/yF5sJf8gBsYJT13uXVyztg3Nq66dWZxaOVnNbVvkwefX0gJw7mX9h/YfG6dvGB7Lz9/sPfpT4QD1/oPKCM0N7/7YFn7gnDAC2fYrMmMtuGLDdqGZ8YnCgl/TUsg8eYFrTC+oLyP1R7CVUoDi+SHtP8ALvw5FMZymfUf2Hzh/pqW4Eu88R/4mJ+v9x9Qu+Dkq42T33svkx+TrpR/wC8pXl588j3/6GR5/hFvfQNfUG/9Jbn4i/zDy4sfoSTpJwFfOi3cwe9hQMvffO9yb/Hyx7T/wLfJBfUfODnPCnp/8z3HlRd/gQlAM/iY/6H+A4uXwT+2/8DRxT+4/8CXP/+D+w+8/HHVf2DVf2DVf2DVf2DVf2DVf2DVf2DVf2DVf2DVf2DVf2DVf2DVf2DVf2DVf2DVf2DVf2DVf2DVf2DVf2DVf2DVf2DVf2DVf2DVf2DVf2DVf2DVf2DVf2DVf2DVf2DVf+D/V/+B/wT15JbOMyhx1QAAAABJRU5ErkJggg=='; + + })(); +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/webgl_geometry_hierarchy.html + +()=>{ + var container, stats; + + var camera, scene, renderer; + + var geometry, group; + + var mouseX = 0, mouseY = 0; + + var windowHalfX = window.innerWidth / 2; + var windowHalfY = window.innerHeight / 2; + + document.addEventListener( 'mousemove', onDocumentMouseMove, false ); + + init(); + animate(); + + function init() { + + container = document.createElement( 'div' ); + document.body.appendChild( container ); + + camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 10000 ); + camera.position.z = 500; + + scene = new THREE.Scene(); + scene.fog = new THREE.Fog( 0xffffff, 1, 10000 ); + + var geometry = new THREE.CubeGeometry( 100, 100, 100 ); + var material = new THREE.MeshNormalMaterial(); + + group = new THREE.Object3D(); + + for ( var i = 0; i < 1000; i ++ ) { + + var mesh = new THREE.Mesh( geometry, material ); + mesh.position.x = Math.random() * 2000 - 1000; + mesh.position.y = Math.random() * 2000 - 1000; + mesh.position.z = Math.random() * 2000 - 1000; + + mesh.rotation.x = Math.random() * 2 * Math.PI; + mesh.rotation.y = Math.random() * 2 * Math.PI; + + mesh.matrixAutoUpdate = false; + mesh.updateMatrix(); + + group.add( mesh ); + + } + + scene.add( group ); + + renderer = new THREE.WebGLRenderer(); + renderer.setSize( window.innerWidth, window.innerHeight ); + renderer.sortObjects = false; + + container.appendChild( renderer.domElement ); + + stats = new Stats(); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.top = '0px'; + stats.domElement.style.zIndex = 100; + container.appendChild( stats.domElement ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + windowHalfX = window.innerWidth / 2; + windowHalfY = window.innerHeight / 2; + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + } + + function onDocumentMouseMove(event) { + + mouseX = ( event.clientX - windowHalfX ) * 10; + mouseY = ( event.clientY - windowHalfY ) * 10; + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + var time = Date.now() * 0.001; + + var rx = Math.sin( time * 0.7 ) * 0.5, + ry = Math.sin( time * 0.3 ) * 0.5, + rz = Math.sin( time * 0.2 ) * 0.5; + + camera.position.x += ( mouseX - camera.position.x ) * .05; + camera.position.y += ( - mouseY - camera.position.y ) * .05; + + camera.lookAt( scene.position ); + + group.rotation.x = rx; + group.rotation.y = ry; + group.rotation.z = rz; + + renderer.render( scene, camera ); + + } + +}; + + +// https://github.com/mrdoob/three.js/blob/master/examples/webgl_geometry_hierarchy2.html + +()=>{ + var container, stats; + + var camera, scene, renderer; + + var geometry, root; + + var mouseX = 0, mouseY = 0; + + var windowHalfX = window.innerWidth / 2; + var windowHalfY = window.innerHeight / 2; + + document.addEventListener( 'mousemove', onDocumentMouseMove, false ); + + init(); + animate(); + + function init() { + + container = document.createElement( 'div' ); + document.body.appendChild( container ); + + camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 15000 ); + camera.position.z = 500; + + scene = new THREE.Scene(); + + var geometry = new THREE.CubeGeometry( 100, 100, 100 ); + var material = new THREE.MeshNormalMaterial(); + + root = new THREE.Mesh( geometry, material ); + root.position.x = 1000; + scene.add( root ); + + var amount = 200, object, parent = root; + + for ( var i = 0; i < amount; i ++ ) { + + object = new THREE.Mesh( geometry, material ); + object.position.x = 100; + + parent.add( object ); + parent = object; + + } + + parent = root; + + for ( var i = 0; i < amount; i ++ ) { + + object = new THREE.Mesh( geometry, material ); + object.position.x = - 100; + + parent.add( object ); + parent = object; + + } + + parent = root; + + for ( var i = 0; i < amount; i ++ ) { + + object = new THREE.Mesh( geometry, material ); + object.position.y = - 100; + + parent.add( object ); + parent = object; + + } + + parent = root; + + for ( var i = 0; i < amount; i ++ ) { + + object = new THREE.Mesh( geometry, material ); + object.position.y = 100; + + parent.add( object ); + parent = object; + + } + + parent = root; + + for ( var i = 0; i < amount; i ++ ) { + + object = new THREE.Mesh( geometry, material ); + object.position.z = - 100; + + parent.add( object ); + parent = object; + + } + + parent = root; + + for ( var i = 0; i < amount; i ++ ) { + + object = new THREE.Mesh( geometry, material ); + object.position.z = 100; + + parent.add( object ); + parent = object; + + } + + renderer = new THREE.WebGLRenderer(); + renderer.setSize( window.innerWidth, window.innerHeight ); + renderer.sortObjects = false; + container.appendChild( renderer.domElement ); + + stats = new Stats(); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.top = '0px'; + stats.domElement.style.zIndex = 100; + container.appendChild( stats.domElement ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + windowHalfX = window.innerWidth / 2; + windowHalfY = window.innerHeight / 2; + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + } + + function onDocumentMouseMove(event) { + + mouseX = ( event.clientX - windowHalfX ) * 10; + mouseY = ( event.clientY - windowHalfY ) * 10; + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + var time = Date.now() * 0.001; + + var rx = Math.sin( time * 0.7 ) * 0.2; + var ry = Math.sin( time * 0.3 ) * 0.1; + var rz = Math.sin( time * 0.2 ) * 0.1; + + camera.position.x += ( mouseX - camera.position.x ) * .05; + camera.position.y += ( - mouseY - camera.position.y ) * .05; + + camera.lookAt( scene.position ); + + root.traverse( function ( object ) { + + object.rotation.x = rx; + object.rotation.y = ry; + object.rotation.z = rz; + + } ); + + renderer.render( scene, camera ); + + } +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/webgl_geometry_large_mesh.html + +()=>{ + var SCREEN_WIDTH = window.innerWidth; + var SCREEN_HEIGHT = window.innerHeight; + var FLOOR = -250; + + var container, stats; + + var camera, scene, canvasRenderer, webglRenderer; + + var loader; + + var mesh, zmesh, lightMesh; + + var directionalLight, pointLight; + + var mouseX = 0, mouseY = 0; + + var windowHalfX = window.innerWidth / 2; + var windowHalfY = window.innerHeight / 2; + + var render_canvas = true, render_gl = true; + var has_gl = false; + + var bcanvas = document.getElementById( "rcanvas" ); + var bwebgl = document.getElementById( "rwebgl" ); + + document.addEventListener( 'mousemove', onDocumentMouseMove, false ); + + init(); + animate(); + + render_canvas = !has_gl; + bwebgl.style.display = has_gl ? "inline" : "none"; + bcanvas.className = render_canvas ? "button" : "button inactive"; + + function addMesh( geometry, scale, x, y, z, rx, ry, rz, material ) { + + mesh = new THREE.Mesh( geometry, material ); + + mesh.scale.set( scale, scale, scale ); + mesh.position.set( x, y, z ); + mesh.rotation.set( rx, ry, rz ); + + scene.add( mesh ); + + } + + function init() { + + container = document.createElement( 'div' ); + document.body.appendChild( container ); + + camera = new THREE.PerspectiveCamera( 50, SCREEN_WIDTH / SCREEN_HEIGHT, 1, 100000 ); + camera.position.z = 1500; + + scene = new THREE.Scene(); + + // LIGHTS + + var ambient = new THREE.AmbientLight( 0x101010 ); + scene.add( ambient ); + + directionalLight = new THREE.DirectionalLight( 0xffffff, 0.5 ); + directionalLight.position.set( 1, 1, 2 ).normalize(); + scene.add( directionalLight ); + + pointLight = new THREE.PointLight( 0xffaa00 ); + pointLight.position.set( 0, 0, 0 ); + scene.add( pointLight ); + + // light representation + + var sphere = new THREE.SphereGeometry( 100, 16, 8, 1 ); + lightMesh = new THREE.Mesh( sphere, new THREE.MeshBasicMaterial( { color: 0xffaa00 } ) ); + lightMesh.scale.set( 0.05, 0.05, 0.05 ); + lightMesh.position = pointLight.position; + scene.add( lightMesh ); + + + if ( render_gl ) { + try { + + webglRenderer = new THREE.WebGLRenderer( { antialias: true, alpha: true } ); + webglRenderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT ); + webglRenderer.domElement.style.position = "relative"; + container.appendChild( webglRenderer.domElement ); + has_gl = true; + + } + catch (e) { + } + } + + if( render_canvas ) { + + canvasRenderer = new THREE.CanvasRenderer(); + canvasRenderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT ); + container.appendChild( canvasRenderer.domElement ); + + } + + + stats = new Stats(); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.top = '0px'; + stats.domElement.style.zIndex = 100; + container.appendChild( stats.domElement ); + + bcanvas.addEventListener( "click", toggleCanvas, false ); + bwebgl.addEventListener( "click", toggleWebGL, false ); + + var loader = new THREE.BinaryLoader( true ); + //loader = new THREE.JSONLoader( true ); + document.body.appendChild( loader.statusDomElement ); + + var start = Date.now(); + + //loader.load( 'obj/lucy/Lucy100k_slim.js', callback ); + loader.load( 'obj/lucy/Lucy100k_bin.js', function ( geometry, materials ) { + + addMesh( geometry, 0.75, 900, 0, 0, 0,0,0, new THREE.MeshPhongMaterial( { ambient: 0x030303, color: 0x030303, specular: 0x990000, shininess: 30 } ) ); + addMesh( geometry, 0.75, 300, 0, 0, 0,0,0, new THREE.MeshFaceMaterial( materials ) ); + addMesh( geometry, 0.75, -300, 0, 0, 0,0,0, new THREE.MeshPhongMaterial( { ambient: 0x030303, color: 0x111111, specular: 0xffaa00, shininess: 10 } ) ); + addMesh( geometry, 0.75, -900, 0, 0, 0,0,0, new THREE.MeshPhongMaterial( { ambient: 0x030303, color: 0x555555, specular: 0x666666, shininess: 10 } ) ); + + loader.statusDomElement.style.display = "none"; + + _log( "geometry.vertices: " + geometry.vertices.length ); + _log( "geometry.faces: " + geometry.faces.length ); + + _log( "model loaded and created in " + ( Date.now() - start ) + " ms" ); + + } ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + windowHalfX = window.innerWidth / 2; + windowHalfY = window.innerHeight / 2; + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + if ( render_canvas ) canvasRenderer.setSize( window.innerWidth, window.innerHeight ); + if ( render_gl && has_gl ) webglRenderer.setSize( window.innerWidth, window.innerHeight ); + + } + + function onDocumentMouseMove( event ) { + + mouseX = ( event.clientX - windowHalfX ); + mouseY = ( event.clientY - windowHalfY ); + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + var r = 0; + + function render() { + + camera.position.x += ( mouseX - camera.position.x ) * .05; + camera.position.y += ( - mouseY - camera.position.y ) * .05; + + camera.lookAt( scene.position ); + + lightMesh.position.x = 700 * Math.cos( r ); + lightMesh.position.z = 700 * Math.sin( r ); + + r += 0.01; + + if ( render_canvas ) canvasRenderer.render( scene, camera ); + if ( render_gl && has_gl ) webglRenderer.render( scene, camera ); + + } + + function _log( text ) { + + var e = document.getElementById( "log" ); + e.innerHTML = text + "
" + e.innerHTML; + + } + + function toggleCanvas() { + + render_canvas = !render_canvas; + bcanvas.className = render_canvas ? "button" : "button inactive"; + + render_gl = !render_canvas; + bwebgl.className = render_gl ? "button" : "button inactive"; + + if( has_gl ) + webglRenderer.domElement.style.display = render_gl ? "block" : "none"; + + canvasRenderer.domElement.style.display = render_canvas ? "block" : "none"; + + } + + function toggleWebGL() { + + render_gl = !render_gl; + bwebgl.className = render_gl ? "button" : "button inactive"; + + render_canvas = !render_gl; + bcanvas.className = render_canvas ? "button" : "button inactive"; + + if( has_gl ) + webglRenderer.domElement.style.display = render_gl ? "block" : "none"; + + canvasRenderer.domElement.style.display = render_canvas ? "block" : "none"; + + } + +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/webgl_geometry_minecraft.html + +()=>{ + + if ( ! Detector.webgl ) { + + Detector.addGetWebGLMessage(); + document.getElementById( 'container' ).innerHTML = ""; + + } + + var container, stats; + + var camera, controls, scene, renderer; + + var mesh; + + var worldWidth = 128, worldDepth = 128, + worldHalfWidth = worldWidth / 2, worldHalfDepth = worldDepth / 2, + data = generateHeight( worldWidth, worldDepth ); + + var clock = new THREE.Clock(); + + init(); + animate(); + + function init() { + + container = document.getElementById( 'container' ); + + camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 20000 ); + camera.position.y = getY( worldHalfWidth, worldHalfDepth ) * 100 + 100; + + controls = new THREE.FirstPersonControls( camera ); + + controls.movementSpeed = 1000; + controls.lookSpeed = 0.125; + controls.lookVertical = true; + + scene = new THREE.Scene(); + + // sides + + var matrix = new THREE.Matrix4(); + + var pxGeometry = new THREE.PlaneGeometry( 100, 100 ); + pxGeometry.faces[ 0 ].materialIndex = 1; + pxGeometry.applyMatrix( matrix.makeRotationY( Math.PI / 2 ) ); + pxGeometry.applyMatrix( matrix.makeTranslation( 50, 0, 0 ) ); + + var nxGeometry = new THREE.PlaneGeometry( 100, 100 ); + nxGeometry.faces[ 0 ].materialIndex = 1; + nxGeometry.applyMatrix( matrix.makeRotationY( - Math.PI / 2 ) ); + nxGeometry.applyMatrix( matrix.makeTranslation( - 50, 0, 0 ) ); + + var pyGeometry = new THREE.PlaneGeometry( 100, 100 ); + pyGeometry.faces[ 0 ].materialIndex = 0; + pyGeometry.applyMatrix( matrix.makeRotationX( - Math.PI / 2 ) ); + pyGeometry.applyMatrix( matrix.makeTranslation( 0, 50, 0 ) ); + + var pzGeometry = new THREE.PlaneGeometry( 100, 100 ); + pzGeometry.faces[ 0 ].materialIndex = 1; + pzGeometry.applyMatrix( matrix.makeTranslation( 0, 0, 50 ) ); + + var nzGeometry = new THREE.PlaneGeometry( 100, 100 ); + nzGeometry.faces[ 0 ].materialIndex = 1; + nzGeometry.applyMatrix( matrix.makeRotationY( Math.PI ) ); + nzGeometry.applyMatrix( matrix.makeTranslation( 0, 0, -50 ) ); + // + + var geometry = new THREE.Geometry(); + var dummy = new THREE.Mesh(); + + for ( var z = 0; z < worldDepth; z ++ ) { + + for ( var x = 0; x < worldWidth; x ++ ) { + + var h = getY( x, z ); + + dummy.position.x = x * 100 - worldHalfWidth * 100; + dummy.position.y = h * 100; + dummy.position.z = z * 100 - worldHalfDepth * 100; + + var px = getY( x + 1, z ); + var nx = getY( x - 1, z ); + var pz = getY( x, z + 1 ); + var nz = getY( x, z - 1 ); + + dummy.geometry = pyGeometry; + THREE.GeometryUtils.merge( geometry, dummy ); + + if ( ( px != h && px != h + 1 ) || x == 0 ) { + + dummy.geometry = pxGeometry; + THREE.GeometryUtils.merge( geometry, dummy ); + + } + + if ( ( nx != h && nx != h + 1 ) || x == worldWidth - 1 ) { + + dummy.geometry = nxGeometry; + THREE.GeometryUtils.merge( geometry, dummy ); + + } + + if ( ( pz != h && pz != h + 1 ) || z == worldDepth - 1 ) { + + dummy.geometry = pzGeometry; + THREE.GeometryUtils.merge( geometry, dummy ); + + } + + if ( ( nz != h && nz != h + 1 ) || z == 0 ) { + + dummy.geometry = nzGeometry; + THREE.GeometryUtils.merge( geometry, dummy ); + + } + + } + + } + + var textureGrass = THREE.ImageUtils.loadTexture( 'textures/minecraft/grass.png' ); + textureGrass.magFilter = THREE.NearestFilter; + textureGrass.minFilter = THREE.LinearMipMapLinearFilter; + + var textureGrassDirt = THREE.ImageUtils.loadTexture( 'textures/minecraft/grass_dirt.png' ); + textureGrassDirt.magFilter = THREE.NearestFilter; + textureGrassDirt.minFilter = THREE.LinearMipMapLinearFilter; + + var material1 = new THREE.MeshLambertMaterial( { map: textureGrass, ambient: 0xbbbbbb } ); + var material2 = new THREE.MeshLambertMaterial( { map: textureGrassDirt, ambient: 0xbbbbbb } ); + + var mesh = new THREE.Mesh( geometry, new THREE.MeshFaceMaterial( [ material1, material2 ] ) ); + scene.add( mesh ); + + var ambientLight = new THREE.AmbientLight( 0xcccccc ); + scene.add( ambientLight ); + + var directionalLight = new THREE.DirectionalLight( 0xffffff, 2 ); + directionalLight.position.set( 1, 1, 0.5 ).normalize(); + scene.add( directionalLight ); + + renderer = new THREE.WebGLRenderer(); + renderer.setSize( window.innerWidth, window.innerHeight ); + + container.innerHTML = ""; + + container.appendChild( renderer.domElement ); + + stats = new Stats(); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.top = '0px'; + container.appendChild( stats.domElement ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + controls.handleResize(); + + } + + function generateHeight( width, height ) { + + var data = [], perlin = new ImprovedNoise(), + size = width * height, quality = 2, z = Math.random() * 100; + + for ( var j = 0; j < 4; j ++ ) { + + if ( j == 0 ) for ( var i = 0; i < size; i ++ ) data[ i ] = 0; + + for ( var i = 0; i < size; i ++ ) { + + var x = i % width, y = ( i / width ) | 0; + data[ i ] += perlin.noise( x / quality, y / quality, z ) * quality; + + + } + + quality *= 4 + + } + + return data; + + } + + function getY( x, z ) { + + return ( data[ x + z * worldWidth ] * 0.2 ) | 0; + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + controls.update( clock.getDelta() ); + renderer.render( scene, camera ); + + } }; \ No newline at end of file diff --git a/threejs/three.d.ts b/threejs/three.d.ts index e4a692f58b..6ae3a2a65c 100644 --- a/threejs/three.d.ts +++ b/threejs/three.d.ts @@ -88,14 +88,15 @@ module THREE { export var AddOperation: Combine; // Mapping modes - export interface Mapping { + export enum Mapping { } + export interface MappingConstructor { new(): Mapping; } - export var UVMapping: Mapping; - export var CubeReflectionMapping: Mapping; - export var CubeRefractionMapping: Mapping; - export var SphericalReflectionMapping: Mapping; - export var SphericalRefractionMapping: Mapping; + export var UVMapping: MappingConstructor; + export var CubeReflectionMapping: MappingConstructor; + export var CubeRefractionMapping: MappingConstructor; + export var SphericalReflectionMapping: MappingConstructor; + export var SphericalRefractionMapping: MappingConstructor; // Wrapping modes export enum Wrapping { } @@ -185,6 +186,24 @@ module THREE { // Core /////////////////////////////////////////////////////////////////////////////////////////////// + interface BufferGeometryAttributeArray extends ArrayBufferView{ + length: number; + } + + interface BufferGeometryAttribute{ + itemSize: number; + array: BufferGeometryAttributeArray; + numItems: number; + } + + interface BufferGeometryAttributes{ + [name: string]: BufferGeometryAttribute; + index?: BufferGeometryAttribute; + position?: BufferGeometryAttribute; + normal?: BufferGeometryAttribute; + color?: BufferGeometryAttribute; + } + /** * This is a superefficent class for geometries because it saves all data in buffers. * It reduces memory costs and cpu cycles. But it is not as easy to work with because of all the nessecary buffer calculations. @@ -206,7 +225,7 @@ module THREE { /** * This hashmap has as id the name of the attribute to be set and as value the buffer to set it to. */ - attributes: { [name: string]: any; }; + attributes: BufferGeometryAttributes; /** * When set, it holds certain buffers in memory to have faster updates for this object. When unset, it deletes those buffers and saves memory. @@ -226,6 +245,8 @@ module THREE { hasTangents: bool; morphTargets: any[]; + offsets: { start: number; count: number; index: number; }[]; + /** * Bakes matrix transform directly into vertex coordinates. */ @@ -3876,6 +3897,7 @@ module THREE { export interface Uniforms { [name: string]: { type: string; value: any; }; //[name:string]:{type:UniformType;value:Object;}; + color?: { type: string; value: THREE.Color; }; } export interface ShaderMaterialParameters { @@ -3928,6 +3950,9 @@ module THREE { constructor(geometry?: Geometry, material?: LineDashedMaterial, type?: number); constructor(geometry?: Geometry, material?: LineBasicMaterial, type?: number); constructor(geometry?: Geometry, material?: ShaderMaterial, type?: number); + constructor(geometry?: BufferGeometry, material?: LineDashedMaterial, type?: number); + constructor(geometry?: BufferGeometry, material?: LineBasicMaterial, type?: number); + constructor(geometry?: BufferGeometry, material?: ShaderMaterial, type?: number); geometry: Geometry; material: Material; type: LineType; @@ -3954,6 +3979,15 @@ module THREE { constructor(geometry?: Geometry, material?: MeshNormalMaterial); constructor(geometry?: Geometry, material?: MeshPhongMaterial); constructor(geometry?: Geometry, material?: ShaderMaterial); + + constructor(geometry?: BufferGeometry , material?: MeshBasicMaterial); + constructor(geometry?: BufferGeometry , material?: MeshDepthMaterial); + constructor(geometry?: BufferGeometry , material?: MeshFaceMaterial); + constructor(geometry?: BufferGeometry , material?: MeshLambertMaterial); + constructor(geometry?: BufferGeometry , material?: MeshNormalMaterial); + constructor(geometry?: BufferGeometry , material?: MeshPhongMaterial); + constructor(geometry?: BufferGeometry , material?: ShaderMaterial); + geometry: Geometry; material: Material; morphTargetBase: number; @@ -4010,6 +4044,10 @@ module THREE { constructor(geometry: Geometry, material?: ParticleCanvasMaterial); constructor(geometry: Geometry, material?: ParticleDOMMaterial); constructor(geometry: Geometry, material?: ShaderMaterial); + constructor(geometry: BufferGeometry, material?: ParticleBasicMaterial); + constructor(geometry: BufferGeometry, material?: ParticleCanvasMaterial); + constructor(geometry: BufferGeometry, material?: ParticleDOMMaterial); + constructor(geometry: BufferGeometry, material?: ShaderMaterial); /** * An instance of Geometry, where each vertex designates the position of a particle in the system. @@ -4037,13 +4075,13 @@ module THREE { } export class SkinnedMesh extends Mesh { - constructor(geometry?: Geometry, material?: MeshBasicMaterial); - constructor(geometry?: Geometry, material?: MeshDepthMaterial); - constructor(geometry?: Geometry, material?: MeshFaceMaterial); - constructor(geometry?: Geometry, material?: MeshLambertMaterial); - constructor(geometry?: Geometry, material?: MeshNormalMaterial); - constructor(geometry?: Geometry, material?: MeshPhongMaterial); - constructor(geometry?: Geometry, material?: ShaderMaterial); + constructor(geometry?: Geometry, material?: MeshBasicMaterial, useVertexTexture?: bool); + constructor(geometry?: Geometry, material?: MeshDepthMaterial, useVertexTexture?: bool); + constructor(geometry?: Geometry, material?: MeshFaceMaterial, useVertexTexture?: bool); + constructor(geometry?: Geometry, material?: MeshLambertMaterial, useVertexTexture?: bool); + constructor(geometry?: Geometry, material?: MeshNormalMaterial, useVertexTexture?: bool); + constructor(geometry?: Geometry, material?: MeshPhongMaterial, useVertexTexture?: bool); + constructor(geometry?: Geometry, material?: ShaderMaterial, useVertexTexture?: bool); useVertexTexture: bool; identityMatrix: Matrix4; bones: Bone[]; @@ -4939,6 +4977,8 @@ module THREE { getNextKeyWith(type: string, h: number, key: number): KeyFrame; // ???? getPrevKeyWith(type: string, h: number, key: number): KeyFrame; + + JITCompile: bool; // https://github.com/mrdoob/three.js/blob/master/examples/webgl_animation_skinning_morph.html#L251 } export class AnimationInterpolation { } @@ -5449,7 +5489,7 @@ module THREE { } export class ConvexGeometry extends Geometry { - constructor(vertices: Vector3); + constructor(vertices: Vector3[]); } /** @@ -5597,7 +5637,12 @@ module THREE { } export class TubeGeometry extends Geometry { - constructor(path: Path, segments?: number, radius?: number, radiusSegments?: number, closed?: bool, debug?: ArrowHelper[]); + constructor(path: Path, segments?: number, radius?: number, radiusSegments?: number, closed?: bool, debug?: Object3D); + + // https://github.com/mrdoob/three.js/blob/master/examples/webgl_geometry_extrude_shapes.html#L208 + // Hmmm? + constructor(path: SplineCurve3, segments?: number, radius?: number, radiusSegments?: number, closed?: bool, debug?: bool); + path: Path; segments: number; radius: number; From bceb6b8082b482412964246673dea26214b69583 Mon Sep 17 00:00:00 2001 From: Kon Date: Tue, 5 Mar 2013 05:04:50 +0900 Subject: [PATCH 3/3] Added a lot of tests to three-tests.ts --- threejs/three-tests.ts | 8012 +++++++++++++++++++++++++++++++++++++++- threejs/three.d.ts | 43 +- 2 files changed, 8046 insertions(+), 9 deletions(-) diff --git a/threejs/three-tests.ts b/threejs/three-tests.ts index f38cb99176..5b3bbb2caa 100644 --- a/threejs/three-tests.ts +++ b/threejs/three-tests.ts @@ -1,7 +1,6 @@ /// /// -// https://github.com/mrdoob/three.js/tree/master/test/unit/math /* The MIT License @@ -26,6 +25,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +// https://github.com/mrdoob/three.js/tree/master/test/unit/math + ()=>{ var x = 2; var y = 3; @@ -3112,6 +3113,7 @@ declare var Detector: any; declare var Qrcode: any; declare var ImprovedNoise: any; + declare module THREE{ var PDBLoader: any; var CSS3Renderer: any; @@ -3135,6 +3137,24 @@ declare module THREE{ var Curves: any; var ParametricGeometries: any; var BinaryLoader: any; + var OculusRiftEffect: any; + var SubdivisionModifier: any; + var TessellateModifier: any; + var ExplodeModifier: any; + var RenderPass: any; + var BloomPass:any; + var FilmPass: any; + var ShaderPass: any; + var FXAAShader: any; + var CopyShader: any; + var ColladaLoader: any; + var CTMLoader: any; + var VTKLoader: any; + var STLLoader: any; + var OBJLoader: any; + var ColladaLoader: any; + var UTF8Loader: any; + var UnpackDepthRGBAShader: any; } interface CSS3Properties{ @@ -11867,7 +11887,7 @@ declare var ballPosition: THREE.Vector3; var segments = 10000; var geometry = new THREE.BufferGeometry(); - var material = new THREE.LineBasicMaterial({ vertexColors: true }); + var material = new THREE.LineBasicMaterial({ vertexColors: THREE.VertexColors }); geometry.attributes = { position: { @@ -15806,4 +15826,7990 @@ function render() { renderer.render( scene, camera ); } -}; \ No newline at end of file +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/webgl_geometry_minecraft_ao.html + +()=>{ + + if ( ! Detector.webgl ) { + + Detector.addGetWebGLMessage(); + document.getElementById( 'container' ).innerHTML = ""; + + } + + var fogExp2 = true; + + var container, stats; + + var camera, controls, scene, renderer; + + var mesh, mat; + + var worldWidth = 200, worldDepth = 200, + worldHalfWidth = worldWidth / 2, worldHalfDepth = worldDepth / 2, + data = generateHeight( worldWidth, worldDepth ); + + var clock = new THREE.Clock(); + + init(); + animate(); + + function init() { + + container = document.getElementById( 'container' ); + + camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 20000 ); + camera.position.y = getY( worldHalfWidth, worldHalfDepth ) * 100 + 100; + + controls = new THREE.FirstPersonControls( camera ); + + controls.movementSpeed = 1000; + controls.lookSpeed = 0.125; + controls.lookVertical = true; + controls.constrainVertical = true; + controls.verticalMin = 1.1; + controls.verticalMax = 2.2; + + scene = new THREE.Scene(); + scene.fog = new THREE.FogExp2( 0xffffff, 0.00015 ); + + // sides + + var light = new THREE.Color( 0xffffff ); + var shadow = new THREE.Color( 0x505050 ); + + var matrix = new THREE.Matrix4(); + + var pxGeometry = new THREE.PlaneGeometry( 100, 100 ); + pxGeometry.faces[ 0 ].materialIndex = 1; + pxGeometry.faces[ 0 ].vertexColors = [ light, shadow, shadow, light ]; + pxGeometry.applyMatrix( matrix.makeRotationY( Math.PI / 2 ) ); + pxGeometry.applyMatrix( matrix.makeTranslation( 50, 0, 0 ) ); + + var nxGeometry = new THREE.PlaneGeometry( 100, 100 ); + nxGeometry.faces[ 0 ].materialIndex = 1; + nxGeometry.faces[ 0 ].vertexColors = [ light, shadow, shadow, light ]; + nxGeometry.applyMatrix( matrix.makeRotationY( - Math.PI / 2 ) ); + nxGeometry.applyMatrix( matrix.makeTranslation( - 50, 0, 0 ) ); + + var pyGeometry = new THREE.PlaneGeometry( 100, 100 ); + pyGeometry.faces[ 0 ].materialIndex = 0; + pyGeometry.faces[ 0 ].vertexColors = [ light, light, light, light ]; + pyGeometry.applyMatrix( matrix.makeRotationX( - Math.PI / 2 ) ); + pyGeometry.applyMatrix( matrix.makeTranslation( 0, 50, 0 ) ); + + var pzGeometry = new THREE.PlaneGeometry( 100, 100 ); + pzGeometry.faces[ 0 ].materialIndex = 1; + pzGeometry.faces[ 0 ].vertexColors = [ light, shadow, shadow, light ]; + pzGeometry.applyMatrix( matrix.makeTranslation( 0, 0, 50 ) ); + + var nzGeometry = new THREE.PlaneGeometry( 100, 100 ); + nzGeometry.faces[ 0 ].materialIndex = 1; + nzGeometry.faces[ 0 ].vertexColors = [ light, shadow, shadow, light ]; + nzGeometry.applyMatrix( matrix.makeRotationY( Math.PI ) ); + nzGeometry.applyMatrix( matrix.makeTranslation( 0, 0, -50 ) ); + + // + + var geometry = new THREE.Geometry(); + var dummy = new THREE.Mesh(); + + for ( var z = 0; z < worldDepth; z ++ ) { + + for ( var x = 0; x < worldWidth; x ++ ) { + + var h = getY( x, z ); + + dummy.position.x = x * 100 - worldHalfWidth * 100; + dummy.position.y = h * 100; + dummy.position.z = z * 100 - worldHalfDepth * 100; + + var px = getY( x + 1, z ); + var nx = getY( x - 1, z ); + var pz = getY( x, z + 1 ); + var nz = getY( x, z - 1 ); + + var pxpz = getY( x + 1, z + 1 ); + var nxpz = getY( x - 1, z + 1 ); + var pxnz = getY( x + 1, z - 1 ); + var nxnz = getY( x - 1, z - 1 ); + + dummy.geometry = pyGeometry; + + var colors = dummy.geometry.faces[ 0 ].vertexColors; + colors[ 0 ] = nx > h || nz > h || nxnz > h ? shadow : light; + colors[ 1 ] = nx > h || pz > h || nxpz > h ? shadow : light; + colors[ 2 ] = px > h || pz > h || pxpz > h ? shadow : light; + colors[ 3 ] = px > h || nz > h || pxnz > h ? shadow : light; + + THREE.GeometryUtils.merge( geometry, dummy ); + + if ( ( px != h && px != h + 1 ) || x == 0 ) { + + dummy.geometry = pxGeometry; + + var colors = dummy.geometry.faces[ 0 ].vertexColors; + colors[ 0 ] = pxpz > px && x > 0 ? shadow : light; + colors[ 3 ] = pxnz > px && x > 0 ? shadow : light; + + THREE.GeometryUtils.merge( geometry, dummy ); + + } + + if ( ( nx != h && nx != h + 1 ) || x == worldWidth - 1 ) { + + dummy.geometry = nxGeometry; + + var colors = dummy.geometry.faces[ 0 ].vertexColors; + colors[ 0 ] = nxnz > nx && x < worldWidth - 1 ? shadow : light; + colors[ 3 ] = nxpz > nx && x < worldWidth - 1 ? shadow : light; + + THREE.GeometryUtils.merge( geometry, dummy ); + + } + + if ( ( pz != h && pz != h + 1 ) || z == worldDepth - 1 ) { + + dummy.geometry = pzGeometry; + + var colors = dummy.geometry.faces[ 0 ].vertexColors; + colors[ 0 ] = nxpz > pz && z < worldDepth - 1 ? shadow : light; + colors[ 3 ] = pxpz > pz && z < worldDepth - 1 ? shadow : light; + + THREE.GeometryUtils.merge( geometry, dummy ); + + } + + if ( ( nz != h && nz != h + 1 ) || z == 0 ) { + + dummy.geometry = nzGeometry; + + var colors = dummy.geometry.faces[ 0 ].vertexColors; + colors[ 0 ] = pxnz > nz && z > 0 ? shadow : light; + colors[ 3 ] = nxnz > nz && z > 0 ? shadow : light; + + THREE.GeometryUtils.merge( geometry, dummy ); + + } + + } + + } + + var textureGrass = THREE.ImageUtils.loadTexture( 'textures/minecraft/grass.png' ); + textureGrass.magFilter = THREE.NearestFilter; + textureGrass.minFilter = THREE.LinearMipMapLinearFilter; + + var textureGrassDirt = THREE.ImageUtils.loadTexture( 'textures/minecraft/grass_dirt.png' ); + textureGrassDirt.magFilter = THREE.NearestFilter; + textureGrassDirt.minFilter = THREE.LinearMipMapLinearFilter; + + var material1 = new THREE.MeshLambertMaterial( { map: textureGrass, ambient: 0xbbbbbb, vertexColors: THREE.VertexColors } ); + var material2 = new THREE.MeshLambertMaterial( { map: textureGrassDirt, ambient: 0xbbbbbb, vertexColors: THREE.VertexColors } ); + + var mesh = new THREE.Mesh( geometry, new THREE.MeshFaceMaterial( [ material1, material2 ] ) ); + scene.add( mesh ); + + var ambientLight = new THREE.AmbientLight( 0xcccccc ); + scene.add( ambientLight ); + + var directionalLight = new THREE.DirectionalLight( 0xffffff, 2 ); + directionalLight.position.set( 1, 1, 0.5 ).normalize(); + scene.add( directionalLight ); + + renderer = new THREE.WebGLRenderer( { clearColor: 0xffffff } ); + renderer.setSize( window.innerWidth, window.innerHeight ); + + container.innerHTML = ""; + + container.appendChild( renderer.domElement ); + + stats = new Stats(); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.top = '0px'; + container.appendChild( stats.domElement ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + controls.handleResize(); + + } + + function loadTexture( path, callback ) { + + var image = new Image(); + + image.onload = function () { callback(); }; + image.src = path; + + return image; + + } + + function generateHeight( width, height ) { + + var data = [], perlin = new ImprovedNoise(), + size = width * height, quality = 2, z = Math.random() * 100; + + for ( var j = 0; j < 4; j ++ ) { + + if ( j == 0 ) for ( var i = 0; i < size; i ++ ) data[ i ] = 0; + + for ( var i = 0; i < size; i ++ ) { + + var x = i % width, y = ( i / width ) | 0; + data[ i ] += perlin.noise( x / quality, y / quality, z ) * quality; + + } + + quality *= 4 + + } + + return data; + + } + + function getY( x, z ) { + + return ( data[ x + z * worldWidth ] * 0.2 ) | 0; + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + controls.update( clock.getDelta() ); + renderer.render( scene, camera ); + + } + +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/webgl_geometry_minecraft_oculusrift.html + +()=>{ + + if ( ! Detector.webgl ) { + + Detector.addGetWebGLMessage(); + document.getElementById( 'container' ).innerHTML = ""; + + } + + var container, stats; + + var camera, controls, scene, renderer; + + var mesh; + + var effect; + + var worldWidth = 128, worldDepth = 128, + worldHalfWidth = worldWidth / 2, worldHalfDepth = worldDepth / 2, + data = generateHeight( worldWidth, worldDepth ); + + var clock = new THREE.Clock(); + + init(); + animate(); + + function init() { + + container = document.getElementById( 'container' ); + + camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 20000 ); + camera.position.y = getY( worldHalfWidth, worldHalfDepth ) * 100 + 100; + + controls = new THREE.FirstPersonControls( camera ); + + controls.movementSpeed = 1000; + controls.lookSpeed = 0.125; + controls.lookVertical = true; + + scene = new THREE.Scene(); + + // sides + + var matrix = new THREE.Matrix4(); + + var pxGeometry = new THREE.PlaneGeometry( 100, 100 ); + pxGeometry.faces[ 0 ].materialIndex = 1; + pxGeometry.applyMatrix( matrix.makeRotationY( Math.PI / 2 ) ); + pxGeometry.applyMatrix( matrix.makeTranslation( 50, 0, 0 ) ); + + var nxGeometry = new THREE.PlaneGeometry( 100, 100 ); + nxGeometry.faces[ 0 ].materialIndex = 1; + nxGeometry.applyMatrix( matrix.makeRotationY( - Math.PI / 2 ) ); + nxGeometry.applyMatrix( matrix.makeTranslation( - 50, 0, 0 ) ); + + var pyGeometry = new THREE.PlaneGeometry( 100, 100 ); + pyGeometry.faces[ 0 ].materialIndex = 0; + pyGeometry.applyMatrix( matrix.makeRotationX( - Math.PI / 2 ) ); + pyGeometry.applyMatrix( matrix.makeTranslation( 0, 50, 0 ) ); + + var pzGeometry = new THREE.PlaneGeometry( 100, 100 ); + pzGeometry.faces[ 0 ].materialIndex = 1; + pzGeometry.applyMatrix( matrix.makeTranslation( 0, 0, 50 ) ); + + var nzGeometry = new THREE.PlaneGeometry( 100, 100 ); + nzGeometry.faces[ 0 ].materialIndex = 1; + nzGeometry.applyMatrix( matrix.makeRotationY( Math.PI ) ); + nzGeometry.applyMatrix( matrix.makeTranslation( 0, 0, -50 ) ); + // + + var geometry = new THREE.Geometry(); + var dummy = new THREE.Mesh(); + + for ( var z = 0; z < worldDepth; z ++ ) { + + for ( var x = 0; x < worldWidth; x ++ ) { + + var h = getY( x, z ); + + dummy.position.x = x * 100 - worldHalfWidth * 100; + dummy.position.y = h * 100; + dummy.position.z = z * 100 - worldHalfDepth * 100; + + var px = getY( x + 1, z ); + var nx = getY( x - 1, z ); + var pz = getY( x, z + 1 ); + var nz = getY( x, z - 1 ); + + dummy.geometry = pyGeometry; + THREE.GeometryUtils.merge( geometry, dummy ); + + if ( ( px != h && px != h + 1 ) || x == 0 ) { + + dummy.geometry = pxGeometry; + THREE.GeometryUtils.merge( geometry, dummy ); + + } + + if ( ( nx != h && nx != h + 1 ) || x == worldWidth - 1 ) { + + dummy.geometry = nxGeometry; + THREE.GeometryUtils.merge( geometry, dummy ); + + } + + if ( ( pz != h && pz != h + 1 ) || z == worldDepth - 1 ) { + + dummy.geometry = pzGeometry; + THREE.GeometryUtils.merge( geometry, dummy ); + + } + + if ( ( nz != h && nz != h + 1 ) || z == 0 ) { + + dummy.geometry = nzGeometry; + THREE.GeometryUtils.merge( geometry, dummy ); + + } + + } + + } + + var textureGrass = THREE.ImageUtils.loadTexture( 'textures/minecraft/grass.png' ); + textureGrass.magFilter = THREE.NearestFilter; + textureGrass.minFilter = THREE.LinearMipMapLinearFilter; + + var textureGrassDirt = THREE.ImageUtils.loadTexture( 'textures/minecraft/grass_dirt.png' ); + textureGrassDirt.magFilter = THREE.NearestFilter; + textureGrassDirt.minFilter = THREE.LinearMipMapLinearFilter; + + var material1 = new THREE.MeshLambertMaterial( { map: textureGrass, ambient: 0xbbbbbb } ); + var material2 = new THREE.MeshLambertMaterial( { map: textureGrassDirt, ambient: 0xbbbbbb } ); + + var mesh = new THREE.Mesh( geometry, new THREE.MeshFaceMaterial( [ material1, material2 ] ) ); + scene.add( mesh ); + + var ambientLight = new THREE.AmbientLight( 0xcccccc ); + scene.add( ambientLight ); + + var directionalLight = new THREE.DirectionalLight( 0xffffff, 2 ); + directionalLight.position.set( 1, 1, 0.5 ).normalize(); + scene.add( directionalLight ); + + renderer = new THREE.WebGLRenderer(); + renderer.setSize( window.innerWidth, window.innerHeight ); + effect = new THREE.OculusRiftEffect( renderer ); + effect.setSize( window.innerWidth, window.innerHeight ); + + // Right Oculus Parameters are yet to be determined + effect.separation = 20; + effect.distortion = 0.1; + effect.fov = 110; + + + document.getElementById( 'distVal' ).innerHTML = effect.distortion.toFixed(2); + document.getElementById( 'sepVal' ).innerHTML = effect.separation; + document.getElementById( 'fovVal' ).innerHTML = effect.fov; + + + container.innerHTML = ""; + + container.appendChild( renderer.domElement ); + + stats = new Stats(); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.top = '0px'; + container.appendChild( stats.domElement ); + + // GUI + window.addEventListener( 'resize', onWindowResize, false ); + document.addEventListener( 'keydown', keyPressed, false ); + + } + + function onWindowResize() { + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + effect.setSize( window.innerWidth, window.innerHeight ); + + controls.handleResize(); + + } + + function keyPressed (event) { + switch ( event.keyCode ) { + case 79: /*O*/ effect.distortion -= 0.01; document.getElementById( 'distVal' ).innerHTML = effect.distortion.toFixed(2); break; + case 80: /*P*/ effect.distortion += 0.01; document.getElementById( 'distVal' ).innerHTML = effect.distortion.toFixed(2); break; + case 75: /*K*/ effect.separation -= 1; document.getElementById( 'sepVal' ).innerHTML = effect.separation; break; + case 76: /*L*/ effect.separation += 1; document.getElementById( 'sepVal' ).innerHTML = effect.separation; break; + case 78: /*N*/ effect.fov -= 1; document.getElementById( 'fovVal' ).innerHTML = effect.fov; break; + case 77: /*M*/ effect.fov += 1; document.getElementById( 'fovVal' ).innerHTML = effect.fov; break; + + } + } + + function generateHeight( width, height ) { + + var data = [], perlin = new ImprovedNoise(), + size = width * height, quality = 2, z = Math.random() * 100; + + for ( var j = 0; j < 4; j ++ ) { + + if ( j == 0 ) for ( var i = 0; i < size; i ++ ) data[ i ] = 0; + + for ( var i = 0; i < size; i ++ ) { + + var x = i % width, y = ( i / width ) | 0; + data[ i ] += perlin.noise( x / quality, y / quality, z ) * quality; + + + } + + quality *= 4 + + } + + return data; + + } + + function getY( x, z ) { + + return ( data[ x + z * worldWidth ] * 0.2 ) | 0; + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + controls.update( clock.getDelta() ); + effect.render( scene, camera ); + + } + +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/webgl_geometry_normals.html + +()=>{ + + var container, stats; + + var camera, scene, renderer; + + var cube, plane; + + var targetYRotation = 0; + var targetXRotation = 0; + var targetYRotationOnMouseDown = 0; + var targetXRotationOnMouseDown = 0; + + var mouseX = 0, mouseY = 0; + var mouseXOnMouseDown = 0; + var mouseYOnMouseDown = 0; + + var windowHalfX = window.innerWidth / 2; + var windowHalfY = window.innerHeight / 2; + + var group; + + var targetRotationOnMouseDown; + var targetRotation; + + + // Create new object by parameters + + var createSomething = function( klass, args ) { + + var F = function( klass, args ) { + + return klass.apply( this, args ); + + } + + F.prototype = klass.prototype; + + return new F( klass, args ); + + }; + + + // Cube + + var materials = []; + + for ( var i = 0; i < 6; i ++ ) { + + materials.push( [ new THREE.MeshBasicMaterial( { color: Math.random() * 0xffffff, wireframe: false } ) ] ); + + } + + + + var geometriesParams: {type:string;args:any[];}[] = [ + + { type: 'CubeGeometry', args: [ 200, 200, 200, 2, 2, 2, materials ] }, + { type: 'TorusGeometry', args: [ 100, 60, 12, 12 ] }, + { type: 'TorusKnotGeometry', args: [ ] }, + { type: 'SphereGeometry', args: [ 100, 12, 12 ] }, + { type: 'SphereGeometry', args: [ 100, 5, 5 ] }, + { type: 'SphereGeometry', args: [ 100, 13, 13 ] }, + { type: 'IcosahedronGeometry', args: [ 100, 1 ] }, + { type: 'CylinderGeometry', args: [ 25, 75, 200, 8, 3 ]} , + { type: 'OctahedronGeometry', args: [200, 0] }, + { type: 'LatheGeometry', args: [ [ + new THREE.Vector3(0,0,-100), + new THREE.Vector3(0,50,-50), + new THREE.Vector3(0,10,0), + new THREE.Vector3(0,50,050), + new THREE.Vector3(0,0,100) ] ]}, + { type: 'LatheGeometry', args: [ [ + new THREE.Vector3(0,0,-100), + new THREE.Vector3(0,50,-50), + new THREE.Vector3(0,10,0), + new THREE.Vector3(0,50,050), + new THREE.Vector3(0,100,100) ], 12, 0, Math.PI ] }, + { type: 'LatheGeometry', args: [ [ + new THREE.Vector3(0,10,-100), + new THREE.Vector3(0,50,-50), + new THREE.Vector3(0,10,0), + new THREE.Vector3(0,50,050), + new THREE.Vector3(0,0,100) ], 12, Math.PI*2/3, Math.PI*3/2 ] }, + { type: 'TextGeometry', args: ['&', { + size: 200, + height: 50, + curveSegments: 1, + font: "helvetiker" + + }]}, + { type: 'PlaneGeometry', args: [ 200, 200, 4, 4 ] } + + ]; + + var info; + var geometryIndex = 0; + + // start scene + + init(); + animate(); + + function nextGeometry() { + + geometryIndex ++; + + if ( geometryIndex > geometriesParams.length - 1 ) { + + geometryIndex = 0; + + } + + addStuff(); + + } + + function switchGeometry(i) { + + geometryIndex = i; + + addStuff(); + } + + function updateInfo() { + + var params = geometriesParams[ geometryIndex ]; + + var dropdown = ''; + + var text = + 'Drag to spin THREE.' + params.type + + '
' + + '
Geometry: ' + dropdown + ' next'; + + text += + '

Blue Arrows: Face Normals' + + '
Red Arrows: Vertex Normals before Geometry.mergeVertices' + + '
Black Arrows: Vertex Normals after Geometry.mergeVertices'; + + info.innerHTML = text; + + } + + function addStuff() { + + if ( group !== undefined ) { + + scene.remove( group ); + + } + + + + var params = geometriesParams[ geometryIndex ]; + + var geometry = createSomething( THREE[ params.type ], params.args ); + + // scale geometry to a uniform size + geometry.computeBoundingSphere(); + + var scaleFactor = 160 / geometry.boundingSphere.radius; + geometry.applyMatrix( new THREE.Matrix4().makeScale( scaleFactor, scaleFactor, scaleFactor ) ); + + var originalGeometry = geometry.clone(); + originalGeometry.computeFaceNormals(); + originalGeometry.computeVertexNormals( true ); + + // in case of duplicated vertices + geometry.mergeVertices(); + geometry.computeCentroids(); + geometry.computeFaceNormals(); + geometry.computeVertexNormals( true ); + + updateInfo(); + + var faceABCD = "abcd"; + var color, f, p, n, vertexIndex; + + for ( i = 0; i < geometry.faces.length; i ++ ) { + + f = geometry.faces[ i ]; + + + n = ( f instanceof THREE.Face3 ) ? 3 : 4; + + for( var j = 0; j < n; j++ ) { + + vertexIndex = f[ faceABCD.charAt( j ) ]; + + p = geometry.vertices[ vertexIndex ]; + + color = new THREE.Color( 0xffffff ); + color.setHSL( ( p.y ) / 400 + 0.5, 1.0, 1.0 ); + + f.vertexColors[ j ] = color; + + } + + } + + + group = new THREE.Object3D(); + var mesh = new THREE.Mesh( geometry, new THREE.MeshBasicMaterial( { color: 0xfefefe, wireframe: true, opacity: 0.5 } ) ); + group.add( mesh ); + scene.add( group ); + + var fvNames = [ 'a', 'b', 'c', 'd' ]; + + var normalLength = 15; + + for( var f = 0, fl = geometry.faces.length; f < fl; f ++ ) { + var face = geometry.faces[ f ]; + var arrow = new THREE.ArrowHelper( + face.normal, + face.centroid, + normalLength, + 0x3333FF ); + mesh.add( arrow ); + } + + for( var f = 0, fl = originalGeometry.faces.length; f < fl; f ++ ) { + var face = originalGeometry.faces[ f ]; + if( face.vertexNormals === undefined ) { + continue; + } + for( var v = 0, vl = face.vertexNormals.length; v < vl; v ++ ) { + var arrow = new THREE.ArrowHelper( + face.vertexNormals[ v ], + originalGeometry.vertices[ face[ fvNames[ v ] ] ], + normalLength, + 0xFF3333 ); + mesh.add( arrow ); + } + } + + for( var f = 0, fl = mesh.geometry.faces.length; f < fl; f ++ ) { + var face = mesh.geometry.faces[ f ]; + if( face.vertexNormals === undefined ) { + continue; + } + for( var v = 0, vl = face.vertexNormals.length; v < vl; v ++ ) { + var arrow = new THREE.ArrowHelper( + face.vertexNormals[ v ], + mesh.geometry.vertices[ face[ fvNames[ v ] ] ], + normalLength, + 0x000000 ); + mesh.add( arrow ); + } + } + + } + + function init() { + + container = document.createElement( 'div' ); + document.body.appendChild( container ); + + info = document.createElement( 'div' ); + info.style.position = 'absolute'; + info.style.top = '10px'; + info.style.width = '100%'; + info.style.textAlign = 'center'; + info.innerHTML = 'Drag to spin the geometry '; + container.appendChild( info ); + + camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 ); + camera.position.z = 500; + + scene = new THREE.Scene(); + + var light = new THREE.PointLight( 0xffffff, 1.5 ); + light.position.set( 1000, 1000, 2000 ); + scene.add( light ); + + addStuff(); + + renderer = new THREE.WebGLRenderer( { antialias: true } ); // WebGLRenderer CanvasRenderer + 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 ); + + } + + // + + function onDocumentMouseDown( event ) { + + //event.preventDefault(); + + document.addEventListener( 'mousemove', onDocumentMouseMove, false ); + document.addEventListener( 'mouseup', onDocumentMouseUp, false ); + document.addEventListener( 'mouseout', onDocumentMouseOut, false ); + + mouseXOnMouseDown = event.clientX - windowHalfX; + mouseYOnMouseDown = event.clientY - windowHalfY; + targetYRotationOnMouseDown = targetYRotation; + targetXRotationOnMouseDown = targetXRotation; + + } + + function onDocumentMouseMove( event ) { + + mouseX = event.clientX - windowHalfX; + mouseY = event.clientY - windowHalfY; + + targetYRotation = targetYRotationOnMouseDown + ( mouseX - mouseXOnMouseDown ) * 0.02; + targetXRotation = targetXRotationOnMouseDown + ( mouseY - mouseYOnMouseDown ) * 0.02; + + } + + function onDocumentMouseUp( event ) { + + document.removeEventListener( 'mousemove', onDocumentMouseMove, false ); + document.removeEventListener( 'mouseup', onDocumentMouseUp, false ); + document.removeEventListener( 'mouseout', onDocumentMouseOut, false ); + } + + function onDocumentMouseOut( event ) { + + document.removeEventListener( 'mousemove', onDocumentMouseMove, false ); + document.removeEventListener( 'mouseup', onDocumentMouseUp, false ); + document.removeEventListener( 'mouseout', onDocumentMouseOut, false ); + } + + 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() { + + group.rotation.x = ( targetXRotation) * 0.15; + group.rotation.y = ( targetYRotation ) * 0.15; + + renderer.render( scene, camera ); + + } + +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/webgl_geometry_shapes.html + +()=>{ + + var container, stats; + + var camera, scene, renderer; + + var 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 parent; + + 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 = 'Simple procedurally generated 3D shapes example by zz85
Drag to spin'; + container.appendChild( info ); + + camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 1000 ); + camera.position.set( 0, 150, 500 ); + + scene = new THREE.Scene(); + + var light = new THREE.DirectionalLight( 0xffffff ); + light.position.set( 0, 0, 1 ); + scene.add( light ); + + parent = new THREE.Object3D(); + parent.position.y = 50; + scene.add( parent ); + + function addShape( shape, extrudeSettings, color, x, y, z, rx, ry, rz, s ) { + + var points = shape.createPointsGeometry(); + var spacedPoints = shape.createSpacedPointsGeometry( 100 ); + + // flat shape + + var geometry = new THREE.ShapeGeometry( shape ); + + var mesh = THREE.SceneUtils.createMultiMaterialObject( geometry, [ new THREE.MeshLambertMaterial( { color: color } ), new THREE.MeshBasicMaterial( { color: 0x000000, wireframe: true, transparent: true } ) ] ); + mesh.position.set( x, y, z - 125 ); + mesh.rotation.set( rx, ry, rz ); + mesh.scale.set( s, s, s ); + parent.add( mesh ); + + // 3d shape + + var geometryExtrude = new THREE.ExtrudeGeometry( shape, extrudeSettings ); + + var mesh = THREE.SceneUtils.createMultiMaterialObject( geometryExtrude, [ new THREE.MeshLambertMaterial( { color: color } ), new THREE.MeshBasicMaterial( { color: 0x000000, wireframe: true, transparent: true } ) ] ); + mesh.position.set( x, y, z - 75 ); + mesh.rotation.set( rx, ry, rz ); + mesh.scale.set( s, s, s ); + parent.add( mesh ); + + // solid line + + var line = new THREE.Line( points, new THREE.LineBasicMaterial( { color: color, linewidth: 2 } ) ); + line.position.set( x, y, z + 25 ); + line.rotation.set( rx, ry, rz ); + line.scale.set( s, s, s ); + parent.add( line ); + + // transparent line from real points + + var line = new THREE.Line( points, new THREE.LineBasicMaterial( { color: color, opacity: 0.5 } ) ); + line.position.set( x, y, z + 75 ); + line.rotation.set( rx, ry, rz ); + line.scale.set( s, s, s ); + parent.add( line ); + + // vertices from real points + + var pgeo = points.clone(); + var particles = new THREE.ParticleSystem( pgeo, new THREE.ParticleBasicMaterial( { color: color, size: 2, opacity: 0.75 } ) ); + particles.position.set( x, y, z + 75 ); + particles.rotation.set( rx, ry, rz ); + particles.scale.set( s, s, s ); + parent.add( particles ); + + // transparent line from equidistance sampled points + + var line = new THREE.Line( spacedPoints, new THREE.LineBasicMaterial( { color: color, opacity: 0.2 } ) ); + line.position.set( x, y, z + 125 ); + line.rotation.set( rx, ry, rz ); + line.scale.set( s, s, s ); + parent.add( line ); + + // equidistance sampled points + + var pgeo = spacedPoints.clone(); + var particles2 = new THREE.ParticleSystem( pgeo, new THREE.ParticleBasicMaterial( { color: color, size: 2, opacity: 0.5 } ) ); + particles2.position.set( x, y, z + 125 ); + particles2.rotation.set( rx, ry, rz ); + particles2.scale.set( s, s, s ); + parent.add( particles2 ); + + } + + + // California + + var californiaPts = []; + + californiaPts.push( new THREE.Vector2 ( 610, 320 ) ); + californiaPts.push( new THREE.Vector2 ( 450, 300 ) ); + californiaPts.push( new THREE.Vector2 ( 392, 392 ) ); + californiaPts.push( new THREE.Vector2 ( 266, 438 ) ); + californiaPts.push( new THREE.Vector2 ( 190, 570 ) ); + californiaPts.push( new THREE.Vector2 ( 190, 600 ) ); + californiaPts.push( new THREE.Vector2 ( 160, 620 ) ); + californiaPts.push( new THREE.Vector2 ( 160, 650 ) ); + californiaPts.push( new THREE.Vector2 ( 180, 640 ) ); + californiaPts.push( new THREE.Vector2 ( 165, 680 ) ); + californiaPts.push( new THREE.Vector2 ( 150, 670 ) ); + californiaPts.push( new THREE.Vector2 ( 90, 737 ) ); + californiaPts.push( new THREE.Vector2 ( 80, 795 ) ); + californiaPts.push( new THREE.Vector2 ( 50, 835 ) ); + californiaPts.push( new THREE.Vector2 ( 64, 870 ) ); + californiaPts.push( new THREE.Vector2 ( 60, 945 ) ); + californiaPts.push( new THREE.Vector2 ( 300, 945 ) ); + californiaPts.push( new THREE.Vector2 ( 300, 743 ) ); + californiaPts.push( new THREE.Vector2 ( 600, 473 ) ); + californiaPts.push( new THREE.Vector2 ( 626, 425 ) ); + californiaPts.push( new THREE.Vector2 ( 600, 370 ) ); + californiaPts.push( new THREE.Vector2 ( 610, 320 ) ); + + var californiaShape = new THREE.Shape( californiaPts ); + + + // Triangle + + var triangleShape = new THREE.Shape(); + triangleShape.moveTo( 80, 20 ); + triangleShape.lineTo( 40, 80 ); + triangleShape.lineTo( 120, 80 ); + triangleShape.lineTo( 80, 20 ); // close path + + + // Heart + + var x = 0, y = 0; + + var heartShape = new THREE.Shape(); // From http://blog.burlock.org/html5/130-paths + + 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 ); + + + // Square + + var sqLength = 80; + + var squareShape = new THREE.Shape(); + squareShape.moveTo( 0,0 ); + squareShape.lineTo( 0, sqLength ); + squareShape.lineTo( sqLength, sqLength ); + squareShape.lineTo( sqLength, 0 ); + squareShape.lineTo( 0, 0 ); + + + // Rectangle + + var rectLength = 120, rectWidth = 40; + + var rectShape = new THREE.Shape(); + rectShape.moveTo( 0,0 ); + rectShape.lineTo( 0, rectWidth ); + rectShape.lineTo( rectLength, rectWidth ); + rectShape.lineTo( rectLength, 0 ); + rectShape.lineTo( 0, 0 ); + + + // Rounded rectangle + + var roundedRectShape = new THREE.Shape(); + + ( function roundedRect( ctx, x, y, width, height, radius ){ + + ctx.moveTo( x, y + radius ); + ctx.lineTo( x, y + height - radius ); + ctx.quadraticCurveTo( x, y + height, x + radius, y + height ); + ctx.lineTo( x + width - radius, y + height) ; + ctx.quadraticCurveTo( x + width, y + height, x + width, y + height - radius ); + ctx.lineTo( x + width, y + radius ); + ctx.quadraticCurveTo( x + width, y, x + width - radius, y ); + ctx.lineTo( x + radius, y ); + ctx.quadraticCurveTo( x, y, x, y + radius ); + + } )( roundedRectShape, 0, 0, 50, 50, 20 ); + + + // Circle + + var circleRadius = 40; + var circleShape = new THREE.Shape(); + circleShape.moveTo( 0, circleRadius ); + circleShape.quadraticCurveTo( circleRadius, circleRadius, circleRadius, 0 ); + circleShape.quadraticCurveTo( circleRadius, -circleRadius, 0, -circleRadius ); + circleShape.quadraticCurveTo( -circleRadius, -circleRadius, -circleRadius, 0 ); + circleShape.quadraticCurveTo( -circleRadius, circleRadius, 0, circleRadius ); + + + // Fish + + x = y = 0; + + var fishShape = new THREE.Shape(); + + fishShape.moveTo(x,y); + fishShape.quadraticCurveTo(x + 50, y - 80, x + 90, y - 10); + fishShape.quadraticCurveTo(x + 100, y - 10, x + 115, y - 40); + fishShape.quadraticCurveTo(x + 115, y, x + 115, y + 40); + fishShape.quadraticCurveTo(x + 100, y + 10, x + 90, y + 10); + fishShape.quadraticCurveTo(x + 50, y + 80, x, y); + + + // Arc circle + + var arcShape = new THREE.Shape(); + arcShape.moveTo( 50, 10 ); + arcShape.absarc( 10, 10, 40, 0, Math.PI*2, false ); + + var holePath = new THREE.Path(); + holePath.moveTo( 20, 10 ); + holePath.absarc( 10, 10, 10, 0, Math.PI*2, true ); + arcShape.holes.push( holePath ); + + + // Smiley + + var smileyShape = new THREE.Shape(); + smileyShape.moveTo( 80, 40 ); + smileyShape.absarc( 40, 40, 40, 0, Math.PI*2, false ); + + var smileyEye1Path = new THREE.Path(); + smileyEye1Path.moveTo( 35, 20 ); + // smileyEye1Path.absarc( 25, 20, 10, 0, Math.PI*2, true ); + smileyEye1Path.absellipse( 25, 20, 10, 10, 0, Math.PI*2, true ); + + smileyShape.holes.push( smileyEye1Path ); + + var smileyEye2Path = new THREE.Path(); + smileyEye2Path.moveTo( 65, 20 ); + smileyEye2Path.absarc( 55, 20, 10, 0, Math.PI*2, true ); + smileyShape.holes.push( smileyEye2Path ); + + var smileyMouthPath = new THREE.Path(); + // ugly box mouth + // smileyMouthPath.moveTo( 20, 40 ); + // smileyMouthPath.lineTo( 60, 40 ); + // smileyMouthPath.lineTo( 60, 60 ); + // smileyMouthPath.lineTo( 20, 60 ); + // smileyMouthPath.lineTo( 20, 40 ); + + smileyMouthPath.moveTo( 20, 40 ); + smileyMouthPath.quadraticCurveTo( 40, 60, 60, 40 ); + smileyMouthPath.bezierCurveTo( 70, 45, 70, 50, 60, 60 ); + smileyMouthPath.quadraticCurveTo( 40, 80, 20, 60 ); + smileyMouthPath.quadraticCurveTo( 5, 50, 20, 40 ); + + smileyShape.holes.push( smileyMouthPath ); + + + // Spline shape + path extrusion + + var splinepts = []; + splinepts.push( new THREE.Vector2 ( 350, 100 ) ); + splinepts.push( new THREE.Vector2 ( 400, 450 ) ); + splinepts.push( new THREE.Vector2 ( -140, 350 ) ); + splinepts.push( new THREE.Vector2 ( 0, 0 ) ); + + var splineShape = new THREE.Shape( ); + splineShape.moveTo( 0, 0 ); + splineShape.splineThru( splinepts ); + + // splineShape.debug( document.getElementById("debug") ); + + // TODO 3d path? + + var apath = new THREE.SplineCurve3(); + apath.points.push(new THREE.Vector3(-50, 150, 10)); + apath.points.push(new THREE.Vector3(-20, 180, 20)); + apath.points.push(new THREE.Vector3(40, 220, 50)); + apath.points.push(new THREE.Vector3(200, 290, 100)); + + + var extrudeSettings:any = { amount: 20 }; // bevelSegments: 2, steps: 2 , bevelSegments: 5, bevelSize: 8, bevelThickness:5 + + // addShape( shape, color, x, y, z, rx, ry,rz, s ); + + addShape( californiaShape, extrudeSettings, 0xffaa00, -300, -100, 0, 0, 0, 0, 0.25 ); + + extrudeSettings.bevelEnabled = true; + extrudeSettings.bevelSegments = 2; + extrudeSettings.steps = 2; + + addShape( triangleShape, extrudeSettings, 0xffee00, -180, 0, 0, 0, 0, 0, 1 ); + addShape( roundedRectShape, extrudeSettings, 0x005500, -150, 150, 0, 0, 0, 0, 1 ); + addShape( squareShape, extrudeSettings, 0x0055ff, 150, 100, 0, 0, 0, 0, 1 ); + addShape( heartShape, extrudeSettings, 0xff1100, 60, 100, 0, 0, 0, Math.PI, 1 ); + addShape( circleShape, extrudeSettings, 0x00ff11, 120, 250, 0, 0, 0, 0, 1 ); + addShape( fishShape, extrudeSettings, 0x222222, -60, 200, 0, 0, 0, 0, 1 ); + addShape( smileyShape, extrudeSettings, 0xee00ff, -200, 250, 0, 0, 0, Math.PI, 1 ); + addShape( arcShape, extrudeSettings, 0xbb4422, 150, 0, 0, 0, 0, 0, 1 ); + + extrudeSettings.extrudePath = apath; + extrudeSettings.bevelEnabled = false; + extrudeSettings.steps = 20; + + addShape( splineShape, extrudeSettings, 0x888888, -50, -100, -50, 0, 0, 0, 0.2 ); + + // + + renderer = new THREE.WebGLRenderer( { antialias: true } ); + 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 ); + + } + + // + + function onDocumentMouseDown( event ) { + + event.preventDefault(); + + document.addEventListener( 'mousemove', onDocumentMouseMove, false ); + document.addEventListener( 'mouseup', onDocumentMouseUp, false ); + document.addEventListener( 'mouseout', onDocumentMouseOut, false ); + + mouseXOnMouseDown = event.clientX - windowHalfX; + targetRotationOnMouseDown = targetRotation; + + } + + function onDocumentMouseMove( event ) { + + mouseX = event.clientX - windowHalfX; + + targetRotation = targetRotationOnMouseDown + ( mouseX - mouseXOnMouseDown ) * 0.02; + + } + + function onDocumentMouseUp( event ) { + + document.removeEventListener( 'mousemove', onDocumentMouseMove, false ); + document.removeEventListener( 'mouseup', onDocumentMouseUp, false ); + document.removeEventListener( 'mouseout', onDocumentMouseOut, false ); + + } + + function onDocumentMouseOut( event ) { + + document.removeEventListener( 'mousemove', onDocumentMouseMove, false ); + document.removeEventListener( 'mouseup', onDocumentMouseUp, false ); + document.removeEventListener( 'mouseout', onDocumentMouseOut, false ); + + } + + 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() { + + parent.rotation.y += ( targetRotation - parent.rotation.y ) * 0.05; + renderer.render( scene, camera ); + + } + +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/webgl_geometry_subdivision.html + +()=>{ + + var container, stats; + + var camera, scene, renderer; + + var cube, plane; + + var targetYRotation = 0; + var targetXRotation = 0; + var targetYRotationOnMouseDown = 0; + var targetXRotationOnMouseDown = 0; + var targetRotationOnMouseDown = 0; + var targetRotation = 0; + + var mouseX = 0, mouseY = 0; + var mouseXOnMouseDown = 0; + var mouseYOnMouseDown = 0; + + var windowHalfX = window.innerWidth / 2; + var windowHalfY = window.innerHeight / 2; + + var scene, group, cube, geometry, smooth; + + + // Create new object by parameters + + var createSomething = function( klass, args ) { + + var F = function( klass, args ) { + + return klass.apply( this, args ); + + } + + F.prototype = klass.prototype; + + return new F( klass, args ); + + }; + + + // Cube + + var materials = []; + + for ( var i = 0; i < 6; i ++ ) { + + materials.push( [ new THREE.MeshBasicMaterial( { color: Math.random() * 0xffffff, wireframe: false } ) ] ); + + } + + + + var geometriesParams:{type:string;args:any[];}[] = [ + + { type: 'CubeGeometry', args: [ 200, 200, 200, 2, 2, 2, materials ] }, + { type: 'TorusGeometry', args: [ 100, 60, 4, 8, Math.PI*2 ] }, + { type: 'TorusKnotGeometry', args: [ ], scale:0.25, meshScale:4 }, + { type: 'SphereGeometry', args: [ 100, 3, 3 ], meshScale:2 }, + { type: 'IcosahedronGeometry', args: [ 100, 1 ], meshScale:2 }, + { type: 'CylinderGeometry', args: [ 25, 75, 200, 8, 3 ]} , + { type: 'OctahedronGeometry', args: [200, 0], meshScale:2 }, + { type: 'LatheGeometry', args: [ [ + new THREE.Vector3(0,0,0), + new THREE.Vector3(0,50,50), + new THREE.Vector3(0,10,100), + new THREE.Vector3(0,50,150), + new THREE.Vector3(0,0,200) ] ]}, + { type: 'TextGeometry', args: ['&', { + size: 200, + height: 50, + curveSegments: 1, + font: "helvetiker" + + }]}, + { type: 'PlaneGeometry', args: [ 200, 200, 4, 4 ] } + + ]; + + var loader = new THREE.JSONLoader(); + loader.load( 'obj/WaltHeadLo.js', function ( geometry ) { + + geometriesParams.push({type: 'WaltHead', args: [ ], meshScale: 6 }); + + THREE["WaltHead"] = function() { + return geometry.clone(); + }; + + updateInfo() + + }); + + var loader2 = new THREE.JSONLoader(); + loader2.load( 'obj/Suzanne.js', function ( geometry ) { + + geometriesParams.push({type: 'Suzanne', args: [ ], scale: 100, meshScale:2 }); + + THREE["Suzanne"] = function() { + return geometry.clone(); + }; + + updateInfo() + + } ); + + + var info; + var subdivisions = 2; + var geometryIndex = 0; + + // start scene + + init(); + animate(); + + function nextSubdivision( x ) { + + subdivisions = Math.max( 0, subdivisions + x ); + addStuff(); + + } + + function nextGeometry() { + + geometryIndex ++; + + if ( geometryIndex > geometriesParams.length - 1 ) { + + geometryIndex = 0; + + } + + addStuff(); + + } + + function switchGeometry(i) { + + geometryIndex = i; + + addStuff(); + } + + function updateInfo() { + + var params = geometriesParams[ geometryIndex ]; + + var dropdown = ''; + + info.innerHTML = 'Drag to spin THREE.' + params.type + + + '

Subdivisions: ' + subdivisions + + ' more/less' + + '
Geometry: ' + dropdown + ' next' + + '

Vertices count: before ' + geometry.vertices.length + ' after ' + smooth.vertices.length + + '
Face count: before ' + geometry.faces.length + ' after ' + smooth.faces.length + ; //+ params.args; + } + + function addStuff() { + + if ( cube ) { + + scene.remove( group ); + scene.remove( cube ); + + } + + + var modifier = new THREE.SubdivisionModifier( subdivisions ); + + + var params:any = geometriesParams[ geometryIndex ]; + + geometry = createSomething( THREE[ params.type ], params.args ); + + // Scale Geometry + + if ( params.scale ) { + + geometry.applyMatrix( new THREE.Matrix4().makeScale( params.scale, params.scale, params.scale ) ); + + } + + // Cloning original geometry for debuging + + var smooth = geometry.clone(); + + // mergeVertices(); is run in case of duplicated vertices + smooth.mergeVertices(); + + smooth.computeCentroids(); + smooth.computeFaceNormals(); + smooth.computeVertexNormals(); + + modifier.modify( smooth ); + + updateInfo(); + + var faceABCD = "abcd"; + var color, f, p, n, vertexIndex; + + for ( i = 0; i < smooth.faces.length; i ++ ) { + + f = smooth.faces[ i ]; + + + n = ( f instanceof THREE.Face3 ) ? 3 : 4; + + for( var j = 0; j < n; j++ ) { + + vertexIndex = f[ faceABCD.charAt( j ) ]; + + p = smooth.vertices[ vertexIndex ]; + + color = new THREE.Color( 0xffffff ); + color.setHSL( ( p.y ) / 200 + 0.5, 1.0, 1.0 ); + + f.vertexColors[ j ] = color; + + } + + } + + + group = new THREE.Object3D(); + group.add( new THREE.Mesh( geometry, new THREE.MeshBasicMaterial( { color: 0xfefefe, wireframe: true, opacity: 0.5 } ) ) ); + scene.add( group ); + + + var debugNewPoints = false; + var debugOldPoints = false; + + // Debug new Points + + if (debugNewPoints) { + var PI2 = Math.PI * 2; + var program = function ( context ) { + + context.beginPath(); + context.arc( 0, 0, 1, 0, PI2, true ); + context.closePath(); + context.fill(); + + } + + for ( var i = 0; i < smooth.vertices.length; i++ ) { + + var particle = new THREE.Particle( new THREE.ParticleCanvasMaterial( { color: Math.random() * 0x808008 + 0x808080, program: program } ) ); + particle.position = smooth.vertices[ i ]; + var pos = smooth.vertices.position + particle.scale.x = particle.scale.y = 5; + group.add( particle ); + } + + } + + + //Debug original points + + if (debugOldPoints) { + + var drawText = function(i) { + + return function ( context ) { + + context.beginPath(); + context.scale(0.1,-0.1); + + context.fillText(i, 0,0); + + }; + + } + + for ( var i = 0; i < geometry.vertices.length; i++ ) { + + particle = new THREE.Particle( new THREE.ParticleCanvasMaterial( { color: Math.random() * 0x808008 + 0x808080, program: drawText(i) } ) ); + particle.position = smooth.vertices[ i ]; + var pos = geometry.vertices.position + particle.scale.x = particle.scale.y = 30; + group.add( particle ); + } + } + + + var meshmaterials:THREE.Material[] = [ + new THREE.MeshLambertMaterial( { color: 0xffffff, shading: THREE.FlatShading, vertexColors: THREE.VertexColors } ), + new THREE.MeshBasicMaterial( { color: 0x405040, wireframe: true, opacity: 0.8, transparent: true } ) + ]; + + cube = THREE.SceneUtils.createMultiMaterialObject( smooth, meshmaterials ); + + var meshScale = params.meshScale ? params.meshScale : 1; + + cube.scale.x = meshScale; + cube.scale.y = meshScale; + cube.scale.z = meshScale; + + scene.add( cube ); + + group.scale.copy( cube.scale ); + + } + + function init() { + + container = document.createElement( 'div' ); + document.body.appendChild( container ); + + info = document.createElement( 'div' ); + info.style.position = 'absolute'; + info.style.top = '10px'; + info.style.width = '100%'; + info.style.textAlign = 'center'; + info.innerHTML = 'Drag to spin the geometry '; + container.appendChild( info ); + + camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 ); + camera.position.z = 500; + + scene = new THREE.Scene(); + + var light = new THREE.PointLight( 0xffffff, 1.5 ); + light.position.set( 1000, 1000, 2000 ); + scene.add( light ); + + addStuff(); + + renderer = new THREE.WebGLRenderer( { antialias: true } ); // WebGLRenderer CanvasRenderer + 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 ); + + } + + // + + function onDocumentMouseDown( event ) { + + //event.preventDefault(); + + document.addEventListener( 'mousemove', onDocumentMouseMove, false ); + document.addEventListener( 'mouseup', onDocumentMouseUp, false ); + document.addEventListener( 'mouseout', onDocumentMouseOut, false ); + + mouseXOnMouseDown = event.clientX - windowHalfX; + mouseYOnMouseDown = event.clientY - windowHalfY; + targetYRotationOnMouseDown = targetYRotation; + targetXRotationOnMouseDown = targetXRotation; + + } + + function onDocumentMouseMove( event ) { + + mouseX = event.clientX - windowHalfX; + mouseY = event.clientY - windowHalfY; + + targetYRotation = targetYRotationOnMouseDown + ( mouseX - mouseXOnMouseDown ) * 0.02; + targetXRotation = targetXRotationOnMouseDown + ( mouseY - mouseYOnMouseDown ) * 0.02; + + } + + function onDocumentMouseUp( event ) { + + document.removeEventListener( 'mousemove', onDocumentMouseMove, false ); + document.removeEventListener( 'mouseup', onDocumentMouseUp, false ); + document.removeEventListener( 'mouseout', onDocumentMouseOut, false ); + } + + function onDocumentMouseOut( event ) { + + document.removeEventListener( 'mousemove', onDocumentMouseMove, false ); + document.removeEventListener( 'mouseup', onDocumentMouseUp, false ); + document.removeEventListener( 'mouseout', onDocumentMouseOut, false ); + } + + 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() { + + group.rotation.x = cube.rotation.x += ( targetXRotation - cube.rotation.x ) * 0.05; + group.rotation.y = cube.rotation.y += ( targetYRotation - cube.rotation.y ) * 0.05; + + renderer.render( scene, camera ); + + } +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/webgl_geometry_terrain.html + +()=>{ + + if ( ! Detector.webgl ) { + + Detector.addGetWebGLMessage(); + document.getElementById( 'container' ).innerHTML = ""; + + } + + var container, stats; + + var camera, controls, scene, renderer; + + var mesh, texture; + + var worldWidth = 256, worldDepth = 256, + worldHalfWidth = worldWidth / 2, worldHalfDepth = worldDepth / 2; + + var clock = new THREE.Clock(); + + var data; + + init(); + animate(); + + function init() { + + container = document.getElementById( 'container' ); + + camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 20000 ); + + scene = new THREE.Scene(); + + controls = new THREE.FirstPersonControls( camera ); + controls.movementSpeed = 1000; + controls.lookSpeed = 0.1; + + data = generateHeight( worldWidth, worldDepth ); + + camera.position.y = data[ worldHalfWidth + worldHalfDepth * worldWidth ] + 500; + + var geometry = new THREE.PlaneGeometry( 7500, 7500, worldWidth - 1, worldDepth - 1 ); + geometry.applyMatrix( new THREE.Matrix4().makeRotationX( - Math.PI / 2 ) ); + + for ( var i = 0, l = geometry.vertices.length; i < l; i ++ ) { + + geometry.vertices[ i ].y = data[ i ] * 10; + + } + + texture = new THREE.Texture( generateTexture( data, worldWidth, worldDepth ), new THREE.UVMapping(), THREE.ClampToEdgeWrapping, THREE.ClampToEdgeWrapping ); + texture.needsUpdate = true; + + mesh = new THREE.Mesh( geometry, new THREE.MeshBasicMaterial( { map: texture } ) ); + scene.add( mesh ); + + renderer = new THREE.WebGLRenderer(); + renderer.setSize( window.innerWidth, window.innerHeight ); + + container.innerHTML = ""; + + container.appendChild( renderer.domElement ); + + stats = new Stats(); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.top = '0px'; + container.appendChild( stats.domElement ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + controls.handleResize(); + + } + + function generateHeight( width, height ) { + + var size = width * height, data = new Float32Array( size ), + perlin = new ImprovedNoise(), quality = 1, z = Math.random() * 100; + + for ( var i = 0; i < size; i ++ ) { + + data[ i ] = 0 + + } + + for ( var j = 0; j < 4; j ++ ) { + + for ( var i = 0; i < size; i ++ ) { + + var x = i % width, y = ~~ ( i / width ); + data[ i ] += Math.abs( perlin.noise( x / quality, y / quality, z ) * quality * 1.75 ); + + + } + + quality *= 5; + + } + + return data; + + } + + function generateTexture( data, width, height ) { + + var canvas, canvasScaled, context, image, imageData, + level, diff, vector3, sun, shade; + + vector3 = new THREE.Vector3( 0, 0, 0 ); + + sun = new THREE.Vector3( 1, 1, 1 ); + sun.normalize(); + + canvas = document.createElement( 'canvas' ); + canvas.width = width; + canvas.height = height; + + context = canvas.getContext( '2d' ); + context.fillStyle = '#000'; + context.fillRect( 0, 0, width, height ); + + image = context.getImageData( 0, 0, canvas.width, canvas.height ); + imageData = image.data; + + for ( var i = 0, j = 0, l = imageData.length; i < l; i += 4, j ++ ) { + + vector3.x = data[ j - 2 ] - data[ j + 2 ]; + vector3.y = 2; + vector3.z = data[ j - width * 2 ] - data[ j + width * 2 ]; + vector3.normalize(); + + shade = vector3.dot( sun ); + + imageData[ i ] = ( 96 + shade * 128 ) * ( 0.5 + data[ j ] * 0.007 ); + imageData[ i + 1 ] = ( 32 + shade * 96 ) * ( 0.5 + data[ j ] * 0.007 ); + imageData[ i + 2 ] = ( shade * 96 ) * ( 0.5 + data[ j ] * 0.007 ); + } + + context.putImageData( image, 0, 0 ); + + // Scaled 4x + + canvasScaled = document.createElement( 'canvas' ); + canvasScaled.width = width * 4; + canvasScaled.height = height * 4; + + context = canvasScaled.getContext( '2d' ); + context.scale( 4, 4 ); + context.drawImage( canvas, 0, 0 ); + + image = context.getImageData( 0, 0, canvasScaled.width, canvasScaled.height ); + imageData = image.data; + + for ( var i = 0, l = imageData.length; i < l; i += 4 ) { + + var v = ~~ ( Math.random() * 5 ); + + imageData[ i ] += v; + imageData[ i + 1 ] += v; + imageData[ i + 2 ] += v; + + } + + context.putImageData( image, 0, 0 ); + + return canvasScaled; + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + controls.update( clock.getDelta() ); + renderer.render( scene, camera ); + + } + +}; + + +// https://github.com/mrdoob/three.js/blob/master/examples/webgl_geometry_terrain_fog.html + +()=>{ + + if ( ! Detector.webgl ) { + + Detector.addGetWebGLMessage(); + document.getElementById( 'container' ).innerHTML = ""; + + } + + var container, stats; + + var camera, controls, scene, renderer; + + var mesh, texture; + + var worldWidth = 256, worldDepth = 256, + worldHalfWidth = worldWidth / 2, worldHalfDepth = worldDepth / 2; + + var clock = new THREE.Clock(); + + var data; + + init(); + animate(); + + function init() { + + container = document.getElementById( 'container' ); + + camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 10000 ); + + controls = new THREE.FirstPersonControls( camera ); + controls.movementSpeed = 150; + controls.lookSpeed = 0.1; + + scene = new THREE.Scene(); + scene.fog = new THREE.FogExp2( 0xefd1b5, 0.0025 ); + + data = generateHeight( worldWidth, worldDepth ); + + camera.position.y = data[ worldHalfWidth + worldHalfDepth * worldWidth ] * 10 + 500; + + var geometry = new THREE.PlaneGeometry( 7500, 7500, worldWidth - 1, worldDepth - 1 ); + geometry.applyMatrix( new THREE.Matrix4().makeRotationX( - Math.PI / 2 ) ); + + for ( var i = 0, l = geometry.vertices.length; i < l; i ++ ) { + + geometry.vertices[ i ].y = data[ i ] * 10; + + } + + texture = new THREE.Texture( generateTexture( data, worldWidth, worldDepth ), new THREE.UVMapping(), THREE.ClampToEdgeWrapping, THREE.ClampToEdgeWrapping ); + texture.needsUpdate = true; + + mesh = new THREE.Mesh( geometry, new THREE.MeshBasicMaterial( { map: texture } ) ); + scene.add( mesh ); + + renderer = new THREE.WebGLRenderer( { clearColor: 0xefd1b5, clearAlpha: 1 } ); + renderer.setSize( window.innerWidth, window.innerHeight ); + + container.innerHTML = ""; + + container.appendChild( renderer.domElement ); + + stats = new Stats(); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.top = '0px'; + container.appendChild( stats.domElement ); + + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + controls.handleResize(); + + } + + function generateHeight( width, height ) { + + var size = width * height, data = new Float32Array( size ), + perlin = new ImprovedNoise(), quality = 1, z = Math.random() * 100; + + for ( var i = 0; i < size; i ++ ) { + + data[ i ] = 0 + + } + + for ( var j = 0; j < 4; j ++ ) { + + for ( var i = 0; i < size; i ++ ) { + + var x = i % width, y = ~~ ( i / width ); + data[ i ] += Math.abs( perlin.noise( x / quality, y / quality, z ) * quality * 1.75 ); + + + } + + quality *= 5; + + } + + return data; + + } + + function generateTexture( data, width, height ) { + + var canvas, canvasScaled, context, image, imageData, + level, diff, vector3, sun, shade; + + vector3 = new THREE.Vector3( 0, 0, 0 ); + + sun = new THREE.Vector3( 1, 1, 1 ); + sun.normalize(); + + canvas = document.createElement( 'canvas' ); + canvas.width = width; + canvas.height = height; + + context = canvas.getContext( '2d' ); + context.fillStyle = '#000'; + context.fillRect( 0, 0, width, height ); + + image = context.getImageData( 0, 0, canvas.width, canvas.height ); + imageData = image.data; + + for ( var i = 0, j = 0, l = imageData.length; i < l; i += 4, j ++ ) { + + vector3.x = data[ j - 2 ] - data[ j + 2 ]; + vector3.y = 2; + vector3.z = data[ j - width * 2 ] - data[ j + width * 2 ]; + vector3.normalize(); + + shade = vector3.dot( sun ); + + imageData[ i ] = ( 96 + shade * 128 ) * ( 0.5 + data[ j ] * 0.007 ); + imageData[ i + 1 ] = ( 32 + shade * 96 ) * ( 0.5 + data[ j ] * 0.007 ); + imageData[ i + 2 ] = ( shade * 96 ) * ( 0.5 + data[ j ] * 0.007 ); + + } + + context.putImageData( image, 0, 0 ); + + // Scaled 4x + + canvasScaled = document.createElement( 'canvas' ); + canvasScaled.width = width * 4; + canvasScaled.height = height * 4; + + context = canvasScaled.getContext( '2d' ); + context.scale( 4, 4 ); + context.drawImage( canvas, 0, 0 ); + + image = context.getImageData( 0, 0, canvasScaled.width, canvasScaled.height ); + imageData = image.data; + + for ( var i = 0, l = imageData.length; i < l; i += 4 ) { + + var v = ~~ ( Math.random() * 5 ); + + imageData[ i ] += v; + imageData[ i + 1 ] += v; + imageData[ i + 2 ] += v; + + } + + context.putImageData( image, 0, 0 ); + + return canvasScaled; + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + + function render() { + + controls.update( clock.getDelta() ); + renderer.render( scene, camera ); + + } +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/webgl_geometry_tessellation.html + +()=>{ + + if ( ! Detector.webgl ) Detector.addGetWebGLMessage(); + + var renderer, scene, camera, stats; + + var mesh, uniforms, attributes; + + var WIDTH = window.innerWidth, + HEIGHT = window.innerHeight; + + var controls; + + init(); + animate(); + + function init() { + + camera = new THREE.PerspectiveCamera( 25, WIDTH / HEIGHT, 1, 10000 ); + camera.position.z = 350; + + controls = new THREE.TrackballControls( camera ); + + scene = new THREE.Scene(); + + // + + attributes = { + + displacement: { type: 'v3', value: [] }, + customColor: { type: 'c', value: [] } + + }; + + uniforms = { + + amplitude: { type: "f", value: 0.0 } + + }; + + var shaderMaterial = new THREE.ShaderMaterial( { + + uniforms: uniforms, + attributes: attributes, + vertexShader: document.getElementById( 'vertexshader' ).textContent, + fragmentShader: document.getElementById( 'fragmentshader' ).textContent, + shading: THREE.FlatShading, + side: THREE.DoubleSide + + }); + + + var geometry = new THREE.TextGeometry( "THREE.JS", { + + size: 40, + height: 5, + curveSegments: 3, + + font: "helvetiker", + weight: "bold", + style: "normal", + + bevelThickness: 2, + bevelSize: 1, + bevelEnabled: true + + }); + + geometry.dynamic = true; + + THREE.GeometryUtils.center( geometry ); + + var tessellateModifier = new THREE.TessellateModifier( 4 ); + + for ( var i = 0; i < 6; i ++ ) { + + tessellateModifier.modify( geometry ); + + } + + var explodeModifier = new THREE.ExplodeModifier(); + explodeModifier.modify( geometry ); + + var vertices = geometry.vertices; + + var colors = attributes.customColor.value; + var displacement = attributes.displacement.value; + + var h, d, x, y, z, s; + var nv, v = 0; + + for( var f = 0; f < geometry.faces.length; f ++ ) { + + var face = geometry.faces[ f ]; + + if ( face instanceof THREE.Face3 ) { + + nv = 3; + + } else { + + nv = 4; + + } + + h = 0.15 * Math.random(); + s = 0.7 * Math.random(); + + d = 10 * ( 0.5 - Math.random() ); + + x = 2 * ( 0.5 - Math.random() ); + y = 2 * ( 0.5 - Math.random() ); + z = 2 * ( 0.5 - Math.random() ); + + for ( var i = 0; i < nv; i ++ ) { + + colors[ v ] = new THREE.Color(); + displacement[ v ] = new THREE.Vector3(); + + colors[ v ].setHSL( h, s, 1 ); + colors[ v ].convertGammaToLinear(); + + displacement[ v ].set( x, y, z ); + + v += 1; + + } + + } + + console.log( "faces", geometry.faces.length ); + + mesh = new THREE.Mesh( geometry, shaderMaterial ); + mesh.rotation.set( 0.5, 0.5, 0 ); + + scene.add( mesh ); + + renderer = new THREE.WebGLRenderer( { clearColor: 0x050505, clearAlpha: 1, antialias: true } ); + renderer.setSize( WIDTH, HEIGHT ); + + var container = document.getElementById( 'container' ); + container.appendChild( renderer.domElement ); + + stats = new Stats(); + container.appendChild( stats.domElement ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + } + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + var time = Date.now() * 0.001; + + uniforms.amplitude.value = 0.125 * Math.sin( time * 0.5 ); + + controls.update(); + renderer.render( scene, camera ); + + } + +}; + +// https://github.com/mrdoob/three.js/blob/master/examples/webgl_geometry_text.html + +()=>{ + + if ( ! Detector.webgl ) Detector.addGetWebGLMessage(); + + var container, stats, permalink, hex, color; + + var camera, cameraTarget, scene, renderer; + + var composer; + var effectFXAA; + + var textMesh1, textMesh2, textGeo, material, parent; + + var firstLetter = true; + + var text = "three.js", + + height = 20, + size = 70, + hover = 30, + + curveSegments = 4, + + bevelThickness = 2, + bevelSize = 1.5, + bevelSegments = 3, + bevelEnabled = true, + + font = "optimer", // helvetiker, optimer, gentilis, droid sans, droid serif + weight = "bold", // normal bold + style = "normal"; // normal italic + + var mirror = true; + + var fontMap = { + + "helvetiker": 0, + "optimer": 1, + "gentilis": 2, + "droid sans": 3, + "droid serif": 4 + + }; + + var weightMap = { + + "normal": 0, + "bold": 1 + + }; + + var reverseFontMap = {}; + var reverseWeightMap = {}; + + for ( var i in fontMap ) reverseFontMap[ fontMap[i] ] = i; + for ( var i in weightMap ) reverseWeightMap[ weightMap[i] ] = i; + + var targetRotation = 0; + var targetRotationOnMouseDown = 0; + + var mouseX = 0; + var mouseXOnMouseDown = 0; + + var windowHalfX = window.innerWidth / 2; + var windowHalfY = window.innerHeight / 2; + + var postprocessing = { enabled : false }; + var glow = 0.9; + + init(); + animate(); + + function capitalize( txt ) { + + return txt.substring( 0, 1 ).toUpperCase() + txt.substring( 1 ); + + } + + function decimalToHex( d ) { + + var hex = Number( d ).toString( 16 ); + hex = "000000".substr( 0, 6 - hex.length ) + hex; + return hex.toUpperCase(); + + } + + function init() { + + container = document.createElement( 'div' ); + document.body.appendChild( container ); + + permalink = document.getElementById( "permalink" ); + + // CAMERA + + camera = new THREE.PerspectiveCamera( 30, window.innerWidth / window.innerHeight, 1, 1500 ); + camera.position.set( 0, 400, 700 ); + + cameraTarget = new THREE.Vector3( 0, 150, 0 ); + + // SCENE + + scene = new THREE.Scene(); + scene.fog = new THREE.Fog( 0x000000, 250, 1400 ); + + // LIGHTS + + var dirLight = new THREE.DirectionalLight( 0xffffff, 0.125 ); + dirLight.position.set( 0, 0, 1 ).normalize(); + scene.add( dirLight ); + + var pointLight = new THREE.PointLight( 0xffffff, 1.5 ); + pointLight.position.set( 0, 100, 90 ); + scene.add( pointLight ); + + //text = capitalize( font ) + " " + capitalize( weight ); + //text = "abcdefghijklmnopqrstuvwxyz0123456789"; + //text = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + + // Get text from hash + + var hash = document.location.hash.substr( 1 ); + + if ( hash.length !== 0 ) { + + var colorhash = hash.substring( 0, 6 ); + var fonthash = hash.substring( 6, 7 ); + var weighthash = hash.substring( 7, 8 ); + var pphash = hash.substring( 8, 9 ); + var bevelhash = hash.substring( 9, 10 ); + var texthash = hash.substring( 10 ); + + hex = colorhash; + pointLight.color.setHex( parseInt( colorhash, 16 ) ); + + font = reverseFontMap[ parseInt( fonthash ) ]; + weight = reverseWeightMap[ parseInt( weighthash ) ]; + + postprocessing.enabled = parseInt( pphash ) ? true : false; + bevelEnabled = parseInt( bevelhash ) ? true : false; + + text = decodeURI( texthash ); + + updatePermalink(); + + } else { + + pointLight.color.setHSL( Math.random(), 0.95, 0.85 ); + hex = decimalToHex( pointLight.color.getHex() ); + + } + + material = new THREE.MeshFaceMaterial( [ + new THREE.MeshPhongMaterial( { color: 0xffffff, shading: THREE.FlatShading } ), // front + new THREE.MeshPhongMaterial( { color: 0xffffff, shading: THREE.SmoothShading } ) // side + ] ); + + parent = new THREE.Object3D(); + parent.position.y = 100; + + scene.add( parent ); + + createText(); + + var plane = new THREE.Mesh( new THREE.PlaneGeometry( 10000, 10000 ), new THREE.MeshBasicMaterial( { color: 0xffffff, opacity: 0.5, transparent: true } ) ); + plane.position.y = 100; + plane.rotation.x = - Math.PI / 2; + scene.add( plane ); + + // RENDERER + + renderer = new THREE.WebGLRenderer( { antialias: true } ); + renderer.setSize( window.innerWidth, window.innerHeight ); + + renderer.setClearColor( scene.fog.color, 1 ); + + container.appendChild( renderer.domElement ); + + // STATS + + stats = new Stats(); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.top = '0px'; + //container.appendChild( stats.domElement ); + + // EVENTS + + document.addEventListener( 'mousedown', onDocumentMouseDown, false ); + document.addEventListener( 'touchstart', onDocumentTouchStart, false ); + document.addEventListener( 'touchmove', onDocumentTouchMove, false ); + document.addEventListener( 'keypress', onDocumentKeyPress, false ); + document.addEventListener( 'keydown', onDocumentKeyDown, false ); + + document.getElementById( "color" ).addEventListener( 'click', function() { + + pointLight.color.setHSL( Math.random(), 0.95, 0.85 ); + hex = decimalToHex( pointLight.color.getHex() ); + + updatePermalink(); + + }, false ); + + document.getElementById( "font" ).addEventListener( 'click', function() { + + if ( font == "helvetiker" ) { + + font = "optimer"; + + } else if ( font == "optimer" ) { + + font = "gentilis"; + + } else if ( font == "gentilis" ) { + + font = "droid sans"; + + } else if ( font == "droid sans" ) { + + font = "droid serif"; + + } else { + + font = "helvetiker"; + + } + + refreshText(); + + }, false ); + + document.getElementById( "weight" ).addEventListener( 'click', function() { + + if ( weight == "bold" ) { + + weight = "normal"; + + } else { + + weight = "bold"; + + } + + refreshText(); + + }, false ); + + document.getElementById( "bevel" ).addEventListener( 'click', function() { + + bevelEnabled = !bevelEnabled; + + refreshText(); + + }, false ); + + document.getElementById( "postprocessing" ).addEventListener( 'click', function() { + + postprocessing.enabled = !postprocessing.enabled; + updatePermalink(); + + }, false ); + + + // POSTPROCESSING + + renderer.autoClear = false; + + var renderModel = new THREE.RenderPass( scene, camera ); + var effectBloom = new THREE.BloomPass( 0.25 ); + var effectFilm = new THREE.FilmPass( 0.5, 0.125, 2048, false ); + + effectFXAA = new THREE.ShaderPass( THREE.FXAAShader ); + + var width = window.innerWidth || 2; + var height = window.innerHeight || 2; + + effectFXAA.uniforms[ 'resolution' ].value.set( 1 / width, 1 / height ); + + effectFilm.renderToScreen = true; + + composer = new THREE.EffectComposer( renderer ); + + composer.addPass( renderModel ); + composer.addPass( effectFXAA ); + composer.addPass( effectBloom ); + composer.addPass( effectFilm ); + + // + + 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 ); + + composer.reset(); + + effectFXAA.uniforms[ 'resolution' ].value.set( 1 / window.innerWidth, 1 / window.innerHeight ); + + } + + // + + function boolToNum( b ) { + + return b ? 1 : 0; + + } + + function updatePermalink() { + + var link = hex + fontMap[ font ] + weightMap[ weight ] + boolToNum( postprocessing.enabled ) + boolToNum( bevelEnabled ) + "#" + encodeURI( text ); + + permalink.href = "#" + link; + window.location.hash = link; + + } + + function onDocumentKeyDown( event ) { + + if ( firstLetter ) { + + firstLetter = false; + text = ""; + + } + + var keyCode = event.keyCode; + + // backspace + + if ( keyCode == 8 ) { + + event.preventDefault(); + + text = text.substring( 0, text.length - 1 ); + refreshText(); + + return false; + + } + + } + + function onDocumentKeyPress( event ) { + + var keyCode = event.which; + + // backspace + + if ( keyCode == 8 ) { + + event.preventDefault(); + + } else { + + var ch = String.fromCharCode( keyCode ); + text += ch; + + refreshText(); + + } + + } + + function createText() { + + textGeo = new THREE.TextGeometry( text, { + + size: size, + height: height, + curveSegments: curveSegments, + + font: font, + weight: weight, + style: style, + + bevelThickness: bevelThickness, + bevelSize: bevelSize, + bevelEnabled: bevelEnabled, + + material: 0, + extrudeMaterial: 1 + + }); + + textGeo.computeBoundingBox(); + textGeo.computeVertexNormals(); + + // "fix" side normals by removing z-component of normals for side faces + // (this doesn't work well for beveled geometry as then we lose nice curvature around z-axis) + + if ( ! bevelEnabled ) { + + var triangleAreaHeuristics = 0.1 * ( height * size ); + + for ( var i = 0; i < textGeo.faces.length; i ++ ) { + + var face = textGeo.faces[ i ]; + + if ( face.materialIndex == 1 ) { + + for ( var j = 0; j < face.vertexNormals.length; j ++ ) { + + face.vertexNormals[ j ].z = 0; + face.vertexNormals[ j ].normalize(); + + } + + var va = textGeo.vertices[ face.a ]; + var vb = textGeo.vertices[ face.b ]; + var vc = textGeo.vertices[ face.c ]; + + var s = THREE.GeometryUtils.triangleArea( va, vb, vc ); + + if ( s > triangleAreaHeuristics ) { + + for ( var j = 0; j < face.vertexNormals.length; j ++ ) { + + face.vertexNormals[ j ].copy( face.normal ); + + } + + } + + } + + } + + } + + var centerOffset = -0.5 * ( textGeo.boundingBox.max.x - textGeo.boundingBox.min.x ); + + textMesh1 = new THREE.Mesh( textGeo, material ); + + textMesh1.position.x = centerOffset; + textMesh1.position.y = hover; + textMesh1.position.z = 0; + + textMesh1.rotation.x = 0; + textMesh1.rotation.y = Math.PI * 2; + + parent.add( textMesh1 ); + + if ( mirror ) { + + textMesh2 = new THREE.Mesh( textGeo, material ); + + textMesh2.position.x = centerOffset; + textMesh2.position.y = -hover; + textMesh2.position.z = height; + + textMesh2.rotation.x = Math.PI; + textMesh2.rotation.y = Math.PI * 2; + + parent.add( textMesh2 ); + + } + + } + + function refreshText() { + + updatePermalink(); + + parent.remove( textMesh1 ); + if ( mirror ) parent.remove( textMesh2 ); + + if ( !text ) return; + + createText(); + + } + + function onDocumentMouseDown( event ) { + + event.preventDefault(); + + document.addEventListener( 'mousemove', onDocumentMouseMove, false ); + document.addEventListener( 'mouseup', onDocumentMouseUp, false ); + document.addEventListener( 'mouseout', onDocumentMouseOut, false ); + + mouseXOnMouseDown = event.clientX - windowHalfX; + targetRotationOnMouseDown = targetRotation; + + } + + function onDocumentMouseMove( event ) { + + mouseX = event.clientX - windowHalfX; + + targetRotation = targetRotationOnMouseDown + ( mouseX - mouseXOnMouseDown ) * 0.02; + + } + + function onDocumentMouseUp( event ) { + + document.removeEventListener( 'mousemove', onDocumentMouseMove, false ); + document.removeEventListener( 'mouseup', onDocumentMouseUp, false ); + document.removeEventListener( 'mouseout', onDocumentMouseOut, false ); + + } + + function onDocumentMouseOut( event ) { + + document.removeEventListener( 'mousemove', onDocumentMouseMove, false ); + document.removeEventListener( 'mouseup', onDocumentMouseUp, false ); + document.removeEventListener( 'mouseout', onDocumentMouseOut, false ); + + } + + 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() { + + parent.rotation.y += ( targetRotation - parent.rotation.y ) * 0.05; + + camera.lookAt( cameraTarget ); + + renderer.clear(); + + if ( postprocessing.enabled ) { + + composer.render( 0.05 ); + + } else { + + renderer.render( scene, camera ); + + } + + } +}; + + +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_hdr.html + +()=>{ + + if ( ! Detector.webgl ) Detector.addGetWebGLMessage(); + + var container, stats; + + var camera, scene, renderer; + var materialHDR, quad; + + var sign = 1, rate = 1; + + var clock = new THREE.Clock(); + + var delta; + + init(); + animate(); + + function init() { + + container = document.getElementById( 'container' ); + + camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 10000 ); + camera.position.z = 900; + + scene = new THREE.Scene(); + + var texture = THREE.ImageUtils.loadTexture( "textures/memorial.png" ); + texture.minFilter = THREE.LinearFilter; + texture.magFilter = THREE.NearestFilter; + + materialHDR = new THREE.ShaderMaterial( { + + uniforms: { + tDiffuse: { type: "t", value: texture }, + exposure: { type: "f", value: 0.125 }, + brightMax: { type: "f", value: 0.5 } + }, + vertexShader: getText( 'vs-hdr' ), + fragmentShader: getText( 'fs-hdr' ) + + } ); + + var plane = new THREE.PlaneGeometry( 512, 768 ); + + quad = new THREE.Mesh( plane, materialHDR ); + quad.position.z = -100; + scene.add( quad ); + + renderer = new THREE.WebGLRenderer(); + 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 ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + } + + function getText( id ) { + + return document.getElementById( id ).textContent; + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + delta = clock.getDelta() * 5; + + if ( materialHDR.uniforms.exposure.value > 0 || materialHDR.uniforms.exposure.value < 1 ) { + + rate = 0.25; + + } else { + + rate = 1; + + } + + if ( materialHDR.uniforms.exposure.value > 5 || materialHDR.uniforms.exposure.value <= 0 ) { + + sign *= -1; + + } + + materialHDR.uniforms.exposure.value += sign * rate * delta; + + renderer.render( scene, camera ); + + } + +}; + +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_interactive_cubes.html + +()=>{ + + var container, stats; + var camera, scene, projector, renderer; + + var mouse = { x: 0, y: 0 }, INTERSECTED; + + 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 webgl - interactive cubes'; + container.appendChild( info ); + + camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 10000 ); + camera.position.set( 0, 300, 500 ); + + scene = new THREE.Scene(); + + var light = new THREE.DirectionalLight( 0xffffff, 2 ); + light.position.set( 1, 1, 1 ).normalize(); + scene.add( light ); + + var light = new THREE.DirectionalLight( 0xffffff ); + light.position.set( -1, -1, -1 ).normalize(); + scene.add( light ); + + var geometry = new THREE.CubeGeometry( 20, 20, 20 ); + + for ( var i = 0; i < 2000; i ++ ) { + + var object = new THREE.Mesh( geometry, new THREE.MeshLambertMaterial( { color: Math.random() * 0xffffff } ) ); + + object.position.x = Math.random() * 800 - 400; + object.position.y = Math.random() * 800 - 400; + object.position.z = Math.random() * 800 - 400; + + object.rotation.x = Math.random() * 2 * Math.PI; + object.rotation.y = Math.random() * 2 * Math.PI; + object.rotation.z = Math.random() * 2 * Math.PI; + + object.scale.x = Math.random() + 0.5; + object.scale.y = Math.random() + 0.5; + object.scale.z = Math.random() + 0.5; + + scene.add( object ); + + } + + projector = new THREE.Projector(); + + renderer = new THREE.WebGLRenderer(); + renderer.sortObjects = false; + 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( 'mousemove', onDocumentMouseMove, false ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + } + + function onDocumentMouseMove( event ) { + + event.preventDefault(); + + mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1; + mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1; + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + var radius = 100; + var theta = 0; + + function render() { + + theta += 0.1; + + camera.position.x = radius * Math.sin( THREE.Math.degToRad( theta ) ); + camera.position.y = radius * Math.sin( THREE.Math.degToRad( theta ) ); + camera.position.z = radius * Math.cos( THREE.Math.degToRad( theta ) ); + + camera.lookAt( scene.position ); + + // find intersections + + var vector = new THREE.Vector3( mouse.x, mouse.y, 1 ); + projector.unprojectVector( vector, camera ); + + var raycaster = new THREE.Raycaster( camera.position, vector.sub( camera.position ).normalize() ); + + var intersects = raycaster.intersectObjects( scene.children ); + + if ( intersects.length > 0 ) { + + if ( INTERSECTED != intersects[ 0 ].object ) { + + if ( INTERSECTED ) INTERSECTED.material.emissive.setHex( INTERSECTED.currentHex ); + + INTERSECTED = intersects[ 0 ].object; + INTERSECTED.currentHex = INTERSECTED.material.emissive.getHex(); + INTERSECTED.material.emissive.setHex( 0xff0000 ); + + } + + } else { + + if ( INTERSECTED ) INTERSECTED.material.emissive.setHex( INTERSECTED.currentHex ); + + INTERSECTED = null; + + } + + renderer.render( scene, camera ); + + } + +}; + +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_interactive_cubes_gpu.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_interactive_draggablecubes.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_interactive_voxelpainter.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_kinect.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_lensflares.html + +()=>{ + + var container, stats; + + var camera, scene, renderer; + + var clock = new THREE.Clock(); + + var composer; + + var controls; + + init(); + animate(); + + function init() { + + container = document.createElement( 'div' ); + document.body.appendChild( container ); + + // camera + + camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 15000 ); + camera.position.z = 250; + + controls = new THREE.FlyControls( camera ); + + controls.movementSpeed = 2500; + controls.domElement = container; + controls.rollSpeed = Math.PI / 6; + controls.autoForward = false; + controls.dragToLook = false + + // scene + + scene = new THREE.Scene(); + scene.fog = new THREE.Fog( 0x000000, 3500, 15000 ); + scene.fog.color.setHSL( 0.51, 0.6, 0.025 ); + + // world + + var s = 250; + + var cube = new THREE.CubeGeometry( s, s, s ); + var material = new THREE.MeshPhongMaterial( { ambient: 0x333333, color: 0xffffff, specular: 0xffffff, shininess: 50 } ); + + + for ( var i = 0; i < 3000; i ++ ) { + + var mesh = new THREE.Mesh( cube, material ); + + mesh.position.x = 8000 * ( 2.0 * Math.random() - 1.0 ); + mesh.position.y = 8000 * ( 2.0 * Math.random() - 1.0 ); + mesh.position.z = 8000 * ( 2.0 * Math.random() - 1.0 ); + + mesh.rotation.x = Math.random() * Math.PI; + mesh.rotation.y = Math.random() * Math.PI; + mesh.rotation.z = Math.random() * Math.PI; + + mesh.matrixAutoUpdate = false; + mesh.updateMatrix(); + + scene.add( mesh ); + + } + + + // lights + + var ambient = new THREE.AmbientLight( 0xffffff ); + ambient.color.setHSL( 0.1, 0.5, 0.3 ); + scene.add( ambient ); + + + var dirLight = new THREE.DirectionalLight( 0xffffff, 0.125 ); + dirLight.position.set( 0, -1, 0 ).normalize(); + scene.add( dirLight ); + + dirLight.color.setHSL( 0.1, 0.725, 0.9 ); + + // lens flares + + var textureFlare0 = THREE.ImageUtils.loadTexture( "textures/lensflare/lensflare0.png" ); + var textureFlare2 = THREE.ImageUtils.loadTexture( "textures/lensflare/lensflare2.png" ); + var textureFlare3 = THREE.ImageUtils.loadTexture( "textures/lensflare/lensflare3.png" ); + + addLight( 0.55, 0.825, 0.99, 5000, 0, -1000 ); + addLight( 0.08, 0.825, 0.99, 0, 0, -1000 ); + addLight( 0.995, 0.025, 0.99, 5000, 5000, -1000 ); + + function addLight( h, s, v, x, y, z ) { + + var light = new THREE.PointLight( 0xffffff, 1.5, 4500 ); + light.color.setHSL( h, s, v ); + light.position.set( x, y, z ); + scene.add( light ); + + var flareColor = new THREE.Color( 0xffffff ); + flareColor.setHSL( h, s - 0.5, v + 0.5 ); + + var lensFlare = new THREE.LensFlare( textureFlare0, 700, 0.0, THREE.AdditiveBlending, flareColor ); + + lensFlare.add( textureFlare2, 512, 0.0, THREE.AdditiveBlending ); + lensFlare.add( textureFlare2, 512, 0.0, THREE.AdditiveBlending ); + lensFlare.add( textureFlare2, 512, 0.0, THREE.AdditiveBlending ); + + lensFlare.add( textureFlare3, 60, 0.6, THREE.AdditiveBlending ); + lensFlare.add( textureFlare3, 70, 0.7, THREE.AdditiveBlending ); + lensFlare.add( textureFlare3, 120, 0.9, THREE.AdditiveBlending ); + lensFlare.add( textureFlare3, 70, 1.0, THREE.AdditiveBlending ); + + lensFlare.customUpdateCallback = lensFlareUpdateCallback; + lensFlare.position = light.position; + + scene.add( lensFlare ); + + } + + // renderer + + renderer = new THREE.WebGLRenderer( { antialias: true, alpha: true } ); + renderer.setSize( window.innerWidth, window.innerHeight ); + renderer.setClearColor( scene.fog.color, 1 ); + + container.appendChild( renderer.domElement ); + + // + + renderer.gammaInput = true; + renderer.gammaOutput = true; + renderer.physicallyBasedShading = true; + + // stats + + stats = new Stats(); + container.appendChild( stats.domElement ); + + // events + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + // + + function lensFlareUpdateCallback( object ) { + + var f, fl = object.lensFlares.length; + var flare; + var vecX = -object.positionScreen.x * 2; + var vecY = -object.positionScreen.y * 2; + + + for( f = 0; f < fl; f++ ) { + + flare = object.lensFlares[ f ]; + + flare.x = object.positionScreen.x + vecX * flare.distance; + flare.y = object.positionScreen.y + vecY * flare.distance; + + flare.rotation = 0; + + } + + object.lensFlares[ 2 ].y += 0.025; + object.lensFlares[ 3 ].rotation = object.positionScreen.x * 0.5 + THREE.Math.degToRad( 45 ); + + } + + // + + function onWindowResize( event ) { + + renderer.setSize( window.innerWidth, window.innerHeight ); + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + var delta = clock.getDelta(); + + controls.update( delta ); + renderer.render( scene, camera ); + + } + +}; + +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_lights_hemisphere.html + +()=>{ + + if ( ! Detector.webgl ) Detector.addGetWebGLMessage(); + + var camera, scene, renderer, dirLight, hemiLight; + var morphs = []; + var stats; + + var clock = new THREE.Clock(); + + var morph: THREE.MorphAnimMesh; + + init(); + animate(); + + function init() { + + var container = document.getElementById( 'container' ); + + camera = new THREE.PerspectiveCamera( 30, window.innerWidth / window.innerHeight, 1, 5000 ); + camera.position.set( 0, 0, 250 ); + + scene = new THREE.Scene(); + + scene.fog = new THREE.Fog( 0xffffff, 1, 5000 ); + scene.fog.color.setHSL( 0.6, 0, 1 ); + + /* + controls = new THREE.TrackballControls( camera ); + + controls.rotateSpeed = 1.0; + controls.zoomSpeed = 1.2; + controls.panSpeed = 0.8; + + controls.noZoom = false; + controls.noPan = false; + + controls.staticMoving = true; + controls.dynamicDampingFactor = 0.15; + */ + + // LIGHTS + + hemiLight = new THREE.HemisphereLight( 0xffffff, 0xffffff, 0.6 ); + hemiLight.color.setHSL( 0.6, 0.75, 1 ); + hemiLight.groundColor.setHSL( 0.095, 0.5, 1 ); + hemiLight.position.set( 0, 500, 0 ); + scene.add( hemiLight ); + + // + + dirLight = new THREE.DirectionalLight( 0xffffff, 1 ); + dirLight.color.setHSL( 0.1, 0.1, 1 ); + dirLight.position.set( -1, 1.75, 1 ); + dirLight.position.multiplyScalar( 50 ); + scene.add( dirLight ); + + dirLight.castShadow = true; + + dirLight.shadowMapWidth = 2048; + dirLight.shadowMapHeight = 2048; + + var d = 50; + + dirLight.shadowCameraLeft = -d; + dirLight.shadowCameraRight = d; + dirLight.shadowCameraTop = d; + dirLight.shadowCameraBottom = -d; + + dirLight.shadowCameraFar = 3500; + dirLight.shadowBias = -0.0001; + dirLight.shadowDarkness = 0.35; + //dirLight.shadowCameraVisible = true; + + // GROUND + + var groundGeo = new THREE.PlaneGeometry( 10000, 10000 ); + var groundMat = new THREE.MeshPhongMaterial( { ambient: 0xffffff, color: 0xffffff, specular: 0x050505 } ); + groundMat.color.setHSL( 0.095, 0.5, 1 ); + + var ground = new THREE.Mesh( groundGeo, groundMat ); + ground.rotation.x = -Math.PI/2; + ground.position.y = -33; + scene.add( ground ); + + ground.receiveShadow = true; + + // SKYDOME + + var vertexShader = document.getElementById( 'vertexShader' ).textContent; + var fragmentShader = document.getElementById( 'fragmentShader' ).textContent; + var uniforms = { + topColor: { type: "c", value: new THREE.Color( 0x0077ff ) }, + bottomColor: { type: "c", value: new THREE.Color( 0xffffff ) }, + offset: { type: "f", value: 33 }, + exponent: { type: "f", value: 0.6 } + } + uniforms.topColor.value.copy( hemiLight.color ); + + scene.fog.color.copy( uniforms.bottomColor.value ); + + var skyGeo = new THREE.SphereGeometry( 4000, 32, 15 ); + var skyMat = new THREE.ShaderMaterial( { vertexShader: vertexShader, fragmentShader: fragmentShader, uniforms: uniforms, side: THREE.BackSide } ); + + var sky = new THREE.Mesh( skyGeo, skyMat ); + scene.add( sky ); + + // MODEL + + var loader = new THREE.JSONLoader(); + + loader.load( "models/animated/flamingo.js", function( geometry ) { + + morphColorsToFaceColors( geometry ); + geometry.computeMorphNormals(); + + var material = new THREE.MeshPhongMaterial( { color: 0xffffff, specular: 0xffffff, shininess: 20, morphTargets: true, morphNormals: true, vertexColors: THREE.FaceColors, shading: THREE.FlatShading } ); + var meshAnim = new THREE.MorphAnimMesh( geometry, material ); + + meshAnim.duration = 1000; + + var s = 0.35; + meshAnim.scale.set( s, s, s ); + meshAnim.position.y = 15; + meshAnim.rotation.y = -1; + + meshAnim.castShadow = true; + meshAnim.receiveShadow = true; + + scene.add( meshAnim ); + morphs.push( meshAnim ); + + } ); + + // RENDERER + + renderer = new THREE.WebGLRenderer( { antialias: true } ); + renderer.setSize( window.innerWidth, window.innerHeight ); + container.appendChild( renderer.domElement ); + + renderer.setClearColor( scene.fog.color, 1 ); + + renderer.gammaInput = true; + renderer.gammaOutput = true; + renderer.physicallyBasedShading = true; + + renderer.shadowMapEnabled = true; + renderer.shadowMapCullFace = THREE.CullFaceBack; + + // STATS + + stats = new Stats(); + container.appendChild( stats.domElement ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + document.addEventListener( 'keydown', onKeyDown, false ); + + } + + function morphColorsToFaceColors( geometry ) { + + if ( geometry.morphColors && geometry.morphColors.length ) { + + var colorMap = geometry.morphColors[ 0 ]; + + for ( var i = 0; i < colorMap.colors.length; i ++ ) { + + geometry.faces[ i ].color = colorMap.colors[ i ]; + + } + + } + + } + + function onWindowResize() { + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + } + + function onKeyDown ( event ) { + + switch ( event.keyCode ) { + + case 72: /*h*/ + + hemiLight.visible = !hemiLight.visible; + break; + + case 68: /*d*/ + + dirLight.visible = !dirLight.visible; + break; + + } + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + var delta = clock.getDelta(); + + //controls.update(); + + for ( var i = 0; i < morphs.length; i ++ ) { + + morph = morphs[ i ]; + morph.updateAnimation( 1000 * delta ); + + } + + renderer.render( scene, camera ); + + } + +}; + +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_lights_pointlights.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_lights_pointlights2.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_lines_colors.html + +()=>{ + + if ( ! Detector.webgl ) Detector.addGetWebGLMessage(); + + var effectFXAA; + + var mouseX = 0, mouseY = 0, + + windowHalfX = window.innerWidth / 2, + windowHalfY = window.innerHeight / 2, + + camera, scene, renderer, material, composer; + + var stats: any; + + init(); + animate(); + + function init() { + + var i, container; + + container = document.createElement( 'div' ); + document.body.appendChild( container ); + + camera = new THREE.PerspectiveCamera( 33, window.innerWidth / window.innerHeight, 1, 10000 ); + camera.position.z = 700; + + scene = new THREE.Scene(); + + renderer = new THREE.WebGLRenderer( { clearColor: 0x000000, clearAlpha: 1, antialias: false } ); + renderer.setSize( window.innerWidth, window.innerHeight ); + renderer.autoClear = false; + + container.appendChild( renderer.domElement ); + + var geometry = new THREE.Geometry(), + geometry2 = new THREE.Geometry(), + geometry3 = new THREE.Geometry(), + points = hilbert3D( new THREE.Vector3( 0,0,0 ), 200.0, 2, 0, 1, 2, 3, 4, 5, 6, 7 ), + colors = [], colors2 = [], colors3 = []; + + for ( i = 0; i < points.length; i ++ ) { + + geometry.vertices.push( points[ i ] ); + + colors[ i ] = new THREE.Color( 0xffffff ); + colors[ i ].setHSV( 0.6, ( 200 + points[ i ].x ) / 400, 1.0 ); + + colors2[ i ] = new THREE.Color( 0xffffff ); + colors2[ i ].setHSV( 0.3, 1.0, ( 200 + points[ i ].x ) / 400 ); + + colors3[ i ] = new THREE.Color( 0xffffff ); + colors3[ i ].setHSV( i / points.length, 1.0, 1.0 ); + + } + + geometry2.vertices = geometry3.vertices = geometry.vertices; + + geometry.colors = colors; + geometry2.colors = colors2; + geometry3.colors = colors3; + + // lines + + material = new THREE.LineBasicMaterial( { color: 0xffffff, opacity: 1, linewidth: 3, vertexColors: THREE.VertexColors } ); + + var line, p, scale = 0.3, d = 225; + var parameters = [ + [ material, scale*1.5, [-d,0,0], geometry ], + [ material, scale*1.5, [0,0,0], geometry2 ], + [ material, scale*1.5, [d,0,0], geometry3 ] + ]; + + for ( i = 0; i < parameters.length; ++i ) { + + p = parameters[ i ]; + line = new THREE.Line( p[ 3 ], p[ 0 ] ); + line.scale.x = line.scale.y = line.scale.z = p[ 1 ]; + line.position.x = p[ 2 ][ 0 ]; + line.position.y = p[ 2 ][ 1 ]; + line.position.z = p[ 2 ][ 2 ]; + scene.add( line ); + + } + + // + + stats = new Stats(); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.top = '0px'; + //container.appendChild( stats.domElement ); + + // + + document.addEventListener( 'mousemove', onDocumentMouseMove, false ); + document.addEventListener( 'touchstart', onDocumentTouchStart, false ); + document.addEventListener( 'touchmove', onDocumentTouchMove, false ); + + // + + var renderModel = new THREE.RenderPass( scene, camera ); + var effectBloom = new THREE.BloomPass( 1.3 ); + var effectCopy = new THREE.ShaderPass( THREE.CopyShader ); + + effectFXAA = new THREE.ShaderPass( THREE.FXAAShader ); + + var width = window.innerWidth || 2; + var height = window.innerHeight || 2; + + effectFXAA.uniforms[ 'resolution' ].value.set( 1 / width, 1 / height ); + + effectCopy.renderToScreen = true; + + composer = new THREE.EffectComposer( renderer ); + + composer.addPass( renderModel ); + composer.addPass( effectFXAA ); + composer.addPass( effectBloom ); + composer.addPass( effectCopy ); + + // + + 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 ); + + effectFXAA.uniforms[ 'resolution' ].value.set( 1 / window.innerWidth, 1 / window.innerHeight ); + + composer.reset(); + + } + + // port of Processing Java code by Thomas Diewald + // http://www.openprocessing.org/visuals/?visualID=15599 + + function hilbert3D( center, side, iterations, v0, v1, v2, v3, v4, v5, v6, v7 ) { + + var half = side / 2, + + vec_s = [ + + new THREE.Vector3( center.x - half, center.y + half, center.z - half ), + new THREE.Vector3( center.x - half, center.y + half, center.z + half ), + new THREE.Vector3( center.x - half, center.y - half, center.z + half ), + new THREE.Vector3( center.x - half, center.y - half, center.z - half ), + new THREE.Vector3( center.x + half, center.y - half, center.z - half ), + new THREE.Vector3( center.x + half, center.y - half, center.z + half ), + new THREE.Vector3( center.x + half, center.y + half, center.z + half ), + new THREE.Vector3( center.x + half, center.y + half, center.z - half ) + + ], + + vec = [ vec_s[ v0 ], vec_s[ v1 ], vec_s[ v2 ], vec_s[ v3 ], vec_s[ v4 ], vec_s[ v5 ], vec_s[ v6 ], vec_s[ v7 ] ]; + + if( --iterations >= 0 ) { + + var tmp = []; + + Array.prototype.push.apply( tmp, hilbert3D ( vec[ 0 ], half, iterations, v0, v3, v4, v7, v6, v5, v2, v1 ) ); + Array.prototype.push.apply( tmp, hilbert3D ( vec[ 1 ], half, iterations, v0, v7, v6, v1, v2, v5, v4, v3 ) ); + Array.prototype.push.apply( tmp, hilbert3D ( vec[ 2 ], half, iterations, v0, v7, v6, v1, v2, v5, v4, v3 ) ); + Array.prototype.push.apply( tmp, hilbert3D ( vec[ 3 ], half, iterations, v2, v3, v0, v1, v6, v7, v4, v5 ) ); + Array.prototype.push.apply( tmp, hilbert3D ( vec[ 4 ], half, iterations, v2, v3, v0, v1, v6, v7, v4, v5 ) ); + Array.prototype.push.apply( tmp, hilbert3D ( vec[ 5 ], half, iterations, v4, v3, v2, v5, v6, v1, v0, v7 ) ); + Array.prototype.push.apply( tmp, hilbert3D ( vec[ 6 ], half, iterations, v4, v3, v2, v5, v6, v1, v0, v7 ) ); + Array.prototype.push.apply( tmp, hilbert3D ( vec[ 7 ], half, iterations, v6, v5, v2, v1, v0, v3, v4, v7 ) ); + + return tmp; + + } + + return vec; + } + + // + + function onDocumentMouseMove( event ) { + + mouseX = event.clientX - windowHalfX; + mouseY = event.clientY - windowHalfY; + + } + + function onDocumentTouchStart( event ) { + + if ( event.touches.length > 1 ) { + + event.preventDefault(); + + mouseX = event.touches[ 0 ].pageX - windowHalfX; + mouseY = event.touches[ 0 ].pageY - windowHalfY; + + } + + } + + function onDocumentTouchMove( event ) { + + if ( event.touches.length == 1 ) { + + event.preventDefault(); + + mouseX = event.touches[ 0 ].pageX - windowHalfX; + mouseY = event.touches[ 0 ].pageY - windowHalfY; + } + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + render(); + + stats.update(); + + } + + function render() { + + camera.position.x += ( mouseX - camera.position.x ) * .05; + camera.position.y += ( - mouseY + 200 - camera.position.y ) * .05; + + camera.lookAt( scene.position ); + + var time = Date.now() * 0.0005; + + for ( var i = 0; i < scene.children.length; i ++ ) { + + var object = scene.children[ i ]; + if ( object instanceof THREE.Line ) object.rotation.y = time * ( i % 2 ? 1 : -1 ); + + } + + renderer.clear(); + composer.render(); + + } + +}; + +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_lines_cubes.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_lines_dashed.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_lines_sphere.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_lines_splines.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_loader_collada.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_loader_collada_keyframe.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_loader_ctm.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_loader_ctm_materials.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_loader_json_blender.html + +()=>{ + + if ( ! Detector.webgl ) Detector.addGetWebGLMessage(); + + var container, stats; + + var camera, scene, renderer, objects; + var particleLight, pointLight; + var dae, skin; + + var clock = new THREE.Clock(); + var morphs = []; + var morph: THREE.MorphAnimMesh; + + // Collada model + + var loader = new THREE.ColladaLoader(); + loader.options.convertUpAxis = true; + loader.load( 'models/collada/monster/monster.dae', function ( collada ) { + + dae = collada.scene; + skin = collada.skins[ 0 ]; + + dae.scale.x = dae.scale.y = dae.scale.z = 0.002; + dae.position.x = -1; + dae.updateMatrix(); + + init(); + animate(); + + } ); + + function init() { + + container = document.createElement( 'div' ); + document.body.appendChild( container ); + + camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 2000 ); + camera.position.set( 2, 4, 5 ); + + scene = new THREE.Scene(); + scene.fog = new THREE.FogExp2( 0x000000, 0.035 ); + + // Add Blender exported Collada model + + var loader = new THREE.JSONLoader(); + loader.load( 'models/animated/monster/monster.js', function ( geometry, materials ) { + + // adjust color a bit + + var material = materials[ 0 ]; + material.morphTargets = true; + material.color.setHex( 0xffaaaa ); + material.ambient.setHex( 0x222222 ); + + var faceMaterial = new THREE.MeshFaceMaterial( materials ); + + for ( var i = 0; i < 729; i ++ ) { + + // random placement in a grid + + var x = ( ( i % 27 ) - 13.5 ) * 2 + THREE.Math.randFloatSpread( 1 ); + var z = ( Math.floor( i / 27 ) - 13.5 ) * 2 + THREE.Math.randFloatSpread( 1 ); + + // leave space for big monster + + if ( Math.abs( x ) < 2 && Math.abs( z ) < 2 ) continue; + + morph = new THREE.MorphAnimMesh( geometry, faceMaterial ); + + // one second duration + + morph.duration = 1000; + + // random animation offset + + morph.time = 1000 * Math.random(); + + var s = THREE.Math.randFloat( 0.00075, 0.001 ); + morph.scale.set( s, s, s ); + + morph.position.set( x, 0, z ); + morph.rotation.y = THREE.Math.randFloat( -0.25, 0.25 ); + + morph.matrixAutoUpdate = false; + morph.updateMatrix(); + + scene.add( morph ); + + morphs.push( morph ); + + } + + } ); + + + // Add the COLLADA + + scene.add( dae ); + + // Lights + + scene.add( new THREE.AmbientLight( 0xcccccc ) ); + + pointLight = new THREE.PointLight( 0xff4400, 5, 30 ); + pointLight.position.set( 5, 0, 0 ); + scene.add( pointLight ); + + // Renderer + + renderer = new THREE.WebGLRenderer(); + renderer.setSize( window.innerWidth, window.innerHeight ); + + container.appendChild( renderer.domElement ); + + // Stats + + stats = new Stats(); + container.appendChild( stats.domElement ); + + // Events + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + // + + function onWindowResize( event ) { + + renderer.setSize( window.innerWidth, window.innerHeight ); + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + } + + // + + var t = 0; + function animate() { + + requestAnimationFrame( animate ); + + // animate Collada model + + if ( t > 30 ) t = 0; + + if ( skin ) { + + // guess this can be done smarter... + + // (Indeed, there are way more frames than needed and interpolation is not used at all + // could be something like - one morph per each skinning pose keyframe, or even less, + // animation could be resampled, morphing interpolation handles sparse keyframes quite well. + // Simple animation cycles like this look ok with 10-15 frames instead of 100 ;) + + for ( var i = 0; i < skin.morphTargetInfluences.length; i++ ) { + + skin.morphTargetInfluences[ i ] = 0; + + } + + skin.morphTargetInfluences[ Math.floor( t ) ] = 1; + + t += 0.5; + + } + + // animate morphs + + var delta = clock.getDelta(); + + if ( morphs.length ) { + + for ( var i = 0; i < morphs.length; i ++ ) + morphs[ i ].updateAnimation( 1000 * delta ); + + + } + + render(); + stats.update(); + + } + + function render() { + + var timer = Date.now() * 0.0005; + + camera.position.x = Math.cos( timer ) * 10; + camera.position.y = 4; + camera.position.z = Math.sin( timer ) * 10; + + camera.lookAt( scene.position ); + + renderer.render( scene, camera ); + + } + +}; + +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_loader_json_objconverter.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_loader_obj.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_loader_obj_mtl.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_loader_scene.html + +()=>{ + + if ( ! Detector.webgl ) Detector.addGetWebGLMessage(); + + var SCREEN_WIDTH = window.innerWidth; + var SCREEN_HEIGHT = window.innerHeight; + + var container,stats; + + var camera, scene, loaded; + var renderer; + + var mouseX = 0, mouseY = 0; + + var windowHalfX = window.innerWidth / 2; + var windowHalfY = window.innerHeight / 2; + + var rotatingObjects = []; + var morphAnimatedObjects = []; + + var clock = new THREE.Clock(); + + document.addEventListener( 'mousemove', onDocumentMouseMove, false ); + + init(); + animate(); + + function $( id ) { + + return document.getElementById( id ); + + } + + function handle_update( result, pieces ) { + + refreshSceneView( result ); + //renderer.initWebGLObjects( result.scene ); + + var m, material, count = 0; + + for ( m in result.materials ) { + + material = result.materials[ m ]; + if ( ! ( material instanceof THREE.MeshFaceMaterial || material instanceof THREE.ShaderMaterial || material.morphTargets ) ) { + + if( !material.program ) { + + renderer.initMaterial( material, result.scene.__lights, result.scene.fog ); + + count += 1; + + if( count > pieces ) { + + //console.log("xxxxxxxxx"); + break; + + } + + } + + } + + } + + } + + function init() { + + container = document.createElement( 'div' ); + document.body.appendChild( container ); + + var loadScene = createLoadScene(); + + camera = loadScene.camera; + scene = loadScene.scene; + + renderer = new THREE.WebGLRenderer( { antialias: true } ); + renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT ); + renderer.domElement.style.position = "relative"; + container.appendChild( renderer.domElement ); + + renderer.gammaInput = true; + renderer.gammaOutput = true; + renderer.physicallyBasedShading = true; + + stats = new Stats(); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.top = '0px'; + stats.domElement.style.right = '0px'; + stats.domElement.style.zIndex = 100; + container.appendChild( stats.domElement ); + + $( "start" ).addEventListener( 'click', onStartClick, false ); + + var callbackProgress = function( progress, result ) { + + var bar = 250, + total = progress.totalModels + progress.totalTextures, + loaded = progress.loadedModels + progress.loadedTextures; + + if ( total ) + bar = Math.floor( bar * loaded / total ); + + $( "bar" ).style.width = bar + "px"; + + var count = 0; + for ( var m in result.materials ) count++; + + handle_update( result, Math.floor( count/total ) ); + + } + + var callbackSync = function( result ) { + + /* + + // uncomment to see progressive scene loading + + scene = result.scene; + camera = result.currentCamera; + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + */ + + //handle_update( result, 1 ); + + } + + var callbackFinished = function ( result ) { + + loaded = result; + + $( "message" ).style.display = "none"; + $( "progressbar" ).style.display = "none"; + $( "start" ).style.display = "block"; + $( "start" ).className = "enabled"; + + handle_update( result, 1 ); + + result.scene.traverse( function ( object ) { + + if ( object.properties.rotating === true ) { + + rotatingObjects.push( object ); + + } + + if ( object instanceof THREE.MorphAnimMesh ) { + + morphAnimatedObjects.push( object ); + + } + + if ( object instanceof THREE.SkinnedMesh ) { + + if ( object.geometry.animation ) { + + THREE.AnimationHandler.add( object.geometry.animation ); + + var animation = new THREE.Animation( object, object.geometry.animation.name ); + animation.JITCompile = false; + animation.interpolationType = THREE.AnimationHandler.LINEAR; + + animation.play(); + + } + + } + + } ); + + } + + $( "progress" ).style.display = "block"; + + var loader = new THREE.SceneLoader(); + + loader.addGeometryHandler( "binary", THREE.BinaryLoader ); + loader.addGeometryHandler( "ctm", THREE.CTMLoader ); + loader.addGeometryHandler( "vtk", THREE.VTKLoader ); + loader.addGeometryHandler( "stl", THREE.STLLoader ); + + loader.addHierarchyHandler( "obj", THREE.OBJLoader ); + loader.addHierarchyHandler( "dae", THREE.ColladaLoader ); + loader.addHierarchyHandler( "utf8", THREE.UTF8Loader ); + + loader.callbackSync = callbackSync; + loader.callbackProgress = callbackProgress; + + loader.load( "scenes/test_scene.js", callbackFinished ); + + $( "plus_exp" ).addEventListener( 'click', createToggle( "exp" ), 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 ); + + } + + function setButtonActive( id ) { + + $( "start" ).style.backgroundColor = "green"; + + } + + function onStartClick() { + + $( "progress" ).style.display = "none"; + + camera = loaded.currentCamera; + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + scene = loaded.scene; + + } + + function onDocumentMouseMove( event ) { + + mouseX = ( event.clientX - windowHalfX ); + mouseY = ( event.clientY - windowHalfY ); + + } + + function createLoadScene() { + + var result = { + + scene: new THREE.Scene(), + camera: new THREE.PerspectiveCamera( 65, window.innerWidth / window.innerHeight, 1, 1000 ) + + }; + + result.camera.position.z = 100; + result.scene.add( result.camera ); + + var object, geometry, material, light, count = 500, range = 200; + + material = new THREE.MeshLambertMaterial( { color:0xffffff } ); + geometry = new THREE.CubeGeometry( 5, 5, 5 ); + + for( var i = 0; i < count; i++ ) { + + object = new THREE.Mesh( geometry, material ); + + object.position.x = ( Math.random() - 0.5 ) * range; + object.position.y = ( Math.random() - 0.5 ) * range; + object.position.z = ( Math.random() - 0.5 ) * range; + + object.rotation.x = Math.random() * 6; + object.rotation.y = Math.random() * 6; + object.rotation.z = Math.random() * 6; + + object.matrixAutoUpdate = false; + object.updateMatrix(); + + result.scene.add( object ); + + } + + result.scene.matrixAutoUpdate = false; + + light = new THREE.PointLight( 0xffffff ); + result.scene.add( light ); + + light = new THREE.DirectionalLight( 0x111111 ); + light.position.x = 1; + result.scene.add( light ); + + return result; + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + var delta = clock.getDelta(); + + camera.position.x += ( mouseX - camera.position.x ) * .001; + camera.position.y += ( - mouseY - camera.position.y ) * .001; + + camera.lookAt( scene.position ); + + // update skinning + + THREE.AnimationHandler.update( delta * 0.75 ); + + for ( var i = 0; i < rotatingObjects.length; i ++ ) { + + var object = rotatingObjects[ i ]; + + if ( object.properties.rotateX ) object.rotation.x += 1 * delta; + if ( object.properties.rotateY ) object.rotation.y += 0.5 * delta; + + } + + for ( var i = 0; i < morphAnimatedObjects.length; i ++ ) { + + var object = morphAnimatedObjects[ i ]; + + object.updateAnimation( 1000 * delta ); + + } + + renderer.render( scene, camera ); + + } + + // Scene explorer user interface + + function toggle( id ) { + + var scn = $( "section_" + id ).style, + btn = $( "plus_" + id ); + + if ( scn.display == "block" ) { + + scn.display = "none"; + btn.innerHTML = "[+]"; + + } + else { + + scn.display = "block"; + btn.innerHTML = "[-]"; + + } + + } + + function createToggle( label ) { return function() { toggle( label ) } }; + + function refreshSceneView( result ) { + + $( "section_exp" ).innerHTML = generateSceneView( result ); + + var config = [ "obj", "geo", "mat", "tex", "lit", "cam" ]; + + for ( var i = 0; i < config.length; i++ ) + $( "plus_" + config[i] ).addEventListener( 'click', createToggle( config[i] ), false ); + + } + + function generateSection( label, id, objects ) { + + var html = ""; + + html += "

[+] " + label + "

"; + html += "
"; + + for( var o in objects ) { + + html += o + "
"; + + } + html += "
"; + + return html; + + } + + function generateSceneView( result ) { + + var config = [ + [ "Objects", "obj", result.objects ], + [ "Geometries", "geo", result.geometries ], + [ "Materials", "mat", result.materials ], + [ "Textures", "tex", result.textures ], + [ "Lights", "lit", result.lights ], + [ "Cameras", "cam", result.cameras ] + ]; + + var html = ""; + + for ( var i = 0; i < config.length; i++ ) + html += generateSection( config[i][0], config[i][1], config[i][2] ); + + return html; + + } + +}; + +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_loader_scene_blender.html + +()=>{ + + if ( ! Detector.webgl ) Detector.addGetWebGLMessage(); + + var SCREEN_WIDTH = window.innerWidth; + var SCREEN_HEIGHT = window.innerHeight; + + var container,stats; + + var camera, scene: THREE.Scene, loaded; + var renderer; + + var mesh, zmesh, geometry; + + var mouseX = 0, mouseY = 0; + + var windowHalfX = window.innerWidth / 2; + var windowHalfY = window.innerHeight / 2; + + document.addEventListener( 'mousemove', onDocumentMouseMove, false ); + + init(); + animate(); + + function $( id ) { + + return document.getElementById( id ); + + } + + function handle_update( result, pieces ) { + + refreshSceneView( result ); + //renderer.initWebGLObjects( result.scene ); + + var m, material, count = 0; + + for ( m in result.materials ) { + + material = result.materials[ m ]; + if ( ! ( material instanceof THREE.MeshFaceMaterial ) ) { + + if( !material.program ) { + + console.log(m); + renderer.initMaterial( material, result.scene.__lights, result.scene.fog ); + + count += 1; + if( count > pieces ) { + + //console.log("xxxxxxxxx"); + break; + + } + + } + + } + + } + + } + + function init() { + + container = document.createElement( 'div' ); + document.body.appendChild( container ); + + var loadScene = createLoadScene(); + + camera = loadScene.camera; + scene = loadScene.scene; + + renderer = new THREE.WebGLRenderer(); + renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT ); + renderer.domElement.style.position = "relative"; + container.appendChild( renderer.domElement ); + + stats = new Stats(); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.top = '0px'; + stats.domElement.style.right = '0px'; + stats.domElement.style.zIndex = 100; + container.appendChild( stats.domElement ); + + $( "start" ).addEventListener( 'click', onStartClick, false ); + + var callbackProgress = function( progress, result ) { + + var bar = 250, + total = progress.total_models + progress.total_textures, + loaded = progress.loaded_models + progress.loaded_textures; + + if ( total ) + bar = Math.floor( bar * loaded / total ); + + $( "bar" ).style.width = bar + "px"; + + var count = 0; + for ( var m in result.materials ) count++; + + handle_update( result, Math.floor( count/total ) ); + + } + + var callbackFinished = function( result ) { + + loaded = result; + + $( "message" ).style.display = "none"; + $( "progressbar" ).style.display = "none"; + $( "start" ).style.display = "block"; + $( "start" ).className = "enabled"; + + handle_update( result, 1 ); + + } + + $( "progress" ).style.display = "block"; + + var loader = new THREE.SceneLoader(); + loader.callbackProgress = callbackProgress; + + loader.load( "obj/blenderscene/scene.js", callbackFinished ); + + $( "plus_exp" ).addEventListener( 'click', createToggle( "exp" ), 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 ); + + } + + function setButtonActive( id ) { + + $( "start" ).style.backgroundColor = "green"; + + } + + function onStartClick() { + + $( "progress" ).style.display = "none"; + + camera = loaded.currentCamera; + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + scene = loaded.scene; + + } + + function onDocumentMouseMove(event) { + + mouseX = ( event.clientX - windowHalfX ); + mouseY = ( event.clientY - windowHalfY ); + + } + + function createLoadScene() { + + var result = { + + scene: new THREE.Scene(), + camera: new THREE.PerspectiveCamera( 65, window.innerWidth / window.innerHeight, 1, 1000 ) + + }; + + result.camera.position.z = 100; + + var object, geometry, material, light, count = 500, range = 200; + + material = new THREE.MeshLambertMaterial( { color:0xffffff } ); + geometry = new THREE.CubeGeometry( 5, 5, 5 ); + + for( var i = 0; i < count; i++ ) { + + object = new THREE.Mesh( geometry, material ); + + object.position.x = ( Math.random() - 0.5 ) * range; + object.position.y = ( Math.random() - 0.5 ) * range; + object.position.z = ( Math.random() - 0.5 ) * range; + + object.rotation.x = Math.random() * 6; + object.rotation.y = Math.random() * 6; + object.rotation.z = Math.random() * 6; + + object.matrixAutoUpdate = false; + object.updateMatrix(); + + result.scene.add( object ); + + } + + result.scene.matrixAutoUpdate = false; + + light = new THREE.PointLight( 0xffffff ); + result.scene.add( light ); + + light = new THREE.DirectionalLight( 0x111111 ); + light.position.x = 1; + result.scene.add( light ); + + return result; + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + camera.position.x += ( mouseX - camera.position.x ) * .001; + camera.position.y += ( - mouseY - camera.position.y ) * .001; + + camera.lookAt( scene.position ); + + renderer.render( scene, camera ); + + } + + // Scene explorer user interface + + function toggle( id ) { + + var scn = $( "section_" + id ).style, + btn = $( "plus_" + id ); + + if ( scn.display == "block" ) { + + scn.display = "none"; + btn.innerHTML = "[+]"; + + } + else { + + scn.display = "block"; + btn.innerHTML = "[-]"; + + } + + } + + function createToggle( label ) { return function() { toggle( label ) } }; + + function refreshSceneView( result ) { + + $( "section_exp" ).innerHTML = generateSceneView( result ); + + var config = [ "obj", "geo", "mat", "tex", "lit", "cam" ]; + + for ( var i = 0; i < config.length; i++ ) + $( "plus_" + config[i] ).addEventListener( 'click', createToggle( config[i] ), false ); + + } + + function generateSection( label, id, objects ) { + + var html = ""; + + html += "

[+] " + label + "

"; + html += "
"; + + for( var o in objects ) { + + html += o + "
"; + + } + html += "
"; + + return html; + + } + + function generateSceneView( result ) { + + var config = [ + [ "Objects", "obj", result.objects ], + [ "Geometries", "geo", result.geometries ], + [ "Materials", "mat", result.materials ], + [ "Textures", "tex", result.textures ], + [ "Lights", "lit", result.lights ], + [ "Cameras", "cam", result.cameras ] + ]; + + var html = ""; + + for ( var i = 0; i < config.length; i++ ) + html += generateSection( config[i][0], config[i][1], config[i][2] ); + + return html; + + } + +}; + +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_loader_stl.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_loader_utf8.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_loader_vtk.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_lod.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_marching_cubes.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_materials.html + +()=>{ + + if ( ! Detector.webgl ) Detector.addGetWebGLMessage(); + + var container, stats; + + var camera, scene, renderer, objects; + var particleLight, pointLight; + + var materials = []; + + init(); + animate(); + + function init() { + + container = document.createElement( 'div' ); + document.body.appendChild( container ); + + camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2000 ); + camera.position.set( 0, 200, 800 ); + + scene = new THREE.Scene(); + + // Grid + + var line_material = new THREE.LineBasicMaterial( { color: 0x303030 } ), + geometry = new THREE.Geometry(), + floor = -75, step = 25; + + for ( var i = 0; i <= 40; i ++ ) { + + geometry.vertices.push( new THREE.Vector3( - 500, floor, i * step - 500 ) ); + geometry.vertices.push( new THREE.Vector3( 500, floor, i * step - 500 ) ); + + geometry.vertices.push( new THREE.Vector3( i * step - 500, floor, -500 ) ); + geometry.vertices.push( new THREE.Vector3( i * step - 500, floor, 500 ) ); + + } + + var line = new THREE.Line( geometry, line_material, THREE.LinePieces ); + scene.add( line ); + + // Materials + + var texture = new THREE.Texture( generateTexture() ); + texture.needsUpdate = true; + + materials.push( new THREE.MeshLambertMaterial( { map: texture, transparent: true } ) ); + materials.push( new THREE.MeshLambertMaterial( { color: 0xdddddd, shading: THREE.FlatShading } ) ); + materials.push( new THREE.MeshPhongMaterial( { ambient: 0x030303, color: 0xdddddd, specular: 0x009900, shininess: 30, shading: THREE.FlatShading } ) ); + materials.push( new THREE.MeshNormalMaterial( ) ); + materials.push( new THREE.MeshBasicMaterial( { color: 0xffaa00, transparent: true, blending: THREE.AdditiveBlending } ) ); + //materials.push( new THREE.MeshBasicMaterial( { color: 0xff0000, blending: THREE.SubtractiveBlending } ) ); + + materials.push( new THREE.MeshLambertMaterial( { color: 0xdddddd, shading: THREE.SmoothShading } ) ); + materials.push( new THREE.MeshPhongMaterial( { ambient: 0x030303, color: 0xdddddd, specular: 0x009900, shininess: 30, shading: THREE.SmoothShading, map: texture, transparent: true } ) ); + materials.push( new THREE.MeshNormalMaterial( { shading: THREE.SmoothShading } ) ); + materials.push( new THREE.MeshBasicMaterial( { color: 0xffaa00, wireframe: true } ) ); + + materials.push( new THREE.MeshDepthMaterial() ); + + materials.push( new THREE.MeshLambertMaterial( { color: 0x666666, emissive: 0xff0000, ambient: 0x000000, shading: THREE.SmoothShading } ) ); + materials.push( new THREE.MeshPhongMaterial( { color: 0x000000, specular: 0x666666, emissive: 0xff0000, ambient: 0x000000, shininess: 10, shading: THREE.SmoothShading, opacity: 0.9, transparent: true } ) ); + + materials.push( new THREE.MeshBasicMaterial( { map: texture, transparent: true } ) ); + + // Spheres geometry + + var geometry_smooth = new THREE.SphereGeometry( 70, 32, 16 ); + var geometry_flat = new THREE.SphereGeometry( 70, 32, 16 ); + var geometry_pieces = new THREE.SphereGeometry( 70, 32, 16 ); // Extra geometry to be broken down for MeshFaceMaterial + + for ( var i = 0, l = geometry_pieces.faces.length; i < l; i ++ ) { + + var face = geometry_pieces.faces[ i ]; + face.materialIndex = Math.floor( Math.random() * materials.length ); + + } + + geometry_pieces["materials"] = materials; + + materials.push( new THREE.MeshFaceMaterial( materials ) ); + + objects = []; + + var sphere, geometry, material; + + for ( var i = 0, l = materials.length; i < l; i ++ ) { + + material = materials[ i ]; + + geometry = material instanceof THREE.MeshFaceMaterial ? geometry_pieces : + ( material.shading == THREE.FlatShading ? geometry_flat : geometry_smooth ); + + sphere = new THREE.Mesh( geometry, material ); + + sphere.position.x = ( i % 4 ) * 200 - 400; + sphere.position.z = Math.floor( i / 4 ) * 200 - 200; + + sphere.rotation.x = Math.random() * 200 - 100; + sphere.rotation.y = Math.random() * 200 - 100; + sphere.rotation.z = Math.random() * 200 - 100; + + objects.push( sphere ); + + scene.add( sphere ); + + } + + particleLight = new THREE.Mesh( new THREE.SphereGeometry( 4, 8, 8 ), new THREE.MeshBasicMaterial( { color: 0xffffff } ) ); + scene.add( particleLight ); + + // Lights + + scene.add( new THREE.AmbientLight( 0x111111 ) ); + + var directionalLight = new THREE.DirectionalLight( /*Math.random() * */ 0xffffff, 0.125 ); + + directionalLight.position.x = Math.random() - 0.5; + directionalLight.position.y = Math.random() - 0.5; + directionalLight.position.z = Math.random() - 0.5; + + directionalLight.position.normalize(); + + scene.add( directionalLight ); + + pointLight = new THREE.PointLight( 0xffffff, 1 ); + scene.add( pointLight ); + + // + + renderer = new THREE.WebGLRenderer( { antialias: true } ); + 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 ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + } + + function generateTexture() { + + var canvas = document.createElement( 'canvas' ); + canvas.width = 256; + canvas.height = 256; + + var context = canvas.getContext( '2d' ); + var image = context.getImageData( 0, 0, 256, 256 ); + + var x = 0, y = 0; + + for ( var i = 0, j = 0, l = image.data.length; i < l; i += 4, j ++ ) { + + x = j % 256; + y = x == 0 ? y + 1 : y; + + image.data[ i ] = 255; + image.data[ i + 1 ] = 255; + image.data[ i + 2 ] = 255; + image.data[ i + 3 ] = Math.floor( x ^ y ); + + } + + context.putImageData( image, 0, 0 ); + + return canvas; + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + var timer = 0.0001 * Date.now(); + + camera.position.x = Math.cos( timer ) * 1000; + camera.position.z = Math.sin( timer ) * 1000; + + camera.lookAt( scene.position ); + + for ( var i = 0, l = objects.length; i < l; i ++ ) { + + var object = objects[ i ]; + + object.rotation.x += 0.01; + object.rotation.y += 0.005; + + } + + materials[ materials.length - 3 ].emissive.setHSV( 0.54, 1, 0.7 * ( 0.5 + 0.5 * Math.sin( 35 * timer ) ) ); + materials[ materials.length - 4 ].emissive.setHSV( 0.04, 1, 0.7 * ( 0.5 + 0.5 * Math.cos( 35 * timer ) ) ); + + particleLight.position.x = Math.sin( timer * 7 ) * 300; + particleLight.position.y = Math.cos( timer * 5 ) * 400; + particleLight.position.z = Math.cos( timer * 3 ) * 300; + + pointLight.position.x = particleLight.position.x; + pointLight.position.y = particleLight.position.y; + pointLight.position.z = particleLight.position.z; + + renderer.render( scene, camera ); + + } + +}; + +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_materials2.html + +()=>{ + + if ( ! Detector.webgl ) Detector.addGetWebGLMessage(); + + var container, stats; + + var camera, scene, renderer, objects; + var particleLight, pointLight; + + init(); + animate(); + + function init() { + + container = document.createElement( 'div' ); + document.body.appendChild( container ); + + camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 2000 ); + camera.position.set( 0, 200, 0 ); + + scene = new THREE.Scene(); + + // Materials + + var imgTexture2 = THREE.ImageUtils.loadTexture( "textures/planets/moon_1024.jpg" ); + imgTexture2.wrapS = imgTexture2.wrapT = THREE.RepeatWrapping; + imgTexture2.anisotropy = 16; + + var imgTexture = THREE.ImageUtils.loadTexture( "textures/lava/lavatile.jpg" ); + imgTexture.repeat.set( 4, 2 ); + imgTexture.wrapS = imgTexture.wrapT = THREE.RepeatWrapping; + imgTexture.anisotropy = 16; + + var shininess = 50, specular = 0x333333, bumpScale = 1, shading = THREE.SmoothShading; + + var materials = []; + + materials.push( new THREE.MeshPhongMaterial( { map: imgTexture, bumpMap: imgTexture, bumpScale: bumpScale, color: 0xffffff, ambient: 0x777777, specular: specular, shininess: shininess, shading: shading } ) ); + materials.push( new THREE.MeshPhongMaterial( { map: imgTexture, bumpMap: imgTexture, bumpScale: bumpScale, color: 0x00ff00, ambient: 0x777777, specular: specular, shininess: shininess, shading: shading } ) ); + materials.push( new THREE.MeshPhongMaterial( { map: imgTexture, bumpMap: imgTexture, bumpScale: bumpScale, color: 0x00ff00, ambient: 0x007700, specular: specular, shininess: shininess, shading: shading } ) ); + materials.push( new THREE.MeshPhongMaterial( { map: imgTexture, bumpMap: imgTexture, bumpScale: bumpScale, color: 0x000000, ambient: 0x00ff00, specular: specular, shininess: shininess, shading: shading } ) ); + + materials.push( new THREE.MeshLambertMaterial( { map: imgTexture, color: 0xffffff, ambient: 0x777777, shading: shading } ) ); + materials.push( new THREE.MeshLambertMaterial( { map: imgTexture, color: 0xff0000, ambient: 0x777777, shading: shading } ) ); + materials.push( new THREE.MeshLambertMaterial( { map: imgTexture, color: 0xff0000, ambient: 0x770000, shading: shading } ) ); + materials.push( new THREE.MeshLambertMaterial( { map: imgTexture, color: 0x000000, ambient: 0xff0000, shading: shading } ) ); + + shininess = 15; + + materials.push( new THREE.MeshPhongMaterial( { map: imgTexture2, bumpMap: imgTexture2, bumpScale: bumpScale, color: 0x000000, ambient: 0x000000, specular: 0xffaa00, shininess: shininess, metal: true, shading: shading } ) ); + materials.push( new THREE.MeshPhongMaterial( { map: imgTexture2, bumpMap: imgTexture2, bumpScale: bumpScale, color: 0x000000, ambient: 0x000000, specular: 0xaaff00, shininess: shininess, metal: true, shading: shading } ) ); + materials.push( new THREE.MeshPhongMaterial( { map: imgTexture2, bumpMap: imgTexture2, bumpScale: bumpScale, color: 0x000000, ambient: 0x000000, specular: 0x00ffaa, shininess: shininess, metal: true, shading: shading } ) ); + materials.push( new THREE.MeshPhongMaterial( { map: imgTexture2, bumpMap: imgTexture2, bumpScale: bumpScale, color: 0x000000, ambient: 0x000000, specular: 0x00aaff, shininess: shininess, metal: true, shading: shading } ) ); + + // Spheres geometry + + var geometry_smooth = new THREE.SphereGeometry( 70, 32, 16 ); + var geometry_flat = new THREE.SphereGeometry( 70, 32, 16 ); + + objects = []; + + var sphere, geometry, material; + + for ( var i = 0, l = materials.length; i < l; i ++ ) { + + material = materials[ i ]; + + geometry = material.shading == THREE.FlatShading ? geometry_flat : geometry_smooth; + + sphere = new THREE.Mesh( geometry, material ); + + sphere.position.x = ( i % 4 ) * 200 - 200; + sphere.position.z = Math.floor( i / 4 ) * 200 - 200; + + objects.push( sphere ); + + scene.add( sphere ); + + } + + particleLight = new THREE.Mesh( new THREE.SphereGeometry( 4, 8, 8 ), new THREE.MeshBasicMaterial( { color: 0xffffff } ) ); + scene.add( particleLight ); + + // Lights + + scene.add( new THREE.AmbientLight( 0x444444 ) ); + + var directionalLight = new THREE.DirectionalLight( 0xffffff, 1 ); + directionalLight.position.set( 1, 1, 1 ).normalize(); + scene.add( directionalLight ); + + pointLight = new THREE.PointLight( 0xffffff, 2, 800 ); + scene.add( pointLight ); + + particleLight.material.color = pointLight.color; + pointLight.position = particleLight.position; + + // + + renderer = new THREE.WebGLRenderer( { clearColor: 0x0a0a0a, clearAlpha: 1, antialias: true } ); + renderer.setSize( window.innerWidth, window.innerHeight ); + renderer.sortObjects = true; + + container.appendChild( renderer.domElement ); + + renderer.gammaInput = true; + renderer.gammaOutput = true; + renderer.physicallyBasedShading = true; + + // + + stats = new Stats(); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.top = '0px'; + + container.appendChild( stats.domElement ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + var timer = Date.now() * 0.00025; + + camera.position.x = Math.cos( timer ) * 800; + camera.position.z = Math.sin( timer ) * 800; + + camera.lookAt( scene.position ); + + for ( var i = 0, l = objects.length; i < l; i ++ ) { + + var object = objects[ i ]; + + object.rotation.y += 0.005; + + } + + particleLight.position.x = Math.sin( timer * 7 ) * 300; + particleLight.position.y = Math.cos( timer * 5 ) * 400; + particleLight.position.z = Math.cos( timer * 3 ) * 300; + + renderer.render( scene, camera ); + + } + +}; + +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_materials_blending.html + +()=>{ + + if ( ! Detector.webgl ) Detector.addGetWebGLMessage(); + + var camera, scene, renderer; + var mesh; + + init(); + animate(); + + function init() { + + // CAMERA + + camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 ); + camera.position.z = 600; + + // SCENE + + scene = new THREE.Scene(); + + // BACKGROUND + + var x = document.createElement( "canvas" ); + var xc = x.getContext( "2d" ); + x.width = x.height = 128; + xc.fillStyle = "#ddd"; + xc.fillRect( 0, 0, 128, 128 ); + xc.fillStyle = "#555"; + xc.fillRect( 0, 0, 64, 64 ); + xc.fillStyle = "#999"; + xc.fillRect( 32, 32, 32, 32 ); + xc.fillStyle = "#555"; + xc.fillRect( 64, 64, 64, 64 ); + xc.fillStyle = "#777"; + xc.fillRect( 96, 96, 32, 32 ); + + var mapBg = new THREE.Texture( x ); + mapBg.wrapS = mapBg.wrapT = THREE.RepeatWrapping; + mapBg.repeat.set( 128, 64 ); + mapBg.needsUpdate = true; + + /* + var mapBg = THREE.ImageUtils.loadTexture( "textures/disturb.jpg" ); + mapBg.wrapS = mapBg.wrapT = THREE.RepeatWrapping; + mapBg.repeat.set( 8, 4 ); + */ + + var materialBg = new THREE.MeshBasicMaterial( { map: mapBg } ); + + var meshBg = new THREE.Mesh( new THREE.PlaneGeometry( 4000, 2000 ), materialBg ); + meshBg.position.set( 0, 0, -1 ); + scene.add( meshBg ); + + // OBJECTS + + var blendings = [ "NoBlending", "NormalBlending", "AdditiveBlending", "SubtractiveBlending", "MultiplyBlending", "AdditiveAlphaBlending" ]; + + var map0 = THREE.ImageUtils.loadTexture( 'textures/ash_uvgrid01.jpg' ); + var map1 = THREE.ImageUtils.loadTexture( 'textures/sprite0.jpg' ); + var map2 = THREE.ImageUtils.loadTexture( 'textures/sprite0.png' ); + var map3 = THREE.ImageUtils.loadTexture( 'textures/lensflare/lensflare0.png' ); + var map4 = THREE.ImageUtils.loadTexture( 'textures/lensflare/lensflare0_alpha.png' ); + + var geo1 = new THREE.PlaneGeometry( 100, 100 ); + var geo2 = new THREE.PlaneGeometry( 100, 25 ); + + addImageRow( map0, 300 ); + addImageRow( map1, 150 ); + addImageRow( map2, 0 ); + addImageRow( map3, -150 ); + addImageRow( map4, -300 ); + + function addImageRow( map, y ) { + + for ( var i = 0; i < blendings.length; i ++ ) { + + var blending = blendings[ i ]; + + var material = new THREE.MeshBasicMaterial( { map: map } ); + material.transparent = true; + material.blending = THREE[ blending ]; + + var x = ( i - blendings.length / 2 ) * 110; + var z = 0; + + var mesh = new THREE.Mesh( geo1, material ); + mesh.position.set( x, y, z ); + scene.add( mesh ); + + + var mesh = new THREE.Mesh( geo2, generateLabelMaterial( blending.replace( "Blending", "" ) ) ); + mesh.position.set( x, y - 75, z ); + scene.add( mesh ); + + } + + } + + // RENDERER + + renderer = new THREE.WebGLRenderer( { clearColor: 0x000000, clearAlpha: 1 } ); + renderer.setSize( window.innerWidth, window.innerHeight ); + document.body.appendChild( renderer.domElement ); + + // EVENTS + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + // + + function onWindowResize( event ) { + + var SCREEN_WIDTH = window.innerWidth; + var SCREEN_HEIGHT = window.innerHeight; + + renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT ); + + camera.aspect = SCREEN_WIDTH / SCREEN_HEIGHT; + camera.updateProjectionMatrix(); + + } + + + function generateLabelMaterial( text ) { + + var x = document.createElement( "canvas" ); + var xc = x.getContext( "2d" ); + x.width = 128; + x.height = 32; + + xc.fillStyle = "rgba( 0, 0, 0, 0.95 )"; + xc.fillRect( 0, 0, 128, 32 ); + + xc.fillStyle = "white"; + xc.font = "12pt arial bold"; + xc.fillText( text, 10, 22 ); + + var map = new THREE.Texture( x ); + map.needsUpdate = true; + + var material = new THREE.MeshBasicMaterial( { map: map, transparent: true } ); + return material; + + } + + function animate() { + + requestAnimationFrame( animate ); + renderer.render( scene, camera ); + + } + +}; + +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_materials_blending_custom.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_materials_bumpmap.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_materials_bumpmap_skin.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_materials_cars.html + +()=>{ + + if ( ! Detector.webgl ) Detector.addGetWebGLMessage(); + + var STATS_ENABLED = false; + + var CARS = { + + "veyron": { + + name: "Bugatti Veyron", + url: "obj/veyron/VeyronNoUv_bin.js", + author: 'Troyano', + init_rotation: [ 0, 0, 0 ], + scale: 5.5, + init_material: 4, + body_materials: [ 2 ], + + object: null, + buttons: null, + materials: null + + }, + + "gallardo": { + + name: "Lamborghini Gallardo", + url: "obj/gallardo/GallardoNoUv_bin.js", + author: 'machman_3d', + init_rotation: [ 0, 0, 0 ], + scale: 3.7, + init_material: 9, + body_materials: [ 3 ], + + object: null, + buttons: null, + materials: null + + }, + + "f50": { + + name: "Ferrari F50", + url: "obj/f50/F50NoUv_bin.js", + author: 'daniel sathya', + init_rotation: [ 0, 0, 0 ], + scale: 0.175, + init_material: 2, + body_materials: [ 3, 6, 7, 8, 9, 10, 23, 24 ], + + object: null, + buttons: null, + materials: null + + }, + + "camaro": { + + name: "Chevrolet Camaro", + url: "obj/camaro/CamaroNoUv_bin.js", + author: 'dskfnwn', + init_rotation: [ 0.0, 0.0, 0.0 /*0, 1, 0*/ ], + scale: 75, + init_material: 0, + body_materials: [ 0 ], + + object: null, + buttons: null, + materials: null + + } + + }; + + + var container, stats; + + var camera, scene, renderer; + var cameraCube, sceneCube; + + var m, mi; + + var directionalLight, pointLight; + + var mouseX = 0, mouseY = 0; + + var windowHalfX = window.innerWidth / 2; + var windowHalfY = window.innerHeight / 2; + + var loader = new THREE.BinaryLoader( true ); + document.body.appendChild( loader.statusDomElement ); + + init(); + animate(); + + function init() { + + container = document.createElement( 'div' ); + document.body.appendChild( container ); + + // CAMERAS + + camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 100000 ); + cameraCube = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 100000 ); + + // SCENE + + scene = new THREE.Scene(); + sceneCube = new THREE.Scene(); + + // LIGHTS + + var ambient = new THREE.AmbientLight( 0x050505 ); + scene.add( ambient ); + + directionalLight = new THREE.DirectionalLight( 0xffffff, 2 ); + directionalLight.position.set( 2, 1.2, 10 ).normalize(); + scene.add( directionalLight ); + + directionalLight = new THREE.DirectionalLight( 0xffffff, 1 ); + directionalLight.position.set( -2, 1.2, -10 ).normalize(); + scene.add( directionalLight ); + + pointLight = new THREE.PointLight( 0xffaa00, 2 ); + pointLight.position.set( 2000, 1200, 10000 ); + scene.add( pointLight ); + + // Skybox + + var shader = THREE.ShaderLib[ "cube" ]; + shader.uniforms[ "tCube" ].value = textureCube; + + var material = new THREE.ShaderMaterial( { + + fragmentShader: shader.fragmentShader, + vertexShader: shader.vertexShader, + uniforms: shader.uniforms, + depthWrite: false, + side: THREE.BackSide + + } ), + + mesh = new THREE.Mesh( new THREE.CubeGeometry( 100, 100, 100 ), material ); + sceneCube.add( mesh ); + + // + + renderer = new THREE.WebGLRenderer(); + renderer.setSize( window.innerWidth, window.innerHeight ); + renderer.setFaceCulling( THREE.CullFaceNone ); + renderer.autoClear = false; + + container.appendChild( renderer.domElement ); + + if ( STATS_ENABLED ) { + + stats = new Stats(); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.top = '0px'; + stats.domElement.style.zIndex = 100; + container.appendChild( stats.domElement ); + + } + + document.addEventListener( 'mousemove', onDocumentMouseMove, false ); + + var r = "textures/cube/Bridge2/"; + var urls = [ r + "posx.jpg", r + "negx.jpg", + r + "posy.jpg", r + "negy.jpg", + r + "posz.jpg", r + "negz.jpg" ]; + + var textureCube = THREE.ImageUtils.loadTextureCube( urls ); + textureCube.format = THREE.RGBFormat; + + // common materials + + var mlib = { + + "Orange": new THREE.MeshLambertMaterial( { color: 0xff6600, ambient: 0xff2200, envMap: textureCube, combine: THREE.MixOperation, reflectivity: 0.3 } ), + "Blue": new THREE.MeshLambertMaterial( { color: 0x001133, ambient: 0x001133, envMap: textureCube, combine: THREE.MixOperation, reflectivity: 0.3 } ), + "Red": new THREE.MeshLambertMaterial( { color: 0x660000, ambient: 0x330000, envMap: textureCube, combine: THREE.MixOperation, reflectivity: 0.25 } ), + "Black": new THREE.MeshLambertMaterial( { color: 0x000000, ambient: 0x000000, envMap: textureCube, combine: THREE.MixOperation, reflectivity: 0.15 } ), + "White": new THREE.MeshLambertMaterial( { color: 0xffffff, ambient: 0x666666, envMap: textureCube, combine: THREE.MixOperation, reflectivity: 0.25 } ), + + "Carmine": new THREE.MeshPhongMaterial( { color: 0x770000, specular:0xffaaaa, envMap: textureCube, combine: THREE.MultiplyOperation } ), + "Gold": new THREE.MeshPhongMaterial( { color: 0xaa9944, specular:0xbbaa99, shininess:50, envMap: textureCube, combine: THREE.MultiplyOperation } ), + "Bronze": new THREE.MeshPhongMaterial( { color: 0x150505, specular:0xee6600, shininess:10, envMap: textureCube, combine: THREE.MixOperation, reflectivity: 0.25 } ), + "Chrome": new THREE.MeshPhongMaterial( { color: 0xffffff, specular:0xffffff, envMap: textureCube, combine: THREE.MultiplyOperation } ), + + "Orange metal": new THREE.MeshLambertMaterial( { color: 0xff6600, ambient: 0xff2200, envMap: textureCube, combine: THREE.MultiplyOperation } ), + "Blue metal": new THREE.MeshLambertMaterial( { color: 0x001133, ambient: 0x002266, envMap: textureCube, combine: THREE.MultiplyOperation } ), + "Red metal": new THREE.MeshLambertMaterial( { color: 0x770000, envMap: textureCube, combine: THREE.MultiplyOperation } ), + "Green metal": new THREE.MeshLambertMaterial( { color: 0x007711, envMap: textureCube, combine: THREE.MultiplyOperation } ), + "Black metal": new THREE.MeshLambertMaterial( { color: 0x222222, envMap: textureCube, combine: THREE.MultiplyOperation } ), + + "Pure chrome": new THREE.MeshLambertMaterial( { color: 0xffffff, envMap: textureCube } ), + "Dark chrome": new THREE.MeshLambertMaterial( { color: 0x444444, envMap: textureCube } ), + "Darker chrome":new THREE.MeshLambertMaterial( { color: 0x222222, envMap: textureCube } ), + + "Black glass": new THREE.MeshLambertMaterial( { color: 0x101016, envMap: textureCube, opacity: 0.975, transparent: true } ), + "Dark glass": new THREE.MeshLambertMaterial( { color: 0x101046, envMap: textureCube, opacity: 0.25, transparent: true } ), + "Blue glass": new THREE.MeshLambertMaterial( { color: 0x668899, envMap: textureCube, opacity: 0.75, transparent: true } ), + "Light glass": new THREE.MeshBasicMaterial( { color: 0x223344, envMap: textureCube, opacity: 0.25, transparent: true, combine: THREE.MixOperation, reflectivity: 0.25 } ), + + "Red glass": new THREE.MeshLambertMaterial( { color: 0xff0000, opacity: 0.75, transparent: true } ), + "Yellow glass": new THREE.MeshLambertMaterial( { color: 0xffffaa, opacity: 0.75, transparent: true } ), + "Orange glass": new THREE.MeshLambertMaterial( { color: 0x995500, opacity: 0.75, transparent: true } ), + + "Orange glass 50": new THREE.MeshLambertMaterial( { color: 0xffbb00, opacity: 0.5, transparent: true } ), + "Red glass 50": new THREE.MeshLambertMaterial( { color: 0xff0000, opacity: 0.5, transparent: true } ), + + "Fullblack rough": new THREE.MeshLambertMaterial( { color: 0x000000 } ), + "Black rough": new THREE.MeshLambertMaterial( { color: 0x050505 } ), + "Darkgray rough": new THREE.MeshLambertMaterial( { color: 0x090909 } ), + "Red rough": new THREE.MeshLambertMaterial( { color: 0x330500 } ), + + "Darkgray shiny": new THREE.MeshPhongMaterial( { color: 0x000000, specular: 0x050505 } ), + "Gray shiny": new THREE.MeshPhongMaterial( { color: 0x050505, shininess: 20 } ) + + } + + // Gallardo materials + + CARS[ "gallardo" ].materials = { + + body: [ + + [ "Orange", mlib[ "Orange" ] ], + [ "Blue", mlib[ "Blue" ] ], + [ "Red", mlib[ "Red" ] ], + [ "Black", mlib[ "Black" ] ], + [ "White", mlib[ "White" ] ], + + [ "Orange metal", mlib[ "Orange metal" ] ], + [ "Blue metal", mlib[ "Blue metal" ] ], + [ "Green metal", mlib[ "Green metal" ] ], + [ "Black metal", mlib[ "Black metal" ] ], + + [ "Carmine", mlib[ "Carmine" ] ], + [ "Gold", mlib[ "Gold" ] ], + [ "Bronze", mlib[ "Bronze" ] ], + [ "Chrome", mlib[ "Chrome" ] ] + + ] + + } + + m = CARS[ "gallardo" ].materials; + mi = CARS[ "gallardo" ].init_material; + + CARS[ "gallardo" ].mmap = { + + 0: mlib[ "Pure chrome" ], // wheels chrome + 1: mlib[ "Black rough" ], // tire + 2: mlib[ "Black glass" ], // windshield + 3: m.body[ mi ][ 1 ], // body + 4: mlib[ "Red glass" ], // back lights + 5: mlib[ "Yellow glass" ], // front lights + 6: mlib[ "Dark chrome" ] // windshield rim + + } + + // Veyron materials + + CARS[ "veyron" ].materials = { + + body: [ + + [ "Orange metal", mlib[ "Orange metal" ] ], + [ "Blue metal", mlib[ "Blue metal" ] ], + [ "Red metal", mlib[ "Red metal" ] ], + [ "Green metal", mlib[ "Green metal" ] ], + [ "Black metal", mlib[ "Black metal" ] ], + + [ "Gold", mlib[ "Gold" ] ], + [ "Bronze", mlib[ "Bronze" ] ], + [ "Chrome", mlib[ "Chrome" ] ] + + ], + + } + + m = CARS[ "veyron" ].materials; + mi = CARS[ "veyron" ].init_material; + + CARS[ "veyron" ].mmap = { + + 0: mlib[ "Black rough" ], // tires + inside + 1: mlib[ "Pure chrome" ], // wheels + extras chrome + 2: m.body[ mi ][ 1 ], // back / top / front torso + 3: mlib[ "Dark glass" ], // glass + 4: mlib[ "Pure chrome" ], // sides torso + 5: mlib[ "Pure chrome" ], // engine + 6: mlib[ "Red glass 50" ], // backlights + 7: mlib[ "Orange glass 50" ] // backsignals + + } + + // F50 materials + + CARS[ "f50" ].materials = { + + body: [ + + [ "Orange", mlib[ "Orange" ] ], + [ "Blue", mlib[ "Blue" ] ], + [ "Red", mlib[ "Red" ] ], + [ "Black", mlib[ "Black" ] ], + [ "White", mlib[ "White" ] ], + + [ "Orange metal", mlib[ "Orange metal" ] ], + [ "Blue metal", mlib[ "Blue metal" ] ], + [ "Black metal", mlib[ "Black metal" ] ], + + [ "Carmine", mlib[ "Carmine" ] ], + [ "Gold", mlib[ "Gold" ] ], + [ "Bronze", mlib[ "Bronze" ] ], + [ "Chrome", mlib[ "Chrome" ] ] + + ], + + } + + m = CARS[ "f50" ].materials; + mi = CARS[ "f50" ].init_material; + + CARS[ "f50" ].mmap = { + + 0: mlib[ "Dark chrome" ], // interior + rim + 1: mlib[ "Pure chrome" ], // wheels + gears chrome + 2: mlib[ "Blue glass" ], // glass + 3: m.body[ mi ][ 1 ], // torso mid + front spoiler + 4: mlib[ "Darkgray shiny" ], // interior + behind seats + 5: mlib[ "Darkgray shiny" ], // tiny dots in interior + 6: m.body[ mi ][ 1 ], // back torso + 7: m.body[ mi ][ 1 ], // right mirror decal + 8: m.body[ mi ][ 1 ], // front decal + 9: m.body[ mi ][ 1 ], // front torso + 10: m.body[ mi ][ 1 ], // left mirror decal + 11: mlib[ "Pure chrome" ], // engine + 12: mlib[ "Darkgray rough" ], // tires side + 13: mlib[ "Darkgray rough" ], // tires bottom + 14: mlib[ "Darkgray shiny" ], // bottom + 15: mlib[ "Black rough" ], // ??? + 16: mlib[ "Orange glass" ], // front signals + 17: mlib[ "Dark chrome" ], // wheels center + 18: mlib[ "Red glass" ], // back lights + 19: mlib[ "Black rough" ], // ??? + 20: mlib[ "Red rough" ], // seats + 21: mlib[ "Black rough" ], // back plate + 22: mlib[ "Black rough" ], // front light dots + 23: m.body[ mi ][ 1 ], // back torso + 24: m.body[ mi ][ 1 ] // back torso center + + } + + + // Camero materials + + CARS[ "camaro" ].materials = { + + body: [ + + [ "Orange", mlib[ "Orange" ] ], + [ "Blue", mlib[ "Blue" ] ], + [ "Red", mlib[ "Red" ] ], + [ "Black", mlib[ "Black" ] ], + [ "White", mlib[ "White" ] ], + + [ "Orange metal", mlib[ "Orange metal" ] ], + [ "Blue metal", mlib[ "Blue metal" ] ], + [ "Red metal", mlib[ "Red metal" ] ], + [ "Green metal", mlib[ "Green metal" ] ], + [ "Black metal", mlib[ "Black metal" ] ], + + [ "Gold", mlib[ "Gold" ] ], + [ "Bronze", mlib[ "Bronze" ] ], + [ "Chrome", mlib[ "Chrome" ] ] + + ], + + } + + m = CARS[ "camaro" ].materials; + mi = CARS[ "camaro" ].init_material; + + CARS[ "camaro" ].mmap = { + + 0: m.body[ mi ][ 1 ], // car body + 1: mlib[ "Pure chrome" ], // wheels chrome + 2: mlib[ "Pure chrome" ], // grille chrome + 3: mlib[ "Dark chrome" ], // door lines + 4: mlib[ "Light glass" ], // windshield + 5: mlib[ "Gray shiny" ], // interior + 6: mlib[ "Black rough" ], // tire + 7: mlib[ "Fullblack rough" ], // tireling + 8: mlib[ "Fullblack rough" ] // behind grille + + } + + loader.load( CARS[ "veyron" ].url, function( geometry ) { createScene( geometry, "veyron" ) } ); + + for( var c in CARS ) initCarButton( c ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + windowHalfX = window.innerWidth / 2; + windowHalfY = window.innerHeight / 2; + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + cameraCube.aspect = window.innerWidth / window.innerHeight; + cameraCube.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + } + + function initCarButton( car ) { + + $( car ).addEventListener( 'click', function() { + + if ( ! CARS[ car ].object ) { + + loader.statusDomElement.style.display = "block"; + loader.load( CARS[ car ].url, function( geometry ) { createScene( geometry, car ) } ); + + } else { + + switchCar( car ); + + } + + }, false ); + + } + + function $( id ) { return document.getElementById( id ) } + function button_name( car, index ) { return "m_" + car + "_" + index } + + function switchCar( car ) { + + for ( var c in CARS ) { + + if ( c != car && CARS[ c ].object ) { + + CARS[ c ].object.visible = false; + CARS[ c ].buttons.style.display = "none"; + + } + } + + CARS[ car ].object.visible = true; + CARS[ car ].buttons.style.display = "block"; + + $( "car_name" ).innerHTML = CARS[ car ].name + " model"; + $( "car_author" ).innerHTML = CARS[ car ].author; + + } + + function createButtons( materials, car ) { + + var buttons, i, src = ""; + + for( i = 0; i < materials.length; i ++ ) { + + src += ' '; + + } + + buttons = document.createElement( "div" ); + buttons.innerHTML = src; + + $( "buttons_materials" ).appendChild( buttons ); + + return buttons; + + } + + function attachButtonMaterials( materials, faceMaterial, material_indices, car ) { + + for( var i = 0; i < materials.length; i ++ ) { + + $( button_name( car, i ) )["counter"] = i; + $( button_name( car, i ) ).addEventListener( 'click', function() { + + for ( var j = 0; j < material_indices.length; j ++ ) { + + faceMaterial.materials[ material_indices [ j ] ] = materials[ this.counter ][ 1 ]; + + } + + }, false ); + + } + + } + + function createScene( geometry, car ) { + + loader.statusDomElement.innerHTML = "Creating model ..."; + + var m = new THREE.MeshFaceMaterial(), + s = CARS[ car ].scale * 1, + r = CARS[ car ].init_rotation, + materials = CARS[ car ].materials, + mi = CARS[ car ].init_material, + bm = CARS[ car ].body_materials; + + for ( var i in CARS[ car ].mmap ) { + + m.materials[ i ] = CARS[ car ].mmap[ i ]; + + } + + var mesh = new THREE.Mesh( geometry, m ); + + mesh.rotation.x = r[ 0 ]; + mesh.rotation.y = r[ 1 ]; + mesh.rotation.z = r[ 2 ]; + + mesh.scale.x = mesh.scale.y = mesh.scale.z = s; + + scene.add( mesh ); + + CARS[ car ].object = mesh; + + CARS[ car ].buttons = createButtons( materials.body, car ); + attachButtonMaterials( materials.body, m, bm, car ); + + switchCar( car ); + + loader.statusDomElement.style.display = "none"; + loader.statusDomElement.innerHTML = "Loading model ..."; + + } + + function onDocumentMouseMove(event) { + + mouseY = ( event.clientY - window.innerHeight ); + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + + } + + function render() { + + var timer = -0.0002 * Date.now(); + + camera.position.x = 1000 * Math.cos( timer ); + camera.position.y += ( - mouseY - camera.position.y ) * .05; + camera.position.z = 1000 * Math.sin( timer ); + + camera.lookAt( scene.position ); + cameraCube.rotation.copy( camera.rotation ); + + renderer.render( sceneCube, cameraCube ); + renderer.render( scene, camera ); + + if ( STATS_ENABLED ) stats.update(); + + } + +}; + +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_materials_cars_anaglyph.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_materials_cars_camaro.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_materials_cars_camaro_crosseyed.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_materials_cars_parallaxbarrier.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_materials_cubemap.html + +()=>{ + + if ( ! Detector.webgl ) Detector.addGetWebGLMessage(); + + var container, stats; + + var camera, scene, renderer; + var cameraCube, sceneCube; + + var mesh, lightMesh, geometry; + + var loader; + + var directionalLight, pointLight; + + var mouseX = 0; + var mouseY = 0; + + var windowHalfX = window.innerWidth / 2; + var windowHalfY = window.innerHeight / 2; + + document.addEventListener('mousemove', onDocumentMouseMove, false); + + init(); + animate(); + + function init() { + + container = document.createElement( 'div' ); + document.body.appendChild( container ); + + camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 5000 ); + camera.position.z = 2000; + + cameraCube = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 100 ); + + scene = new THREE.Scene(); + sceneCube = new THREE.Scene(); + + // LIGHTS + + var ambient = new THREE.AmbientLight( 0xffffff ); + scene.add( ambient ); + + pointLight = new THREE.PointLight( 0xffffff, 2 ); + scene.add( pointLight ); + + // light representation + + var sphere = new THREE.SphereGeometry( 100, 16, 8 ); + lightMesh = new THREE.Mesh( sphere, new THREE.MeshBasicMaterial( { color: 0xffaa00 } ) ); + lightMesh.position = pointLight.position; + lightMesh.scale.x = lightMesh.scale.y = lightMesh.scale.z = 0.05; + scene.add( lightMesh ); + + var path = "textures/cube/SwedishRoyalCastle/"; + var format = '.jpg'; + var urls = [ + path + 'px' + format, path + 'nx' + format, + path + 'py' + format, path + 'ny' + format, + path + 'pz' + format, path + 'nz' + format + ]; + + var reflectionCube = THREE.ImageUtils.loadTextureCube( urls ); + reflectionCube.format = THREE.RGBFormat; + + var refractionCube = new THREE.Texture( reflectionCube.image, new THREE.CubeRefractionMapping() ); + refractionCube.format = THREE.RGBFormat; + + //var cubeMaterial3 = new THREE.MeshPhongMaterial( { color: 0x000000, specular:0xaa0000, envMap: reflectionCube, combine: THREE.MixOperation, reflectivity: 0.25 } ); + var cubeMaterial3 = new THREE.MeshLambertMaterial( { color: 0xff6600, ambient: 0x993300, envMap: reflectionCube, combine: THREE.MixOperation, reflectivity: 0.3 } ); + var cubeMaterial2 = new THREE.MeshLambertMaterial( { color: 0xffee00, ambient: 0x996600, envMap: refractionCube, refractionRatio: 0.95 } ); + var cubeMaterial1 = new THREE.MeshLambertMaterial( { color: 0xffffff, ambient: 0xaaaaaa, envMap: reflectionCube } ) + + // Skybox + + var shader = THREE.ShaderLib[ "cube" ]; + shader.uniforms[ "tCube" ].value = reflectionCube; + + var material = new THREE.ShaderMaterial( { + + fragmentShader: shader.fragmentShader, + vertexShader: shader.vertexShader, + uniforms: shader.uniforms, + depthWrite: false, + side: THREE.BackSide + + } ), + + mesh = new THREE.Mesh( new THREE.CubeGeometry( 100, 100, 100 ), material ); + sceneCube.add( mesh ); + + // + + renderer = new THREE.WebGLRenderer(); + renderer.setSize( window.innerWidth, window.innerHeight ); + renderer.autoClear = false; + container.appendChild( renderer.domElement ); + + // + + stats = new Stats(); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.top = '0px'; + stats.domElement.style.zIndex = 100; + container.appendChild( stats.domElement ); + + // + + loader = new THREE.BinaryLoader( true ); + document.body.appendChild( loader.statusDomElement ); + + loader.load( "obj/walt/WaltHead_bin.js", function( geometry ) { createScene( geometry, cubeMaterial1, cubeMaterial2, cubeMaterial3 ) } ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + windowHalfX = window.innerWidth / 2; + windowHalfY = window.innerHeight / 2; + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + cameraCube.aspect = window.innerWidth / window.innerHeight; + cameraCube.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + } + + function createScene( geometry, m1, m2, m3 ) { + + var s = 15; + + var mesh = new THREE.Mesh( geometry, m1 ); + mesh.position.z = - 100; + mesh.scale.x = mesh.scale.y = mesh.scale.z = s; + scene.add( mesh ); + + var mesh = new THREE.Mesh( geometry, m2 ); + mesh.position.x = - 900; + mesh.position.z = - 100; + mesh.scale.x = mesh.scale.y = mesh.scale.z = s; + scene.add( mesh ); + + var mesh = new THREE.Mesh( geometry, m3 ); + mesh.position.x = 900; + mesh.position.z = - 100; + mesh.scale.x = mesh.scale.y = mesh.scale.z = s; + scene.add( mesh ); + + loader.statusDomElement.style.display = "none"; + + } + + function onDocumentMouseMove(event) { + + mouseX = ( event.clientX - windowHalfX ) * 4; + mouseY = ( event.clientY - windowHalfY ) * 4; + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + var timer = -0.0002 * Date.now(); + + lightMesh.position.x = 1500 * Math.cos( timer ); + lightMesh.position.z = 1500 * Math.sin( timer ); + + camera.position.x += ( mouseX - camera.position.x ) * .05; + camera.position.y += ( - mouseY - camera.position.y ) * .05; + + camera.lookAt( scene.position ); + cameraCube.rotation.copy( camera.rotation ); + + renderer.render( sceneCube, cameraCube ); + renderer.render( scene, camera ); + + } + +}; + +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_materials_cubemap_balls_reflection.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_materials_cubemap_balls_reflection_anaglyph.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_materials_cubemap_balls_refraction.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_materials_cubemap_balls_refraction_crosseyed.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_materials_cubemap_dynamic.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_materials_cubemap_dynamic2.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_materials_cubemap_escher.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_materials_cubemap_refraction.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_materials_grass.html + +()=>{ + + if ( ! Detector.webgl ) Detector.addGetWebGLMessage(); + + var camera, scene, renderer, + mesh, levels = []; + + init(); + animate(); + + function init() { + + camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 1000 ); + camera.position.set( 0, 75, 100 ); + + scene = new THREE.Scene(); + + var geometry = new THREE.PlaneGeometry( 100, 100 ); + + var bitmap = generateTextureBase(); + + for ( var i = 0; i < 15; i ++ ) { + + mesh = levels[ i ] = new THREE.Mesh( geometry, new THREE.MeshBasicMaterial( { map: new THREE.Texture( generateTextureLevel( bitmap ) ), transparent: true, depthWrite: false, depthTest: false } ) ); + mesh.material.map.needsUpdate = true; + + mesh.position.y = i * 0.25; + mesh.rotation.x = - Math.PI / 2; + + scene.add( mesh ); + + } + + renderer = new THREE.WebGLRenderer(); + renderer.sortObjects = false; + renderer.setSize( window.innerWidth, window.innerHeight ); + document.body.appendChild( renderer.domElement ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + } + + function generateTextureBase() { + + var canvas = document.createElement( 'canvas' ); + canvas.width = 512; + canvas.height = 512; + + var context = canvas.getContext( '2d' ); + + for ( var i = 0; i < 20000; i ++ ) { + + context.fillStyle = 'rgba(0,' + Math.floor( Math.random() * 64 + 32 ) + ',16,1)'; + context.beginPath(); + context.arc( Math.random() * canvas.width, Math.random() * canvas.height, Math.random() * 1 + 0.5, 0, Math.PI * 2, true ); + context.closePath(); + context.fill(); + + } + + context.globalAlpha = 0.075; + context.globalCompositeOperation = 'lighter'; + + return canvas; + + } + + function generateTextureLevel( texture ) { + + texture.getContext( '2d' ).drawImage( texture, 0, 0 ); + + var canvas = document.createElement( 'canvas' ); + canvas.width = texture.width; + canvas.height = texture.height; + + canvas.getContext( '2d' ).drawImage( texture, 0, 0 ); + + return canvas; + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + + } + + function render() { + + var time = Date.now() / 6000; + + camera.position.x = 80 * Math.cos( time ); + camera.position.z = 80 * Math.sin( time ); + + camera.lookAt( scene.position ); + + for ( var i = 0, l = levels.length; i < l; i ++ ) { + + mesh = levels[ i ]; + mesh.position.x = Math.sin( time * 4 ) * i * i * 0.005; + mesh.position.z = Math.cos( time * 6 ) * i * i * 0.005; + + } + + renderer.render( scene, camera ); + + } + +}; + +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_materials_lightmap.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_materials_normalmap.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_materials_normalmap2.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_materials_shaders.html + +()=>{ + + var SCREEN_WIDTH = window.innerWidth; + var SCREEN_HEIGHT = window.innerHeight; + var FLOOR = -250; + + var container, stats; + + var camera, scene, canvasRenderer, webglRenderer; + + var mesh, zmesh, lightMesh, geometry; + + var directionalLight, pointLight; + + var mouseX = 0, mouseY = 0; + + var windowHalfX = window.innerWidth / 2; + var windowHalfY = window.innerHeight / 2; + + var render_canvas = false, render_gl = true; + var has_gl = false; + + var bcanvas = document.getElementById( "rcanvas" ); + var bwebgl = document.getElementById( "rwebgl" ); + + init(); + animate(); + + render_canvas = !has_gl; + bwebgl.style.display = has_gl ? "inline" : "none"; + bcanvas.className = render_canvas ? "button" : "button inactive"; + + function addMesh( geometry, scale, x, y, z, rx, ry, rz, material ) { + + mesh = new THREE.Mesh( geometry, material ); + + mesh.scale.set( scale, scale, scale ); + mesh.position.set( x, y, z ); + mesh.rotation.set( rx, ry, rz ); + + scene.add( mesh ); + + } + + function init() { + + container = document.createElement( 'div' ); + document.body.appendChild( container ); + + camera = new THREE.PerspectiveCamera( 75, SCREEN_WIDTH / SCREEN_HEIGHT, 1, 100000 ); + camera.position.z = 1000; + + scene = new THREE.Scene(); + + // LIGHTS + + var ambient = new THREE.AmbientLight( 0x101010 ); + scene.add( ambient ); + + directionalLight = new THREE.DirectionalLight( 0xffffff ); + directionalLight.position.set( 1, 1, 2 ).normalize(); + scene.add( directionalLight ); + + pointLight = new THREE.PointLight( 0xffffff ); + scene.add( pointLight ); + + // light representation + + var sphere = new THREE.SphereGeometry( 100, 16, 8 ); + lightMesh = new THREE.Mesh( sphere, new THREE.MeshBasicMaterial( { color: 0xffaa00 } ) ); + lightMesh.scale.set( 0.05, 0.05, 0.05 ); + lightMesh.position = pointLight.position; + scene.add( lightMesh ); + + // material samples + + sphere = new THREE.SphereGeometry( 100, 32, 32 ); + + var y1 = 0, y2 = - 200; + + addMesh( sphere, 1, -600, y1, 0, 0,0,0, new THREE.MeshPhongMaterial( { ambient: 0x050505, color: 0x000000, specular: 0x555555, shininess: 30 } ) ); + addMesh( sphere, 1, -600, y2, 0, 0,0,0, new THREE.MeshLambertMaterial( { color: 0x050505 } ) ); + + addMesh( sphere, 1, -400, y1, 0, 0,0,0, new THREE.MeshPhongMaterial( { ambient: 0x000000, color: 0xffffff, specular: 0x555555, shininess: 30 } ) ); + addMesh( sphere, 1, -400, y2, 0, 0,0,0, new THREE.MeshLambertMaterial( { color: 0xffffff } ) ); + + addMesh( sphere, 1, -200, y1, 0, 0,0,0, new THREE.MeshPhongMaterial( { ambient: 0x000000, color: 0xff5500, specular: 0x555555, shininess: 10 } ) ); + addMesh( sphere, 1, -200, y2, 0, 0,0,0, new THREE.MeshLambertMaterial( { color: 0xff5500 } ) ); + + addMesh( sphere, 1, 0, y1, 0, 0,0,0, new THREE.MeshPhongMaterial( { ambient: 0x000000, color: 0xffaa00, specular: 0x555555, shininess: 30 } ) ); + addMesh( sphere, 1, 0, y2, 0, 0,0,0, new THREE.MeshLambertMaterial( { color: 0xffaa00 } ) ); + + addMesh( sphere, 1, 200, y1, 0, 0,0,0, new THREE.MeshPhongMaterial( { ambient: 0x000000, color: 0x55ff00, specular: 0x555555, shininess: 30 } ) ); + addMesh( sphere, 1, 200, y2, 0, 0,0,0, new THREE.MeshLambertMaterial( { color: 0x55ff00 } ) ); + + addMesh( sphere, 1, 400, y1, 0, 0,0,0, new THREE.MeshPhongMaterial( { ambient: 0x000000, color: 0x0055ff, specular: 0x555555, shininess: 30 } ) ); + addMesh( sphere, 1, 400, y2, 0, 0,0,0, new THREE.MeshLambertMaterial( { color: 0x0055ff } ) ); + + addMesh( sphere, 1, 600, y1, 0, 0,0,0, new THREE.MeshPhongMaterial( { ambient: 0x000000, color: 0x5500ff, specular: 0x555555, shininess: 30 } ) ); + addMesh( sphere, 1, 600, y2, 0, 0,0,0, new THREE.MeshLambertMaterial( { color: 0x5500ff } ) ); + + addToruses( new THREE.TorusGeometry( 100, 20, 32, 32 ) ); + + // + + if ( render_gl ) { + + try { + + webglRenderer = new THREE.WebGLRenderer(); + webglRenderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT ); + webglRenderer.domElement.style.position = "relative"; + container.appendChild( webglRenderer.domElement ); + has_gl = true; + + } catch (e) { + + } + + } + + canvasRenderer = new THREE.CanvasRenderer(); + canvasRenderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT ); + container.appendChild( canvasRenderer.domElement ); + + // + + stats = new Stats(); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.top = '0px'; + stats.domElement.style.zIndex = 100; + container.appendChild( stats.domElement ); + + bcanvas.addEventListener("click", toggleCanvas, false); + bwebgl.addEventListener("click", toggleWebGL, false); + + document.addEventListener('mousemove', onDocumentMouseMove, false); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + windowHalfX = window.innerWidth / 2; + windowHalfY = window.innerHeight / 2; + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + if ( webglRenderer ) webglRenderer.setSize( window.innerWidth, window.innerHeight ); + if ( canvasRenderer ) canvasRenderer.setSize( window.innerWidth, window.innerHeight ); + + } + + function addToruses( geometry ) { + + var s = 0.85, t = s + 100, y = 200, rx = 0; + + addMesh( geometry, s, -6*t, y, 0, rx,0,0, new THREE.MeshPhongMaterial( { ambient: 0x000000, color: 0x000000, specular: 0x333333, shininess: 10 } ) ); + addMesh( geometry, s, -4*t, y, 0, rx,0,0, new THREE.MeshPhongMaterial( { ambient: 0x030303, color: 0x888888, specular: 0x333333, shininess: 10 } ) ); + addMesh( geometry, s, -2*t, y, 0, rx,0,0, new THREE.MeshPhongMaterial( { ambient: 0x030303, color: 0x030303, specular: 0xff5500, shininess: 10 } ) ); + addMesh( geometry, s, 0, y, 0, rx,0,0, new THREE.MeshPhongMaterial( { ambient: 0x030303, color: 0x030303, specular: 0xffaa00, shininess: 10 } ) ); + addMesh( geometry, s, 2*t, y, 0, rx,0,0, new THREE.MeshPhongMaterial( { ambient: 0x030303, color: 0x030303, specular: 0x55ff00, shininess: 10 } ) ); + addMesh( geometry, s, 4*t, y, 0, rx,0,0, new THREE.MeshPhongMaterial( { ambient: 0x030303, color: 0x030303, specular: 0x0055ff, shininess: 10 } ) ); + addMesh( geometry, s, 6*t, y, 0, rx,0,0, new THREE.MeshPhongMaterial( { ambient: 0x030303, color: 0x030303, specular: 0x5500ff, shininess: 10 } ) ); + + } + + + function onDocumentMouseMove(event) { + + mouseX = ( event.clientX - windowHalfX ); + mouseY = ( event.clientY - windowHalfY ); + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + var timer = -0.0002 * Date.now(); + + camera.position.x += ( mouseX - camera.position.x ) * .05; + camera.position.y += ( - mouseY - camera.position.y ) * .05; + + camera.lookAt( scene.position ); + + lightMesh.position.x = 700 * Math.cos( timer ); + lightMesh.position.z = 700 * Math.sin( timer ); + + if ( render_canvas ) canvasRenderer.render( scene, camera ); + if ( render_gl && has_gl ) webglRenderer.render( scene, camera ); + + } + + function toggleCanvas() { + + render_canvas = !render_canvas; + bcanvas.className = render_canvas ? "button" : "button inactive"; + + render_gl = !render_canvas; + bwebgl.className = render_gl ? "button" : "button inactive"; + + if( has_gl ) + webglRenderer.domElement.style.display = render_gl ? "block" : "none"; + + canvasRenderer.domElement.style.display = render_canvas ? "block" : "none"; + + } + + function toggleWebGL() { + + render_gl = !render_gl; + bwebgl.className = render_gl ? "button" : "button inactive"; + + render_canvas = !render_gl; + bcanvas.className = render_canvas ? "button" : "button inactive"; + + if( has_gl ) + webglRenderer.domElement.style.display = render_gl ? "block" : "none"; + + canvasRenderer.domElement.style.display = render_canvas ? "block" : "none"; + + } +}; + +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_materials_shaders_fresnel.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_materials_skin.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_materials_texture_anisotropy.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_materials_texture_compressed.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_materials_texture_filters.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_materials_texture_manualmipmap.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_materials_video.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_materials_wireframe.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_morphnormals.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_morphtargets.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_morphtargets_horse.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_morphtargets_md2.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_morphtargets_md2_control.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_multiple_canvases_circle.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_multiple_canvases_complex.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_multiple_canvases_grid.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_multiple_views.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_panorama_equirectangular.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_particles_billboards.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_particles_billboards_colors.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_particles_dynamic.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_particles_random.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_particles_shapes.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_particles_sprites.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_performance.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_performance_doublesided.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_performance_static.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_postprocessing.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_postprocessing2.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_postprocessing_advanced.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_postprocessing_dof.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_postprocessing_godrays.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_ribbons.html + +()=>{ + + if ( ! Detector.webgl ) Detector.addGetWebGLMessage(); + + var container, stats; + var camera, scene, renderer, ribbon, geometry, geometry2, ribbons = [], + parameters, i, i2, h, color, x, y, z, z2, s, n, n2, nribbons, grid; + + var mouseX = 0, mouseY = 0; + + var windowHalfX = window.innerWidth / 2; + var windowHalfY = window.innerHeight / 2; + + var postprocessing = { enabled : true }; + + var composer; + + init(); + animate(); + + function init() { + + container = document.createElement( 'div' ); + document.body.appendChild( container ); + + camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 3000 ); + camera.position.z = 1200; + + scene = new THREE.Scene(); + scene.fog = new THREE.FogExp2( 0x000000, 0.0016 ); + + geometry = new THREE.Geometry(); + geometry2 = new THREE.Geometry(); + + n = 1000; + n2 = 2 * n; + + for ( i = -n; i < n; i++ ) { + + i2 = i + n; + + x = i * 1.175; + y = ( i2 % 2 ) * 5; + + if ( i2 % 2 ) { + + z = 10 * Math.sin( i2 * 0.3 ) * Math.cos( i2 * 0.1 ); + + } + + geometry.vertices.push( new THREE.Vector3( x, y, z ) ); + geometry2.vertices.push( new THREE.Vector3( x, y, z ) ); + + h = i2 % 2 ? 1 : 0.15; + if( i2 % 4 <= 2 ) h -= 0.15; + + color = new THREE.Color( 0xffffff ); + color.setHSL( 0.1, 0, h ); + geometry.colors.push( color ); + geometry2.colors.push( color ); + + } + + var tmpRot = new THREE.Matrix4(); + tmpRot.makeRotationAxis( new THREE.Vector3( 1, 0, 0 ), Math.PI/2 ); + + var xgrid = 34; + var ygrid = 15; + var nribbons = xgrid * ygrid; + + var c = 0; + for (var i = 0; i < xgrid; i ++ ) + for (var j = 0; j < ygrid; j ++ ) { + + var material = new THREE.MeshBasicMaterial( { color: 0xffffff, vertexColors: THREE.VertexColors, side: THREE.DoubleSide } ); + + ribbon = new THREE.Ribbon( i % 2 ? geometry : geometry2, material ); + ribbon.rotation.x = 0; + ribbon.rotation.y = Math.PI / 2; + ribbon.rotation.z = Math.PI; + + x = 40 * ( i - xgrid/2 ); + y = 40 * ( j - ygrid/2 ); + z = 0; + + ribbon.position.set( x, y, z ); + + ribbon.matrixAutoUpdate = false; + + // manually create local matrix + + ribbon.matrix.setPosition( ribbon.position ); + ribbon.matrixRotationWorld.setRotationFromEuler( ribbon.rotation ); + + ribbon.matrix.elements[ 0 ] = ribbon.matrixRotationWorld.elements[ 0 ]; + ribbon.matrix.elements[ 4 ] = ribbon.matrixRotationWorld.elements[ 4 ]; + ribbon.matrix.elements[ 8 ] = ribbon.matrixRotationWorld.elements[ 8 ]; + + ribbon.matrix.elements[ 1 ] = ribbon.matrixRotationWorld.elements[ 1 ]; + ribbon.matrix.elements[ 5 ] = ribbon.matrixRotationWorld.elements[ 5 ]; + ribbon.matrix.elements[ 9 ] = ribbon.matrixRotationWorld.elements[ 9 ]; + + ribbon.matrix.elements[ 2 ] = ribbon.matrixRotationWorld.elements[ 2 ]; + ribbon.matrix.elements[ 6 ] = ribbon.matrixRotationWorld.elements[ 6 ]; + ribbon.matrix.elements[ 10 ] = ribbon.matrixRotationWorld.elements[ 10 ]; + + ribbon.matrix.multiply( tmpRot ); + + ribbon.matrix.scale( ribbon.scale ); + + ribbons.push( ribbon ); + scene.add( ribbon ); + + c ++; + + } + + scene.matrixAutoUpdate = false; + + // + + renderer = new THREE.WebGLRenderer( { antialias: false } ); + renderer.setSize( window.innerWidth, window.innerHeight ); + renderer.autoClear = false; + renderer.setClearColor( scene.fog.color, 1 ); + + container.appendChild( renderer.domElement ); + + // + + stats = new Stats(); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.top = '0px'; + container.appendChild( stats.domElement ); + + // + + document.addEventListener( 'mousemove', onDocumentMouseMove, false ); + document.addEventListener( 'touchstart', onDocumentTouchStart, false ); + document.addEventListener( 'touchmove', onDocumentTouchMove, false ); + + // + + var renderModel = new THREE.RenderPass( scene, camera ); + var effectBloom = new THREE.BloomPass( 1.0 ); + var effectCopy = new THREE.ShaderPass( THREE.CopyShader ); + + effectCopy.renderToScreen = true; + + composer = new THREE.EffectComposer( renderer ); + + composer.addPass( renderModel ); + composer.addPass( effectBloom ); + composer.addPass( effectCopy ); + + // + + 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 ); + + composer.reset(); + + } + + function onDocumentMouseMove( event ) { + + mouseX = event.clientX - windowHalfX; + mouseY = event.clientY - windowHalfY; + + } + + function onDocumentTouchStart( event ) { + + if ( event.touches.length === 1 ) { + + event.preventDefault(); + + mouseX = event.touches[ 0 ].pageX - windowHalfX; + mouseY = event.touches[ 0 ].pageY - windowHalfY; + + } + + } + + function onDocumentTouchMove( event ) { + + if ( event.touches.length === 1 ) { + + event.preventDefault(); + + mouseX = event.touches[ 0 ].pageX - windowHalfX; + mouseY = event.touches[ 0 ].pageY - windowHalfY; + + } + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + var time = Date.now() * 0.00005; + + camera.position.x += ( mouseX - camera.position.x ) * 0.036; + camera.position.y += ( - mouseY - camera.position.y ) * 0.036; + + camera.lookAt( scene.position ); + + for ( i = -n; i < n; i ++ ) { + + i2 = i + n; + + z = 10 * Math.sin( i2 * 0.1 + time*30 ); + z2 = 20 * Math.cos( Math.sin( i2 * 0.1 + time * 20 ) ); + + geometry.vertices[ i2 ].z = z; + geometry2.vertices[ i2 ].z = z2; + + } + + geometry.verticesNeedUpdate = true; + geometry2.verticesNeedUpdate = true; + + for ( i = 0; i < nribbons; i++ ) { + + h = ( 360 * ( i / nribbons + time ) % 360 ) / 360; + ribbons[ i ].material.color.setHSL( h, ( i % 20 / 20 ) * 0.3 + 0.7, 0.6 ); + + } + + renderer.clear(); + composer.render( 0.1 ); + + } + +}; + +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_rtt.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_sandbox.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_shader.html + +()=>{ + + if ( ! Detector.webgl ) Detector.addGetWebGLMessage(); + + var container, stats; + + var camera, scene, renderer; + + var uniforms, material, mesh; + + var mouseX = 0, mouseY = 0, + lat = 0, lon = 0, phy = 0, theta = 0; + + var windowHalfX = window.innerWidth / 2; + var windowHalfY = window.innerHeight / 2; + + init(); + animate(); + + function init() { + + container = document.getElementById( 'container' ); + + camera = new THREE.Camera(); + camera.position.z = 1; + + scene = new THREE.Scene(); + + uniforms = { + time: { type: "f", value: 1.0 }, + resolution: { type: "v2", value: new THREE.Vector2() } + }; + + material = new THREE.ShaderMaterial( { + + uniforms: uniforms, + vertexShader: document.getElementById( 'vertexShader' ).textContent, + fragmentShader: document.getElementById( 'fragmentShader' ).textContent + + } ); + + mesh = new THREE.Mesh( new THREE.PlaneGeometry( 2, 2 ), material ); + scene.add( mesh ); + + renderer = new THREE.WebGLRenderer(); + container.appendChild( renderer.domElement ); + + stats = new Stats(); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.top = '0px'; + container.appendChild( stats.domElement ); + + onWindowResize(); + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize( event? ) { + + uniforms.resolution.value.x = window.innerWidth; + uniforms.resolution.value.y = window.innerHeight; + renderer.setSize( window.innerWidth, window.innerHeight ); + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + uniforms.time.value += 0.05; + + renderer.render( scene, camera ); + + } + +}; + +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_shader2.html + +()=>{ + + if ( ! Detector.webgl ) Detector.addGetWebGLMessage(); + + var container, stats; + + var start_time; + + var camera, scene, renderer; + + var uniforms1, uniforms2, material1, material2, mesh, meshes = []; + + var mouseX = 0, mouseY = 0, + lat = 0, lon = 0, phy = 0, theta = 0; + + var windowHalfX = window.innerWidth / 2; + var windowHalfY = window.innerHeight / 2; + + var clock = new THREE.Clock(); + + init(); + animate(); + + function init() { + + container = document.getElementById( 'container' ); + + camera = new THREE.PerspectiveCamera( 40, windowHalfX / windowHalfY, 1, 3000 ); + camera.position.z = 4; + + scene = new THREE.Scene(); + + start_time = Date.now(); + + uniforms1 = { + time: { type: "f", value: 1.0 }, + resolution: { type: "v2", value: new THREE.Vector2() } + }; + + uniforms2 = { + time: { type: "f", value: 1.0 }, + resolution: { type: "v2", value: new THREE.Vector2() }, + texture: { type: "t", value: THREE.ImageUtils.loadTexture( "textures/disturb.jpg" ) } + }; + + uniforms2.texture.value.wrapS = uniforms2.texture.value.wrapT = THREE.RepeatWrapping; + + var size = 0.75, mlib = [], + params = [ [ 'fragment_shader1', uniforms1 ], [ 'fragment_shader2', uniforms2 ], [ 'fragment_shader3', uniforms1 ], [ 'fragment_shader4', uniforms1 ] ]; + + for( var i = 0; i < params.length; i++ ) { + + var material = new THREE.ShaderMaterial( { + + uniforms: params[ i ][ 1 ], + vertexShader: document.getElementById( 'vertexShader' ).textContent, + fragmentShader: document.getElementById( params[ i ][ 0 ] ).textContent + + } ); + + mlib[ i ] = material; + + mesh = new THREE.Mesh( new THREE.CubeGeometry( size, size, size ), new THREE.MeshFaceMaterial( [ mlib[ i ], mlib[ i ], mlib[ i ], mlib[ i ], mlib[ i ], mlib[ i ] ] ) ); + mesh.position.x = i - ( params.length - 1 ) / 2; + mesh.position.y = i % 2 - 0.5; + scene.add( mesh ); + + meshes[ i ] = mesh; + + } + + renderer = new THREE.WebGLRenderer(); + container.appendChild( renderer.domElement ); + + stats = new Stats(); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.top = '0px'; + container.appendChild( stats.domElement ); + + onWindowResize(); + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize( event? ) { + + uniforms1.resolution.value.x = window.innerWidth; + uniforms1.resolution.value.y = window.innerHeight; + + uniforms2.resolution.value.x = window.innerWidth; + uniforms2.resolution.value.y = window.innerHeight; + + camera.aspect = window.innerWidth / window.innerHeight; + camera.updateProjectionMatrix(); + + renderer.setSize( window.innerWidth, window.innerHeight ); + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + var delta = clock.getDelta(); + + uniforms1.time.value += delta * 5; + uniforms2.time.value = clock.elapsedTime; + + for( var i = 0; i < meshes.length; ++ i ) { + + meshes[ i ].rotation.y += delta * 0.5 * ( i % 2 ? 1 : -1 ); + meshes[ i ].rotation.x += delta * 0.5 * ( i % 2 ? -1 : 1 ); + + } + + renderer.render( scene, camera ); + + } + +}; + +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_shader_lava.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_shading_physical.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_shadowmap.html + +()=>{ + + if ( ! Detector.webgl ) Detector.addGetWebGLMessage(); + + var SHADOW_MAP_WIDTH = 2048, SHADOW_MAP_HEIGHT = 1024; + + var MARGIN = 100; + + var SCREEN_WIDTH = window.innerWidth; + var SCREEN_HEIGHT = window.innerHeight - 2 * MARGIN; + var FLOOR = -250; + + var camera, controls, scene, renderer; + var container, stats; + + var NEAR = 5, FAR = 3000; + + var sceneHUD, cameraOrtho, hudMaterial; + + var morph, morphs = []; + + var light; + + var clock = new THREE.Clock(); + + init(); + animate(); + + + function init() { + + container = document.createElement( 'div' ); + document.body.appendChild( container ); + + // SCENE CAMERA + + camera = new THREE.PerspectiveCamera( 23, SCREEN_WIDTH / SCREEN_HEIGHT, NEAR, FAR ); + camera.position.set( 700, 50, 1900 ); + + controls = new THREE.FirstPersonControls( camera ); + + controls.lookSpeed = 0.0125; + controls.movementSpeed = 500; + controls.noFly = false; + controls.lookVertical = true; + controls.constrainVertical = true; + controls.verticalMin = 1.5; + controls.verticalMax = 2.0; + + controls.lon = -110; + + // SCENE + + scene = new THREE.Scene(); + scene.fog = new THREE.Fog( 0x59472b, 1000, FAR ); + + // LIGHTS + + var ambient = new THREE.AmbientLight( 0x444444 ); + scene.add( ambient ); + + light = new THREE.SpotLight( 0xffffff, 1, 0, Math.PI, 1 ); + light.position.set( 0, 1500, 1000 ); + light.target.position.set( 0, 0, 0 ); + + light.castShadow = true; + + light.shadowCameraNear = 700; + light.shadowCameraFar = camera.far; + light.shadowCameraFov = 50; + + //light.shadowCameraVisible = true; + + light.shadowBias = 0.0001; + light.shadowDarkness = 0.5; + + light.shadowMapWidth = SHADOW_MAP_WIDTH; + light.shadowMapHeight = SHADOW_MAP_HEIGHT; + + scene.add( light ); + + createHUD(); + createScene(); + + // RENDERER + + renderer = new THREE.WebGLRenderer( { clearColor: 0x000000, clearAlpha: 1, antialias: false } ); + renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT ); + renderer.domElement.style.position = "relative"; + renderer.domElement.style.top = MARGIN + 'px'; + container.appendChild( renderer.domElement ); + + renderer.setClearColor( scene.fog.color, 1 ); + renderer.autoClear = false; + + // + + renderer.shadowMapEnabled = true; + renderer.shadowMapType = THREE.PCFShadowMap; + + // STATS + + stats = new Stats(); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.top = '0px'; + stats.domElement.style.zIndex = 100; + //container.appendChild( stats.domElement ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + SCREEN_WIDTH = window.innerWidth; + SCREEN_HEIGHT = window.innerHeight - 2 * MARGIN; + + camera.aspect = SCREEN_WIDTH / SCREEN_HEIGHT; + camera.updateProjectionMatrix(); + + renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT ); + + controls.handleResize(); + + } + + function createHUD() { + + cameraOrtho = new THREE.OrthographicCamera( SCREEN_WIDTH / - 2, SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, SCREEN_HEIGHT / - 2, -10, 1000 ); + cameraOrtho.position.z = 10; + + var shader = THREE.UnpackDepthRGBAShader; + var uniforms = THREE.UniformsUtils.clone( shader.uniforms ); + + hudMaterial = new THREE.ShaderMaterial( { vertexShader: shader.vertexShader, fragmentShader: shader.fragmentShader, uniforms: uniforms } ); + + var hudGeo = new THREE.PlaneGeometry( SHADOW_MAP_WIDTH / 2, SHADOW_MAP_HEIGHT / 2 ); + var hudMesh = new THREE.Mesh( hudGeo, hudMaterial ); + hudMesh.position.x = ( SCREEN_WIDTH - SHADOW_MAP_WIDTH / 2 ) * -0.5; + hudMesh.position.y = ( SCREEN_HEIGHT - SHADOW_MAP_HEIGHT / 2 ) * -0.5; + hudMesh.rotation.x = Math.PI / 2; + + sceneHUD = new THREE.Scene(); + sceneHUD.add( hudMesh ); + + cameraOrtho.lookAt( sceneHUD.position ); + + } + + function createScene( ) { + + // GROUND + + var geometry = new THREE.PlaneGeometry( 100, 100 ); + var planeMaterial = new THREE.MeshPhongMaterial( { color: 0xffdd99 } ); + planeMaterial.ambient = planeMaterial.color; + + var ground = new THREE.Mesh( geometry, planeMaterial ); + + ground.position.set( 0, FLOOR, 0 ); + ground.rotation.x = - Math.PI / 2; + ground.scale.set( 100, 100, 100 ); + + ground.castShadow = false; + ground.receiveShadow = true; + + scene.add( ground ); + + // TEXT + + var textGeo = new THREE.TextGeometry( "THREE.JS", { + + size: 200, + height: 50, + curveSegments: 12, + + font: "helvetiker", + weight: "bold", + style: "normal", + + bevelThickness: 2, + bevelSize: 5, + bevelEnabled: true + + }); + + textGeo.computeBoundingBox(); + var centerOffset = -0.5 * ( textGeo.boundingBox.max.x - textGeo.boundingBox.min.x ); + + var textMaterial = new THREE.MeshPhongMaterial( { color: 0xff0000, specular: 0xffffff, ambient: 0xaa0000 } ); + + var mesh = new THREE.Mesh( textGeo, textMaterial ); + mesh.position.x = centerOffset; + mesh.position.y = FLOOR + 67; + + mesh.castShadow = true; + mesh.receiveShadow = true; + + scene.add( mesh ); + + // CUBES + + var mesh = new THREE.Mesh( new THREE.CubeGeometry( 1500, 220, 150 ), planeMaterial ); + + mesh.position.y = FLOOR - 50; + mesh.position.z = 20; + + mesh.castShadow = true; + mesh.receiveShadow = true; + + scene.add( mesh ); + + var mesh = new THREE.Mesh( new THREE.CubeGeometry( 1600, 170, 250 ), planeMaterial ); + + mesh.position.y = FLOOR - 50; + mesh.position.z = 20; + + mesh.castShadow = true; + mesh.receiveShadow = true; + + scene.add( mesh ); + + // MORPHS + + function addMorph( geometry, speed, duration, x, y, z, fudgeColor ) { + + var material = new THREE.MeshLambertMaterial( { color: 0xffaa55, morphTargets: true, vertexColors: THREE.FaceColors } ); + + if ( fudgeColor ) { + + material.color.offsetHSL( 0, Math.random() * 0.5 - 0.25, Math.random() * 0.5 - 0.25 ); + material.ambient = material.color; + + } + + var meshAnim = new THREE.MorphAnimMesh( geometry, material ); + + (meshAnim).speed = speed; + meshAnim.duration = duration; + meshAnim.time = 600 * Math.random(); + + meshAnim.position.set( x, y, z ); + meshAnim.rotation.y = Math.PI/2; + + meshAnim.castShadow = true; + meshAnim.receiveShadow = true; + + scene.add( meshAnim ); + + morphs.push( meshAnim ); + + } + + function morphColorsToFaceColors( geometry ) { + + if ( geometry.morphColors && geometry.morphColors.length ) { + + var colorMap = geometry.morphColors[ 0 ]; + + for ( var i = 0; i < colorMap.colors.length; i ++ ) { + + geometry.faces[ i ].color = colorMap.colors[ i ]; + + } + + } + + } + + var loader = new THREE.JSONLoader(); + + loader.load( "models/animated/horse.js", function( geometry ) { + + morphColorsToFaceColors( geometry ); + + addMorph( geometry, 550, 1000, 100 - Math.random() * 1000, FLOOR, 300, true ); + addMorph( geometry, 550, 1000, 100 - Math.random() * 1000, FLOOR, 450, true ); + addMorph( geometry, 550, 1000, 100 - Math.random() * 1000, FLOOR, 600, true ); + + addMorph( geometry, 550, 1000, 100 - Math.random() * 1000, FLOOR, -300, true ); + addMorph( geometry, 550, 1000, 100 - Math.random() * 1000, FLOOR, -450, true ); + addMorph( geometry, 550, 1000, 100 - Math.random() * 1000, FLOOR, -600, true ); + + } ); + + /* + loader.load( "obj/morphs/fox.js", function( geometry ) { + + morphColorsToFaceColors( geometry ); + addMorph( geometry, 200, 1000, 100 - Math.random() * 500, FLOOR - 5, 600 ); + + } ); + + loader.load( "obj/morphs/shdw3walk.js", function( geometry ) { + + morphColorsToFaceColors( geometry ); + addMorph( geometry, 40, 2000, -500, FLOOR + 60, 245 ); + + } ); + + loader.load( "obj/morphs/flamingo.js", function( geometry ) { + + morphColorsToFaceColors( geometry ); + addMorph( geometry, 500, 1000, 500 - Math.random() * 500, FLOOR + 350, 40 ); + + } ); + + loader.load( "obj/morphs/stork.js", function( geometry ) { + + morphColorsToFaceColors( geometry ); + addMorph( geometry, 350, 1000, 500 - Math.random() * 500, FLOOR + 350, 340 ); + + } ); + + loader.load( "obj/morphs/mountainlion.js", function( geometry ) { + + morphColorsToFaceColors( geometry ); + addMorph( geometry, 400, 1000, 500 - Math.random() * 500, FLOOR - 5, 700 ); + + } ); + + loader.load( "obj/morphs/bearBrown.js", function( geometry ) { + + morphColorsToFaceColors( geometry ); + addMorph( geometry, 300, 2500, -500, FLOOR - 5, -750 ); + + } ); + + loader.load( "obj/morphs/parrot.js", function( geometry ) { + + morphColorsToFaceColors( geometry ); + addMorph( geometry, 450, 500, 500 - Math.random() * 500, FLOOR + 300, 700 ); + + } ); + */ + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + var delta = clock.getDelta(); + + for ( var i = 0; i < morphs.length; i ++ ) { + + morph = morphs[ i ]; + + morph.updateAnimation( 1000 * delta ); + + morph.position.x += morph.speed * delta; + + if ( morph.position.x > 2000 ) { + + morph.position.x = -1000 - Math.random() * 500; + + } + + } + + controls.update( delta ); + + renderer.clear(); + renderer.render( scene, camera ); + + // Render debug HUD with shadow map + + //hudMaterial.uniforms.tDiffuse.texture = light.shadowMap; + //renderer.render( sceneHUD, cameraOrtho ); + + } +}; + +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_shadowmap_performance.html + +()=>{ + + if ( ! Detector.webgl ) Detector.addGetWebGLMessage(); + + var SHADOW_MAP_WIDTH = 2048, SHADOW_MAP_HEIGHT = 1024; + + var MARGIN = 100; + + var SCREEN_WIDTH = window.innerWidth; + var SCREEN_HEIGHT = window.innerHeight - 2 * MARGIN; + var FLOOR = -250; + + var camera, controls, scene, renderer; + var container, stats; + + var NEAR = 5, FAR = 3000; + + var sceneHUD, cameraOrtho, hudMaterial; + + var morph, morphs = []; + + var light; + + var clock = new THREE.Clock(); + + init(); + animate(); + + + function init() { + + container = document.createElement( 'div' ); + document.body.appendChild( container ); + + // SCENE CAMERA + + camera = new THREE.PerspectiveCamera( 23, SCREEN_WIDTH / SCREEN_HEIGHT, NEAR, FAR ); + camera.position.set( 700, 50, 1900 ); + + controls = new THREE.FirstPersonControls( camera ); + + controls.lookSpeed = 0.0125; + controls.movementSpeed = 500; + controls.noFly = false; + controls.lookVertical = true; + controls.constrainVertical = true; + controls.verticalMin = 1.5; + controls.verticalMax = 2.0; + + controls.lon = -110; + + // SCENE + + scene = new THREE.Scene(); + scene.fog = new THREE.Fog( 0x59472b, 1000, FAR ); + + // LIGHTS + + var ambient = new THREE.AmbientLight( 0x444444 ); + scene.add( ambient ); + + light = new THREE.SpotLight( 0xffffff, 1, 0, Math.PI, 1 ); + light.position.set( 0, 1500, 1000 ); + light.target.position.set( 0, 0, 0 ); + + light.castShadow = true; + + light.shadowCameraNear = 700; + light.shadowCameraFar = camera.far; + light.shadowCameraFov = 50; + + //light.shadowCameraVisible = true; + + light.shadowBias = 0.0001; + light.shadowDarkness = 0.5; + + light.shadowMapWidth = SHADOW_MAP_WIDTH; + light.shadowMapHeight = SHADOW_MAP_HEIGHT; + + scene.add( light ); + + createHUD(); + createScene(); + + // RENDERER + + renderer = new THREE.WebGLRenderer( { clearColor: 0x000000, clearAlpha: 1, antialias: false } ); + renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT ); + renderer.domElement.style.position = "relative"; + renderer.domElement.style.top = MARGIN + 'px'; + container.appendChild( renderer.domElement ); + + renderer.setClearColor( scene.fog.color, 1 ); + renderer.autoClear = false; + + // + + renderer.shadowMapEnabled = true; + renderer.shadowMapType = THREE.PCFSoftShadowMap; + + // STATS + + stats = new Stats(); + stats.domElement.style.position = 'absolute'; + stats.domElement.style.top = '0px'; + stats.domElement.style.zIndex = 100; + container.appendChild( stats.domElement ); + + // + + window.addEventListener( 'resize', onWindowResize, false ); + + } + + function onWindowResize() { + + SCREEN_WIDTH = window.innerWidth; + SCREEN_HEIGHT = window.innerHeight - 2 * MARGIN; + + camera.aspect = SCREEN_WIDTH / SCREEN_HEIGHT; + camera.updateProjectionMatrix(); + + renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT ); + + controls.handleResize(); + + } + + function createHUD() { + + cameraOrtho = new THREE.OrthographicCamera( SCREEN_WIDTH / - 2, SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, SCREEN_HEIGHT / - 2, -10, 1000 ); + cameraOrtho.position.z = 10; + + var shader = THREE.UnpackDepthRGBAShader; + var uniforms = THREE.UniformsUtils.clone( shader.uniforms ); + + hudMaterial = new THREE.ShaderMaterial( { vertexShader: shader.vertexShader, fragmentShader: shader.fragmentShader, uniforms: uniforms } ); + + var hudGeo = new THREE.PlaneGeometry( SHADOW_MAP_WIDTH / 2, SHADOW_MAP_HEIGHT / 2 ); + var hudMesh = new THREE.Mesh( hudGeo, hudMaterial ); + hudMesh.position.x = ( SCREEN_WIDTH - SHADOW_MAP_WIDTH / 2 ) * -0.5; + hudMesh.position.y = ( SCREEN_HEIGHT - SHADOW_MAP_HEIGHT / 2 ) * -0.5; + hudMesh.rotation.x = Math.PI / 2; + + sceneHUD = new THREE.Scene(); + sceneHUD.add( hudMesh ); + + cameraOrtho.lookAt( sceneHUD.position ); + + } + + function createScene( ) { + + // GROUND + + var geometry = new THREE.PlaneGeometry( 100, 100 ); + var planeMaterial = new THREE.MeshPhongMaterial( { color: 0xffdd99 } ); + planeMaterial.ambient = planeMaterial.color; + + var ground = new THREE.Mesh( geometry, planeMaterial ); + + ground.position.set( 0, FLOOR, 0 ); + ground.rotation.x = - Math.PI / 2; + ground.scale.set( 100, 100, 100 ); + + ground.castShadow = false; + ground.receiveShadow = true; + + scene.add( ground ); + + // TEXT + + var textGeo = new THREE.TextGeometry( "THREE.JS", { + + size: 200, + height: 50, + curveSegments: 12, + + font: "helvetiker", + weight: "bold", + style: "normal", + + bevelThickness: 2, + bevelSize: 5, + bevelEnabled: true + + }); + + textGeo.computeBoundingBox(); + var centerOffset = -0.5 * ( textGeo.boundingBox.max.x - textGeo.boundingBox.min.x ); + + var textMaterial = new THREE.MeshPhongMaterial( { color: 0xff0000, specular: 0xffffff, ambient: 0xaa0000 } ); + + var mesh = new THREE.Mesh( textGeo, textMaterial ); + mesh.position.x = centerOffset; + mesh.position.y = FLOOR + 67; + + mesh.castShadow = true; + mesh.receiveShadow = true; + + scene.add( mesh ); + + // CUBES + + var mesh = new THREE.Mesh( new THREE.CubeGeometry( 1500, 220, 150 ), planeMaterial ); + + mesh.position.y = FLOOR - 50; + mesh.position.z = 20; + + mesh.castShadow = true; + mesh.receiveShadow = true; + + scene.add( mesh ); + + var mesh = new THREE.Mesh( new THREE.CubeGeometry( 1600, 170, 250 ), planeMaterial ); + + mesh.position.y = FLOOR - 50; + mesh.position.z = 20; + + mesh.castShadow = true; + mesh.receiveShadow = true; + + scene.add( mesh ); + + // MORPHS + + function addMorph( geometry, speed, duration, x, y, z, fudgeColor ) { + + var material = new THREE.MeshLambertMaterial( { color: 0xffaa55, morphTargets: true, vertexColors: THREE.FaceColors } ); + + if ( fudgeColor ) { + + material.color.offsetHSL( 0, Math.random() * 0.5 - 0.25, Math.random() * 0.5 - 0.25 ); + material.ambient = material.color; + + } + + var meshAnim = new THREE.MorphAnimMesh( geometry, material ); + + (meshAnim).speed = speed; + meshAnim.duration = duration; + meshAnim.time = 600 * Math.random(); + + meshAnim.position.set( x, y, z ); + meshAnim.rotation.y = Math.PI/2; + + meshAnim.castShadow = true; + meshAnim.receiveShadow = true; + + scene.add( meshAnim ); + + morphs.push( meshAnim ); + + } + + function morphColorsToFaceColors( geometry ) { + + if ( geometry.morphColors && geometry.morphColors.length ) { + + var colorMap = geometry.morphColors[ 0 ]; + + for ( var i = 0; i < colorMap.colors.length; i ++ ) { + + geometry.faces[ i ].color = colorMap.colors[ i ]; + + } + + } + + } + + var loader = new THREE.JSONLoader(); + + loader.load( "models/animated/horse.js", function( geometry ) { + + morphColorsToFaceColors( geometry ); + + + var i = -600; + while (i < 601){ + addMorph( geometry, 550, 1000, 100 - Math.random() * 3000, FLOOR, i, true ); + i += 2; + } + + } ); + + /* + loader.load( "obj/morphs/fox.js", function( geometry ) { + + morphColorsToFaceColors( geometry ); + addMorph( geometry, 200, 1000, 100 - Math.random() * 500, FLOOR - 5, 600 ); + + } ); + + loader.load( "obj/morphs/shdw3walk.js", function( geometry ) { + + morphColorsToFaceColors( geometry ); + addMorph( geometry, 40, 2000, -500, FLOOR + 60, 245 ); + + } ); + + loader.load( "obj/morphs/flamingo.js", function( geometry ) { + + morphColorsToFaceColors( geometry ); + addMorph( geometry, 500, 1000, 500 - Math.random() * 500, FLOOR + 350, 40 ); + + } ); + + loader.load( "obj/morphs/stork.js", function( geometry ) { + + morphColorsToFaceColors( geometry ); + addMorph( geometry, 350, 1000, 500 - Math.random() * 500, FLOOR + 350, 340 ); + + } ); + + loader.load( "obj/morphs/mountainlion.js", function( geometry ) { + + morphColorsToFaceColors( geometry ); + addMorph( geometry, 400, 1000, 500 - Math.random() * 500, FLOOR - 5, 700 ); + + } ); + + loader.load( "obj/morphs/bearBrown.js", function( geometry ) { + + morphColorsToFaceColors( geometry ); + addMorph( geometry, 300, 2500, -500, FLOOR - 5, -750 ); + + } ); + + loader.load( "obj/morphs/parrot.js", function( geometry ) { + + morphColorsToFaceColors( geometry ); + addMorph( geometry, 450, 500, 500 - Math.random() * 500, FLOOR + 300, 700 ); + + } ); + */ + + } + + // + + function animate() { + + requestAnimationFrame( animate ); + + render(); + stats.update(); + + } + + function render() { + + var delta = clock.getDelta(); + + for ( var i = 0; i < morphs.length; i ++ ) { + + morph = morphs[ i ]; + + morph.updateAnimation( 1000 * delta ); + + morph.position.x += morph.speed * delta; + + if ( morph.position.x > 2000 ) { + + morph.position.x = -1000 - Math.random() * 500; + + } + + } + + controls.update( delta ); + + renderer.clear(); + renderer.render( scene, camera ); + + // Render debug HUD with shadow map + + //hudMaterial.uniforms.tDiffuse.texture = light.shadowMap; + //renderer.render( sceneHUD, cameraOrtho ); + + } + +}; + +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_sprites.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_terrain_dynamic.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_test_memory.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_test_memory2.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgl_trails.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgldeferred_animation.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgldeferred_arealights.html +// https://github.com/mrdoob/three.js/tree/master/examples/webgldeferred_pointlights.html \ No newline at end of file diff --git a/threejs/three.d.ts b/threejs/three.d.ts index 6ae3a2a65c..0ae2bc67ec 100644 --- a/threejs/three.d.ts +++ b/threejs/three.d.ts @@ -3400,6 +3400,27 @@ module THREE { add(loader: Loader): void; } + interface SceneLoaderResult{ + scene: Scene; + geometries: {[id:string]:Geometry;}; + face_materials: {[id:string]:Material;}; + materials: {[id:string]:Material;}; + textures: {[id:string]:Texture;}; + objects: {[id:string]:Object3D;}; + cameras: {[id:string]:Camera;}; + lights: {[id:string]:Light;}; + fogs: {[id:string]:IFog;}; + empties: {[id:string]:any;}; + groups: {[id:string]:any;}; + } + + interface SceneLoaderProgress{ + totalModels: number; + totalTextures: number; + loadedModels: number; + loadedTextures: number; + } + /** * A loader for loading a complete scene out of a JSON file. */ @@ -3428,19 +3449,29 @@ module THREE { * Will be called when load completes. * The default is a function with empty body. */ - callbackSync: () => void; + callbackSync: (result: SceneLoaderResult) => void; /** * Will be called as load progresses. * The default is a function with empty body. */ - callbackProgress: () => void; + callbackProgress: (progress: SceneLoaderProgress, result: SceneLoaderResult) => void; + + geometryHandlerMap: any; + hierarchyHandlerMap: any; + /** * @param url * @param callbackFinished This function will be called with the loaded model as an instance of scene when the load is completed. */ load(url: string, callbackFinished: (scene: Scene) => void ): void; + + addGeometryHandler(typeID: string, loaderClass: Object): void; + + addHierarchyHandler(typeID: string, loaderClass: Object): void; + + static parse(json: any, callbackFinished:(result: SceneLoaderResult)=>void, url: string): void; } /** @@ -3576,7 +3607,7 @@ module THREE { linewidth?: number; linecap?: string; linejoin?: string; - vertexColors?: bool; + vertexColors?: Colors; fog?: bool; } @@ -5744,11 +5775,11 @@ module THREE { } export class LensFlare extends Object3D { - constructor(texture?: Texture, size?: number, distance?: number, blending?: Blending, color?: number); + constructor(texture?: Texture, size?: number, distance?: number, blending?: Blending, color?: Color); lensFlares: LensFlareProperty[]; positionScreen: Vector3; - customUpdateCallback: () => void; - add(texture?: Texture, size?: number, distance?: number, blending?: Blending, color?: number, opacity?: number): void; + customUpdateCallback: (object:LensFlare) => void; + add(texture?: Texture, size?: number, distance?: number, blending?: Blending, color?: Color, opacity?: number): void; updateLensFlares(): void; }