Vue集成three.js并加載glb、gltf、FBX、json模型的場景分析
最近剛開始做的一個項目,后面有個模塊要通過three.js實現(xiàn)3D的場景,因為之前也沒接觸過3D這塊,就提前學了一下,做個記錄。
先上幾個網(wǎng)址
ThreeJS官方:http://www.thingjs.com/guide/city2/
ThreeJS文檔:https://threejs.org/docs/index.html#manual/en/introduction/Creating-a-scene
免費模型網(wǎng):http://glbxz.com/err/search.php?keyword=%E5%85%8D%E8%B4%B9
接下來就我做的一個demo開始
安裝
npm i three npm i three-orbitcontrols npm i stats.js // 性能監(jiān)測
組件中引入
import * as THREE from 'three' import * as Stats from 'stats.js' import OrbitControls from 'three-orbitcontrols' import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader' import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js' import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader.js'
基本使用
1.創(chuàng)建場景
this.scene = new THREE.Scene();
2.相機
this.camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.1, 1000); // 設(shè)置攝像機位置,相機方向逆X軸方向,傾斜向下看 this.camera.position.set(360, 360, 360); // 指向場景中心 this.camera.lookAt(this.scene.position);
3. 渲染器
this.renderer = new THREE.WebGLRenderer({ antialias: true }); // 設(shè)置環(huán)境 this.renderer.setClearColor(new THREE.Color("#f1f9fb")); // 設(shè)置場景大小 this.renderer.setSize(window.innerWidth / window.innerHeight); // 渲染器開啟陰影效果 this.renderer.shadowMap.enabled = true;
4.創(chuàng)建紋理加載器
this.textureLoader = new THREE.TextureLoader();
5.創(chuàng)建組合對象
加載外部模型的時候,基本上都是一個組合對象,因為外部模型都是比較大的,把零散的模型組合到一塊便于操作,可以使用THREE.Group來操作一組對象,包括旋轉(zhuǎn),縮放,移動等,里面的子對象都會受到影響。THREE.Group繼承自THREE.Object3D對象,并且和THREE.Object3D對象沒有任何區(qū)別,僅僅是名字上的差異
this.groupBox = new THREE.Group();
6.添加坐標軸,輔助判斷位置
let axes = new THREE.AxesHelper(1000); this.scene.add(axes);
7.點光源
// 點光源 let point = new THREE.PointLight(0xffffff); point.position.set(500, 300, 400); // 點光源位置 this.scene.add(point); // 點光源添加到場景中
8.環(huán)境光
// 環(huán)境光 let ambient = new THREE.AmbientLight(0x999999); this.scene.add(ambient);
9.性能監(jiān)測
//創(chuàng)建性能監(jiān)測 this.stats = new Stats() this.stats.showPanel(0) // 0: fps, 1: ms, 2: mb, 3+: custom this.stats.domElement.style.position = 'absolute'; //絕對坐標 this.stats.domElement.style.left = '0px';// (0,0)px,左上角 this.stats.domElement.style.top = '0px'; $('#stats').appendChild(this.stats.domElement)
10.相機控件
//創(chuàng)建相機控件 this.control = new OrbitControls(this.camera, this.renderer.domElement) this.control.enableDamping = true // 動態(tài)阻尼系數(shù) 就是鼠標拖拽旋轉(zhuǎn)靈敏度,阻尼越小越靈敏 this.control.dampingFactor = 0.5; // 是否可以縮放 this.control.enableZoom = true; // 是否自動旋轉(zhuǎn) this.control.autoRotate = false; // 設(shè)置相機距離原點的最近距離 this.control.minDistance = 20; // 設(shè)置相機距離原點的最遠距離 this.control.maxDistance = 1000; // 是否開啟右鍵拖拽 this.control.enablePan = true; // 上下翻轉(zhuǎn)的最大角度 this.control.maxPolarAngle = 1.5; // 上下翻轉(zhuǎn)的最小角度 this.control.minPolarAngle = 0.0; // 是否可以旋轉(zhuǎn) this.enableRotate = true;
11.渲染canvas到容器
$('#container').appendChild(this.renderer.domElement);
12.加載glb、gltf模型
loadGlbModel() { const loader = new GLTFLoader() // const dracoLoader = new DRACOLoader() // dracoLoader.setDecoderPath('/draco/') // dracoLoader.preload() // loader.setDRACOLoader(dracoLoader) loader.load(`${this.publicPath}model/12OJJ6MOWT722N61Z5N92KA9C.glb`, (gltf) => { console.log(gltf, 'gltf----->>>') gltf.scene.scale.set(100,100,100) // 設(shè)置模型大小縮放 gltf.scene.position.set(0,0,0) let axis = new THREE.Vector3(0,1,0);//向量axis gltf.scene.rotateOnAxis(axis,Math.PI/2); //繞axis軸逆旋轉(zhuǎn)π/16 gltf.scene.rotateOnAxis(axis,Math.PI/-20); gltf.scene.rotateOnAxis(axis,Math.PI/50); // gltf.rotateY(Math.PI / 2); // this.groupBox.add(gltf); this.scene.add(gltf.scene) }, (xhr) => { console.log((xhr.loaded / xhr.total) * 100 + '% loaded') }, (error) => { console.error(error) }) },
13.加載FBX模型
// 加載 FBX 模型 loadFbxModel() { const loader = new FBXLoader(); loader.load(`${this.publicPath}model/glbxz.com6031.FBX`, object => {//加載路徑fbx文件 console.log(object, 'object----->>>') object.traverse( child => { if ( child.isMesh ){ child.castShadow = true; child.receiveShadow = true; } }); this.scene.add(object);//模型 }) },
14.加載json模型
//加載 JSON格式 模型 loadJsonModel() { //設(shè)置相機位置 this.camera.position.z = 130 this.camera.position.y = 80 const loader = new THREE.ObjectLoader() loader.load(`${this.publicPath}model/xxxx.json`, json => { //處理加載模型為黑色問題 json.traverse(child => { if (child.isMesh) { child.material.emissive = child.material.color child.material.emissiveMap = child.material.map } }) this.scene.add(group) }, xhr => { // called while loading is progressing console.log(`${( xhr.loaded / xhr.total * 100 )}% loaded`); }, error => { // called when loading has errors console.error('An error happened', error); }) },
15.創(chuàng)建材質(zhì)
// 創(chuàng)建材質(zhì) createMaterial() { // 創(chuàng)建三維用到的材質(zhì) /** * * MeshBasicMaterial: 網(wǎng)格基礎(chǔ)材質(zhì) * MeshDepthMaterial: 網(wǎng)格深度材質(zhì) * MeshNormalMaterial: 網(wǎng)格法向材質(zhì) * MeshLambertMaterial: 網(wǎng)格Lambert 材質(zhì) * MeshPhongMaterial: 網(wǎng)格 Phong式材質(zhì) * MeshStandardMaterial: 網(wǎng)格標準材質(zhì) * MeshPhysicalMaterial: 網(wǎng)格物理材質(zhì) * MeshToonMaterial: 網(wǎng)格卡通材質(zhì) * ShadowMaterial: 陰影材質(zhì) * ShaderMaterial: 著色器材質(zhì) * LineBasicMaterial: 直線基礎(chǔ)材質(zhì) * LineDashMaterial: 虛線材質(zhì) */ // 外墻 let wallMaterial = new THREE.MeshLambertMaterial({ color: 0x00ffff }); let wallGeo = new THREE.BoxGeometry(439 + 2 + 2, 120, 376.5 + 2 + 2); // 創(chuàng)建幾何體 let wallMesh = new THREE.Mesh(wallGeo, wallMaterial); wallMesh.position.set(0, 60, 0); //(0, 60, -14.95); this.scene.add(wallMesh) // 添加結(jié)果到場景中 // 內(nèi)墻 let wallInnerMaterial = new THREE.MeshLambertMaterial({ color: 0x2d1bff, }); let wallInnerGeo = new THREE.BoxGeometry(439, 120, 376.5); //(270, 120, 390); let wallInnerMesh = new THREE.Mesh(wallInnerGeo, wallInnerMaterial); wallInnerMesh.position.set(0, 60, 0); //(0, 60, -14.95); this.scene.add(wallInnerMesh) // 添加結(jié)果到場景中 // 門 let doorTexture = this.textureLoader.load( require("../../../../assets/img/1.png") // 暫時注掉 ); let boxTextureMaterial = new THREE.MeshStandardMaterial({ map: doorTexture, metalness: 0.2, roughness: 0.07, side: THREE.DoubleSide, }); //let doorInnerMaterial = new THREE.MeshLambertMaterial({color: 0x2D1BFF}); let doorGeo = new THREE.BoxGeometry(2, 80, 74.5); let doorMesh = new THREE.Mesh(doorGeo, boxTextureMaterial); doorMesh.position.set(-220.5, 40, 0); this.scene.add(doorMesh); // 添加結(jié)果到場景中 /** * threeBSP - 引用還有問題 */ // //轉(zhuǎn)BSP // let wallBSP = new ThreeBSP(wallMesh); // let wallInnerBSP = new ThreeBSP(wallInnerMesh); // let doorBSP = new ThreeBSP(doorMesh); // // let window1BSP = new ThreeBSP(this.createWindowRight()); // //let window2BSP = new ThreeBSP(this.createWindowRight());// createWindowLeft // let wallResultBSP = wallBSP.subtract(wallInnerBSP); // wallResultBSP = wallResultBSP.subtract(doorBSP); // // wallResultBSP = wallResultBSP.subtract(window1BSP); // //wallResultBSP = wallResultBSP.subtract(window2BSP); // let wallResultMesh = wallResultBSP.toMesh(); // //轉(zhuǎn)換后的Mesh配置屬性 // let wallTexture = this.textureLoader.load(require("../../../../assets/img/3.jpg")); // 暫時注掉 // let wallTextureMaterial = new THREE.MeshStandardMaterial({ // map: wallTexture, // metalness: 0.2, // roughness: 0.07, // side: THREE.DoubleSide, // }); // let wallInnerTexture = this.textureLoader.load( // require("../../../../assets/img/6.jpg") // 暫時注掉 // ); // let wallInnerTextureMaterial = new THREE.MeshStandardMaterial({ // map: wallInnerTexture, // metalness: 0.2, // roughness: 0.07, // side: THREE.DoubleSide, // }); // let wallResultMeshMaterial = []; // wallResultMeshMaterial.push(wallTextureMaterial); // wallResultMeshMaterial.push(wallInnerTextureMaterial); // //wallResultMeshMaterial.push(boxTextureMaterial); // wallResultMesh.material = wallResultMeshMaterial; // // console.log(wallResultMesh.geometry.faces, 112233); // wallResultMesh.geometry.faces.forEach((item, i) => { // if (i < 160) { // item.materialIndex = 0; // } else { // item.materialIndex = 1; // } // }); // wallResultMesh.geometry.computeFaceNormals(); // wallResultMesh.geometry.computeVertexNormals(); // //添加結(jié)果到場景中 // this.scene.add(wallResultMesh); },
16.進行渲染
render() { let animate = () => { //循環(huán)調(diào)用函數(shù) this.clearAnim = requestAnimationFrame(animate) //更新相機控件 this.control.update() // 更新性能插件 this.stats.update() //渲染界面 this.renderer.render(this.scene, this.camera) } animate() }
17.為模型綁定事件
這里以點擊事件為例
this.renderer.domElement.addEventListener('click', this.modelMouseClick, false)
// 模型的點擊事件 modelMouseClick( event ) { var raycaster = new THREE.Raycaster(); var mouse = new THREE.Vector2(); // 將鼠標位置歸一化為設(shè)備坐標。x 和 y 方向的取值范圍是 (-1 to +1) mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1; mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1; raycaster.setFromCamera(mouse, this.camera); const intersects = raycaster.intersectObjects(this.scene.children); // 根據(jù)它來判斷點擊的什么,length為0即沒有點擊到模型 console.log(intersects, 'intersects----->>>') }
完整代碼
<template> <div id="import-template"> <!-- 放性能監(jiān)測的容器 --> <div id="stats"></div> <!-- 3D模型容器 --> <div id="container"></div> </div> </template> <script> // import '@/utils/ThreeBSP.js' // 不可以這么引 import * as THREE from 'three' import * as Stats from 'stats.js' // import * as dat from 'dat.gui' import OrbitControls from 'three-orbitcontrols' import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader' import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js' import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader.js' const $ = name => document.querySelector(name) export default { data() { return { scene: null, // 場景 camera: null, // 照相機 renderer: null, // 渲染器 mesh: null, // 網(wǎng)格 textureLoader: null, // 紋理加載器 mixer: null, groupBox: null, stats: null, // 性能監(jiān)測 control: null, // 相機控件 publicPath: process.env.BASE_URL, clearAnim: null, clock: null } }, created() { // this.init() }, mounted() { this.init() }, destroyed() { cancelAnimationFrame(this.clearAnim) // 清除requestAnimationFrame this.renderer.domElement.removeEventListener('click', this.modelMouseClick, false) this.scene = null, // 場景 this.camera = null, // 照相機 this.renderer = null, // 渲染器 this.mesh = null, // 網(wǎng)格 this.textureLoader = null, // 紋理加載器 this.mixer = null, this.groupBox = null, this.stats = null, // 性能監(jiān)測 this.control = null, // 相機控件 this.publicPath = process.env.BASE_URL, this.clock = null }, methods: { //初始化 init() { // 場景 this.scene = new THREE.Scene(); // 1.2 相機 this.camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.1, 1000); // 設(shè)置攝像機位置,相機方向逆X軸方向,傾斜向下看 this.camera.position.set(360, 360, 360); //this.camera.position.set(-20, 40 ,30) // 指向場景中心 this.camera.lookAt(this.scene.position); // 1.3 渲染器 this.renderer = new THREE.WebGLRenderer({ antialias: true }); // 創(chuàng)建紋理加載器 this.textureLoader = new THREE.TextureLoader(); // 創(chuàng)建一個組合對象 this.groupBox = new THREE.Group(); // 添加坐標軸,輔助判斷位置 let axes = new THREE.AxesHelper(1000); this.scene.add(axes); // 設(shè)置環(huán)境 this.renderer.setClearColor(new THREE.Color("#f1f9fb")); // 設(shè)置場景大小 this.renderer.setSize( $('#container').getBoundingClientRect().width, $('#container').getBoundingClientRect().height ); // 渲染器開啟陰影效果 this.renderer.shadowMap.enabled = true; // 點光源 let point = new THREE.PointLight(0xffffff); point.position.set(500, 300, 400); // 點光源位置 this.scene.add(point); // 點光源添加到場景中 // 環(huán)境光 let ambient = new THREE.AmbientLight(0x999999); this.scene.add(ambient); //創(chuàng)建性能監(jiān)測 this.stats = new Stats() this.stats.showPanel(0) // 0: fps, 1: ms, 2: mb, 3+: custom this.stats.domElement.style.position = 'absolute'; //絕對坐標 this.stats.domElement.style.left = '0px';// (0,0)px,左上角 this.stats.domElement.style.top = '0px'; $('#stats').appendChild(this.stats.domElement) // 渲染div到canvas $('#container').appendChild(this.renderer.domElement); //創(chuàng)建相機控件 this.control = new OrbitControls(this.camera, this.renderer.domElement) this.control.enableDamping = true // 動態(tài)阻尼系數(shù) 就是鼠標拖拽旋轉(zhuǎn)靈敏度,阻尼越小越靈敏 this.control.dampingFactor = 0.5; // 是否可以縮放 this.control.enableZoom = true; // 是否自動旋轉(zhuǎn) this.control.autoRotate = false; // 設(shè)置相機距離原點的最近距離 this.control.minDistance = 20; // 設(shè)置相機距離原點的最遠距離 this.control.maxDistance = 1000; // 是否開啟右鍵拖拽 this.control.enablePan = true; // 上下翻轉(zhuǎn)的最大角度 this.control.maxPolarAngle = 1.5; // 上下翻轉(zhuǎn)的最小角度 this.control.minPolarAngle = 0.0; // 是否可以旋轉(zhuǎn) this.enableRotate = true; this.loadGlbModel(); // 加載 glb、gltf模型 // this.loadFbxModel() // 加載 FBX 模型 // this.loadJsonModel() // 加載 json 模型 // this.createMaterial() // 創(chuàng)建材質(zhì) // 最后進行渲染 this.render() }, // 最后的渲染 render() { let animate = () => { //循環(huán)調(diào)用函數(shù) this.clearAnim = requestAnimationFrame(animate) //更新相機控件 this.control.update() // 更新性能插件 this.stats.update() //渲染界面 this.renderer.render(this.scene, this.camera) } animate() // 為模型綁定點擊事件 this.renderer.domElement.addEventListener('click', this.modelMouseClick, false) }, // 創(chuàng)建材質(zhì) createMaterial() { // 創(chuàng)建三維用到的材質(zhì) /** * * MeshBasicMaterial: 網(wǎng)格基礎(chǔ)材質(zhì) * MeshDepthMaterial: 網(wǎng)格深度材質(zhì) * MeshNormalMaterial: 網(wǎng)格法向材質(zhì) * MeshLambertMaterial: 網(wǎng)格Lambert 材質(zhì) * MeshPhongMaterial: 網(wǎng)格 Phong式材質(zhì) * MeshStandardMaterial: 網(wǎng)格標準材質(zhì) * MeshPhysicalMaterial: 網(wǎng)格物理材質(zhì) * MeshToonMaterial: 網(wǎng)格卡通材質(zhì) * ShadowMaterial: 陰影材質(zhì) * ShaderMaterial: 著色器材質(zhì) * LineBasicMaterial: 直線基礎(chǔ)材質(zhì) * LineDashMaterial: 虛線材質(zhì) */ // 外墻 let wallMaterial = new THREE.MeshLambertMaterial({ color: 0x00ffff }); let wallGeo = new THREE.BoxGeometry(439 + 2 + 2, 120, 376.5 + 2 + 2); // 創(chuàng)建幾何體 let wallMesh = new THREE.Mesh(wallGeo, wallMaterial); wallMesh.position.set(0, 60, 0); //(0, 60, -14.95); this.scene.add(wallMesh) // 內(nèi)墻 let wallInnerMaterial = new THREE.MeshLambertMaterial({ color: 0x2d1bff, }); let wallInnerGeo = new THREE.BoxGeometry(439, 120, 376.5); //(270, 120, 390); let wallInnerMesh = new THREE.Mesh(wallInnerGeo, wallInnerMaterial); wallInnerMesh.position.set(0, 60, 0); //(0, 60, -14.95); this.scene.add(wallInnerMesh) // 門 let doorTexture = this.textureLoader.load( require("../../../../assets/img/1.png") // 暫時注掉 ); let boxTextureMaterial = new THREE.MeshStandardMaterial({ map: doorTexture, metalness: 0.2, roughness: 0.07, side: THREE.DoubleSide, }); //let doorInnerMaterial = new THREE.MeshLambertMaterial({color: 0x2D1BFF}); let doorGeo = new THREE.BoxGeometry(2, 80, 74.5); let doorMesh = new THREE.Mesh(doorGeo, boxTextureMaterial); doorMesh.position.set(-220.5, 40, 0); this.scene.add(doorMesh); /** * threeBSP - 引用還有問題 */ // //轉(zhuǎn)BSP // let wallBSP = new ThreeBSP(wallMesh); // let wallInnerBSP = new ThreeBSP(wallInnerMesh); // let doorBSP = new ThreeBSP(doorMesh); // // let window1BSP = new ThreeBSP(this.createWindowRight()); // //let window2BSP = new ThreeBSP(this.createWindowRight());// createWindowLeft // let wallResultBSP = wallBSP.subtract(wallInnerBSP); // wallResultBSP = wallResultBSP.subtract(doorBSP); // // wallResultBSP = wallResultBSP.subtract(window1BSP); // //wallResultBSP = wallResultBSP.subtract(window2BSP); // let wallResultMesh = wallResultBSP.toMesh(); // //轉(zhuǎn)換后的Mesh配置屬性 // let wallTexture = this.textureLoader.load(require("../../../../assets/img/3.jpg")); // 暫時注掉 // let wallTextureMaterial = new THREE.MeshStandardMaterial({ // map: wallTexture, // metalness: 0.2, // roughness: 0.07, // side: THREE.DoubleSide, // }); // let wallInnerTexture = this.textureLoader.load( // require("../../../../assets/img/6.jpg") // 暫時注掉 // ); // let wallInnerTextureMaterial = new THREE.MeshStandardMaterial({ // map: wallInnerTexture, // metalness: 0.2, // roughness: 0.07, // side: THREE.DoubleSide, // }); // let wallResultMeshMaterial = []; // wallResultMeshMaterial.push(wallTextureMaterial); // wallResultMeshMaterial.push(wallInnerTextureMaterial); // //wallResultMeshMaterial.push(boxTextureMaterial); // wallResultMesh.material = wallResultMeshMaterial; // // console.log(wallResultMesh.geometry.faces, 112233); // wallResultMesh.geometry.faces.forEach((item, i) => { // if (i < 160) { // item.materialIndex = 0; // } else { // item.materialIndex = 1; // } // }); // wallResultMesh.geometry.computeFaceNormals(); // wallResultMesh.geometry.computeVertexNormals(); // //添加結(jié)果到場景中 // this.scene.add(wallResultMesh); }, // 加載 GLTF 模型 loadGlbModel() { const loader = new GLTFLoader() // const dracoLoader = new DRACOLoader() // dracoLoader.setDecoderPath('/draco/') // dracoLoader.preload() // loader.setDRACOLoader(dracoLoader) loader.load(`${this.publicPath}model/12OJJ6MOWT722N61Z5N92KA9C.glb`, (gltf) => { console.log(gltf, 'gltf----->>>') gltf.scene.scale.set(100,100,100) // 設(shè)置模型大小縮放 gltf.scene.position.set(0,0,0) let axis = new THREE.Vector3(0,1,0);//向量axis gltf.scene.rotateOnAxis(axis,Math.PI/2); //繞axis軸逆旋轉(zhuǎn)π/16 gltf.scene.rotateOnAxis(axis,Math.PI/-20); gltf.scene.rotateOnAxis(axis,Math.PI/50); // gltf.rotateY(Math.PI / 2); // this.groupBox.add(gltf); this.scene.add(gltf.scene) }, (xhr) => { console.log((xhr.loaded / xhr.total) * 100 + '% loaded') }, (error) => { console.error(error) }) }, // 加載 FBX 模型 loadFbxModel() { const loader = new FBXLoader(); loader.load(`${this.publicPath}model/glbxz.com6031.FBX`, object => {//加載路徑fbx文件 console.log(object, 'object----->>>') object.traverse( child => { if ( child.isMesh ){ child.castShadow = true; child.receiveShadow = true; } }); this.scene.add(object);//模型 }) }, //加載 JSON格式 模型 loadJsonModel() { //設(shè)置相機位置 this.camera.position.z = 130 this.camera.position.y = 80 const loader = new THREE.ObjectLoader() loader.load(`${this.publicPath}model/xxxx.json`, json => { //處理加載模型為黑色問題 json.traverse(child => { if (child.isMesh) { child.material.emissive = child.material.color child.material.emissiveMap = child.material.map } }) this.scene.add(group) }, xhr => { // called while loading is progressing console.log(`${( xhr.loaded / xhr.total * 100 )}% loaded`); }, error => { // called when loading has errors console.error('An error happened', error); }) }, // 模型的點擊事件 modelMouseClick( event ) { var raycaster = new THREE.Raycaster(); var mouse = new THREE.Vector2(); // 將鼠標位置歸一化為設(shè)備坐標。x 和 y 方向的取值范圍是 (-1 to +1) mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1; mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1; raycaster.setFromCamera(mouse, this.camera); const intersects = raycaster.intersectObjects(this.scene.children); // 根據(jù)它來判斷點擊的什么,length為0即沒有點擊到模型 console.log(intersects, 'intersects----->>>') } } } </script> <style scoped> #import-template { width: 100%; height: 100%; } #stats { width: 100%; height: 50px; position: relative; } #container { width: 100%; height: calc(100% - 50px); } </style>
效果
最后再補充一下,有個threeBSP,,到現(xiàn)在還沒知道怎么去引用,搞這個東西才兩天,很多還需要慢慢摸索 ,好像這個threBSP不支持npm裝,而且必須要引在THREE后面。。。慢慢再搞
<script src="https://johnson2heng.github.io/three.js-demo/lib/threebsp.js"></script>
這個是threeBSP在線的包,如果向上面例子按需引入THREE,那應該怎么去引這個包呢,,
不斷學習中。。。
補充
接上面的問題,【已解決】ThreeBSP引入問題
見下篇博文three.js 利用uv和ThreeBSP制作一個快遞柜功能
到此這篇關(guān)于Vue集成three.js,并加載glb、gltf、FBX、json模型的文章就介紹到這了,更多相關(guān)Vue集成three.js內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue2項目導出操作實現(xiàn)方法(后端接口導出、前端直接做導出)
這篇文章主要給大家介紹了關(guān)于vue2項目導出操作實現(xiàn)方法的相關(guān)資料,文中介紹的是后端接口導出、前端直接做導出,通過代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考借鑒價值,需要的朋友可以參考下2024-05-05解決Vue+Element ui開發(fā)中碰到的IE問題
今天小編就為大家分享一篇解決Vue+Element ui開發(fā)中碰到的IE問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-09-09vue+elementui實現(xiàn)動態(tài)控制表格列的顯示和隱藏
這篇文章主要介紹了vue+elementui實現(xiàn)動態(tài)控制表格列的顯示和隱藏,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-04-04vue使用echarts實現(xiàn)柱狀圖動態(tài)排序效果
echarts在前端開發(fā)中實屬必不可缺的大數(shù)據(jù)可視化工具,這篇文章主要為大家詳細介紹了vue如何使用echarts實現(xiàn)柱狀圖動態(tài)排序效果,感興趣的可以了解下2023-10-10關(guān)于新建的vue3項目一直提示代碼格式警告的問題
這篇文章主要介紹了關(guān)于新建的vue3項目一直提示代碼格式警告的問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-10-10