function cubeBlob()
{
    this.start_time = 0;
    this.end_time = 0;

    this.angularSpeed = 0.2; 
    this.lastTime = 0;
    this.cube;
    this.blob;
    this.blob_hide;
    this.map;
    this.modifier;
    this.bumpmap;
    this.renderer;
    this.scene;
    this.camera;
    this.angleChange;    
    this.light;

    this.composer;
    this.vblur;
    this.hblur;

    this.nBarHalf;
    this.histo;
    this.histoIdx;

    this.obj;
    this.obj_material;
    this.backMaterial;

    this.spike = 0.2;

    this.p1;

    var blur = 0.1;

    var back_obj;

    this.bx = [], this.by = [], this.bz = [];

    this.init = function(renderer, camera)
    {      
    
      this.renderer = renderer;
            
      this.camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 10000 );
      this.camera.position.z = 40;
      this.scene = new THREE.Scene();

      var light = new THREE.DirectionalLight( 0xffffff );
      light.position.set( 0, 0, 100 ).normalize();
      this.scene.add(light);

      this.map = THREE.ImageUtils.loadTexture('assets/glass.jpg');
      this.bumpmap = THREE.ImageUtils.loadTexture('assets/glass_norms.jpg');

      this.backMaterial = new THREE.MeshPhongMaterial({ 
        map: this.map, 
        bumpMap: this.bumpmap        
      });
      
      var path = "assets/cube/";
      var format = '.jpg';
      var urls = [
          path + 'posx_1' + format, path + 'negx_1' + format,
          path + 'posy_1' + format, path + 'negy_1' + format,
          path + 'posz_1' + format, path + 'negz_1' + format
        ];

      var reflectionCube = THREE.ImageUtils.loadTextureCube(urls);
      reflectionCube.format = THREE.RGBFormat;

      var blob_text = THREE.ImageUtils.loadTexture('assets/glass.jpg');      
      blob_text.wrapS = THREE.RepeatWrapping;
      blob_text.wrapT = THREE.RepeatWrapping;
      blob_text.repeat.x = 4;
      blob_text.repeat.y = 4;

      var blob_text_norms = THREE.ImageUtils.loadTexture('assets/glass_norms.jpg');
      blob_text_norms.wrapS = THREE.RepeatWrapping;
      blob_text_norms.wrapT = THREE.RepeatWrapping;
      blob_text_norms.repeat.x = 4;
      blob_text_norms.repeat.y = 4;
      
      var cubeMaterial = new THREE.MeshPhongMaterial({ 
        color: 0xFF0000, 
        ambient: 0xFF0000, 
        specular: 0xFFFFFF, 
        map: blob_text, 
        bumpMap: blob_text_norms, 
        envMap: reflectionCube, 
        combine: THREE.MixOperation, 
        reflectivity: 0.1
      });

      this.obj_material = this.cubeMaterial;

      this.blob = new THREE.Mesh(new THREE.SphereGeometry(1, 100, 100), cubeMaterial);
      
      this.blob.scale.set(15, 15, 15);

      for (i = 0; i<this.blob.geometry.vertices.length; i ++)
      {
          this.bx[i] = this.blob.geometry.vertices[i].x;
          this.by[i] = this.blob.geometry.vertices[i].y;
          this.bz[i] = this.blob.geometry.vertices[i].z;
      }
      
      this.scene.add(this.blob);
      
      this.blob.doubleSided = true;     

      this.blob.castShadow = true;
      this.blob.receiveShadow = true;       

      /*
      this.light = new THREE.SpotLight(0xffffff, 1.25);
      this.light.position.set(-75, 175, 100);
      this.light.target.position.set( 0, 0, 0);
      this.light.castShadow = true;
    
      this.scene.add(this.light);
      */
      var spotLight = new THREE.SpotLight( 0xffffff );
      spotLight.position.set( -10, -10, 50 );

      spotLight.castShadow = true;

      spotLight.shadowDarkness = 0.5;      
      spotLight.shadowMapWidth  = 512;
      spotLight.shadowMapHeight = 512;

      spotLight.shadowCameraRight  =  5;
      spotLight.shadowCameraLeft   = -5;
      spotLight.shadowCameraTop    =  5;
      spotLight.shadowCameraBottom = -5;
      
      this.scene.add(spotLight);

      var loader = new THREE.OBJLoader();
      var scene = this.scene;      
      var obj_map = this.blob_text;
      var obj_bumpmap = this.blob_text_norms;
      loader.load('assets/blobox.obj', function(object) 
      {
        object.traverse(function(child) 
        {

          if (child instanceof THREE.Mesh) 
          {
            child.material.specular = 0xFFFFFF;
            child.material.map = THREE.ImageUtils.loadTexture('assets/concrete.png');
            child.material.bumpmap = THREE.ImageUtils.loadTexture('assets/concrete_norms.jpg');

            child.castShadow = true;
            child.receiveShadow = true;
          }

        });
            
        scene.add(object);

        back_obj = object;
        back_obj.doubleSided = true;                    

      });    

      this.composer = new THREE.EffectComposer(this.renderer);
      this.composer.addPass(new THREE.RenderPass(this.scene, this.camera));     

      this.hblur = new THREE.ShaderPass(THREE.HorizontalTiltShiftShader);
      // this.hblur = new THREE.ShaderPass(THREE.KaleidoShader);
      this.composer.addPass(this.hblur);
        
      this.vblur = new THREE.ShaderPass(THREE.VerticalTiltShiftShader);
      this.vblur.renderToScreen = true;
      this.composer.addPass(this.vblur);

    };

    this.setupRenderer = function()
    {     
      this.renderer.setClearColor( 0x000000, 0 );
      this.camera.position.z = 40;          
      this.renderer.autoClear = true;

      this.renderer.shadowMapEnabled = true;      
      this.renderer.shadowMapSoft = true;            
    }

