2050.earth 代碼分析-——第二部分(旋轉、縮放、觸摸,更新)




/*
██████╗  ██████╗ ████████╗ █████╗ ████████╗███████╗
██╔══██╗██╔═══██╗╚══██╔══╝██╔══██╗╚══██╔══╝██╔════╝
██████╔╝██║   ██║   ██║   ███████║   ██║   █████╗  
██╔══██╗██║   ██║   ██║   ██╔══██║   ██║   ██╔══╝  
██║  ██║╚██████╔╝   ██║   ██║  ██║   ██║   ███████╗
╚═╝  ╚═╝ ╚═════╝    ╚═╝   ╚═╝  ╚═╝   ╚═╝   ╚══════╝
*/
	function  setMousePosition( x, y, start ) {
		mouse.x = x;
		mouse.y = y;
		
		mouse.delta_x = start ? 0 : mouse.x - mouse.prev_x;
		mouse.delta_y = start ? 0 : mouse.y - mouse.prev_y;
		mouse.prev_x = mouse.x;
		mouse.prev_y = mouse.y;

		if( is_dragging ){
			t_spherical.phi -= mouse.delta_y * .002;
			t_spherical.theta -= mouse.delta_x * .002;
			t_spherical.makeSafe();			
		}
	}


	// ROTATE
	function onMouseDown ( e ) {
		if ( scope.enabled === false ) return;
		e.preventDefault();
		is_dragging = true;

		setMousePosition( e.clientX, e.clientY, true );
	}



	function onMouseMove ( e ) {
		
		if ( scope.enabled === false ) return;
		setMousePosition( e.clientX, e.clientY ); 
		
	}
	

	function onMouseUp ( e ) {
		if ( scope.enabled === false ) return;

		e.preventDefault();
		is_dragging = false;
	}







/*
███████╗ ██████╗  ██████╗ ███╗   ███╗
╚══███╔╝██╔═══██╗██╔═══██╗████╗ ████║
  ███╔╝ ██║   ██║██║   ██║██╔████╔██║
 ███╔╝  ██║   ██║██║   ██║██║╚██╔╝██║
███████╗╚██████╔╝╚██████╔╝██║ ╚═╝ ██║
╚══════╝ ╚═════╝  ╚═════╝ ╚═╝     ╚═╝
*/
	// WHEEL
	function onMouseWheel( e ) {

		if ( scope.enabled === false || scope.enableZoom === false ) return;

		e.preventDefault();
		e.stopPropagation();

		if ( e.deltaY < 0 ) {

			// dollyOut( getZoomScale() );
			changeZoom( -scope.zoomSpeed );

		} else if ( e.deltaY > 0 ) {

			// dollyIn( getZoomScale() );
			changeZoom( scope.zoomSpeed );

		}

	}

	function changeZoom ( _add ) {
		t_spherical.radius += _add;
		// restrict radius to be between desired limits
		t_spherical.radius = Math.max( scope.minDistance, Math.min( scope.maxDistance, t_spherical.radius ) );
	}







/*
████████╗ ██████╗ ██╗   ██╗ ██████╗██╗  ██╗
╚══██╔══╝██╔═══██╗██║   ██║██╔════╝██║  ██║
   ██║   ██║   ██║██║   ██║██║     ███████║
   ██║   ██║   ██║██║   ██║██║     ██╔══██║
   ██║   ╚██████╔╝╚██████╔╝╚██████╗██║  ██║
   ╚═╝    ╚═════╝  ╚═════╝  ╚═════╝╚═╝  ╚═╝
*/
	// TOUCH
