title: Three.js memory leak with object wrapper
body: <p>This is a little modified version of  "three.js webgl cameras." (got from examples)
  I have created a wrapper div for the future canvas and a 'three_webgl' instance. 
  (I create an instance for a new three_webgl, which is the original function instanced as an object).</p>
  
  <p>As you can see there are two buttons one to create the instance and the animation and the other to stop the animation and delete the instance. 
  I have a 'stop' control inside the animate loop.</p>
  
  <p>Also  I have increased the number of points for the pointcloud (100 000) to measure the memory spent.</p>
  
  <p>The problem I have is that delete works fine but I leave 10 000 KB 'lost'
  You can play with create-start  / stop- delete and you can see how the memory grows and grows.</p>
  
  <p>My question is how to delete the three  environment and data correctly. The goal is to avoid memory leaks.</p>
  
  <p>I'm using the dev branch dated on 12 / 05, chrome 34.0 and Windows XP.</p>
  
  <p>This is the code. (Maybe it is neccesary to change the tree paths for three and stats.)</p>
  
  <pre><code>&lt;!DOCTYPE html&gt;
  &lt;html lang="en"&gt;
      &lt;head&gt;
          &lt;title&gt;three.js webgl - cameras&lt;/title&gt;
          &lt;meta charset="utf-8"&gt;
          &lt;meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"&gt;
          &lt;style&gt;
              body {
                  color: #808080;
                  font-family:Monospace;
                  font-size:13px;
                  text-align:center;
  
                  background-color: #000;
                  margin: 0px;
                  overflow: hidden;
              }
  
              #info {
                  position: absolute;
                  top: 0px; width: 100%;
                  padding: 5px;
                  z-index: 100;
              }
  
              a {
  
                  color: #0080ff;
              }
  
              b { color: lightgreen }
  
              #stats { position: absolute; top:0; left: 0 }
              #stats #fps { background: transparent !important }
              #stats #fps #fpsText { color: #777 !important }
              #stats #fps #fpsGraph { display: none }
          #apDiv1 {
      position: absolute;
      width: 652px;
      height: 376px;
      z-index: 101;
      left: 54px;
      top: 95px;
      border: 1px solid white;
  }
          #apDiv2 {
      position: absolute;
      width: 655px;
      height: 80px;
      z-index: 102;
      left: 53px;
      top: 490px;
      border: 1px red  solid;
  }
          #apDiv3 {
      position: absolute;
      width: 200px;
      height: 34px;
      z-index: 103;
      left: 54px;
      top: 52px;
  }
          &lt;/style&gt;
      &lt;/head&gt;
  &lt;body&gt;
  
          &lt;div id="container"&gt;&lt;/div&gt;
          &lt;div id="info"&gt;&lt;a href="http://threejs.org" target="_blank"&gt;three.js&lt;/a&gt; - cameras&lt;br/&gt;
          &lt;b&gt;O&lt;/b&gt; orthographic &lt;b&gt;P&lt;/b&gt; perspective
          &lt;/div&gt;
          &lt;div id="apDiv1"&gt;&lt;/div&gt;             
          &lt;div id="apDiv2"&gt;&lt;/div&gt;
          &lt;div id="apDiv3"&gt;
          &lt;input type="submit" name="b1" id="b1" value="crete-start"  onClick="new_webgl()"&gt;
          &lt;input type="submit" name="b2" id="b2" value="stop-delete" onClick="del_webgl()"&gt;
          &lt;/div&gt;
  
  
          &lt;script src="tree/build/three.js"&gt;&lt;/script&gt;
          &lt;script src="tree/examples/js/libs/stats.min.js"&gt;&lt;/script&gt;
  
          &lt;script&gt;
  
          var webgl_true;
          try 
          { var canvas = document.createElement( 'canvas' ); 
          webgl_true =  !! window.WebGLRenderingContext &amp;&amp; ( canvas.getContext( 'webgl' ) || canvas.getContext( 'experimental-webgl' ) ); }
          catch( e ) { webgl_true= false; } 
          THE_DIV2 = document.getElementById("apDiv2");
          THE_DIV2.innerHTML = "Webgl detector : "+webgl_true;                        
          &lt;/script&gt;
  
     &lt;script&gt;
  
    var webgl;
    var renderer;
    var del_renderer = false;
  
    new_webgl = function ()     {  webgl = new three_webgl();  }
  
    var del_webgl = function () {  del_renderer = true;
    THE_DIV.parentNode.removeChild(THE_DIV);
    webgl = null;
  
  //              THE_DIV.appendChild( renderer.domElement );
  
    }
  
  
  
          three_webgl = function () {
  
          del_renderer = false;
  
          THE_DIV = document.createElement( 'div' );                      
          THE_DIV.style.height="100%";
          document.getElementById("apDiv1").appendChild(THE_DIV);
  
  
              var SCREEN_WIDTH  = THE_DIV.clientWidth;
              var SCREEN_HEIGHT = THE_DIV.clientHeight;
  
              var container, stats;
              var camera, scene,  mesh;
              var cameraRig, activeCamera, activeHelper;
              var cameraPerspective, cameraOrtho;
              var cameraPerspectiveHelper, cameraOrthoHelper;
  
              init();
              animate();
  
               function init () {
  
                  //container = document.createElement( 'div' );
                  //document.body.appendChild( container );
  
  
                  scene = new THREE.Scene();
  
                  //
  
                  camera = new THREE.PerspectiveCamera( 50, 0.5 * SCREEN_WIDTH / SCREEN_HEIGHT, 1, 10000 );
                  camera.position.z = 2500;
  
                  cameraPerspective = new THREE.PerspectiveCamera( 50, 0.5 * SCREEN_WIDTH / SCREEN_HEIGHT, 150, 1000 );
  
                  cameraPerspectiveHelper = new THREE.CameraHelper( cameraPerspective );
                  scene.add( cameraPerspectiveHelper );
  
                  //
  
                  cameraOrtho = new THREE.OrthographicCamera( 0.5 * SCREEN_WIDTH / - 2, 0.5 * SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, SCREEN_HEIGHT / - 2, 150, 1000 );
  
                  cameraOrthoHelper = new THREE.CameraHelper( cameraOrtho );
                  scene.add( cameraOrthoHelper );
  
                  //
  
                  activeCamera = cameraPerspective;
                  activeHelper = cameraPerspectiveHelper;
  
  
                  // counteract different front orientation of cameras vs rig
  
                  cameraOrtho.rotation.y = Math.PI;
                  cameraPerspective.rotation.y = Math.PI;
  
                  cameraRig = new THREE.Object3D();
  
                  cameraRig.add( cameraPerspective );
                  cameraRig.add( cameraOrtho );
  
                  scene.add( cameraRig );
  
                  //
  
                  mesh = new THREE.Mesh( new THREE.SphereGeometry( 100, 16, 8 ), new THREE.MeshBasicMaterial( { color: 0xffffff, wireframe: true } ) );
                  scene.add( mesh );
  
                  var mesh2 = new THREE.Mesh( new THREE.SphereGeometry( 50, 16, 8 ), new THREE.MeshBasicMaterial( { color: 0x00ff00, wireframe: true } ) );
                  mesh2.position.y = 150;
                  mesh.add( mesh2 );
  
                  var mesh3 = new THREE.Mesh( new THREE.SphereGeometry( 5, 16, 8 ), new THREE.MeshBasicMaterial( { color: 0x0000ff, wireframe: true } ) );
                  mesh3.position.z = 150;
                  cameraRig.add( mesh3 );
  
                  //
  
                  var geometry = new THREE.Geometry();
  
                  for ( var i = 0; i &lt; 100000; i ++ ) {
  
                      var vertex = new THREE.Vector3();
                      vertex.x = THREE.Math.randFloatSpread( 2000 );
                      vertex.y = THREE.Math.randFloatSpread( 2000 );
                      vertex.z = THREE.Math.randFloatSpread( 2000 );
  
                      geometry.vertices.push( vertex );
  
                  }
  
                  var particles = new THREE.PointCloud( geometry, new THREE.PointCloudMaterial( { color: 0x888888 } ) );
                  scene.add( particles );
  
                  //
  
  
                  renderer = new THREE.WebGLRenderer( { antialias: true } );
                  renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
                  renderer.domElement.style.position = "relative";
                  THE_DIV.appendChild( renderer.domElement );
  
                  renderer.autoClear = false;
  
                  //
  
                  stats = new Stats();
                  THE_DIV2.appendChild( stats.domElement );
  
                  //
  
                  window.addEventListener( 'resize', onWindowResize, false );
                  document.addEventListener( 'keydown', onKeyDown, false );
  
              }
  
              //
  
              function onKeyDown ( event ) {
  
                  switch( event.keyCode ) {
  
                      case 79: /*O*/
  
                          activeCamera = cameraOrtho;
                          activeHelper = cameraOrthoHelper;
  
                          break;
  
                      case 80: /*P*/
  
                          activeCamera = cameraPerspective;
                          activeHelper = cameraPerspectiveHelper;
  
                          break;
  
                  }
  
              };
  
              //
  
              function onWindowResize( event ) {
  
                  SCREEN_WIDTH = window.innerWidth;
                  SCREEN_HEIGHT = window.innerHeight;
  
                  renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
  
                  camera.aspect = 0.5 * SCREEN_WIDTH / SCREEN_HEIGHT;
                  camera.updateProjectionMatrix();
  
                  cameraPerspective.aspect = 0.5 * SCREEN_WIDTH / SCREEN_HEIGHT;
                  cameraPerspective.updateProjectionMatrix();
  
                  cameraOrtho.left   = - 0.5 * SCREEN_WIDTH / 2;
                  cameraOrtho.right  =   0.5 * SCREEN_WIDTH / 2;
                  cameraOrtho.top    =   SCREEN_HEIGHT / 2;
                  cameraOrtho.bottom = - SCREEN_HEIGHT / 2;
                  cameraOrtho.updateProjectionMatrix();
  
              }
  
              //
  
              function animate() {
  
                  if (!(del_renderer))
                  { requestAnimationFrame( animate );
                    render();
                  }
                  stats.update();
                  if (del_renderer) {renderer=null;}
              }
  
  
              function render() {
  
                  var r = Date.now() * 0.0005;
  
                  mesh.position.x = 700 * Math.cos( r );
                  mesh.position.z = 700 * Math.sin( r );
                  mesh.position.y = 700 * Math.sin( r );
  
                  mesh.children[ 0 ].position.x = 70 * Math.cos( 2 * r );
                  mesh.children[ 0 ].position.z = 70 * Math.sin( r );
  
                  if ( activeCamera === cameraPerspective ) {
  
                      cameraPerspective.fov = 35 + 30 * Math.sin( 0.5 * r );
                      cameraPerspective.far = mesh.position.length();
                      cameraPerspective.updateProjectionMatrix();
  
                      cameraPerspectiveHelper.update();
                      cameraPerspectiveHelper.visible = true;
  
                      cameraOrthoHelper.visible = false;
  
                  } else {
  
                      cameraOrtho.far = mesh.position.length();
                      cameraOrtho.updateProjectionMatrix();
  
                      cameraOrthoHelper.update();
                      cameraOrthoHelper.visible = true;
  
                      cameraPerspectiveHelper.visible = false;
  
                  }
  
                  cameraRig.lookAt( mesh.position );
  
                  renderer.clear();
  
                  activeHelper.visible = false;
  
                  renderer.setViewport( 0, 0, SCREEN_WIDTH/2, SCREEN_HEIGHT );
                  renderer.render( scene, activeCamera );
  
                  activeHelper.visible = true;
  
                  renderer.setViewport( SCREEN_WIDTH/2, 0, SCREEN_WIDTH/2, SCREEN_HEIGHT );
                  renderer.render( scene, camera );
  
              }
  
  
          }
  
          &lt;/script&gt;
  &lt;/body&gt;
  &lt;/html&gt;
  </code></pre>