vue集成three.js加載外部模型

版本號:
vue:2.6.10
vue-cli3.x
three.js:0.115.0
引入方式:
import * as THREE from 'three'
import Stats from 'stats.js'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
import { STLLoader } from 'three/examples/jsm/loaders/STLLoader'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
模型目錄:在這裏插入圖片描述
.glb經過了webpack的處理,需要把.obj文件放到vue中處理靜態文件的文件夾中,在vue-cli3中public文件夾下的文件不需要經過webpack處理,在vue-cli3.0之前就是放在static靜態文件文件夾下,在vue-cli3.0中需要放在public文件夾下,並且在組件中通過process.env.BASE_URL+public文件夾下的.obj文件的路徑來引用。
組件引用:
通過全局process.env.BASE_URL直接引入及可`${process.env.BASE_URL}model/Soldier.glb`
this.gltfLoader.load(
            `${process.env.BASE_URL}model/Soldier.glb`,
            gltf => {
                alert('11')
                gltf.scene.name = 'Soldier'
                gltf.scene.rotation.y = Math.PI
                this.scene.add(gltf.scene)
                this.treeData = [gltf.scene]
                this.scene.add(new AmbientLight(0xffffff, 2))

                this.orbitControls.target.set(0, 1, 0)

                const animationClip = gltf.animations.find(
                    animationClip => animationClip.name === 'Walk'
                )
                this.walkAction = this.animationMixer.clipAction(
                    animationClip
                )
                this.walkAction.play()
            }
        )
其他:
贈送一個官方的glb格式的文件
http://www.webgl3d.cn/threejs/examples/models/gltf/Soldier.glb
附上代碼
<template>
    <div>
        <el-row>
            <el-col :span="5" class="left-trees">
            </el-col>
            <el-col :span="19">
                <div id="container"></div>
            </el-col>
        </el-row>
    </div>
</template>
 
<script>
import * as THREE from 'three'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
import { STLLoader } from 'three/examples/jsm/loaders/STLLoader'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'

export default {
    name: 'ThreeTest',
    data() {
        return {
        }
    },
    methods: {
        init() {
            this.scene = new THREE.Scene()
            this.clock = new THREE.Clock()
            this.camera = new THREE.PerspectiveCamera(
                75,
                window.innerWidth / window.innerHeight,
                0.1,
                100
            )
            console.log(Twidth, Theight)

            this.renderer = new THREE.WebGLRenderer({ antialias: true })
            this.gltfLoader = new GLTFLoader()
            this.stlLoader = new STLLoader()
            this.orbitControls = new OrbitControls(
                this.camera,
                this.renderer.domElement
            )
            this.animationMixer = new THREE.AnimationMixer(this.scene)

            this.renderer.setSize(window.innerWidth, window.innerHeight)

            // document.body.appendChild(this.renderer.domElement)
            document
                .getElementById('container')
                .appendChild(this.renderer.domElement)
            window.addEventListener('resize', () => this.onWindowResize())

            this.camera.position.set(-0.5, 2, 1)
            const planeBufferGeometry = new THREE.PlaneBufferGeometry(80, 80)
            const plane = new THREE.Mesh(
                planeBufferGeometry,
                new THREE.MeshBasicMaterial({
                    color: 0xffffff,
                    side: THREE.DoubleSide
                })
            )
            plane.name = 'plane'
            plane.rotation.x = -Math.PI / 2
            this.scene.add(plane)
            this.scene.add(new THREE.GridHelper(10, 10))

            this.gltfLoader.load(
                `${process.env.BASE_URL}model/Soldier.glb`,
                gltf => {
                    gltf.scene.name = 'Soldier'
                    gltf.scene.rotation.y = Math.PI
                    this.scene.add(gltf.scene)
                    this.treeData = [gltf.scene]
                    this.scene.add(new THREE.AmbientLight(0xffffff, 2))

                    this.orbitControls.target.set(0, 1, 0)

                    const animationClip = gltf.animations.find(
                        animationClip => animationClip.name === 'Walk'
                    )
                    this.walkAction = this.animationMixer.clipAction(
                        animationClip
                    )
                    this.walkAction.play()
                }
            )
            this.renderer.domElement.addEventListener('click', event => {
                const { offsetX, offsetY } = event
                const x = (offsetX / window.innerWidth) * 2 - 1
                const y = -(offsetY / window.innerHeight) * 2 + 1
                const mousePoint = new THREE.Vector2(x, y)
                const raycaster = new THREE.Raycaster()
                // 設置鼠標位置和參考相機
                raycaster.setFromCamera(mousePoint, this.camera)
                // 鼠標點擊對應的物體(所有鼠標映射到的物體,包括被遮擋的)
                const intersects = raycaster.intersectObjects(
                    this.scene.children,
                    true
                )
                // console.log(intersects)

                // 過濾網格和地面
                const intersect = intersects.filter(
                    intersect =>
                        !(intersect.object instanceof THREE.GridHelper) &&
                        intersect.object.name !== 'plane'
                )[0]
                if (intersect && this.isClickSoldier(intersect.object)) {
                    // 停止動畫
                    // this.walkAction.stop();
                    // 暫停動畫
                    this.walkAction.paused = !this.walkAction.paused
                    console.log(intersect)

                    intersect.object.material.color.set(0xff0000)
                }
            })
            this.render()
        },
        isClickSoldier(object) {
            if (object.name === 'Soldier') {
                return object
            } else if (object.parent) {
                return this.isClickSoldier(object.parent)
            } else {
                return null
            }
        },

        render() {
            // 更新動畫
            this.animationMixer.update(this.clock.getDelta())

            this.renderer.render(this.scene, this.camera)

            this.orbitControls.update()
            window.requestAnimationFrame(() => this.render())
            // this.stats.update()
        },

        onWindowResize() {
            this.renderer.setSize(window.innerWidth, window.innerHeight)
            this.camera.aspect = window.innerWidth / window.innerHeight
            this.camera.updateProjectionMatrix()
        },
     
    },
    mounted() {
        this.init()
    }
}
</script>
<style >
#container {
    height: 400px;
}
</style>
還在摸索中可以交流哈
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章