mirror of
				https://github.com/jiawanlong/Cesium-Examples.git
				synced 2025-11-04 09:14:17 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			428 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			428 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
/**
 | 
						|
 * dat.globe Javascript WebGL Globe Toolkit
 | 
						|
 * http://dataarts.github.com/dat.globe
 | 
						|
 *
 | 
						|
 * Copyright 2011 Data Arts Team, Google Creative Lab
 | 
						|
 *
 | 
						|
 * Licensed under the Apache License, Version 2.0 (the 'License');
 | 
						|
 * you may not use this file except in compliance with the License.
 | 
						|
 * You may obtain a copy of the License at
 | 
						|
 *
 | 
						|
 * http://www.apache.org/licenses/LICENSE-2.0
 | 
						|
 */
 | 
						|
 | 
						|
var DAT = DAT || {};
 | 
						|
 | 
						|
DAT.Globe = function(container, colorFn) {
 | 
						|
 | 
						|
  colorFn = colorFn || function(x) {
 | 
						|
    var c = new THREE.Color();
 | 
						|
    c.setHSV( ( 0.6 - ( x * 0.5 ) ), 1.0, 1.0 );
 | 
						|
    return c;
 | 
						|
  };
 | 
						|
 | 
						|
  var Shaders = {
 | 
						|
    'earth' : {
 | 
						|
      uniforms: {
 | 
						|
        'texture': { type: 't', value: 0, texture: null }
 | 
						|
      },
 | 
						|
      vertexShader: [
 | 
						|
        'varying vec3 vNormal;',
 | 
						|
        'varying vec2 vUv;',
 | 
						|
        'void main() {',
 | 
						|
          'gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );',
 | 
						|
          'vNormal = normalize( normalMatrix * normal );',
 | 
						|
          'vUv = uv;',
 | 
						|
        '}'
 | 
						|
      ].join('\n'),
 | 
						|
      fragmentShader: [
 | 
						|
        'uniform sampler2D texture;',
 | 
						|
        'varying vec3 vNormal;',
 | 
						|
        'varying vec2 vUv;',
 | 
						|
        'void main() {',
 | 
						|
          'vec3 diffuse = texture2D( texture, vUv ).xyz;',
 | 
						|
          'float intensity = 1.05 - dot( vNormal, vec3( 0.0, 0.0, 1.0 ) );',
 | 
						|
          'vec3 atmosphere = vec3( 1.0, 1.0, 1.0 ) * pow( intensity, 3.0 );',
 | 
						|
          'gl_FragColor = vec4( diffuse + atmosphere, 1.0 );',
 | 
						|
        '}'
 | 
						|
      ].join('\n')
 | 
						|
    },
 | 
						|
    'atmosphere' : {
 | 
						|
      uniforms: {},
 | 
						|
      vertexShader: [
 | 
						|
        'varying vec3 vNormal;',
 | 
						|
        'void main() {',
 | 
						|
          'vNormal = normalize( normalMatrix * normal );',
 | 
						|
          'gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );',
 | 
						|
        '}'
 | 
						|
      ].join('\n'),
 | 
						|
      fragmentShader: [
 | 
						|
        'varying vec3 vNormal;',
 | 
						|
        'void main() {',
 | 
						|
          'float intensity = pow( 0.8 - dot( vNormal, vec3( 0, 0, 1.0 ) ), 12.0 ) * 0.7;',
 | 
						|
          'gl_FragColor = vec4( 0.55 + 0.36*intensity, 0.83 + 0.14*intensity, 0.95 + 0.04 * intensity, 1.0 * intensity ) ;',
 | 
						|
        '}'
 | 
						|
      ].join('\n')
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
  var camera, scene, sceneAtmosphere, renderer, w, h;
 | 
						|
  var vector, mesh, atmosphere, point;
 | 
						|
 | 
						|
  var overRenderer;
 | 
						|
 | 
						|
  /*custom change: the 'imgDir' attribute control the path of the globle's texture*/
 | 
						|
  var imgDir = './images/';
 | 
						|
 | 
						|
  var curZoomSpeed = 0;
 | 
						|
  var zoomSpeed = 50;
 | 
						|
 | 
						|
  var mouse = { x: 0, y: 0 }, mouseOnDown = { x: 0, y: 0 };
 | 
						|
  var rotation = { x: 0, y: 0 },
 | 
						|
      target = { x: Math.PI*3/2, y: Math.PI / 6.0 },
 | 
						|
      targetOnDown = { x: 0, y: 0 };
 | 
						|
 | 
						|
  var distance = 100000, distanceTarget = 100000;
 | 
						|
  var padding = 40;
 | 
						|
  var PI_HALF = Math.PI / 2;
 | 
						|
 | 
						|
  function init() {
 | 
						|
 | 
						|
    container.style.color = '#ff0';
 | 
						|
    container.style.font = '13px/20px Arial, sans-serif';
 | 
						|
 | 
						|
    var shader, uniforms, material;
 | 
						|
    w = container.offsetWidth || window.innerWidth;
 | 
						|
    h = container.offsetHeight || window.innerHeight;
 | 
						|
 | 
						|
    camera = new THREE.Camera(
 | 
						|
        30, w / h, 1, 10000);
 | 
						|
    camera.position.z = distance;
 | 
						|
 | 
						|
    vector = new THREE.Vector3();
 | 
						|
 | 
						|
    scene = new THREE.Scene();
 | 
						|
    sceneAtmosphere = new THREE.Scene();
 | 
						|
 | 
						|
    var geometry = new THREE.Sphere(200, 40, 30);
 | 
						|
 | 
						|
    shader = Shaders['earth'];
 | 
						|
    uniforms = THREE.UniformsUtils.clone(shader.uniforms);
 | 
						|
 | 
						|
    uniforms['texture'].texture = THREE.ImageUtils.loadTexture(imgDir+'world' +
 | 
						|
        '.jpg');
 | 
						|
 | 
						|
    material = new THREE.MeshShaderMaterial({
 | 
						|
 | 
						|
          uniforms: uniforms,
 | 
						|
          vertexShader: shader.vertexShader,
 | 
						|
          fragmentShader: shader.fragmentShader
 | 
						|
 | 
						|
        });
 | 
						|
 | 
						|
    mesh = new THREE.Mesh(geometry, material);
 | 
						|
    mesh.matrixAutoUpdate = false;
 | 
						|
    scene.addObject(mesh);
 | 
						|
 | 
						|
    shader = Shaders['atmosphere'];
 | 
						|
    uniforms = THREE.UniformsUtils.clone(shader.uniforms);
 | 
						|
 | 
						|
    material = new THREE.MeshShaderMaterial({
 | 
						|
 | 
						|
          uniforms: uniforms,
 | 
						|
          vertexShader: shader.vertexShader,
 | 
						|
          fragmentShader: shader.fragmentShader
 | 
						|
 | 
						|
        });
 | 
						|
 | 
						|
    mesh = new THREE.Mesh(geometry, material);
 | 
						|
    mesh.scale.x = mesh.scale.y = mesh.scale.z = 1.1;
 | 
						|
    mesh.flipSided = true;
 | 
						|
    mesh.matrixAutoUpdate = false;
 | 
						|
    mesh.updateMatrix();
 | 
						|
    sceneAtmosphere.addObject(mesh);
 | 
						|
 | 
						|
    geometry = new THREE.Cube(0.75, 0.75, 1, 1, 1, 1, null, false, { px: true,
 | 
						|
          nx: true, py: true, ny: true, pz: false, nz: true});
 | 
						|
 | 
						|
    for (var i = 0; i < geometry.vertices.length; i++) {
 | 
						|
 | 
						|
      var vertex = geometry.vertices[i];
 | 
						|
      vertex.position.z += 0.5;
 | 
						|
 | 
						|
    }
 | 
						|
 | 
						|
    point = new THREE.Mesh(geometry);
 | 
						|
 | 
						|
    renderer = new THREE.WebGLRenderer({antialias: true});
 | 
						|
    renderer.autoClear = false;
 | 
						|
    renderer.setClearColorHex(0x000000, 0.0);
 | 
						|
    renderer.setSize(w, h);
 | 
						|
 | 
						|
    renderer.domElement.style.position = 'absolute';
 | 
						|
 | 
						|
    container.appendChild(renderer.domElement);
 | 
						|
 | 
						|
    container.addEventListener('mousedown', onMouseDown, false);
 | 
						|
 | 
						|
    container.addEventListener('mousewheel', onMouseWheel, false);
 | 
						|
 | 
						|
    document.addEventListener('keydown', onDocumentKeyDown, false);
 | 
						|
 | 
						|
    window.addEventListener('resize', onWindowResize, false);
 | 
						|
 | 
						|
    container.addEventListener('mouseover', function() {
 | 
						|
      overRenderer = true;
 | 
						|
    }, false);
 | 
						|
 | 
						|
    container.addEventListener('mouseout', function() {
 | 
						|
      overRenderer = false;
 | 
						|
    }, false);
 | 
						|
  }
 | 
						|
 | 
						|
  addData = function(data, opts) {
 | 
						|
    var lat, lng, size, color, i, step, colorFnWrapper;
 | 
						|
 | 
						|
    opts.animated = opts.animated || false;
 | 
						|
    this.is_animated = opts.animated;
 | 
						|
    opts.format = opts.format || 'magnitude'; // other option is 'legend'
 | 
						|
    console.log(opts.format);
 | 
						|
    if (opts.format === 'magnitude') {
 | 
						|
      step = 3;
 | 
						|
      colorFnWrapper = function(data, i) { return colorFn(data[i+2]); }
 | 
						|
    } else if (opts.format === 'legend') {
 | 
						|
      step = 4;
 | 
						|
      colorFnWrapper = function(data, i) { return colorFn(data[i+3]); }
 | 
						|
    } else {
 | 
						|
      throw('error: format not supported: '+opts.format);
 | 
						|
    }
 | 
						|
 | 
						|
    if (opts.animated) {
 | 
						|
      if (this._baseGeometry === undefined) {
 | 
						|
        this._baseGeometry = new THREE.Geometry();
 | 
						|
        for (i = 0; i < data.length; i += step) {
 | 
						|
          lat = data[i];
 | 
						|
          lng = data[i + 1];
 | 
						|
//        size = data[i + 2];
 | 
						|
          color = colorFnWrapper(data,i);
 | 
						|
          size = 0;
 | 
						|
          addPoint(lat, lng, size, color, this._baseGeometry);
 | 
						|
        }
 | 
						|
      }
 | 
						|
      if(this._morphTargetId === undefined) {
 | 
						|
        this._morphTargetId = 0;
 | 
						|
      } else {
 | 
						|
        this._morphTargetId += 1;
 | 
						|
      }
 | 
						|
      opts.name = opts.name || 'morphTarget'+this._morphTargetId;
 | 
						|
    }
 | 
						|
    var subgeo = new THREE.Geometry();
 | 
						|
    for (i = 0; i < data.length; i += step) {
 | 
						|
      lat = data[i];
 | 
						|
      lng = data[i + 1];
 | 
						|
      color = colorFnWrapper(data,i);
 | 
						|
      size = data[i + 2];
 | 
						|
      size = size*200;
 | 
						|
      addPoint(lat, lng, size, color, subgeo);
 | 
						|
    }
 | 
						|
    if (opts.animated) {
 | 
						|
      this._baseGeometry.morphTargets.push({'name': opts.name, vertices: subgeo.vertices});
 | 
						|
    } else {
 | 
						|
      this._baseGeometry = subgeo;
 | 
						|
    }
 | 
						|
 | 
						|
  };
 | 
						|
 | 
						|
  function createPoints() {
 | 
						|
    if (this._baseGeometry !== undefined) {
 | 
						|
      if (this.is_animated === false) {
 | 
						|
        this.points = new THREE.Mesh(this._baseGeometry, new THREE.MeshBasicMaterial({
 | 
						|
              color: 0xffffff,
 | 
						|
              vertexColors: THREE.FaceColors,
 | 
						|
              morphTargets: false
 | 
						|
            }));
 | 
						|
      } else {
 | 
						|
        if (this._baseGeometry.morphTargets.length < 8) {
 | 
						|
          console.log('t l',this._baseGeometry.morphTargets.length);
 | 
						|
          var padding = 8-this._baseGeometry.morphTargets.length;
 | 
						|
          console.log('padding', padding);
 | 
						|
          for(var i=0; i<=padding; i++) {
 | 
						|
            console.log('padding',i);
 | 
						|
            this._baseGeometry.morphTargets.push({'name': 'morphPadding'+i, vertices: this._baseGeometry.vertices});
 | 
						|
          }
 | 
						|
        }
 | 
						|
        this.points = new THREE.Mesh(this._baseGeometry, new THREE.MeshBasicMaterial({
 | 
						|
              color: 0xffffff,
 | 
						|
              vertexColors: THREE.FaceColors,
 | 
						|
              morphTargets: true
 | 
						|
            }));
 | 
						|
      }
 | 
						|
      scene.addObject(this.points);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  function addPoint(lat, lng, size, color, subgeo) {
 | 
						|
    var phi = (90 - lat) * Math.PI / 180;
 | 
						|
    var theta = (180 - lng) * Math.PI / 180;
 | 
						|
 | 
						|
    point.position.x = 200 * Math.sin(phi) * Math.cos(theta);
 | 
						|
    point.position.y = 200 * Math.cos(phi);
 | 
						|
    point.position.z = 200 * Math.sin(phi) * Math.sin(theta);
 | 
						|
 | 
						|
    point.lookAt(mesh.position);
 | 
						|
 | 
						|
    point.scale.z = -size;
 | 
						|
    point.updateMatrix();
 | 
						|
 | 
						|
    var i;
 | 
						|
    for (i = 0; i < point.geometry.faces.length; i++) {
 | 
						|
 | 
						|
      point.geometry.faces[i].color = color;
 | 
						|
 | 
						|
    }
 | 
						|
 | 
						|
    GeometryUtils.merge(subgeo, point);
 | 
						|
  }
 | 
						|
 | 
						|
  function onMouseDown(event) {
 | 
						|
    event.preventDefault();
 | 
						|
 | 
						|
    container.addEventListener('mousemove', onMouseMove, false);
 | 
						|
    container.addEventListener('mouseup', onMouseUp, false);
 | 
						|
    container.addEventListener('mouseout', onMouseOut, false);
 | 
						|
 | 
						|
    mouseOnDown.x = - event.clientX;
 | 
						|
    mouseOnDown.y = event.clientY;
 | 
						|
 | 
						|
    targetOnDown.x = target.x;
 | 
						|
    targetOnDown.y = target.y;
 | 
						|
 | 
						|
    container.style.cursor = 'move';
 | 
						|
  }
 | 
						|
 | 
						|
  function onMouseMove(event) {
 | 
						|
    mouse.x = - event.clientX;
 | 
						|
    mouse.y = event.clientY;
 | 
						|
 | 
						|
    var zoomDamp = distance/1000;
 | 
						|
 | 
						|
    target.x = targetOnDown.x + (mouse.x - mouseOnDown.x) * 0.005 * zoomDamp;
 | 
						|
    target.y = targetOnDown.y + (mouse.y - mouseOnDown.y) * 0.005 * zoomDamp;
 | 
						|
 | 
						|
    target.y = target.y > PI_HALF ? PI_HALF : target.y;
 | 
						|
    target.y = target.y < - PI_HALF ? - PI_HALF : target.y;
 | 
						|
  }
 | 
						|
 | 
						|
  function onMouseUp(event) {
 | 
						|
    container.removeEventListener('mousemove', onMouseMove, false);
 | 
						|
    container.removeEventListener('mouseup', onMouseUp, false);
 | 
						|
    container.removeEventListener('mouseout', onMouseOut, false);
 | 
						|
    container.style.cursor = 'auto';
 | 
						|
  }
 | 
						|
 | 
						|
  function onMouseOut(event) {
 | 
						|
    container.removeEventListener('mousemove', onMouseMove, false);
 | 
						|
    container.removeEventListener('mouseup', onMouseUp, false);
 | 
						|
    container.removeEventListener('mouseout', onMouseOut, false);
 | 
						|
  }
 | 
						|
 | 
						|
  function onMouseWheel(event) {
 | 
						|
    event.preventDefault();
 | 
						|
    if (overRenderer) {
 | 
						|
      zoom(event.wheelDeltaY * 0.3);
 | 
						|
    }
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  function onDocumentKeyDown(event) {
 | 
						|
    switch (event.keyCode) {
 | 
						|
      case 38:
 | 
						|
        zoom(100);
 | 
						|
        event.preventDefault();
 | 
						|
        break;
 | 
						|
      case 40:
 | 
						|
        zoom(-100);
 | 
						|
        event.preventDefault();
 | 
						|
        break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  function onWindowResize( event ) {
 | 
						|
    console.log('resize');
 | 
						|
    camera.aspect = window.innerWidth / window.innerHeight;
 | 
						|
    camera.updateProjectionMatrix();
 | 
						|
      /*custom change: if there is a container, the width and height is the container's width and height*/
 | 
						|
    renderer.setSize( container.offsetWidth || window.innerWidth, container.offsetHeight || window.innerHeight );
 | 
						|
  }
 | 
						|
 | 
						|
  function zoom(delta) {
 | 
						|
    distanceTarget -= delta;
 | 
						|
    distanceTarget = distanceTarget > 1000 ? 1000 : distanceTarget;
 | 
						|
    distanceTarget = distanceTarget < 350 ? 350 : distanceTarget;
 | 
						|
  }
 | 
						|
 | 
						|
  function animate() {
 | 
						|
    requestAnimationFrame(animate);
 | 
						|
    render();
 | 
						|
  }
 | 
						|
 | 
						|
  function render() {
 | 
						|
    zoom(curZoomSpeed);
 | 
						|
 | 
						|
    rotation.x += (target.x - rotation.x) * 0.1;
 | 
						|
    rotation.y += (target.y - rotation.y) * 0.1;
 | 
						|
    distance += (distanceTarget - distance) * 0.3;
 | 
						|
 | 
						|
    camera.position.x = distance * Math.sin(rotation.x) * Math.cos(rotation.y);
 | 
						|
    camera.position.y = distance * Math.sin(rotation.y);
 | 
						|
    camera.position.z = distance * Math.cos(rotation.x) * Math.cos(rotation.y);
 | 
						|
 | 
						|
    vector.copy(camera.position);
 | 
						|
 | 
						|
    renderer.clear();
 | 
						|
    renderer.render(scene, camera);
 | 
						|
    renderer.render(sceneAtmosphere, camera);
 | 
						|
  }
 | 
						|
 | 
						|
  init();
 | 
						|
  this.animate = animate;
 | 
						|
 | 
						|
 | 
						|
  this.__defineGetter__('time', function() {
 | 
						|
    return this._time || 0;
 | 
						|
  });
 | 
						|
 | 
						|
  this.__defineSetter__('time', function(t) {
 | 
						|
    var validMorphs = [];
 | 
						|
    var morphDict = this.points.morphTargetDictionary;
 | 
						|
    for(var k in morphDict) {
 | 
						|
      if(k.indexOf('morphPadding') < 0) {
 | 
						|
        validMorphs.push(morphDict[k]);
 | 
						|
      }
 | 
						|
    }
 | 
						|
    validMorphs.sort();
 | 
						|
    var l = validMorphs.length-1;
 | 
						|
    var scaledt = t*l+1;
 | 
						|
    var index = Math.floor(scaledt);
 | 
						|
    for (i=0;i<validMorphs.length;i++) {
 | 
						|
      this.points.morphTargetInfluences[validMorphs[i]] = 0;
 | 
						|
    }
 | 
						|
    var lastIndex = index - 1;
 | 
						|
    var leftover = scaledt - index;
 | 
						|
    if (lastIndex >= 0) {
 | 
						|
      this.points.morphTargetInfluences[lastIndex] = 1 - leftover;
 | 
						|
    }
 | 
						|
    this.points.morphTargetInfluences[index] = leftover;
 | 
						|
    this._time = t;
 | 
						|
  });
 | 
						|
 | 
						|
  this.addData = addData;
 | 
						|
  this.createPoints = createPoints;
 | 
						|
  this.renderer = renderer;
 | 
						|
  this.scene = scene;
 | 
						|
 | 
						|
  return this;
 | 
						|
 | 
						|
};
 | 
						|
 |