threejs实现一个三维太阳系行星围绕太阳公转自转效果代码

代码语言:html

所属分类:三维

代码描述:threejs实现一个三维太阳系行星围绕太阳公转自转效果代码

代码标签: three 太阳系 行星 公转 自转

下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">

<script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/three.61.js"></script>
    <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/jquery.17.js"></script>
    <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/jquery.mousewheel.js"></script>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <style>
        body{background:url(//repo.bfw.wiki/bfwrepo/image/607e4ca28879b.png) no-repeat;background-size:cover}
    </style>
</head>

<body>
    <!-- partial:index.partial.html -->
    <div id="fiddleHook"></div>
    <!-- partial -->
    <script>
        (function(app) {
  "use strict";

  let metadata = {
    urls: {
      github: '',
      sun: {
        surfaceMaterial: '//repo.bfw.wiki/bfwrepo/images/universer/sunSurfaceMaterial.jpg',
        atmosphereMaterial: '//repo.bfw.wiki/bfwrepo/images/universer/sunAtmosphereMaterial.png'
      },
      mercury: {
        surfaceMaterial: '//repo.bfw.wiki/bfwrepo/images/universer/mercurySurfaceMaterial.jpg'
      },
      venus: {
        surfaceMaterial: '//repo.bfw.wiki/bfwrepo/image/5ec0779dc7b4d.png'
      },
      earth: {
        normalMaterial: '//repo.bfw.wiki/bfwrepo/images/universer/earthSurfaceNormal.jpg',
        surfaceMaterial: '//repo.bfw.wiki/bfwrepo/images/universer/earthSurface.jpg',
        specularMaterial: '//repo.bfw.wiki/bfwrepo/images/universer/earthSurfaceSpecular.jpg',
        cloudsMaterial: '//repo.bfw.wiki/bfwrepo/images/universer/earthAtmosphere.png'
      },
      moon: '//repo.bfw.wiki/bfwrepo/images/universer/moon.jpg',
      mars: {
        surfaceMaterial: '//repo.bfw.wiki/bfwrepo/images/universer/marsSurfaceMaterial.png'
      },
      jupiter: {
        surfaceMaterial: '//repo.bfw.wiki/bfwrepo/images/universer/jupiterSurfaceMaterial.jpg'
      },
      saturn: {
        surfaceMaterial: '//repo.bfw.wiki/bfwrepo/images/universer/saturnSurface.jpg',
        ringsMaterial: '//repo.bfw.wiki/bfwrepo/images/universer/saturnRings.png'
      },
      uranus: {
        surfaceMaterial: '//repo.bfw.wiki/bfwrepo/images/universer/uranusSurfaceMaterial.jpg'
      },
      neptune: {
        surfaceMaterial: '//repo.bfw.wiki/bfwrepo/images/universer/neptuneSurfaceMaterial.jpg'
      },
      pluto: {
        surfaceMaterial: '//repo.bfw.wiki/bfwrepo/images/universer/plutoSurfaceMaterial.jpg'
      },
    },
    consoleTag: 'H O U S E ~ f i d d l e s',
    constants: {
      SUN_SIZE_IN_EARTHS: 20,
      MOUSE_MOVE_TOLERANCE: 4,
      MAX_ROTATION_X: Math.PI / 2,
      MAX_CAMERA_Z: 10 * 50,
      MIN_CAMERA_Z: 10 * 3,
      EARTH_DISTANCE: 50,
      PLUTO_DISTANCE_IN_EARTHS: 77.2,
      EARTH_DISTANCE_SQUARED: 45000,
      EXAGGERATED_PLANET_SCALE: 5.55,
      MOON_DISTANCE_FROM_EARTH: 356400,
      MOON_PERIOD: 28,
      MOON_ROTATION_SPEED: 0.003,
      MOON_EXAGGERATE_FACTOR: 1.2,
      MOON_SIZE_IN_EARTHS: 1 / 3.7 * 1.2
    }
  };

  app.toolkit = app.toolkit || {};
  app.toolkit.three = app.toolkit.three || {};
  app.view = app.view || {};
  app.view.milkyway = app.view.milkyway || {};
  app.view.milkyway.saturn = app.view.milkyway.saturn || {};
  app.view.milkyway.earth = app.view.milkyway.earth || {};

  app.toolkit.three.Publisher = class {
    constructor() {
      this._messageTypes = {};
    }
    get messageTypes() {
      return this._messageTypes;
    }
    subscribe(message, subscriber, callback) {
      var subscribers = this.messageTypes[message];
      if (subscribers) {
        if (this.findSubscriber(subscribers, subscriber) != -1) {
          return;
        }
      } else {
        subscribers = [];
        this.messageTypes[message] = subscribers;
      }
      subscribers.push({
        subscriber: subscriber,
        callback: callback
      });
    }
    unsubscribe(message, subscriber, callback) {
      if (subscriber) {
        var subscribers = this.messageTypes[message];
        if (subscribers) {
          var i = this.findSubscriber(subscribers, subscriber, callback);
          if (i != -1) {
            this.messageTypes[message].splice(i, 1);
          }
        }
      } else {
        delete this.messageTypes[message];
      }
    }
    publish(message) {
      var subscribers = this.messageTypes[message];
      if (subscribers) {
        for (var i = 0; i < subscribers.length; i++) {
          var args = [];
          for (var j = 0; j < arguments.length - 1; j++) {
            args.push(arguments[j + 1]);
          }
          subscribers[i].callback.apply(subscribers[i].subscriber, args);
        }
      }
    }
    findSubscriber(subscribers, subscriber) {
      for (var i = 0; i < subscribers.length; i++) {
        if (subscribers[i] == subscriber) {
          return i;
        }
      }
      return -1;
    }
  }

  app.toolkit.three.R = class extends app.toolkit.three.Publisher {
    config() {
      return {
        keyUp: null,
        keyDown: null,
        keyPress: null,
        mouseMove: null,
        mouseDown: null,
        mouseUp: null,
        mouseScroll: null
      }
    }
    constructor(config) {
      super(config);
      this._objects = [];
      this._handleKeyUp = config && config.hasOwnProperty('keyUp') ? config.keyUp : this.config().keyUp;
      this._handleKeyDown = config && config.hasOwnProperty('keyDown') ? config.keyDown : this.config().keyDown;
      this._handleKeyPress = config && config.hasOwnProperty('keyPress') ? config.keyPress : this.config().keyPress;
      this._handleMouseMove = config && config.hasOwnProperty('mouseMove') ? config.mouseMove : this.config().mouseMove;
      this._handleMouseDown = config && config.hasOwnProperty('mouseDown') ? config.mouseDown : this.config().mouseDown;
      this._handleMouseUp = config && config.hasOwnProperty('mouseUp') ? config.mouseUp : this.config().mouseUp;
      this._handleMouseScroll = config && config.hasOwnProperty('mouseScroll') ? config.mouseScroll : this.config().mouseScroll;
      this._overObject = null;
      this._clickedObject = null;
    }
    get hook() {
      return this._hook;
    }
    get renderer() {
      return this._renderer;
    }
    get scene() {
      return this._scene;
    }
    get camera() {
      return this._camera;
    }
    get root() {
      return this._root;
    }
    get projector() {
      return this._projector;
    }
    get objects() {
      return this._objects;
    }
    get handleKeyUp() {
      return this._handleKeyUp;
    }
    get handleKeyDown() {
      return this._handleKeyDown;
    }
    get handleKeyPress() {
      return this._handleKeyPress;
    }
    get handleMouseMove() {
      return this._handleMouseMove;
    }
    get handleMouseDown() {
      return this._handleMouseDown;
    }
    get handleMouseUp() {
      return this._handleMouseUp;
    }
    get handleMouseScroll() {
      return this._handleMouseScroll;
    }
    get clickedObject() {
      return this._clickedObject;
    }
    set clickedObject(o) {
      this._clickedObject = o;
    }
    get overObject() {
      return this._overObject;
    }
    set overObject(o) {
      this._overObject = o;
    }
    onDocumentMouseMove(event) {
      event.preventDefault();
      if (this.clickedObject && this.clickedObject.handleMouseMove) {
        let hitpoint = null,
          hitnormal = null;
        let intersected = this.objectFromMouse(event.pageX, event.pageY);
        if (intersected.object == this.clickedObject) {
          hitpoint = intersected.point;
          hitnormal = intersected.normal;
        }
        this.clickedObject.handleMouseMove(event.pageX, event.pageY, hitpoint, hitnormal);
      } else {
        let handled = false;
        let oldObj = this.overObject;
        let intersected = this.objectFromMouse(event.pageX, event.pageY);
        this.overObject = intersected.object;
        if (this.overObject != oldObj) {
          if (oldObj) {
            this.hook.style.cursor = 'auto';
            if (oldObj.handleMouseOut) {
              oldObj.handleMouseOut(event.pageX, event.pageY);
            }
          }
          if (this.overObject) {
            if (this.overObject.overCursor) {
              this.hook.style.cursor = this.overObject.overCursor;
            }
            if (this.overObject.handleMouseOver) {
              this.overObject.handleMouseOver(event.pageX, event.pageY);
            }
          }
          handled = true;
        }
        if (!handled && this.handleMouseMove) {
          this.handleMouseMove(event.pageX, event.pageY);
        }
      }
    }
    onDocumentMouseDown(event) {
      event.preventDefault();
      let handled = false;
      let intersected = this.objectFromMouse(event.pageX, event.pageY);
      if (intersected.object) {
        if (intersected.object.handleMouseDown) {
          intersected.object.handleMouseDown(event.pageX, event.pageY, intersected.point, intersected.normal);
          this.clickedObject = intersected.object;
          handled = true;
        }
      }
      if (!handled && this.handleMouseDown) {
        this.handleMouseDown(event.pageX, event.pageY);
      }
    }
    onDocumentMouseUp(event) {
      event.preventDefault();
      let handled = false;
      let intersected = this.objectFromMouse(event.pageX, event.pageY);
      if (intersected.object) {
        if (intersected.object.handleMouseUp) {
          intersected.object.handleMouseUp(event.pageX, event.pageY, intersected.point, intersected.normal);
          handled = true;
        }
      }
      if (!handled && this.handleMouseUp) {
        this.handleMouseUp(event.pageX, event.pageY);
      }
      this.clickedObject = null;
    }
    onDocumentMouseScroll(event, delta) {
      event.preventDefault();
      if (this.handleMouseScroll) {
        this.handleMouseScroll(delta);
      }
    }
    onKeyUp(event) {
      event.preventDefault();
      if (this.handleKeyUp) {
        this.handleKeyUp(event.keyCode, event.charCode);
      }
    }
    onKeyDown(event) {
      event.preventDefault();
      if (this.handleKeyUp) {
        this.handleKeyUp(event.keyCode, event.charCode);
      }
    }
    onKeyPress(event) {
      event.preventDefault();
      if (this.handleKeyPress) {
        this.handleKeyPress(event.keyCode, event.charCode);
      }
    }
    onWindowResize(event) {
      this.renderer.setSize(this.hook.offsetWidth, this.hook.offsetHeight);
      this.camera.aspect = this.hook.offsetWidth / this.hook.offsetHeight;
      this.camera.updateProjectionMatrix();
    }
    objectFromMouse(pagex, pagey) {
      let offset = $(this.renderer.domElement).offset();
      let eltx = pagex - offset.left;
      let elty = pagey - offset.top;
      let vpx = (eltx / this.hook.offsetWidth) * 2 - 1;
      let vpy = -(elty / this.hook.offsetHeight) * 2 + 1;
      let vector = new THREE.Vector3(vpx, vpy, 0.5);
      this.projector.unprojectVector(vector, this.camera);
      let ray = new THREE.Ray(this.camera.position, vector.subSelf(this.camera.position).normalize());
      let intersects = ray.intersectScene(this.scene);
      if (intersects.length > 0) {
        let i = 0;
        while (!intersects[i].object.visible) {
          i++;
        }
        let intersected = intersects[i];
        let mat = new THREE.Matrix4().getInverse(intersected.object.matrixWorld);
        let point = mat.multiplyVector3(intersected.point);
        return (this.findObjectFromIntersected(intersected.object, intersected.point, intersected.face.normal));
      } else {
        return {
          object: null,
          point: null,
          normal: null
        };
      }
    }
    findObjectFromIntersected(object, point, normal) {
      if (object.data) {
        return {
          object: object.data,
          point: point,
          normal: normal
        };
      } else if (object.parent) {
        return this.findObjectFromIntersected(object.parent, point, normal);
      } else {
        return {
          object: null,
          point: null,
          normal: null
        };
      }
    }
    addObject(obj) {
      if (obj) {
        this._objects.push(obj);
        if (obj.object3D) {
          this._root.add(obj.object3D);
        }
      }
    }
    removeObject(obj) {
      var index = this.objects.indexOf(obj);
      if (index != -1) {
        this.objects.splice(index, 1);
        if (obj.object3D) {
          this.root.remove(obj.object3D);
        }
      }
    }
    initMouseListeners() {
      let dom = this.renderer.domElement,
        that = this;
      dom.addEventListener('mousemove',
        function(e) {
          that.onDocumentMouseMove(e);
        }, false);
      dom.addEventListener('mousedown',
        function(e) {
          that.onDocumentMouseDown(e);
        }, false);
      dom.addEventListener('mouseup',
        function(e) {
          that.onDocumentMouseUp(e);
        }, false);
      $(dom).mousewheel(
        function(e, delta) {
          that.onDocumentMouseScroll(e, delta);
        }
      );
    }
    initKeyboardListeners() {
      let dom = this.renderer.domElement;
      let that = this;
      dom.addEventListener('keydown',
        function(e) {
          that.onKeyDown(e);
        }, false);
      dom.addEventListener('keyup',
        function(e) {
          that.onKeyUp(e);
        }, false);
      dom.addEventListener('keypress',
        function(e) {
          that.onKeyPress(e);
        }, false);
      dom.setAttribute("tabindex", 1);
      dom.style.outline = 'none';
    }
    initWindowListeners() {
      let that = this;
      window.addEventListener('resize', function(event) {
        that.onWindowResize(event);
      }, false);
    }
    init(config) {
      let myConfig = config || {},
        container = myConfig.container,
        canvas = myConfig.canvas,
        renderer,
        scene,
        camera,
        root,
        projector;
      renderer = new THREE.WebGLRenderer({
        antialias: true,
        canvas: canvas
      });
      renderer.setSize(container.offsetWidth, container.offsetHeight);
      container.appendChild(renderer.domElement);
      scene = new THREE.Scene();
      scene.add(new THREE.AmbientLight(0x505050));
      scene.data = this;
      camera = new THREE.PerspectiveCamera(45, container.offsetWidth / container.offsetHeight, 1, 10000);
      camera.position.set(0, 0, 100);
      scene.add(camera);
      root = new THREE.Object3D();
      scene.add(root);
      projector = new THREE.Projector();
      this._hook = container;
      this._renderer = renderer;
      this._scene = scene;
      this._camera = camera;
      this._projector = projector;
      this._root = root;
      this.initMouseListeners();
      this.initKeyboardListeners();
      this.initWindowListeners();
    }
    run() {
      this.update();
      this.renderer.render(this.scene, this.camera);
      var that = this;
      requestAnimationFrame(function() {
        that.run();
      });
    }
    update() {
      var i, len;
      len = this.objects.length;
      for (i = 0; i < len; i++) {
        this.objects[i].update();
      }
    }
  }

  app.toolkit.three.Object = class extends app.toolkit.three.Publisher {
    constructor() {
      super();
      this._object3D = null;
      this._children = [];
    }
    get object3D() {
      return this._object3D;
    }
    set object3D(o) {
      //this._object3D.data = this;
      this._object3D = o;
    }
    get scene() {
      var scene = null;
      if (this.object3D) {
        var obj = this.object3D;
        while (obj.parent) {
          obj = obj.parent;
        }
        scene = obj;
      }
      return scene;
    }
    get app() {
      var scene = this.scene;
      return scene ? scene.data : null;
    }
    get children() {
      return this._children;
    }
    removeChild(child) {
      var index = this.children.indexOf(child);
      if (index != -1) {
        this.children.splice(index, 1);
        if (child.object3D) {
          this.object3D.remove(child.object3D);
        }
      }
    }
    addChild(child) {
      this.children.push(child);
      if (child.object3D) {
        this.object3D.add(child.object3D);
      }
    }
    updateChildren() {
      var i, len;
      len = this.children.length;
      for (i = 0; i < len; i++) {
        this.children[i].update();
      }
    }
    setPosition(x, y, z) {
      if (this.object3D) {
        this.object3D.position.set(x, y, z);
      }
    }
    setScale(x, y, z) {
      if (this.object3D) {
        this.object3D.scale.set(x, y, z);
      }
    }
    setVisible(visible) {
      function setVisible(obj, visible) {
        obj.visible = visible;
        var i, len = obj.children.length;
        for (i = 0; i < len; i++) {
          setVisible(obj.children[i], visible);
        }
      }
      if (this.object3D) {
        setVisible(this.object3D, visible);
      }
    }
    update() {
      this.updateChildren();
    }
    init() {}
  }

  app.view.milkyway.Stars = class extends app.toolkit.three.Object {
    config() {
      return {
        autoInit: false,
        verticeCount: 667,
        materialCount: 8,
        systemCount: 24,
        distance: 1000
      }
    }
    constructor(config) {
      super();
      this._autoInit = config && config.hasOwnProperty('autoInit') ? config.autoInit : this.config().autoInit;
      this._verticeCount = config && config.hasOwnProperty('verticeCount') ? config.verticeCount : this.config().verticeCount;
      this._materialCount = config && config.hasOwnProperty('materialCount') ? config.materialCount : this.config().materialCount;
      this._systemCount = config && config.hasOwnProperty('systemCount') ? config.systemCount : this.config().systemCount;
      this._distance = config && config.hasOwnProperty('distance') ? config.distance : this.config().distance;
      if (this.autoInit) {
        this.init();
      }
    }
    get autoInit() {
      return this._autoInit;
    }
    get verticeCount() {
      return this._verticeCount;
    }
    get materialCount() {
      return this._materialCount;
    }
    get systemCount() {
      return this._systemCount;
    }
    get distance() {
      return this._distance;
    }
    init() {
      let starsGroup = new THREE.Object3D(),
        starsGeometry = new THREE.Geometry(),
        starsMaterials = [];
      for (let i = 0; i < this.verticeCount; i++) {
        let vector = new THREE.Vector3((Math.random() * 2 - 1) * this.distance, (Math.random() * 2 - 1) * this.distance, (Math.random() * 2 - 1) * this.distance);
        if (vector.length() < this.distance) {
          vector = vector.setLength(this.distance);
        }
        starsGeometry.vertices.push(new THREE.Vertex(vector));
      }
      for (let i = 0; i < this.materialCount; i++) {
        starsMaterials.push(
          new THREE.ParticleBasicMaterial({
            color: 0x101010 * (i + 1),
            size: i % 2 + 1,
            sizeAttenuation: false
          })
        );
      }
      for (let i = 0; i < this.systemCount; i++) {
        let stars = new THREE.ParticleSystem(starsGeometry, starsMaterials[i % this.materialCount]);
        stars.rotation.y = i / (Math.PI * 2);
        starsGroup.add(stars);
      }
      this.object3D = starsGroup;
    }
  };

  app.view.milkyway.Sun = class extends app.toolkit.three.Object {
    config() {
      return {
        autoInit: false,
        size: metadata.constants.SUN_SIZE_IN_EARTHS,
        fragmentShader: 'uniform float time;\n' +
          'uniform sampler2D texture1;\n' +
          'uniform sampler2D texture2;\n' +
          'varying vec2 texCoord;\n' +
          'void main( void ) {\n' +
          '   vec4 noise = texture2D( texture1, texCoord );\n' +
          '   vec2 T1 = texCoord + vec2( 1.5, -1.5 ) * time  * 0.01;\n' +
          '   vec2 T2 = texCoord + vec2( -0.5, 2.0 ) * time *  0.01;\n' +
          '   T1.x -= noise.r * 2.0;\n' +
          '   T1.y += noise.g * 4.0;\n' +
          '   T2.x += noise.g * 0.2;\n' +
          '   T2.y += noise.b * 0.2;\n' +
          '   float p = texture2D( texture1, T1 * 2.0 ).a + 0.25;\n' +
          '   vec4 color = texture2D( texture2, T2 );\n' +
          '   vec4 temp = color * 2.0 * ( vec4( p, p, p, p ) ) + ( color * color );\n' +
          '   gl_FragColor = temp;\n' +
          '}',
        vertexShader: 'varying vec2 texCoord;\n' +
          'void main() {\n' +
          '	texCoord = uv;\n' +
          '	vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\n' +
          '	gl_Position = projectionMatrix * mvPosition;\n' +
          '}',
        clock: new THREE.Clock()
      }
    }
    constructor(config) {
      super();
      this._autoInit = config && config.hasOwnProperty('autoInit') ? config.autoInit : this.config().autoInit;
      this._fragmentShader = config && config.hasOwnProperty('fragmentShader') ? config.fragmentShader : this.config().fragmentShader;
      this._vertexShader = config && config.hasOwnProperty('vertexShader') ? config.vertexShader : this.config().vertexShader;
      this._clock = config && config.hasOwnProperty('clock') ? config.clock : this.config().clock;
      this._size = config && config.hasOwnProperty('size') ? config.size : this.config().size;
      if (this.autoInit) {
        this.init();
      }
    }
    get clock() {
      return this._clock;
    }
    get fragment.........完整代码请登录后点击上方下载按钮下载查看

网友评论0