跟着感觉学threejs-第二篇

327 阅读2分钟

上一篇我们学习了threejs的基本使用 本篇我们将用上一篇学习的基础知识做一个室内3D的demo

话不多说 直接上代码 首先还是3要素

scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000 );
renderer = new THREE.WebGLRenderer({ antialias: true });
// 加入辅助坐标
axesHelper = new THREE.AxesHelper( 10 );
// 加入光源
ambient = new THREE.AmbientLight(0xffffff);
// 加入控制器
controls = new OrbitControls(this.camera, this.renderer.domElement);

加入辅助坐标可以让我们更清晰的认识到模型在整个场景中的位置 则是为了通过相机能够看到场景中的物体,这里面使用的是环境光,环境光会均匀的照亮场景中的所有物体。 控制器可以让我们使用鼠标拖动视角

接下来我们思考一下如何实现3D的室内场景

  1. 我们需要一个几何体(一个球体或者立方体);
  2. 我们需要一张360全景图或者一个6面图片
  3. 将视角移动道几何题内部

这里我们从网上找一张360的全景图

F69568CB-422B-407E-ACAF-BD6C1C226883.png

既然是360的全景图 那么我们就选用球体 首先创建一个球体

// 这里我们创建一个半径为5的球体,另外两个参数代表水平分段数和垂直分段数,具体可参考文档
const geometry = new THREE.SphereGeometry( 5, 32, 16 )

然后我们加载图片, 这里需要用到loader,threejs提供了多种loader 来加载不同的资源,这里我们选用ImageBitmapLoader

const loader = new THREE.ImageBitmapLoader();
// 加载图片
loader.load('images/360rome.webp', (imageBitmap) => {
    // 将图片转换为网格材质
    const texture = new THREE.CanvasTexture( imageBitmap );
    const material = new THREE.MeshBasicMaterial( { map: texture } );
    // 将几何体和材质链接起来
    const sphere = new THREE.Mesh( geometry, material );
})

这样我们就创建好了一个3D的房屋场景, 但是此时我们看到的 是一个球体,并非一个3d的房间,这个时候我们需要把相机视角移动到球体内部

camera.position.set(0, 0, 1)

这时候视角就会被移动到球体内部,但是会发现一片黑什么也看不到,那是因为图片覆盖在球体外表面,我们需要将球体沿z轴缩放-1

geometry.scale(1, -1, 1);

这样就可以看到一个简单的3d室内场景了 全部代码如下:

import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';

class MyThree {
  scene = new THREE.Scene();
  camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000 );
  renderer = new THREE.WebGLRenderer({ antialias: true });
  axesHelper = new THREE.AxesHelper( 10 );
  // 光源
  ambient = new THREE.AmbientLight(0xffffff);

  controls = new OrbitControls(this.camera, this.renderer.domElement);

  source = {}

  render() {
    this.renderer.render(this.scene, this.camera)
  }

  initGl() {
    // 将rennder的dom元素(canvas)挂载到页面
    document.body.appendChild( this.renderer.domElement );
    this.controls.enableDamping = true
    this.controls.enableZoom = false
  
    // 这里设置camera的位置为
    this.camera.position.set(0, 0, 1)
    // 设置渲染器的尺寸
    // https://threejs.org/docs/index.html#manual/zh/introduction/Creating-a-scene
    this.renderer.setSize( window.innerWidth, window.innerHeight);
    this.scene.add(this.ambient)
    this.scene.add(this.axesHelper)
  }

  createBall() {
    const geometry = new THREE.SphereGeometry( 5, 32, 16 )
    geometry.scale(1, -1, 1);
    const loader = new THREE.ImageBitmapLoader();
    loader.load('images/360rome.webp', (imageBitmap) => {
      const texture = new THREE.CanvasTexture( imageBitmap );
      const material = new THREE.MeshBasicMaterial( { map: texture } );
      const sphere = new THREE.Mesh( geometry, material );
      this.scene.add(sphere)
      this.render()
    })
  }

  async start() {
    this.initGl()
    this.createBall()
    this.animate()
  }

  animate() {
    requestAnimationFrame( this.animate.bind(this) );
    this.controls.update();
    this.render();
  }

}

const myThree = new MyThree()

myThree.start()