function onTouchStart( event ) {

		if ( scope.enabled === false ) return;

		var touches = event.touches;

		switch ( touches.length ) {

			case 1:	// one-fingered touch: rotate
				is_dragging = true;
				setMousePosition( touches[ 0 ].pageX, touches[ 0 ].pageY, true );
				break;

			case 2:	// two-fingered touch: dolly

				if ( scope.enableZoom === false ) return;
				var dx = touches[ 0 ].pageX - touches[ 1 ].pageX;
				var dy = touches[ 0 ].pageY - touches[ 1 ].pageY;
				var distance = Math.sqrt( dx * dx + dy * dy );
				dollyStart.set( 0, distance );

				break;

		}
	}

	function onTouchMove( event ) {

		if ( scope.enabled === false ) return;

		event.preventDefault();
		event.stopPropagation();

		var touches = event.touches;

		switch ( touches.length ) {

			case 1: // one-fingered touch: rotate
				setMousePosition( touches[ 0 ].pageX, touches[ 0 ].pageY );
				break;

			case 2: // two-fingered touch: dolly
				if ( scope.enableZoom === false ) return;

				var dx = touches[ 0 ].pageX - touches[ 1 ].pageX;
				var dy = touches[ 0 ].pageY - touches[ 1 ].pageY;

				var distance = Math.sqrt( dx * dx + dy * dy );

				dollyEnd.set( 0, distance );

				dollyDelta.subVectors( dollyEnd, dollyStart );

				if ( dollyDelta.y > 0 ) {

					changeZoom( -scope.zoomSpeed );

				} else if ( dollyDelta.y < 0 ) {

					changeZoom( scope.zoomSpeed );

				}

				dollyStart.copy( dollyEnd );
				break;

		}

	}

	function onTouchEnd( event ) {

		if ( scope.enabled === false ) return;
		is_dragging = false;

	}





/*
██╗   ██╗██████╗ ██████╗  █████╗ ████████╗███████╗
██║   ██║██╔══██╗██╔══██╗██╔══██╗╚══██╔══╝██╔════╝
██║   ██║██████╔╝██║  ██║███████║   ██║   █████╗  
██║   ██║██╔═══╝ ██║  ██║██╔══██║   ██║   ██╔══╝  
╚██████╔╝██║     ██████╔╝██║  ██║   ██║   ███████╗
 ╚═════╝ ╚═╝     ╚═════╝ ╚═╝  ╚═╝   ╚═╝   ╚══════╝
*/
	// UPDATE
	scope.update = function () {
		
		// zoom
		lo_spherical.radius += (t_spherical.radius - lo_spherical.radius) * scope.zoomFactor;
		// console.log( "> ", t_spherical.radius, scale);

		// restrict theta to be between desired limits
		t_spherical.theta = Math.max( scope.minAzimuthAngle, Math.min( scope.maxAzimuthAngle, t_spherical.theta ) );

		// restrict phi to be between desired limits
		t_spherical.phi = Math.max( scope.minPolarAngle, Math.min( scope.maxPolarAngle, t_spherical.phi ) );

		if( !is_dragging && scope.autoRotate ) {
			t_spherical.theta += scope.autoRotateSpeed;
			t_spherical.makeSafe();
		}

		// console.log( t_spherical.radius, scale );

		if( scope.enableDamping ){
			lo_spherical.phi += ( t_spherical.phi - lo_spherical.phi ) * scope.dampingFactor;
			lo_spherical.theta += ( t_spherical.theta - lo_spherical.theta ) * scope.dampingFactor;
			lo_spherical.makeSafe();
		}else{
			lo_spherical.radius = t_spherical.radius;
			lo_spherical.phi = t_spherical.phi;
			lo_spherical.theta = t_spherical.theta;
		}
		

		looking_object.position.setFromSpherical( lo_spherical );
		looking_object.lookAt( target );

	}



	scope.attach();

}
// d.potekhin
// TODO: stop animation of the grid effect

