From 6a43b6fe856d1da11a3d15f2a648af9459acef0f Mon Sep 17 00:00:00 2001 From: Kon Date: Mon, 4 Mar 2013 05:54:36 +0900 Subject: [PATCH] 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 c086e3aaf..2d59266c3 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 e3868af58..e4a692f58 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: {