// vipadmin:$1$f00.6A1.$f2F0tj0E6emBgWgugYpWW1
    this.render = function(demoFrame)
    {
        this.angleChange = this.angularSpeed * demoFrame * 2 * Math.PI / 1000;
        var tspeed = clock.getElapsedTime();
                
        back_obj.rotation.y += demoFrame;
        back_obj.rotation.x += demoFrame/2;
        back_obj.rotation.z += demoFrame/3;        
        
        this.nBarHalf = Math.ceil(41/2)
        this.histo = sound.makeHistogram(this.nBarHalf);
        this.histoIdx = this.barIdx < this.nBarHalf ? this.nBarHalf-1-this.barIdx : this.barIdx - this.nBarHalf;       
        
        if (this.histo[10] > 120)  
        { 
          this.spike = 0.5;                             
        } 

        if (this.spike > 0.2) this.spike -= demoFrame;

        if (this.histo[10] > 120)  
        { 
          blur = 20;                             
        } 

        if (blur > 1) blur -= demoFrame * 100.0;
        // blur = 1;

        this.spike = 0.2;

        for (i = 0, il = this.blob.geometry.vertices.length; i < il; i ++)
        {
            this.blob.geometry.vertices[i].x = this.bx[i] + 1.0 * Math.sin(tspeed * 1.15 + this.by[i] * this.bz[i]*5)*this.spike;
            this.blob.geometry.vertices[i].y = this.by[i] + 1.2 * Math.cos(tspeed * 1.80 + this.bx[i] * this.by[i]*5)*this.spike;
            this.blob.geometry.vertices[i].z = this.bz[i] - 1.4 * Math.cos(tspeed * 1.58 + this.by[i] * this.bx[i]*5)*this.spike;
        }        
        
        this.blob.geometry.dynamic = true;
        this.blob.geometry.verticesNeedUpdate = true;

        this.blob.rotation.y -= demoFrame;
        this.blob.rotation.x -= demoFrame/2;
        this.blob.rotation.z -= demoFrame/3;    

        // this.hblur.uniforms["h"].value = blur / window.innerHeight;    
        this.vblur.uniforms["v"].value = blur / window.innerWidth;    
                        
        // this.renderer.render(this.scene, this.camera);
        this.composer.render();
    }
}