THREE.XRayMaterial = function( params ){

	var uniforms = {
		uTex: { type:"t", value: params.map || new THREE.Texture() },
		offsetRepeat: { value: new THREE.Vector4( 0, 0, 1, 1 ) },
		alphaProportion: { type: "1f", value: params.alphaProportion || 0.5 },
		diffuse: { value: params.color || new THREE.Color( 0xffffff ) },
		opacity: { value: params.opacity || 1 },
		gridOffset: { value: 0 }
	}

	setInterval(function(){
		uniforms.gridOffset.value += params.gridOffsetSpeed || 1;
		// m.needsUpdate = true;
	}, 40 );

	var m = new THREE.ShaderMaterial( {

		uniforms: uniforms,

		// attributes: {
		// 	vertexOpacity: { value: [] }
		// },
		vertexShader:
			"\
			varying float _alpha;\
			varying vec2 vUv;\
			uniform vec4 offsetRepeat;\
			uniform float alphaProportion;\
			\
		    void main() {\
				gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\
				vUv = uv * offsetRepeat.zw + offsetRepeat.xy;\
				\
				vec4 worldPosition = modelMatrix * vec4( vec3( position ), 1.0 );\
				vec3 cameraToVertex = normalize( cameraPosition - worldPosition.xyz);\
				_alpha = 1.0 - max( 0.0, dot( normal, cameraToVertex ) );\
				_alpha = max( 0.0, (_alpha - alphaProportion) / (1.0 - alphaProportion) );\
		    }"
		,
		//alpha = alphaProportion + (alpha - 0.0) * (1.0 - alphaProportion) / (1.0 - 0.0);\

		fragmentShader:
	  		
	  		"uniform sampler2D uTex;\
	  		uniform vec3 diffuse;\
	  		uniform float opacity;\
	  		uniform float gridOffset;\
	  		\
			varying float _alpha;\
			varying vec2 vUv;\
	  		\
	  		void main() {\
				vec4 texColor = texture2D( uTex, vUv );\
				float _a = _alpha * opacity;\
				if( _a <= 0.0 ) discard;\
				_a = _a * ( sin( vUv.y * 2000.0 + gridOffset ) * .5 + .5 );\
				gl_FragColor = vec4( texColor.rgb * diffuse, _a );\
			\
			}"
		,
		//if ( alpha < .5 ) discard;\

		transparent: true,
		blending: THREE.AdditiveBlending,
		depthTest: false
	} );

	return m;
};

