vue-three 3d机房

<template>
  <div>
    <div id="three"></div>
  </div>
</template>

<script>
import * as THREE from "three";
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
import { CSS2DRenderer, CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer.js';
export default {
  data() {
    return {
      scene: {}, // 场景
      camera: {}, // 摄像机
      renderer: {}, // 渲染器

      labelRenderer: {}, // 
      clock: {},
    };
  },
  mounted(){
    this.threes();
    this.resize(); // 自适应
  },
  methods: {
    // 浏览器窗口发生变化时 自适应
    resize(){
      window.addEventListener('resize', () => {

        // 初始化摄像机
        this.camera.aspect = window.innerWidth/window.innerHeight;

        // 摄像机矩阵效果
        this.camera.updateProjectionMatrix();

        // 初始化渲染器
        this.renderer.setSize(window.innerWidth, window.innerHeight);
        
        // 文字位置
        this.labelRenderer.setSize( window.innerWidth, window.innerHeight );

      })
    },

    threes() {
      // 创建场景
      this.scene = new THREE.Scene();

      // 创建摄像机 // 参数含义: 视角、窗口投影长宽比、摄像机从哪里开始渲染、距离摄像机多远截至渲染
      this.camera = new THREE.PerspectiveCamera(100, window.innerWidth/window.innerHeight, 0.1, 10000);

      // 创建three渲染器 参数: 去锯齿
      this.renderer = new THREE.WebGLRenderer({ antialias: true });

      // 开启阴影,加上阴影渲染
      this.renderer.shadowMapEnabled = true;

      // 设置渲染器场景大小 参数: 宽,高
      this.renderer.setSize(window.innerWidth, window.innerHeight);
      
      // 把渲染器添加到页面中
      document.getElementById('three').appendChild(this.renderer.domElement);

      this.ground() // 地面模型

      this.wall({x: 5060, y: 1500, z: 20}, {x: 0, y: 750, z: -1400})
      this.wall({x: 5060, y: 1500, z: 20}, {x: 0, y: 750, z: 1400})
      this.wall({x: 20, y: 1500, z: 2880}, {x: 2490, y: 750, z: 0})
      this.wall({x: 20, y: 1500, z: 2880}, {x: -2490, y: 750, z: 0})
      this.wall({x: 5060, y: 30, z: 2880}, {x: 0, y: 1500, z: 0})

      // 机柜
      for(let i = 0; i < 5; i ++){
        this.chartlet((2100 - i * 740), 600, 300)
      }
      this.chartlet(800, 600, -1100)

      // 灭火器
      this.extinguisher(-2300, 150, 1200)

      // 配电柜
      this.power(1400, 240, -1170)

      // 烟感
      this.smokeSensor(200, 1470, 200)
      this.smokeSensor(1400, 1470, 200)
      this.smokeSensor(-1400, 1470, -700)
      
      // 温湿度
      this.humitureSensor(200, 1470, -700)
      this.humitureSensor(1400, 1470, -700)

      // 监控
      this.monitorSentor(2400, 1470, 900)
      this.monitorSentor(2400, 1470, -900)

      // 门
      this.door(-1500, 450, 1395)

      // 精密空调
      this.stulz(2300, 500, -1050)
      this.stulz(-2100, 500, -1180, 0, 200, 128, 90)

      // 创建光源
      this.createLight()

      // 辅助坐标系  参数表示坐标系大小,可以根据场景大小去设置
      // this.axesHelper = new THREE.AxesHelper(3000);
      // this.scene.add(this.axesHelper);

      // 摄像机空间轴位置
      this.camera.position.x = 0
      this.camera.position.y = 3000
      this.camera.position.z = 3000

      // 创建鼠标控件对象
      this.controls = new OrbitControls( this.camera, this.labelRenderer.domElement );
      this.clock = new THREE.Clock();

      this.animate()
    },

    // 添加帧渲染
    animate(){
      requestAnimationFrame(this.animate);

      // 初始化controls
      this.controls.update()
      this.labelRenderer.render( this.scene, this.camera );
      this.render()
    },

    // 渲染器渲染场景和摄像机
    render(){
      this.renderer.render(this.scene, this.camera)
    },

    // 创建光源
    createLight () {
      // 环境光
      const ambint = new THREE.AmbientLight(0xffffff)
      this.scene.add(ambint)

      this.pointLight(0xffffff, -3000, 3000, -1000, 10000)
    },

    // 点光灯光源
    pointLight (color, x, y, z, dis) {
      const pointLight = new THREE.PointLight(color)
      pointLight.position.set(x, y, z); // 光源位置
      pointLight.castShadow = true; //开启灯光投射阴影
      pointLight.intensity = 2; // 强度
      pointLight.penumbra = 1; // 半影
      pointLight.distance = dis; // 距离

      this.scene.add(pointLight)

      // 光源寄托
      // this.createLightView(color, x, y, z)
    },
    
    // 聚光灯光源
    spotLight (color, x, y, z, dis) {
      const spotLight = new THREE.SpotLight(color)
      spotLight.position.set(x, y, z); // 光源位置
      spotLight.castShadow = true; //开启灯光投射阴影
      spotLight.intensity = 3 // 强度
      spotLight.angle = 0.3; // 角度
      spotLight.penumbra = 1; // 半影
      spotLight.decay = 1; // 衰退
      spotLight.distance = dis; // 距离

      this.scene.add(spotLight)

      // 辅助线
      let spotLightHelper = new THREE.SpotLightHelper(spotLight, 0x976fb6);
      this.scene.add(spotLightHelper)

      // 光源寄托
      // this.createLightView(color, x, y, z)
    },

    // 光源寄托
    createLightView(color, x, y, z){
      let geometry = new THREE.SphereGeometry(30, 30, 30);
      let material = new THREE.MeshPhongMaterial({ color });
      let cube = new THREE.Mesh(geometry, material);
      cube.position.set(x, y, z)
      this.scene.add(cube)
    },
    
    // 平面模型
    ground(){
      let geometry = new THREE.BoxGeometry(5000, 2800, 0);
      let material = new THREE.MeshLambertMaterial({ color: 0x659cae });
      let cube = new THREE.Mesh(geometry, material);
      cube.rotation.x = -0.5 * Math.PI
      cube.position.set(0, 0, 0)
      cube.receiveShadow = true
      this.scene.add(cube)
    },

    // 墙壁
    wall(size, position, opacity = 0.1){
      let data = {
        color: 0x07313F,
        transparent: true,
        opacity
      }
      let geometry = new THREE.BoxGeometry(size.x, size.y,size.z);
      let material = new THREE.MeshLambertMaterial(data);
      let cube = new THREE.Mesh(geometry, material);
      cube.position.set(position.x, position.y, position.z)
      this.scene.add(cube);
    },
    
    // 机柜
    chartlet(x, y, z){
      let map = new THREE.TextureLoader().load(require('@/assets/three/zhengm.png'));
      let map2 = new THREE.TextureLoader().load(require('@/assets/three/cem.png'));
      let map3 = new THREE.TextureLoader().load(require('@/assets/three/fanm.png'));
      let group = new THREE.Mesh();
      let color = 0x0c0c0c // 0x3C3B42
      let mats = [];
      let matsItems = [
        { map: map2 },
        { map: map2 },
        { color },
        { color },
        { map },
        { map: map3 },
      ]
      matsItems.forEach(item => {
        mats.push(new THREE.MeshPhongMaterial(item))
      })

      let cubeGeom = new THREE.BoxBufferGeometry(700, 1200, 360);
      let cube = new THREE.Mesh(cubeGeom, mats);
      cube.position.set(x, y, z)

      group.add(cube);
      this.scene.add(group)
      let objectContent = [
        {
          name: '名称:',
          content: '机柜'
        },
        {
          name: '状态:',
          content: '正常'
        }
      ]
      this.fontText(cube, objectContent)
    },

    // 配电柜
    power(x = 0, y = 0, z = 0, big = 1){

      // 配电柜平面
      let powerItem = [
        [{x: 440, y: 780, z: 10},{x: 50, y: 150, z: -100}, null], // 后
        [{x: 440, y: 780, z: 10},{x: 50, y: 150, z: 30}, 0x888888], // 前
        [{x: 60, y: 780, z: 10},{x: -150, y: 150, z: 100}, null], // 前左
        [{x: 60, y: 780, z: 10},{x: 250, y: 150, z: 100}, null], // 前右
        [{x: 440, y: 60, z: 10},{x: 50, y: 515, z: 100}, null], // 前上
        [{x: 440, y: 60, z: 10},{x: 50, y: -210, z: 100}, null], // 前下
        [{x: 10, y: 780, z: 210},{x: -170, y: 150, z: 0}, null], // 左
        [{x: 10, y: 780, z: 200},{x: 270, y: 150, z: 0}, null], // 右
        [{x: 450, y: 10, z: 200},{x: 50, y: 540, z: 0}, null], // 上
        [{x: 450, y: 10, z: 200},{x: 50, y: -245, z: 0}, null], // 下
      ]
      for(let i = 0; i < powerItem.length; i ++){
        powerItem[i][1].x += x;
        powerItem[i][1].y += y;
        powerItem[i][1].z += z;
        this.powerItem(powerItem[i][0],powerItem[i][1],powerItem[i][2],powerItem[i][3]);
      }

      // 配电柜指示灯
      this.powerLamp({x: -30 + x, y: 280 + y, z: 35 + z}, 0xe73939)
      this.pointLight(0xe73939, -30 + x, 280 + y, 50 + z, 300)

      this.powerLamp({x: 50 + x, y: 280 + y, z: 35 + z}, 0x15c02d)
      this.pointLight(0x15c02d, 50 + x, 280 + y, 50 + z, 300)

      this.powerLamp({x: 130 + x, y: 280 + y, z: 35 + z}, 0xd1d81e)
      this.pointLight(0xd1d81e, 130 + x, 280 + y, 50 + z, 300)

      // 闪电标识
      let map = new THREE.TextureLoader().load(require('@/assets/three/shand.png'));
      let geometry = new THREE.BoxGeometry(340, 480, 5);
      let material = new THREE.MeshLambertMaterial({map, transparent: true});
      let cube = new THREE.Mesh(geometry, material);
      cube.position.set(50 + x, 50 + y, 100 + z)
      this.scene.add(cube);
      let objectContent = [
        {
          name: '名称:',
          content: '配电柜'
        },
        {
          name: '状态:',
          content: '正常',
        },
        {
          name: 'ABC相电压:',
          content: '35KV / 15KV / 20KV',
          class: 'success'
        },
        {
          name: 'ABC相电流:',
          content: '1100A / 1000A / 1200A',
          class: 'warning'
        }
      ]
      this.fontText(cube, objectContent)

      // 锁子
      let map2 = new THREE.TextureLoader().load(require('@/assets/three/suoz.png'));
      let geometry2 = new THREE.BoxGeometry(40, 120, 5);
      let material2 = new THREE.MeshLambertMaterial({map: map2, transparent: true});
      let cube2 = new THREE.Mesh(geometry2, material2);
      cube2.position.set(-150 + x, 120 + y, 110 + z)
      this.scene.add(cube2);
    },

    // 配电柜平面
    powerItem(size, position, color){
      let data = {
        color: color ? color : 0xc5c5c3
      }
      let geometry = new THREE.BoxGeometry(size.x, size.y, size.z);
      let material = new THREE.MeshLambertMaterial(data);
      let cube = new THREE.Mesh(geometry, material);
      cube.position.set(position.x, position.y, position.z)
      this.scene.add(cube);

    },

    // 配电柜指示灯
    powerLamp(size, color){
      let sphere = new THREE.SphereGeometry(20, 20, 20);
      let material = new THREE.MeshLambertMaterial({color});
      let cube = new THREE.Mesh(sphere, material);
      cube.position.set(size.x, size.y, size.z)
      this.scene.add(cube);
    },

    // 灭火器
    extinguisher(x, y, z){
      // 圆柱 1
      let cylinder = new THREE.CylinderGeometry( 20, 20, 30, 10 );
      let material0 = new THREE.MeshLambertMaterial({color: 0x333333});
      let cube = new THREE.Mesh(cylinder, material0);
      cube.position.set(x, 340, z)

      // 球体 2
      let sphere = new THREE.SphereGeometry(60, 60, 60);
      let material1 = new THREE.MeshLambertMaterial({color: 0xdb2c1f});
      let cube2 = new THREE.Mesh(sphere, material1);
      cube2.position.set(x, 280, z)

      // 圆柱 3
      let cylinder2 = new THREE.CylinderGeometry( 60, 60, 280, 100 );
      let texture = new THREE.TextureLoader().load(require('@/assets/three/mhq.png'));
      let material2 = new THREE.MeshLambertMaterial({map: texture});
      let cube3 = new THREE.Mesh(cylinder2, material2);
      cube3.position.set(x, y, z)
      cube3.rotation.y -= 1.6

      this.scene.add(cube);
      this.scene.add(cube2);
      this.scene.add(cube3);

      let objectContent = [
        {
          name: '名称:',
          content: '灭火器'
        }
      ]
      this.fontText(cube2, objectContent)
    },

    // 烟感
    smokeSensor(x, y, z){
      // 柱状1
      let cylinder = new THREE.CylinderGeometry( 55, 55, 4, 20 );
      let material = new THREE.MeshLambertMaterial({color: 0xd8d8c0, transparent: true, opacity: 0.8});
      let cube = new THREE.Mesh(cylinder, material);
      cube.position.set(x, y + 12, z)
      this.scene.add(cube);

      // 柱状2
      let cylinder2 = new THREE.CylinderGeometry( 50, 50, 22, 20 );
      let material2 = new THREE.MeshLambertMaterial({color: 0xd8d8c0});
      let cube2 = new THREE.Mesh(cylinder2, material2);
      cube2.position.set(x, y, z)
      this.scene.add(cube2);

      // 柱状3
      let texture = new THREE.TextureLoader().load(require('@/assets/three/yang.png'));
      let cylinder3 = new THREE.CylinderGeometry( 45, 35, 20, 15 );
      let material3 = new THREE.MeshLambertMaterial({map: texture});
      let cube3 = new THREE.Mesh(cylinder3, material3);
      cube3.position.set(x, y-15, z)
      this.scene.add(cube3);

      let objectContent = [
        {
          name: '名称:',
          content: '烟感'
        },
        {
          name: '状态:',
          content: '正常',
          class: 'success'
        }
      ]
      this.fontText(cube3, objectContent)

    },

    // 温湿度
    humitureSensor(x, y, z){

      // 立方体1
      let data = {
        color: 0xdcdcd9,
        transparent: true,
        opacity: 0.8
      }
      let geometry0 = new THREE.BoxGeometry(90, 4, 90);
      let material0 = new THREE.MeshLambertMaterial(data);
      let cube0 = new THREE.Mesh(geometry0, material0);
      cube0.position.set(x, y + 14, z)
      this.scene.add(cube0);

      // 立方体2
      let map = new THREE.TextureLoader().load(require('@/assets/three/wens.png'));
      let group = new THREE.Mesh();
      let color = 0xdcdcd9
      let mats = [];
      let matsItems = [
        { color },
        { color },
        { color },
        { map },
        { color },
        { color },
      ]
      matsItems.forEach(item => {
        mats.push(new THREE.MeshPhongMaterial(item))
      })

      let cubeGeom = new THREE.BoxBufferGeometry(80, 25, 80);
      let cube = new THREE.Mesh(cubeGeom, mats);
      cube.position.set(x, y, z)

      group.add(cube);
      this.scene.add(group)

      let objectContent = [
        {
          name: '名称:',
          content: '温湿度传感器'
        },
        {
          name: '温度:',
          content: '24℃',
          class: 'warning'
        },
        {
          name: '湿度:',
          content: '23%',
          class: 'primary'
        }
      ]
      this.fontText(cube, objectContent)
    },

    // 监控
    monitorSentor(x, y, z){
      // 柱状
      let cylinder = new THREE.CylinderGeometry( 30, 30, 10, 20 );
      let material = new THREE.MeshLambertMaterial({color: 0xd8d8c0, opacity: 0.6});
      let cube = new THREE.Mesh(cylinder, material);
      cube.position.set(x, y, z)
      this.scene.add(cube);
      // 柱状2-1
      let cylinder2 = new THREE.CylinderGeometry( 3, 3, 40, 20 );
      let material2 = new THREE.MeshLambertMaterial({color: 0xd8d8c0});
      let cube2 = new THREE.Mesh(cylinder2, material2);
      cube2.position.set(x, y - 20, z)
      cube2.rotation.z -= 0.3
      this.scene.add(cube2);
      // 柱状2-2
      let cylinder5 = new THREE.CylinderGeometry( 3, 3, 50, 20 );
      let material5 = new THREE.MeshLambertMaterial({color: 0xd8d8c0});
      let cube5 = new THREE.Mesh(cylinder5, material5);
      cube5.position.set(x - 30, y - 45, z)
      cube5.rotation.z += 5
      this.scene.add(cube5);

      // 柱状3
      let cylinder3 = new THREE.CylinderGeometry( 35, 35, 70, 20 );
      let material3 = new THREE.MeshLambertMaterial({color: 0xd8d8c0});
      let cube3 = new THREE.Mesh(cylinder3, material3);
      cube3.position.set(x - 70, y - 60, z)
      cube3.rotation.z += 5
      this.scene.add(cube3);

      // 球体
      let sphere = new THREE.SphereGeometry(25, 25, 25);
      let material4 = new THREE.MeshPhongMaterial({color: 0x333333});
      let cube4 = new THREE.Mesh(sphere, material4);
      cube4.position.set(x - 90, y - 65, z)
      this.scene.add(cube4);

      let objectContent = [
        {
          name: '名称:',
          content: '监控'
        },
        {
          name: '状态:',
          content: '正常',
          class: 'success'
        }
      ]
      this.fontText(cube4, objectContent)
    },

    // 门
    door(x, y, z){
      let data = {
        color: 0x07313F,
        transparent: true,
        opacity: 0.3
      }
      let geometry = new THREE.BoxGeometry(550, 900, 40);
      let material = new THREE.MeshLambertMaterial(data);
      let cube = new THREE.Mesh(geometry, material);
      cube.position.set(x, y, z)
      this.scene.add(cube);
    },
    
    // 精密空调 rotation-旋转度数
    stulz(x, y, z, x1 = 128, y1 = 200, z1 = 0, rotation = 0){
      let geometry = new THREE.BoxGeometry(250, 1000, 600);
      let material = new THREE.MeshPhongMaterial({color: 0x3e3e3e});
      let cube = new THREE.Mesh(geometry, material);
      cube.position.set(x, y, z)

      rotation = Math.PI/(180/rotation)

      cube.rotation.y -= rotation
      this.scene.add(cube);
      this.stulzDevice(x, y, z, x1, y1, z1, rotation)

      let objectContent = [
        {
          name: '名称:',
          content: '精密空调',
          class: 'primary'
        },
        {
          name: '开关状态:',
          content: '已开',
          class: 'success'
        },
        {
          name: '温度:',
          content: '24℃',
          class: 'success'
        },
        {
          name: '湿度:',
          content: '46%',
          class: 'warning'
        },
        {
          name: '报警信息:',
          content: '暂无报警信息',
          class: 'danger'
        }
      ]
      this.fontText(cube, objectContent)
    },

    // 精密空调 显示器
    stulzDevice(x, y, z, x1, y1, z1, rotation){
      let map = new THREE.TextureLoader().load(require('@/assets/three/jingm.jpg'));
      let geometry = new THREE.BoxGeometry(5, 200, 460);
      let material = new THREE.MeshPhongMaterial({map, transparent: true});
      let cube = new THREE.Mesh(geometry, material);
      
      cube.position.set(x - x1, y + y1, z + z1) 
      
      cube.rotation.y -= rotation
      this.scene.add(cube);
    },

    // 文字
    fontText(moon, contObj = []){

      // 创建文字容器
      const moonDiv = document.createElement( 'div' );
      moonDiv.className = 'label';
      moonDiv.style.marginTop = '3em';
      moonDiv.style.color = '#dddddd';
      moonDiv.style.fontSize = '12px';
      moonDiv.style.padding = '5px';
      moonDiv.style.backgroundColor = 'rgba(0,0,0,0.7)';

      if(contObj.length){
        contObj.forEach(item => {
          let moonTitle = document.createElement( 'span' )
          let moonContent = document.createElement( 'span' )
          let moonBr = document.createElement( 'br' )
          if(item.class) moonContent.className = item.class;
          moonTitle.textContent = item.name
          moonContent.textContent = item.content
          moonDiv.appendChild(moonTitle)
          moonDiv.appendChild(moonContent)
          moonDiv.appendChild(moonBr)
        })
      }

      const moonLabel = new CSS2DObject( moonDiv );
      moonLabel.position.set(0, 0.275, 0);
      moon.add( moonLabel );
   
      // 每次添加div前 先把原有的删除
      let chArr = document.body.getElementsByClassName("labelRenderer")
      for(let i = 0;i < chArr.length; i++) if (chArr[i] != null) chArr[i].parentNode.removeChild(chArr[i]);

      // 创建2d渲染
      this.labelRenderer = new CSS2DRenderer();
      this.labelRenderer.setSize( window.innerWidth, window.innerHeight );
      this.labelRenderer.domElement.style.position = 'absolute';
      this.labelRenderer.domElement.style.top = '0px';
      this.labelRenderer.domElement.className = 'labelRenderer'
      document.body.appendChild( this.labelRenderer.domElement );
    },
  },
  beforeDestroy(){
    // 页面卸载时 删除创建的div
    let chArr = document.body.getElementsByClassName("labelRenderer")
    for(let i = 0;i < chArr.length; i++) if (chArr[i] != null) chArr[i].parentNode.removeChild(chArr[i]);
  }
};
</script>

<style scoped>
body {
  margin: 0;
  padding: 0;
  background-color: #000;
  color: #fff;
  font-family: Monospace;
  font-size: 13px;
  line-height: 24px;
  overscroll-behavior: none;
}
#info {
  position: absolute;
  top: 0px;
  width: 100%;
  padding: 0;
  box-sizing: border-box;
  text-align: center;
  -moz-user-select: none;
  -webkit-user-select: none;
  -ms-user-select: none;
  user-select: none;
  pointer-events: none;
  z-index: 1; /* TODO Solve this in HTML */
}

</style>
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,607评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,047评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,496评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,405评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,400评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,479评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,883评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,535评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,743评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,544评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,612评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,309评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,881评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,891评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,136评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,783评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,316评论 2 342

推荐阅读更多精彩内容

  • 1、WebGL与threeJS WebGL是一种3D绘图协议,其允许JavaScript和OpenGL ES2.0...
    患者_阅读 19,891评论 1 22
  • 上次说到需要准备的有了, 这是一种开发的思路,就是如果做东西的技术已经储备的没问题了,那就先想好要做什么,然后再准...
    刚道阅读 669评论 0 0
  • 之前在公司做项目的时候接到过一个需求, 因公司业务是做IT监控,所以客户要一个机房的3D展示,展示环境啊设备什么的...
    刚道阅读 1,441评论 2 0
  • 机房的抽象准备好了,下面该做呗做了, 但是呢,突然有个想法, 就是,IT项目很多,每个机房都不一样,不可能每个都写...
    刚道阅读 994评论 2 0
  • 由于对WebGL的兴趣,初步接触Three.js,决定将学习过程进行记录,以便于后期复习。 初步以实现3D机房为目...
    Mr_ZhaiDK阅读 2,726评论 0 2