上一篇我们学习了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的室内场景
- 我们需要一个几何体(一个球体或者立方体);
- 我们需要一张360全景图或者一个6面图片
- 将视角移动道几何题内部
这里我们从网上找一张360的全景图
既然是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()