(function (kaspersky){
    /*
    // !! In some cause Detector doesn't see webGL content on my configuration with nVidia GTS250
    console.log("Detector.webgl", Detector, Detector.webgl);
    if ( ! Detector.webgl ){
        console.log("Your graphics card does not seem to support WebGL. Find out how to get it here.");
        Detector.addGetWebGLMessage()
        return;
    }
    */

    var scope = this;
    var $container = scope.$container = $(".main-container");

    if ( !Detector.webgl ){
        $container.hide();
        return;
    }

    var enable_screenshot = !true;// !!!    Flag enables making Screenshot functionality
    var dpr = window.devicePixelRatio !== undefined ? window.devicePixelRatio : 1;

    // WEBGL
    var scene = scope.scene = new THREE.Scene();
    
    scene.fog = new THREE.Fog( 0x000000, 7, enable_screenshot ? 60 : 40 );

    var renderer = scope.renderer =  new THREE.WebGLRenderer({
        preserveDrawingBuffer: enable_screenshot
    });
    renderer.autoClearColor = new THREE.Color( 0, 0, 0, 0 );
    renderer.setPixelRatio( dpr );

    $container.append( renderer.domElement );

    // CAMERA
    var camera =  scope.camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 700);
    camera.position.set(-16,11,0);
    camera.lookAt( new THREE.Vector3(0,0,0));

    // !!! SCREENSHOT
    if( enable_screenshot ){
        
        $("body").css("background-color","#ff0000");
        $(".main-container").css("background-color","rgba(0,0,0,0)");

        $("<div id='screenshot-button' style='\
        display : inline-block;\
        font-family: Tahoma;\
        font-size : 18px;\
        color: white;\
        width: auto;\
        height: auto;\
        padding:10px;\
        background-color: red;\
        opacity: .99;\
        z-index: 100;\
        position: absolute;\
        bottom: 50px;\
        left: 50%;\
        cursor: pointer;\
        '>MAKE SCREENSHOT</div>").appendTo($("body")).click(function(){
            
            planet.bg.visible = false;

            if( composer ) composer.render();
            else renderer.render( scene, camera );

            var dataURL = renderer.domElement.toDataURL();
            $("<img id='ready-screenshot' style='position:fixed;opacity:.99;z-index:999999;top:0;left:0;'>").attr("src", dataURL ).appendTo($("body"));
        });
    }
    // !!! SCREENSHOT

    // EFFECTS
    
    var composer;

    if( !isMobile.any ){
        var effect, pass;

        composer = new THREE.EffectComposer(renderer);
    
        effect = new THREE.RenderPass(scene, camera);
        composer.addPass(effect);
        
        // RGB shift
        effect = new THREE.ShaderPass( THREE.RGBShiftShader );
        effect.uniforms[ 'amount' ].value = 0.0025;//0.005;
    
        composer.addPass( effect );

        // FXAA
        var FXAAShaderPass = effect = new THREE.ShaderPass( THREE.FXAAShader );
        composer.addPass(effect);

        var VerticalTiltShiftShader = effect = new THREE.ShaderPass( THREE.VerticalTiltShiftShader );
        effect.uniforms['r'].value = .35;

        effect.renderToScreen = true;
        composer.addPass( effect );

    }

    // STATS
    var stats;

    // RESIZE
    window.addEventListener('resize', onWindowResize, false );
    function onWindowResize() {
        var w =  window.innerWidth > 1000 ? window.innerWidth - 302 : window.innerWidth;
        var h = window.innerHeight;

        window.canvasWidth = w;
        
        renderer.domElement.originalSize = { width: w, height: h};
        camera.aspect = w / h;
        camera.updateProjectionMatrix();

        renderer.setPixelRatio( dpr );
        renderer.setSize( w, h );

        if(composer) {
            composer.setSize( w, h );
            FXAAShaderPass.uniforms['resolution'].value.set( 1 / w , 1 / h  );
            VerticalTiltShiftShader.uniforms["v"].value = 1 / h;
        }
    
    }
    onWindowResize();

    var controls = scope.controls = new THREE.POrbitControls( camera, renderer.domElement );
    
    controls.minPolarAngle = Math.PI * .15;
    controls.maxPolarAngle = Math.PI * .85;
    
    controls.enableDamping = true;
    controls.dampingFactor = .063;

    controls.autoRotate = true;
    controls.autoRotateSpeed = -.002*3;

    controls.enableZoom = !false;
    controls.minDistance = 18;
    controls.maxDistance = enable_screenshot ? 40 : 20;
    controls.zoomSpeed = .2;
    controls.zoomFactor = .1;

    // PLanet
    var planet;

    var def = kaspersky.ready.addWait();
    kaspersky.planetMain = function (api, locationAPI) {
        api()
            .then(function( data  ) {
                setTimeout(function(){
                    planet = new Planet( scope, data, function () {
                        def.resolve();
                        def = undefined;
                    }, locationAPI );
                    animate();
                }, 500);
            })
            .fail(function() {
                console.log( "error" );
            })
            .always(function() {
            })
    };

    $(document).trigger("panetMainLoaded");

    // ANIMATION LOOP
    function animate() {

        window.requestAnimationFrame( animate );
        
        if( planet.state != planet.ANIMATED ) controls.update();
        planet.update();

        if( composer ) composer.render();
            else renderer.render( scene, camera );

        if ( stats ) stats.update(renderer);
    }

    this.animateIn = function( t, onComplete ) {
        
        t = t || 3;
    
        TweenLite.to( controls, t,{
            autoRotateSpeed: -.002,
            ease: Sine.easeOut
        });
        
        camera.updateProjectionMatrix();
        TweenLite.to( camera, t,{
            fov: 60,
            ease: Sine.easeInOut,
            onUpdate:function() {
                camera.updateProjectionMatrix();
            },
            onComplete: function() {
                if( onComplete ) onComplete();
            }
        })
    };

    this.animateOut = function( t, onComplete ) {
        
        t = t || 2;
        
        TweenLite.to( camera, t,{
            fov: 10,
            ease: Sine.easeInOut,
            onUpdate:function() {
                camera.updateProjectionMatrix();
            },
            onComplete: function() {
                if( onComplete ) onComplete();
            }
        })
    };

})(kaspersky = kaspersky || {});
//------------------------------------------------------------

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章