vue2中trhee.js加載模型展示天空盒子

![在這里插入圖片描述](https://i-blog.csdnimg.cn/direct/13b9193d6738428791fc1ff112e03627.png
加載模型的時候需要把模型放在public文件下面
創建場景

this.scene = new THREE.Scene()

創建相機

  this.camera = new THREE.PerspectiveCamera(45,this.viewNode.clientWidth / this.viewNode.clientHeight,1,9999999)

調整相機位置

this.camera.position.set(600, 800, 1000)this.camera.lookAt(0, 0, 0)

創建渲染器

this.renderer = new THREE.WebGLRenderer({ antialias: true,alpha: true })this.renderer.setSize(this.viewNode.clientWidth, this.viewNode.clientHeight)this.renderer.setPixelRatio(window.devicePixelRatio)this.renderer.shadowMap.enabled = true // 啟用陰影this.viewNode.appendChild(this.renderer.domElement)

添加軌道控制器

   // 添加軌道控制器this.controls = new OrbitControls(this.camera, this.renderer.domElement)this.controls.enableDamping = truethis.controls.dampingFactor = 0.05this.controls.maxPolarAngle = Math.PI * 0.45this.controls.minPolarAngle = Math.PI * 0.1this.controls.minDistance = 5this.controls.maxDistance = 30this.controls.enableRotate = false // 禁止相機旋轉this.controls.enableZoom = false // 禁止相機縮放this.controls.enablePan = false // 禁止相機平移this.initLights()this.initWater()this.initSky()this.loadGLTFModel()},

天空盒子

initSky() {this.sky = new Sky()this.sky.name='sky'this.sky.scale.setScalar(999999) // 調整天空盒子的大小this.scene.add(this.sky)const skyUniforms = this.sky.material.uniformsskyUniforms['turbidity'].value = 10skyUniforms['rayleigh'].value = 2skyUniforms['mieCoefficient'].value = 0.005skyUniforms['mieDirectionalG'].value = 0.8const parameters = {elevation: 2,azimuth: 180}const pmremGenerator = new THREE.PMREMGenerator(this.renderer)const phi = THREE.MathUtils.degToRad(90 - parameters.elevation)const theta = THREE.MathUtils.degToRad(parameters.azimuth)const sun = new THREE.Vector3()sun.setFromSphericalCoords(1, phi, theta)this.sky.material.uniforms['sunPosition'].value.copy(sun)},

添加模型的點擊事件

onMouseClick(event) {const mouse = new THREE.Vector2()mouse.x = (event.clientX / this.viewNode.clientWidth) * 2 - 1mouse.y = -(event.clientY / this.viewNode.clientHeight) * 2 + 1const raycaster = new THREE.Raycaster()raycaster.setFromCamera(mouse, this.camera)console.log(';點擊了模型上的某一個點點擊了模型上的某一個點點擊了模型上的某一個點');const intersects = raycaster.intersectObjects(this.scene.children, true)if (intersects.length > 0) {console.log(';點擊了模型上的某一個點點擊了模型上的某一個點點擊了模型上的某一個點');const baifenDom = document.querySelector('.baifen')const intersect = intersects[0]console.log(intersect,'intersect-*-*-*--*');// if (intersect.object.type === this.model) {if (intersect.object.type === "Mesh" && intersect.object.parent.type === "Group") {console.log(this.icondom,'icon-*-*-*--*');console.log(this.divdom,'divdivdiv-*-*-*--*');//  // 清除上一次點擊的所有操作this.icondom&&this.scene.remove(this.icondom);this.divdom&&baifenDom.removeChild(this.divdom)// 創建icon圖標const iconGeometry = new THREE.SphereGeometry(0.5, 60, 60);const iconMaterial = new THREE.MeshBasicMaterial({ color: 0xffff00 });this.icondom = new THREE.Mesh(iconGeometry, iconMaterial);this.icondom.position.set(intersect.point.x, intersect.point.y, intersect.point.z);this.scene.add(this.icondom);console.log( intersect,'baifenDombaifenDom');this.divdom = document.createElement('div')this.divdom.style.position = 'absolute'this.divdom.style.width = '200px'this.divdom.style.height = '200px'this.divdom.style.backgroundColor = 'rgba(0, 0, 0, 0.5)'this.divdom.style.color = 'white'this.divdom.style.padding = '10px'this.divdom.style.borderRadius = '5px'this.divdom.style.zIndex = '1000'this.divdom.style.top = `${event.clientY}px`this.divdom.style.left = `${event.clientX}px`this.divdom.innerHTML = `點擊了模型上的某一個點,位置為: (${intersect.point.x}, ${intersect.point.y}, ${intersect.point.z})`baifenDom.appendChild(this.divdom)// 調整相機位置以拉近模型// this.camera.position.set(intersect.point.x, intersect.point.y, intersect.point.z + 10); // 將相機位置設置為點擊點的位置,并在z軸上偏移10單位以拉近模型// this.camera.lookAt(intersect.point); // 讓相機看向點擊點}}},

完整代碼

<template><div class="contente"><div class="baifen"><div class="app-wrap" ref="view"></div></div></div>
</template><script>
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import { Water } from 'three/examples/jsm/objects/Water.js'
import { Sky } from 'three/examples/jsm/objects/Sky.js'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
// 導入glb模型
// const gltfModel = './models/dapeng2.glb' // 改為使用公共路徑export default {name: 'MineTd',data() {return {viewNode: null,animationId: null,scene: null,camera: null,renderer: null,controls: null,water: null,sky: null,model: null,mixer: null, // 用于動畫混合器moveForward: false,moveBackward: false,moveLeft: false,moveRight: false,moveSpeed: 0.05, // 相機移動速度icondom: null,divdom: null,}},mounted() {this.$nextTick(() => {this.initScene()this.animate()})window.addEventListener('resize', this.onWindowResize)document.addEventListener('keydown', this.onKeyDown)document.addEventListener('keyup', this.onKeyUp)this.$refs.view.addEventListener('click', this.onMouseClick)},methods: {initScene() {this.viewNode = this.$refs.view// 創建場景this.scene = new THREE.Scene()// 創建相機this.camera = new THREE.PerspectiveCamera(45,this.viewNode.clientWidth / this.viewNode.clientHeight,1,9999999)// // 調整相機位置this.camera.position.set(600, 800, 1000)this.camera.lookAt(0, 0, 0)// 創建渲染器this.renderer = new THREE.WebGLRenderer({ antialias: true,alpha: true })this.renderer.setSize(this.viewNode.clientWidth, this.viewNode.clientHeight)this.renderer.setPixelRatio(window.devicePixelRatio)this.renderer.shadowMap.enabled = true // 啟用陰影this.viewNode.appendChild(this.renderer.domElement)// 添加軌道控制器this.controls = new OrbitControls(this.camera, this.renderer.domElement)this.controls.enableDamping = truethis.controls.dampingFactor = 0.05this.controls.maxPolarAngle = Math.PI * 0.45this.controls.minPolarAngle = Math.PI * 0.1this.controls.minDistance = 5this.controls.maxDistance = 30this.controls.enableRotate = false // 禁止相機旋轉this.controls.enableZoom = false // 禁止相機縮放this.controls.enablePan = false // 禁止相機平移this.initLights()this.initWater()this.initSky()this.loadGLTFModel()},initLights() {// 環境光const ambientLight = new THREE.AmbientLight(0xffffff, 0.6)this.scene.add(ambientLight)// 平行光const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8)directionalLight.position.set(10, 10, 10)directionalLight.castShadow = true // 啟用陰影投射this.scene.add(directionalLight)},initWater() {const waterGeometry = new THREE.PlaneGeometry(100, 100)this.water = new Water(waterGeometry, {textureWidth: 512,textureHeight: 512,waterNormals: new THREE.TextureLoader().load('https://threejs.org/examples/textures/waternormals.jpg',texture => {texture.wrapS = texture.wrapT = THREE.RepeatWrapping}),alpha: 1.0,waterColor: 0x001e0f,distortionScale: 3.7,fog: this.scene.fog !== undefined,depth: 10,flowDirection: new THREE.Vector2(1, 0.1),scale: 4.0})this.water.rotation.x = -Math.PI / 2this.water.receiveShadow = true // 接收陰影this.water.name = 'water' // 設置namethis.scene.add(this.water)},initSky() {this.sky = new Sky()this.sky.name='sky'this.sky.scale.setScalar(999999) // 調整天空盒子的大小this.scene.add(this.sky)const skyUniforms = this.sky.material.uniformsskyUniforms['turbidity'].value = 10skyUniforms['rayleigh'].value = 2skyUniforms['mieCoefficient'].value = 0.005skyUniforms['mieDirectionalG'].value = 0.8const parameters = {elevation: 2,azimuth: 180}const pmremGenerator = new THREE.PMREMGenerator(this.renderer)const phi = THREE.MathUtils.degToRad(90 - parameters.elevation)const theta = THREE.MathUtils.degToRad(parameters.azimuth)const sun = new THREE.Vector3()sun.setFromSphericalCoords(1, phi, theta)this.sky.material.uniforms['sunPosition'].value.copy(sun)},loadGLTFModel() {const loader = new GLTFLoader()const loadingManager = new THREE.LoadingManager()// 加載管理器loadingManager.onProgress = (url, loaded, total) => {const progress = (loaded / total * 100).toFixed(2)console.log(`加載進度: ${progress}%`)}// 加載GLB模型loader.load("/models/dapeng2.gltf", // 修改為.glb文件(gltf) => {this.model = gltf.scenethis.model.name = 'dapeng'// 遍歷模型網格啟用陰影this.model.traverse((node) => {if (node.isMesh) {node.castShadow = truenode.receiveShadow = true}})// 調整模型位置和大小this.model.position.set(0, 1, 0) // 將模型位置調整到相機的正下方this.model.scale.set(0.2, 0.2, 0.2)// 將模型添加到場景this.scene.add(this.model)// 處理動畫if (gltf.animations && gltf.animations.length) {this.mixer = new THREE.AnimationMixer(this.model)gltf.animations.forEach((clip) => {const action = this.mixer.clipAction(clip)action.play()})}const bbox = new THREE.Box3().setFromObject(this.model);
const center = bbox.getCenter(new THREE.Vector3());
// this.camera.position.set(center.x+1000, center.y+1000, center.z+600);
// this.camera.lookAt(scene.position); // 讓相機看向場景中心},(xhr) => {console.log(`模型加載中: ${(xhr.loaded / xhr.total * 100)}%`)},(error) => {console.error('模型加載失敗:', error)this.$message.error('模型加載失敗,請檢查模型文件是否存在')})},animate() {this.animationId = requestAnimationFrame(this.animate)// 更新水面動畫if (this.water) {this.water.material.uniforms['time'].value += 1.0 / 60.0}// 更新模型動畫if (this.mixer) {this.mixer.update(0.016) // 假設60fps}this.controls.update()this.renderer.render(this.scene, this.camera)// 根據鍵盤輸入移動相機if (this.moveForward) {this.camera.position.z -= this.moveSpeed}if (this.moveBackward) {this.camera.position.z += this.moveSpeed}if (this.moveLeft) {this.camera.position.x -= this.moveSpeed}if (this.moveRight) {this.camera.position.x += this.moveSpeed}},onMouseClick(event) {const mouse = new THREE.Vector2()mouse.x = (event.clientX / this.viewNode.clientWidth) * 2 - 1mouse.y = -(event.clientY / this.viewNode.clientHeight) * 2 + 1const raycaster = new THREE.Raycaster()raycaster.setFromCamera(mouse, this.camera)console.log(';點擊了模型上的某一個點點擊了模型上的某一個點點擊了模型上的某一個點');const intersects = raycaster.intersectObjects(this.scene.children, true)if (intersects.length > 0) {console.log(';點擊了模型上的某一個點點擊了模型上的某一個點點擊了模型上的某一個點');const baifenDom = document.querySelector('.baifen')const intersect = intersects[0]console.log(intersect,'intersect-*-*-*--*');// if (intersect.object.type === this.model) {if (intersect.object.type === "Mesh" && intersect.object.parent.type === "Group") {console.log(this.icondom,'icon-*-*-*--*');console.log(this.divdom,'divdivdiv-*-*-*--*');//  // 清除上一次點擊的所有操作this.icondom&&this.scene.remove(this.icondom);this.divdom&&baifenDom.removeChild(this.divdom)// 創建icon圖標const iconGeometry = new THREE.SphereGeometry(0.5, 60, 60);const iconMaterial = new THREE.MeshBasicMaterial({ color: 0xffff00 });this.icondom = new THREE.Mesh(iconGeometry, iconMaterial);this.icondom.position.set(intersect.point.x, intersect.point.y, intersect.point.z);this.scene.add(this.icondom);console.log( intersect,'baifenDombaifenDom');this.divdom = document.createElement('div')this.divdom.style.position = 'absolute'this.divdom.style.width = '200px'this.divdom.style.height = '200px'this.divdom.style.backgroundColor = 'rgba(0, 0, 0, 0.5)'this.divdom.style.color = 'white'this.divdom.style.padding = '10px'this.divdom.style.borderRadius = '5px'this.divdom.style.zIndex = '1000'this.divdom.style.top = `${event.clientY}px`this.divdom.style.left = `${event.clientX}px`this.divdom.innerHTML = `點擊了模型上的某一個點,位置為: (${intersect.point.x}, ${intersect.point.y}, ${intersect.point.z})`baifenDom.appendChild(this.divdom)// 調整相機位置以拉近模型// this.camera.position.set(intersect.point.x, intersect.point.y, intersect.point.z + 10); // 將相機位置設置為點擊點的位置,并在z軸上偏移10單位以拉近模型// this.camera.lookAt(intersect.point); // 讓相機看向點擊點}}},onKeyDown(event) {switch (event.key) {case 'w':this.moveForward = truebreakcase 's':this.moveBackward = truebreakcase 'a':this.moveLeft = truebreakcase 'd':this.moveRight = truebreak}},onKeyUp(event) {switch (event.key) {case 'w':this.moveForward = falsebreakcase 's':this.moveBackward = falsebreakcase 'a':this.moveLeft = falsebreakcase 'd':this.moveRight = falsebreak}},onWindowResize() {if (this.viewNode) {this.camera.aspect = this.viewNode.clientWidth / this.viewNode.clientHeightthis.camera.updateProjectionMatrix()this.renderer.setSize(this.viewNode.clientWidth, this.viewNode.clientHeight)}}},beforeDestroy() {window.removeEventListener('resize', this.onWindowResize)document.removeEventListener('keydown', this.onKeyDown)document.removeEventListener('keyup', this.onKeyUp)if (this.animationId) {cancelAnimationFrame(this.animationId)}if (this.scene) {this.scene.clear()}if (this.renderer) {this.renderer.dispose()this.renderer.forceContextLoss()this.renderer.content = null}if (this.mixer) {this.mixer.stopAllAction()}}
}
</script><style lang="scss" scoped>
.contente {width: 100%;height: 100%;position: relative;.baifen {background: #fff;height: 100%;position: relative;.app-wrap {width: 100%;height: 100%;position: relative;overflow: hidden;}}
}
</style>

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/67045.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/67045.shtml
英文地址,請注明出處:http://en.pswp.cn/web/67045.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

汽車免拆診斷案例 | 2007 款日產天籟車起步加速時偶爾抖動

故障現象  一輛2007款日產天籟車&#xff0c;搭載VQ23發動機&#xff08;氣缸編號如圖1所示&#xff0c;點火順序為1-2-3-4-5-6&#xff09;&#xff0c;累計行駛里程約為21萬km。車主反映&#xff0c;該車起步加速時偶爾抖動&#xff0c;且行駛中加速無力。 圖1 VQ23發動機…

對神經網絡基礎的理解

目錄 一、《python神經網絡編程》 二、一些粗淺的認識 1&#xff09; 神經網絡也是一種擬合 2&#xff09;神經網絡不是真的大腦 3&#xff09;網絡構建需要反復迭代 三、數字圖像識別的實現思路 1&#xff09;建立一個神經網絡類 2&#xff09;權重更新的具體實現 3&am…

新項目傳到git步驟

1.首先創建遠程倉庫,創建一個空白項目,即可生成一個克隆URL,可以是http也可以是SSH,copy下這個地址 2.找到項目的本機目錄,進入根目錄,打開git bash here命令行 3.初始化: git init 4.關聯遠程地址: git remote add origin "遠程倉庫的URL" 5.查看關聯 git re…

PAT甲級-1024 Palindromic Number

題目 題目大意 一個非回文數&#xff0c;加上它的翻轉數所得的和&#xff0c;進行k次&#xff0c;有可能會得到一個回文數。給出一個數n&#xff0c;限制相加次數為k次&#xff0c;如果小于k次就得到回文數&#xff0c;那么輸出該回文數和相加的次數&#xff1b;如果進行k次還…

appium自動化環境搭建

一、appium介紹 appium介紹 appium是一個開源工具、支持跨平臺、用于自動化ios、安卓手機和windows桌面平臺上面的原生、移動web和混合應用&#xff0c;支持多種編程語言(python&#xff0c;java&#xff0c;Ruby&#xff0c;Javascript、PHP等) 原生應用和混合應用&#xf…

C#高級:常用的擴展方法大全

1.String public static class StringExtensions {/// <summary>/// 字符串轉List&#xff08;中逗 英逗分隔&#xff09;/// </summary>public static List<string> SplitCommaToList(this string data){if (string.IsNullOrEmpty(data)){return new List&…

【Numpy核心編程攻略:Python數據處理、分析詳解與科學計算】1.1 從零搭建NumPy環境:安裝指南與初體驗

1. 從零搭建NumPy環境&#xff1a;安裝指南與初體驗 NumPy核心能力圖解&#xff08;架構圖&#xff09; NumPy 是 Python 中用于科學計算的核心庫&#xff0c;它提供了高效的多維數組對象以及用于處理這些數組的各種操作。NumPy 的核心能力可以概括為以下幾個方面&#xff1a…

【SpringBoot教程】Spring Boot + MySQL + HikariCP 連接池整合教程

&#x1f64b;大家好&#xff01;我是毛毛張! &#x1f308;個人首頁&#xff1a; 神馬都會億點點的毛毛張 在前面一篇文章中毛毛張介紹了SpringBoot中數據源與數據庫連接池相關概念&#xff0c;今天毛毛張要分享的是關于SpringBoot整合HicariCP連接池相關知識點以及底層源碼…

Java進階(一)

目錄 一.Java注解 什么是注解&#xff1f; 內置注解 元注解 二.對象克隆 什么是對象克隆? 為什么用到對象克隆 三.淺克隆深克隆 一.Java注解 什么是注解&#xff1f; java中注解(Annotation)又稱java標注&#xff0c;是一種特殊的注釋。 可以添加在包&#xff0c;類&…

【PyCharm】將包含多個參數的 shell 腳本配置到執行文件來調試 Python 程序

要配置 PyCharm 以使用包含多個參數的 shell 腳本&#xff08;如 run.sh&#xff09;來調試 Python 程序&#xff0c;您可以按照以下步驟操作&#xff1a; 創建一個新的運行/調試配置&#xff1a; 在 PyCharm 中&#xff0c;點擊“運行”菜單旁邊的齒輪圖標&#xff0c;選擇“…

即夢(Dreamina)技術淺析(二):后端AI服務

1. 文本處理(Text Processing) 1.1 功能概述 文本處理模塊的主要任務是將用戶輸入的文字提示詞轉換為機器可以理解的向量表示。這一過程包括分詞、詞嵌入和語義編碼,旨在捕捉文本的語義信息,為后續的圖像和視頻生成提供準確的指導。 1.2 關鍵技術 1.分詞(Tokenization…

藍橋杯之c++入門(一)【第一個c++程序】

目錄 前言一、第?個C程序1.1 基礎程序1.2 main函數1.3 字符串1.4 頭文件1.5 cin 和 cout 初識1.6 名字空間1.7 注釋 二、四道簡單習題&#xff08;點擊跳轉鏈接&#xff09;練習1&#xff1a;Hello,World!練習2&#xff1a;打印飛機練習3&#xff1a;第?個整數練習4&#xff…

【C++初階】第11課—vector

文章目錄 1. 認識vector2. vector的遍歷3. vector的構造4. vector常用的接口5. vector的容量6. vector的元素訪問7. vector的修改8. vector<vector\<int\>>的使用9. vector的使用10. 模擬實現vector11. 迭代器失效11.1 insert插入數據內部迭代器失效11.2 insert插入…

【AIGC學習筆記】扣子平臺——精選有趣應用,探索無限可能

背景介紹&#xff1a; 由于近期業務發展的需求&#xff0c;我開始接觸并深入了解了扣子平臺的相關知識&#xff0c;并且通過官方教程自學了簡易PE工作流搭建的技巧。恰逢周會需要準備與工作相關的分享主題&#xff0c;而我作為一個扣子平臺的初學者&#xff0c;也想探索一下這…

mysql 學習6 DML語句,對數據庫中的表進行 增 刪 改 操作

添加數據 我們對 testdatabase 數據中 的 qqemp 這張表進行 增加數據&#xff0c;在這張表 下 打開 命令行 query console 在 軟件中就是打開命令行的意思 可以先執行 desc qqemp; 查看一下當前表的結構。 插入一條數據 到qqemp 表&#xff0c;插入時要每個字段都有值 insert…

Java Web-Request與Response

在 Java Web 開發中&#xff0c;Request 和 Response 是兩個非常重要的對象&#xff0c;用于在客戶端和服務器之間進行請求和響應的處理&#xff0c;以下是詳細介紹&#xff1a; Request&#xff08;請求對象&#xff09; Request繼承體系 在 Java Web 開發中&#xff0c;通…

李沐vscode配置+github管理+FFmpeg視頻搬運+百度API添加翻譯字幕

終端輸入nvidia-smi查看cuda版本 我的是12.5&#xff0c;在網上沒有找到12.5的torch&#xff0c;就安裝12.1的。torch&#xff0c;torchvision&#xff0c;torchaudio版本以及python版本要對應 參考&#xff1a;https://blog.csdn.net/FengHanI/article/details/135116114 創…

論文閱讀(十六):利用線性鏈條件隨機場模型檢測陣列比較基因組雜交數據的拷貝數變異

1.論文鏈接&#xff1a;Detection of Copy Number Variations from Array Comparative Genomic Hybridization Data Using Linear-chain Conditional Random Field Models 摘要&#xff1a; 拷貝數變異&#xff08;CNV&#xff09;約占人類基因組的12%。除了CNVs在癌癥發展中的…

Alibaba Spring Cloud 十三 Nacos,Gateway,Nginx 部署架構與負載均衡方案

在微服務體系中&#xff0c;Nacos 主要承擔“服務注冊與發現、配置中心”的職能&#xff0c;Gateway&#xff08;如 Spring Cloud Gateway&#xff09;通常負責“路由轉發、過濾、安全鑒權、灰度流量控制”等功能&#xff0c;而 Nginx 則常被用作“邊緣反向代理”或“統一流量入…

Next.js 實戰 (十):中間件的魅力,打造更快更安全的應用

什么是中間件&#xff1f; 在 Next.js 中&#xff0c;中間件&#xff08;Middleware&#xff09;是一種用于處理每個傳入請求的功能。它允許你在請求到達頁面之前對其進行修改或響應。 通過中間件&#xff0c;你可以實現諸如日志記錄、身份驗證、重定向、CORS配置、壓縮等任務…