three.js场景的背景旋转主体不动
程序员文章站
2022-05-26 18:28:56
...
方法一 创建两个THREE对象分层控制
两个DIV,创建两个THREE对象,完全弄出两套
<div id="divBG"></div>
<div id="divZT"></div>
divBG,绑定创建THREE对象1,在场景中添加背景图片,设置controls的自动旋转,关键代码如下:
initScene () {
// 场景作为一个容器
scene = new THREE.Scene()
let urls = ['dark-s_px.jpg', 'dark-s_nx.jpg', 'dark-s_py.jpg', 'dark-s_ny.jpg', 'dark-s_pz.jpg', 'dark-s_nz.jpg']
let loader = new THREE.CubeTextureLoader()
loader.setPath('/static/three/MilkyWay/')
let background = loader.load(urls)
scene.background = background
},
initControls () {
controls = new OrbitControls(camera, renderer.domElement)
controls.autoRotate = true // 是否自动旋转
controls.autoRotateSpeed = 1.0 // 自动旋转的速度,默认值是 2.0,即渲染满60帧的情况下30秒旋转360度。
},
注意camera、renderer等绑定的是divBG对应的dom。
divZT,绑定创建THREE对象2,场景不要设置背景,直接加载主体不需要转动的部分。
在此不赘述,重点在方法二。
方法二 场景旋转主体逆向旋转
全部绑定在一个DIV上实现,创建一个THREE对象,给其最外层场景设置背景,同时设置controls.autoRotate的自动旋转。此时,整个场景里的对象都会旋转起来,为了让主体部分保持不动,只需设置主体部分进行逆向旋转即可。
关键步骤如下:
1、创建DIV
<div id="divOne"></div>
divOne = document.getElementById('divOne')
2、创建外层场景并添加背景图片,创建子场景放置不旋转的对象
// 场景
initScene () {
scene = new THREE.Scene()
// 给当前场景容器添加背景图片
let urls = ['dark-s_px.jpg', 'dark-s_nx.jpg', 'dark-s_py.jpg', 'dark-s_ny.jpg', 'dark-s_pz.jpg', 'dark-s_nz.jpg']
let loader = new THREE.CubeTextureLoader()
loader.setPath('/static/three/MilkyWay/')
let background = loader.load(urls)
scene.background = background
// 创建一个groupNoRotate不随着场景旋转而旋转
groupNoRotate = new THREE.Group()
scene.add(groupNoRotate)
},
3、添加灯光至外层场景,跟随背景旋转
// 灯光
initLight () {
let ambientLight = new THREE.AmbientLight(0xffffff) // 环境光
let directionalLight = new THREE.DirectionalLight(0xffffff, 0.1) // 平行光
directionalLight.position.set(5, 10, 5)
let pointLight = new THREE.PointLight(0xffffff) // 点光源
pointLight.position.set(30, 10, 10)
// 将光源加入场景 因为加入scene而不是groupNoRotate 所以光源也会自动转动
scene.add(ambientLight)
scene.add(directionalLight)
scene.add(pointLight)
},
4、设置控制器的自动旋转及自动旋转速度
// 控制器
initControls () {
controls = new OrbitControls(camera, renderer.domElement)
……
controls.autoRotate = true // 是否自动旋转
controls.autoRotateSpeed = 1.0 // 自动旋转的速度,默认值是 2.0,即渲染满60帧的情况下30秒旋转360度。
……
},
5、加载模型至内层场景groupNoRotate
// 模型加载
initModel () {
// 实例化加载器
let loader = new GLTFLoader()
loader.load('/static/three/model/line.glb', function (obj) {
if (groupNoRotate !== null) {
groupNoRotate.add(obj.scene) // 此处需将模型加载到groupNoRotate中一同控制groupNoRotate逆旋转
}
console.log('loaded')
}, function (xhr) {
console.log(xhr.loaded, 'loading')
}, function (error) {
console.error(error, 'load error!')
})
},
6、场景动画,将内层场景y轴旋转设置为逆向旋转
// 场景动画
animate () {
// 控制groupNoRotate里面的所有对象一起逆向旋转,场景在自动旋转,所以表现为不旋转
if (groupNoRotate !== null) {
groupNoRotate.rotation.y = groupNoRotate.rotation.y - Math.PI / (30 * 60)
}
controls.update()
renderer.render(scene, camera)
stop = requestAnimationFrame(this.animate)
},
关键点
自动旋转的速度controls.autoRotateSpeed要和逆向旋转的角度groupNoRotate.rotation.y相抵消!!!
controls.autoRotateSpeed = 1.0 // 自动旋转的速度,默认值是 2.0,即渲染满60帧的情况下30秒旋转360度。
groupNoRotate.rotation.y = groupNoRotate.rotation.y - Math.PI / (30 * 60)
经测试发现,groupNoRotate.rotation.y每次的减幅应该是Math.PI / (30 * 60) * autoRotateSpeed。
即
controls.autoRotateSpeed = k
groupNoRotate.rotation.y = groupNoRotate.rotation.y - Math.PI * k / (30 * 60)
为什么呢?我不知道瞎蒙的试了几次中了,求解…………
效果截图
明显能看出背景在转动,而主体部分(蓝色线)保持不动。
推荐阅读