Vue集成three.js并加載glb、gltf、FBX、json模型的場景分析
最近剛開始做的一個項目,后面有個模塊要通過three.js實現(xiàn)3D的場景,因為之前也沒接觸過3D這塊,就提前學(xué)了一下,做個記錄。
先上幾個網(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.添加坐標(biāo)軸,輔助判斷位置
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'; //絕對坐標(biāo) 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ù) 就是鼠標(biāo)拖拽旋轉(zhuǎn)靈敏度,阻尼越小越靈敏 this.control.dampingFactor = 0.5; // 是否可以縮放 this.control.enableZoom = true; // 是否自動旋轉(zhuǎn) this.control.autoRotate = false; // 設(shè)置相機距離原點的最近距離 this.control.minDistance = 20; // 設(shè)置相機距離原點的最遠(yuǎn)距離 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)格標(biāo)準(zhǔn)材質(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();
// 將鼠標(biāo)位置歸一化為設(shè)備坐標(biāo)。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();
// 添加坐標(biāo)軸,輔助判斷位置
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'; //絕對坐標(biāo)
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ù) 就是鼠標(biāo)拖拽旋轉(zhuǎn)靈敏度,阻尼越小越靈敏
this.control.dampingFactor = 0.5;
// 是否可以縮放
this.control.enableZoom = true;
// 是否自動旋轉(zhuǎn)
this.control.autoRotate = false;
// 設(shè)置相機距離原點的最近距離
this.control.minDistance = 20;
// 設(shè)置相機距離原點的最遠(yuǎn)距離
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)格標(biāo)準(zhǔn)材質(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();
// 將鼠標(biāo)位置歸一化為設(shè)備坐標(biāo)。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,那應(yīng)該怎么去引這個包呢,,
不斷學(xué)習(xí)中。。。
補充
接上面的問題,【已解決】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.x中的provide和inject用法小結(jié)
這篇文章主要介紹了vue2.x中的provide和inject用法小結(jié),本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧2023-12-12
Vue3報錯Cannot convert undefined or null&n
Vue3與Vue-cli5中出現(xiàn)“Cannot convert undefined or null to object”錯誤,因基類組件data()未返回默認(rèn)空值對象導(dǎo)致屬性合并異常,解決方法是確保data()返回對象,避免繼承組件屬性沖突2025-08-08
Vue+Express實現(xiàn)登錄注銷功能的實例代碼
這篇文章主要介紹了Vue+Express實現(xiàn)登錄,注銷功能,本文通過實例代碼講解的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下2019-05-05
vue項目頁面嵌入代碼塊vue-prism-editor的實現(xiàn)
這篇文章主要介紹了vue項目頁面嵌入代碼塊vue-prism-editor的實現(xiàn),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-10-10
vue-electron使用serialport時問題解決方案
這篇文章主要介紹了vue-electron使用serialport時問題解決方案,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-09-09
利用vuex-persistedstate將vuex本地存儲實現(xiàn)
這篇文章主要介紹了利用vuex-persistedstate將vuex本地存儲的實現(xiàn),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-04-04

