2050.earth 代碼分析-——第六部分(sputnik)


/*
███████╗██████╗ ██╗   ██╗████████╗███╗   ██╗██╗██╗  ██╗
██╔════╝██╔══██╗██║   ██║╚══██╔══╝████╗  ██║██║██║ ██╔╝
███████╗██████╔╝██║   ██║   ██║   ██╔██╗ ██║██║█████╔╝ 
╚════██║██╔═══╝ ██║   ██║   ██║   ██║╚██╗██║██║██╔═██╗ 
███████║██║     ╚██████╔╝   ██║   ██║ ╚████║██║██║  ██╗
╚══════╝╚═╝      ╚═════╝    ╚═╝   ╚═╝  ╚═══╝╚═╝╚═╝  ╚═╝
*/
Planet.prototype.drawSputniks = function () {
    // SPUTNIKS
    this.sputniks = [];

    var sputnik1 = this.addSputnik( 'station_b.js', this.radius*1.2, this.container, new THREE.Vector3(-.5,0,0) );
    var sputnik2 = this.addSputnik( 'station_c.js', this.radius*1.25, this.container, new THREE.Vector3(.6,3,-1.2) );
}


Planet.prototype.addSputnik = function ( name, radius, container, rotation ) {

    var scope = this;
    var loader = new THREE.JSONLoader();
    
    var ring = scope.drawRing( new THREE.Vector3(), radius, .05, new THREE.Vector3() );
    var m = ring.material;
    m.opacity = .3;

    loader.load(
        // resource URL
        PlanetData.textures_path + name,
        // Function when resource is loaded
        function ( geometry, materials ) {

            var m = new THREE.MeshBasicMaterial( { color: scope.planet_color });
            m.wireframe = true;
            // m.transparent = true;
            // m.blending = THREE.AdditiveBlending;
            // m.depthWrite = false;

            var object = new THREE.Mesh( geometry, m );
            object.position.x = -radius;
            object.rotation.x = .5;
            object.scale.set( .03, .03, .03 );
            object.matrixAutoUpdate = false;
            object.updateMatrix();
            ring.add( object );
        }
    );

    scope.sputniks.push( ring );

    var ring_container = new THREE.Object3D();
    scope.container.add( ring_container );
    ring_container.add( ring );
    
    ring_container.rotation.x = rotation.x;
    ring_container.rotation.y = rotation.y;
    ring_container.rotation.z = rotation.z;

    ring_container.matrixAutoUpdate = false;
    ring_container.updateMatrix();

    return ring;
}
function PlanetPointed( planet ) {
    
    var scope = this;

    /// INIT
    var parts_count = 2;
    var u_grid = 250;
    var v_grid = 250;

	var texture = planet.textureLoader.load( PlanetData.textures_path + "dot.png" );
    texture.generateMipalphaMaps = false;
    texture.magFilter = THREE.LinearFilter;
    texture.minFilter = THREE.LinearFilter;

    var materials = [];
    for (var i = 0; i < parts_count; i++) {
        var m = new THREE.PointsMaterial( { size: .15 / planet.ratio  } );// 
        m.color = new THREE.Color(0x31b477);
        m.map = texture;
        m.depthWrite = false;
        m.transparent = true;
        m.opacity = 0;
        m.blending = THREE.AdditiveBlending;
        // m.side = THREE.BackSide;//FrontSide;

        var prop = i/parts_count;
        m.t_ = prop*Math.PI*2;
	    m.speed_ = .04;
	    m.min_ = Math.random()*.2+.5;
	    m.delta_ = Math.random()*.1+.1;
	    m.opacity_coef_ = 1;

        materials.push( m );
    }

    var current_container;







    var sea_hex_material;

    // METHODS
    this.init = function( _year ) {
	    
	    var container = new THREE.Object3D();
	    container.matrixAutoUpdate = false;

	    // LAND

	    var sphere_parts = [];

	    for (var i = 0; i < parts_count; i++) {
	        sphere_parts[i] = {
	            positions: [],
	            // colors: [],
	        };
	    };

	    var positions = [];
	    // var colors = [];

	    spherical = new THREE.Spherical();
	    spherical.radius = planet.radius;
	    var pos = new THREE.Vector3();
	    var projectiveImage = PlanetData.years[_year].earth_image;

	    // var col = new THREE.Color(0xb1f7a0);
	    for (var sv = 0; sv < v_grid; sv++) {
	        var st = (u_grid * ( 1 - Math.sin( sv/v_grid*Math.PI) ))/u_grid+.5;
	        // console.log(sv,st);
	        for (var su = 0; su < u_grid; su+=st) {
	            var u = su/u_grid;
	            var v = sv/v_grid;
	            var is_land = projectiveImage.isLandByUV( u, v );
	            if( is_land ){
	                var o = sphere_parts[ Math.floor(Math.random()*parts_count)];
	                spherical.theta = u * Math.PI *2 - Math.PI/2;
	                spherical.phi = v * Math.PI;
	                pos.setFromSpherical( spherical );
	                o.positions.push( pos.x );
	                o.positions.push( pos.y );
	                o.positions.push( pos.z );
	                // o.colors.push( col.r );
	                // o.colors.push( col.g );
	                // o.colors.push( col.b );
	            }
	        }
	    };

	    // POINTS
	    for (var i = 0; i < sphere_parts.length; i++) {
	        var o = sphere_parts[i];
	        var geometry = new THREE.BufferGeometry();
	        
	        var positions_ = new Float32Array( o.positions.length );
	        for (var j = 0; j < o.positions.length; j++) {
	            positions_[j] = o.positions[j];
	        };

	        // var colors_ = Float32Array.from( o.colors );
	        geometry.addAttribute( 'position', new THREE.BufferAttribute( positions_, 3 ) );
	        // geometry.addAttribute( 'color', new THREE.BufferAttribute( colors_, 3 ) );
	        geometry.computeBoundingSphere();
	        
	        o.material = materials[i];

	        var points = o.mesh = new THREE.Points( geometry, o.material );
	        points.matrixAutoUpdate = false;
	        container.add( points );
	    };





	    // SEA HEXS
	    
	    var r = planet.radius * .97;

	    sea_hex_material = new THREE.MeshBasicMaterial({
	    	transparent : true,
		    opacity : 0,
		    color : new THREE.Color( 0x31b477 ),
		    blending : THREE.AdditiveBlending,
		    // side : THREE.DoubleSide,
		    depthWrite : false
		    // ,wireframe: true
	    });
	    
	    // Utils.drawFunction( undefined, 0 );

	    var hex = Utils.createHexagon( .12, false, sea_hex_material, .025 );
	    var geo = new THREE.Geometry();//hex.geometry.clone();
	    var step = .01;
	    var stp = step;
	    var end, xx, y, yy;
	    var pi2 = Math.PI*2;
	    var check_offset = .02;
	    var row = false;

	    for (var _y = -Math.PI + .5; _y < -.6; _y+= .04 ) {
	    	y = Math.cos( _y ) * .5 + .5;
	    	// console.log(">>", _y, y );
	    	row = !row;
	    	stp = Math.abs( step / Math.sin( y * Math.PI ) );
	    	end = Math.floor( 1 / stp );
	    	// console.log( y, stp, end );

	    	for (var x = 0; x < end; x++ ) {
	    		
	    		xx = .5 + ( end/2 - x - (row ? .5 : 0) ) * stp;
	    		yy = y;
	    		
	    		if( 
	    			Math.random()>.25 ||
	    			projectiveImage.isLandByUV( xx, yy )
	    			|| projectiveImage.isLandByUV( xx - check_offset, yy )
	    			|| projectiveImage.isLandByUV( xx + check_offset, yy )
	    			|| projectiveImage.isLandByUV( xx, yy - check_offset ) 
	    			|| projectiveImage.isLandByUV( xx, yy + check_offset ) 
	    		) continue;

	    		Utils.setFromSpherical( planet.radius * (.97 - Math.random()*.01), xx, yy, hex.position );
	        	hex.lookAt( THREE.Vector3.ZERO );
	        	hex.updateMatrix();
	        	hex.updateMatrixWorld();

	    		geo.merge( hex.geometry, hex.matrixWorld );	

	    	}
	    };

	    // console.log("=>", geo );
	    var hexs = new THREE.Mesh( geo, sea_hex_material );
	    hexs.matrixAutoUpdate = false;
	    container.add( hexs );




	    return container;
	}



	this.update = function(){
	    for (var i = 0; i < materials.length; i++) {
	        var m = materials[i];
	        m.t_ += m.speed_;
	        // o.material.opacity = Math.sin(o.t)*.2+.5;
	        m.opacity = (Math.sin( m.t_ ) * m.delta_ + m.min_) * m.opacity_coef_;
	    };
	}


	this.show = function( _year, t ){
		var year_data = PlanetData.years[_year];
		
		if( !year_data.pointed_sphere ) year_data.pointed_sphere = this.init( _year );
		current_container = year_data.pointed_sphere;

		planet.container.add( current_container );

		for (var i = 0; i < materials.length; i++) {
			var m = materials[i];
			TweenLite.killTweensOf(m);
			TweenLite.to( m, t, {
				opacity_coef_: 1,
				ease: Sine.easeInOut,
				onComplete: function(){
					
				}
			})
		};

		TweenLite.killTweensOf(sea_hex_material);
		TweenLite.to( sea_hex_material, t, {
			opacity: .4,
			ease: Sine.easeInOut
		});
	}

	
	this.hide = function ( t ) {
		
		for (var i = 0; i < materials.length; i++) {
			var m = materials[i];
			TweenLite.killTweensOf(m);
			TweenLite.to( m, t, {
				opacity_coef_: 0,
				ease: Sine.easeInOut,
				onComplete: function(){
					planet.container.remove( current_container );
				}
			})
		};

		TweenLite.killTweensOf(sea_hex_material);
		TweenLite.to( sea_hex_material, t, {
			opacity: 0,
			ease: Sine.easeInOut
		});
	}

}
// LAND CONTOUR
PlanetContour = function ( planet ) {
    
    var max_opacity = .8;//.65;

    var _geometry = new THREE.SphereGeometry( planet.radius * .995, 32, 32, 0, Math.PI );
    var m1 = new THREE.MeshBasicMaterial();
    m1.color = new THREE.Color( 0x31b477 );
    m1.fog = false;
    m1.transparent = true;
    m1.blending = THREE.AdditiveBlending;
    m1.depthWrite = false;
    
    var sphere1 = new THREE.Mesh( _geometry, m1 );
    sphere1.visible = false;
    sphere1.matrixAutoUpdate = false;
    // sphere1.rotation.y = Math.PI * .999;
    sphere1.updateMatrix();
    planet.container.add( sphere1 );
    sphere1.matrixAutoUpdate = false;

    // 2nd halfsphere
    var m2 = m1.clone();
    
    var sphere2 = sphere1.clone();
    sphere2.material = m2;
    planet.container.add( sphere2 );
    sphere2.rotation.y = Math.PI;
    sphere2.updateMatrix();




    // METHODS

    this.show = function( _year, t ){
		var year_data = PlanetData.years[_year];
    	
    	if( !year_data.contour_texture ){
    		var urls = year_data.contour_url;
    		year_data.contour_texture = [ getTexture( urls[0] ), getTexture( urls[1] ) ];
    	}
    	
    	m1.map = year_data.contour_texture[0];
        m1.map.generateMipalphaMaps = false;
        m1.map.magFilter = THREE.LinearFilter;
        m1.map.minFilter = THREE.LinearFilter;
    	m1.needsUpdate = true;

    	m2.map = year_data.contour_texture[1];
    	m2.map.generateMipalphaMaps = false;
        m2.map.magFilter = THREE.LinearFilter;
        m2.map.minFilter = THREE.LinearFilter;
        m2.needsUpdate = true;

    	fadeIn( sphere1, t );
    	fadeIn( sphere2, t );
    }



    this.hide = function( t ){
    	fadeOut( sphere1, t );
    	fadeOut( sphere2, t );
    }





	function getTexture( path ){
		var map = planet.textureLoader.load( path );// PlanetData.textures_path + "contour1_1.png"
	    map.generateMipalphaMaps = false;
	    map.magFilter = THREE.LinearFilter;
	    map.minFilter = THREE.LinearFilter;
	    return map;
	}

	function fadeIn ( o, t ){
		o.visible = true;
		var m = o.material;
		m.opacity = 0;
		TweenLite.killTweensOf( m );
		TweenLite.to( m, t,{
			opacity: max_opacity,
			ease: Sine.easeInOut
			// ,onComplete: function(){
				
			// }
		})
	}

	function fadeOut ( o, t ){
		var m = o.material;
		TweenLite.killTweensOf( m );
		TweenLite.to( m, t,{
			opacity: 0,
			ease: Sine.easeInOut,
			onComplete: function(){
				// o.visible = false;
			}
		})
	}

}
// COMMENT POPUP
function  PlanetCommentPopup( $container ) {
    var comment_is_shown = false;
    var planet = window.PLANET;
    var shownext_timer;

    var $line = $("<div class='planet-comment-line'>")
        .appendTo( $container )
        .hide();

    var $comment = $("<div class='planet-comment'>")
        .appendTo( $container )
        .hide();

    var $text = $("<div class='planet-comment-text'>")
        .appendTo( $comment )

    var camera = planet.main.camera;

    var comment_dummy = new THREE.Object3D();
    planet.container.add( comment_dummy );
    
    this.show = function( text, _position, delay, onFinish ) {    
        if( planet.state != planet.IDLE ){
            setTimeout( show.bind( this, text.name, _position, delay, onFinish ), 2000 );
            return;
        }

        $line.show();
        $text.text( text.name );
        $text.attr("href", text.id);
        $text.on("click",function(){
            location.href = $(this).attr("href");
        });
        $comment.stop().show(200);
        comment_is_shown = true;

        comment_dummy.position.copy( _position );

        if(delay){
            clearTimeout( shownext_timer );
            shownext_timer = setTimeout( function(){
                hide( onFinish );
            }, delay );
        }
    }




    this.hide = function( onFinish ) {
        clearTimeout( shownext_timer );
        $comment.stop().hide(200, function() {
            $line.hide();
            comment_is_shown = false;
            if(onFinish) onFinish();
        });
    }



    var _timeout;

    this.showRandom = function () {
        
        var _location;
        var _locations = planet.planetLocations.current_locations;

        clearTimeout( _timeout );
        if ( !_locations ) {
            _timeout = setTimeout( this.showRandom, 100 );
            return;
        }
        
        for( var i=0; _locations.length > 0 && i<10; i++){
            _location = _locations[ ~~(Math.random()*_locations.length) ];

            if( _location.position && PlanetData.hasLocationAnyBriefs( _location, true ) && planet.isInFrontOfPlanet( _location.position ) ) {
                break;
            }
            _location = null;
        }

        if( !_location ){
            _timeout = setTimeout( this.showRandom, 200 );
            return;
        }

        planet.getLocationBriefs( _location.location_id, function( briefs ){

            if( briefs && briefs.length ){
                var brief = briefs[ ~~(Math.random()*briefs.length) ];
                show( brief, _location.position, 3000, showRandom );

            }else{
                _timeout = setTimeout( this.showRandom, 100 );

            }

        });
    }




    this.update = function() {
        if( !comment_is_shown ) return;

        var pos = comment_dummy.getWorldPosition();
        var v1 = pos.clone().project( camera );
        v1.x = (v1.x + 1) / 2 * window.canvasWidth;
        v1.y = -(v1.y - 1) / 2 * window.innerHeight;

        var v2 = pos.clone().multiplyScalar( 1.1 ).project( camera );
        v2.x = (v2.x + 1) / 2 * window.canvasWidth;
        v2.y = -(v2.y - 1) / 2 * window.innerHeight;

        $comment.css({
            transform: "translate("+ v2.x +"px, "+v2.y+"px)",
            height: "auto",
            width: "auto",
        });

        var w = v1.x - v2.x;
        var h = v1.y - v2.y;
        var scl = Math.sqrt( w*w + h*h )+1;
        var a = Math.atan2( h + 1, w );

        $line.css({
            transform: "translate("+ (v2.x) +"px, "+ (v2.y) +"px) rotate("+a+"rad)",
            width: scl+"px"
        });

        if( !planet.isInFrontOfPlanet( pos ) ) showRandom();
        
    }


    return this;
}

