1.概要
最近學習Three.js,嘗試加載一些3d max導出的obj、stl模型,在展示模型的時候遇到了一些問題,模型的尺寸、位置和旋轉角度每次都靠手工調整,非常的不方便,就想着寫一個方法來隨心所欲的控制模型的尺寸、位置、角度。
2.實現思路
先看看官方加載外部模型的標准代碼:
var mtlLoader = new THREE.MTLLoader(); mtlLoader.load(mtlPath, function (materials) { materials.preload(); var loader = new THREE.OBJLoader(); loader.setMaterials(materials); loader.load(modelPath, function (obj) { obj.castShadow = true; obj.receiveShadow = true; //場景加載 scene.add(obj); //渲染 renderer.render(scene, camera); }});
通過以上代碼,可以實現obj模型和mtl紋理的加載。但是在實際使用中,模型的尺寸和方向不是完美合適的,比如博主我在使用過程中就遇到了以下三個問題。
問題1 模型尺寸
外部模型往往是3d max導出,模型的大小尺寸和實際中往往不一樣。three.js 官方有scale 屬性可以更改模型的尺寸比例,代碼如下。
obj.scale.set(x,y,z);
現在問題來了,我知道的參數其實是模型的長、寬、高,並不是比例。解決的方法如下,先計算出模型的實際長寬高,轉換成比例。
//計算模型尺寸 var box = new THREE.Box3(); box.expandByObject(obj); var length = box.max.x - box.min.x; var width = box.max.z - box.min.z; var height = box.max.y - box.min.y; //l w h對應模型的長寬高 obj.scale.set(l / length, h / height, w / width);
問題2 模型角度
和模型尺寸一樣,外部模型的朝向和實際中有時候不同,有時候一種模型會在場景中有多個朝向的分布,例如辦公室的椅子。還是先看看官方的方法position屬性可以設置模型x、y、z的轉向。代碼如下:
obj.position.set(angleX, angleY, angleZ);
現在看起來是沒有問題了,不過當你遇到一個模型中心點坐標和場景中心點坐標相差幾百萬單位的時候,估計旋轉后連模型影子都看不見了...例如博主我遇到的下圖這種模型參數:
如上圖,模型本身只有78.5單位長,但是中心x坐標卻是2219638.25,導致博主我硬是找了一下午沒有加載出模型來。
在此感謝 https://blog.csdn.net/ruangong1203/article/details/60476782 這篇博客給了我思路。解決方法是增加一個容器,將模型放入容器中,然后指定容器的中心點,然后旋轉容器代替旋轉模型即可。
let wrapper = new THREE.Object3D(); //模型在場景中的為准 wrapper.position.set(x,y,z); wrapper.add(obj); wrapper.rotation.set(angleX, angleY, angleZ);
問題三 模型位置
模型的位置是最頭痛的,three.js默認的以模型的中心偏移來定位的,同樣看看官方的方法,有個position屬性可以更改模型位置。如果遇到問題二里面那種偏移超級遠的模型就尷尬了。
我的解決思路是先計算出模型的實際尺寸,然后再找到模型的中心點,根據x=0,y=0,z=0將模型移動到正常位置,然后通過問題二的容器解決方法來重新設置容器位置解決。代碼如下:
//計算模型尺寸 var box = new THREE.Box3(); box.expandByObject(obj); var x = (box.max.x + box.min.x) / 2; var y = (box.max.y + box.min.y) / 2; var z = (box.max.z + box.min.z) / 2; obj.position.set(0 - x, 0 - y, 0 - z); obj.castShadow = true; obj.receiveShadow = true; let wrapper = new THREE.Object3D(); //模型在場景中實際位置 var pt={x:0,y:0,z:0}; wrapper.position.set(pt.x, pt.y, pt.z); wrapper.add(obj);
3.實現效果
放張效果圖:
在線體驗地址:http://www.88gis.cn/plugins/dgis3d/pages/index.html
4.代碼
詳細代碼請移步我的個人博客88gis.cn查看更多。
代碼下載地址:點擊前往