threejs全景圖和錨點(diǎn)編輯的實(shí)現(xiàn)方案
全景圖和錨點(diǎn)編輯
今天來(lái)簡(jiǎn)單聊聊threejs全景圖和錨點(diǎn)編輯的方案。 全景圖也就是所謂的天空盒子,所應(yīng)用到的場(chǎng)景例如:場(chǎng)景模型的天空背景、夜晚的星空背景、VR看房等~
錨點(diǎn)編輯這篇重點(diǎn)講一講錨點(diǎn)編輯,也就是所謂場(chǎng)景編輯的方案。其中思想無(wú)限接近于Low Code,說(shuō)到Low Code!我拖更了四篇文章,由于過(guò)年那段時(shí)間太忙了,實(shí)在是沒(méi)時(shí)間更新!看到許多人都在等我完事,感到十分抱歉,后續(xù)一定會(huì)整理好更新!
全景圖
其實(shí)全景圖沒(méi)什么內(nèi)容??梢韵胂蟪梢粋€(gè)非常大正方體的盒子,通過(guò)六個(gè)面的圖片銜接而成。而我們相機(jī)則是存在于正方體內(nèi)部,這樣就能形成一個(gè)視覺(jué)誤差,認(rèn)為我們處于場(chǎng)景中。
全景圖拆解
以下就是全景圖正方體拆解圖,六個(gè)面互相銜接,可以腦補(bǔ)下當(dāng)將這個(gè)正方體組裝后,我們所看到就是一個(gè)無(wú)縫銜接的一個(gè)場(chǎng)景,當(dāng)然認(rèn)真看還是可以看出正方體的邊界處。
可以把骰子腦補(bǔ)成相機(jī)所在的位置,這樣就很容易理解
既然有天空盒子,那多個(gè)場(chǎng)景的天空盒子肯定存在不同之處。在我們切換場(chǎng)景如何切換對(duì)應(yīng)的天空盒子呢?很簡(jiǎn)單,我們只需封裝一個(gè)切換函數(shù)如下
// 添加地面和天空盒 Viewer.prototype.changeSkyBox = function (skydir) { const that = this // 創(chuàng)建幾何模型 BoxGeometry('x軸', '軸', 'z軸') const geometry = new THREE.BoxGeometry(999, 999, 999) // 創(chuàng)建紋理貼圖 前后 上下 左右 const texture0 = new THREE.TextureLoader().load((gAppPath + `/images/ysThree/sky/${skydir}/px.jpg`)) const texture1 = new THREE.TextureLoader().load((gAppPath + `/images/ysThree/sky/${skydir}/nx.jpg`)) const texture2 = new THREE.TextureLoader().load((gAppPath + `/images/ysThree/sky/${skydir}/py.jpg`)) const texture3 = new THREE.TextureLoader().load((gAppPath + `/images/ysThree/sky/${skydir}/ny.jpg`)) const texture4 = new THREE.TextureLoader().load((gAppPath + `/images/ysThree/sky/${skydir}/pz.jpg`)) const texture5 = new THREE.TextureLoader().load((gAppPath + `/images/ysThree/sky/${skydir}/nz.jpg`)) // 添加材質(zhì) const material = [ new THREE.MeshBasicMaterial({color: 0xffddff, map: texture0, side: THREE.DoubleSide}), new THREE.MeshBasicMaterial({color: 0xffddff, map: texture1, side: THREE.DoubleSide}), new THREE.MeshBasicMaterial({color: 0xffddff, map: texture2, side: THREE.DoubleSide}), new THREE.MeshBasicMaterial({color: 0xffddff, map: texture3, side: THREE.DoubleSide}), new THREE.MeshBasicMaterial({color: 0xffddff, map: texture4, side: THREE.DoubleSide}), new THREE.MeshBasicMaterial({color: 0xffddff, map: texture5, side: THREE.DoubleSide}) ] // 創(chuàng)建網(wǎng)格對(duì)象 const cube = new _3d.Mesh(geometry, material) cube.layers.enableAll() cube.name = 'skybox' that.skybox && this.scene.remove(that.skybox) that.skybox = cube that.AmbientGroup.add(cube) }
場(chǎng)景編輯方案
不同場(chǎng)景的燈光位置以及圖標(biāo)點(diǎn)位可能不同,作為一個(gè)基礎(chǔ)編輯平臺(tái),我們肯定要考慮如何將我們的場(chǎng)景變成可配置化,根據(jù)不同的需求做出不同的改變。之前的文章介紹過(guò)我們將模型通過(guò)JSON的形式去配置,那我們?nèi)绾螌?chǎng)景中的點(diǎn)位以及燈光位置做出配置呢?
transformControls
變換控制器,這里它的作用主要是對(duì)錨點(diǎn)的平移、縮放、旋轉(zhuǎn)操作
初始化控制器
//移動(dòng)控制器 this.transformControls = new TransformControls(this.camera, this.renderer.domElement) this.transformControls.setSize(0.5) this.scene.add(this.transformControls) //添加入場(chǎng)景
添加可移動(dòng)對(duì)象
我們可以在比如說(shuō)燈光類中,添加一個(gè)transform_attach方法,在啟用編輯后調(diào)用該方法。只有attach后才能夠被拾取,進(jìn)行平移、旋轉(zhuǎn)、縮放的操作
transformControls.attach(...) //對(duì)象類中 transform_attach(value){ if (value) { this.transformControls.attach(this.dlight) } else { this.transformControls.detach(this.dlight) } }
平移、縮放、旋轉(zhuǎn)
gapp.history.execute 這里主要是業(yè)務(wù)邏輯,將編輯后的對(duì)象保存起來(lái),主要用于回顯
SetPositionCommand 這里主要的作用是記錄下舊的位置信息與新的位置信息
拋開(kāi)上面兩個(gè)方法,其實(shí)只要添加進(jìn)變換控制器就可以對(duì)物體就行操作了,下面我單獨(dú)介紹為什么需要保存信息
Viewer.prototype.bindTransformEvent = function () { this.transformControls.addEventListener('mouseDown', () => { //鼠標(biāo)拾取到 var object = gapp.transformControls.object //獲取拾取對(duì)象 this.objectPositionOnDown = object.position.clone()//保存位置 this.objectRotationOnDown = object.rotation.clone()//保存角度 this.objectScaleOnDown = object.scale.clone()//保存縮放大小 gapp.controls.enabled = false }) this.transformControls.addEventListener('mouseUp', () => {//鼠標(biāo)提起 var object = gapp.transformControls.object//獲取拾取對(duì)象 if (object !== undefined) { switch (gapp.transformControls.getMode()) { //這里判斷是要進(jìn)行平移、縮放、旋轉(zhuǎn)操作 case 'translate': if (!this.objectPositionOnDown.equals(object.position)) { gapp.history.execute(new SetPositionCommand(this, object, object.position, this.objectPositionOnDown)) } break case 'rotate': if (!this.objectRotationOnDown.equals(object.rotation)) { gapp.history.execute(new SetRotationCommand(this, object, object.rotation, this.objectRotationOnDown)) } break case 'scale': if (!this.objectScaleOnDown.equals(object.scale)) { gapp.history.execute(new SetScaleCommand(this, object, object.scale, this.objectScaleOnDown)) } break } } gapp.controls.enabled = true }) }
保存對(duì)象
其實(shí)這里和我Low Code的思想很像,就是我們最終要將所有配置好的物體信息保存成一個(gè)JSON的形式。以便于在任意其它項(xiàng)目中做回顯。怎么回顯呢? 假如說(shuō)我們現(xiàn)在編輯好一個(gè)燈光的位置信息以及通過(guò)gui調(diào)整好的顏色、亮度等,我們可以將該燈光object對(duì)象通過(guò)toJSON轉(zhuǎn)成JSON后存儲(chǔ)于我們最終對(duì)象中,后續(xù)通過(guò)接口取回JSON通過(guò)轉(zhuǎn)化重新add到場(chǎng)景中即可
//轉(zhuǎn)化為threejs特有的json格式 scene.toJSON() (了解過(guò)json的同學(xué)可以發(fā)現(xiàn),threejs為了縮小大小,將瓦片對(duì)象最大限度的拆分材質(zhì)等,通過(guò)id關(guān)聯(lián)并保存為json) //解析json轉(zhuǎn)為對(duì)象 Viewer.prototype.fromJSON = function (json, layeridx, isRayobj) { return new Promise((resolve, reject) => { // 解析 json 對(duì)象 let loader = new THREE.ObjectLoader(); let loadedMesh = loader.parse(json); let scene = this.mergeToMaterialsMap(loadedMesh, true) resolve(scene) }) }
結(jié)語(yǔ)
這篇文章主要介紹思想,相對(duì)來(lái)說(shuō)這篇文章比較基礎(chǔ),當(dāng)然后續(xù)可以根據(jù)自己的要求進(jìn)行擴(kuò)展
到此這篇關(guān)于threejs全景圖和錨點(diǎn)編輯的文章就介紹到這了,更多相關(guān)threejs全景圖和錨點(diǎn)編輯內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript實(shí)現(xiàn)文字與圖片拖拽效果的方法
這篇文章主要介紹了JavaScript實(shí)現(xiàn)文字與圖片拖拽效果的方法,涉及javascript操作文字與圖片的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-02-02Bootstrap 設(shè)置datetimepicker在屏幕上面彈出設(shè)置方法
datetimepicker默認(rèn)是在輸入框下面彈出的,但是遇到輸入框在屏幕下面時(shí),日期選擇框會(huì)有一部分在屏幕下面,顯示不了,因此需要能夠從上面彈出,下面小編給大家介紹下Bootstrap 設(shè)置datetimepicker在屏幕上面彈出的設(shè)置方法2017-03-03setTimeout和setInterval的區(qū)別你真的了解嗎?
setTimeout和setInterval這兩個(gè)函數(shù), 大家肯定都不陌生, 但可能并不是每個(gè)用過(guò)這兩個(gè)方法的同學(xué), 都了解其內(nèi)部的實(shí)質(zhì)2011-03-03利用js來(lái)實(shí)現(xiàn)縮略語(yǔ)列表、文獻(xiàn)來(lái)源鏈接和快捷鍵列表
本文主要對(duì)利用js來(lái)實(shí)現(xiàn)縮略語(yǔ)列表、文獻(xiàn)來(lái)源鏈接和快捷鍵列表的方法進(jìn)行詳細(xì)分析介紹。具有很好的參考價(jià)值,需要的朋友一起來(lái)看下吧2016-12-12Bootstrap的Carousel配合dropload.js實(shí)現(xiàn)移動(dòng)端滑動(dòng)切換圖片
這篇文章主要介紹了bootstrap的Carousel配合dropload.js實(shí)現(xiàn)移動(dòng)端滑動(dòng)切換圖片,實(shí)現(xiàn)方法非常簡(jiǎn)單,具有參考借鑒價(jià)值,需要的朋友可以參考下2017-03-03