var PlanetData = (function(){
	
	var scope = this;

	this.textures_path = "/assets/earth/";

	this.YEAR = null;// Current YEAR data container
	this.YEAR_ID = null;// Current year id container

	// YEARS DATA
	this.years = {
		
		"2030":{
			"earth_url" : this.textures_path + "earth_1.png",
			"contour_url" : [ this.textures_path + "contour1_1.png", this.textures_path + "contour2_1.png" ]
			,min_locations: 100
		},

		"2040":{
			"earth_url" : this.textures_path + "earth_1.png",
			"contour_url" : [ this.textures_path + "contour1_1.png", this.textures_path + "contour2_1.png" ]
			,min_locations: 50
		},

		"2050":{
			"earth_url" : this.textures_path + "earth_1.png",
			"contour_url" : [ this.textures_path + "contour1_1.png", this.textures_path + "contour2_1.png" ]
			,min_locations: 10
		},
	};

	// 
	this.year_ids = [];
	for (var i in this.years) {
		this.year_ids.push( i );
	};

	this.hasLocationAnyBriefs = function( _location, year ){
		// current year
		if( year === true && !!_location.years[ scope.YEAR_ID ]){
			return _location.years[ scope.YEAR_ID ].briefs;
		
		// specified year
		}else if( year !== undefined && !!_location.years[ year ]){
			return _location.years[ year ].briefs;

		}

		// any year
		for (var i in _location.years) {
			var briefs = _location.years[ i ].briefs;
			if( briefs ) return briefs;
		};

		return 0;

	}

	this.hasLocationAnyBriefTexts = function( _location, year ){

		// current year
		if( year === true ){

			return _location.years[ scope.YEAR_ID ].briefs_text;

		// specified year
		}else if( year !== undefined ){

			return _location.years[ year ].briefs_text;

		}

		// any year
		for (var i in _location.years) {
			var briefs = _location.years[ i ].briefs;
			if( briefs ) return _location.years[ i ].briefs_text;
		};

		return 0;

	}

	this.getWorkList = function( _location, year ) {
		if(year == true){
			return _location.years[ scope.YEAR_ID ].works_list;
		} else if( year !== undefined ){
			return _location.years[ year ].works_list;
		}

		return 0;
	}

	this.getMoreText = function( _location, year ) {
		if(year == true){
			return _location.years[ scope.YEAR_ID ].more_btn;
		} else if( year !== undefined ){
			return _location.years[ year ].more_btn;
		}

		return 0;
	}

	return this;

})();

 

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