共计 4455 个字符,预计需要花费 12 分钟才能阅读完成。
onMouseClick()办法实现射线拾取
创立模型的时候能够将 mesh 的 group 特地提出来
gltf.scene.traverse((child) => {if (child.isGroup) {
child.name = 'dikuai'
this.groups.push(child);
}
});
上面是残缺代码👇👇
<template>
<div class="main-3d">
<div id="scene-container" ref="sceneContainer"></div>
<div class="tool-box">
<div class="tool-site flexC" @click="show"> 隐身 </div>
<div class="tool-site flexC" @click="isRotate=!isRotate"> 旋转 </div>
</div>
</div>
</template>
<script>
import * as THREE from 'three'
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls'
import {GLTFLoader} from 'three/examples/jsm/loaders/GLTFLoader'
export default {
name: 'HelloWorld',
data () {
return {
container: null,
scene: null,
camera: null,
controls: null,
renderer: null,
stats: null,
models:null,
isRotate:false,
groups:[]}
},
methods: {onMouseClick() {
let that = this;
debugger
function onMouseClick(event) {let a = document.getElementsByTagName("canvas")
var canvas
for(let i of a){if(i.parentElement&&i.parentElement.id&&i.parentElement.id =="scene-container"){canvas = i}
}
let x =
((event.clientX - canvas.getBoundingClientRect().left) /
canvas.offsetWidth) *
2 -
1; // 规范设施横坐标
// 这里的 mainCanvas 是个 dom 元素,getBoundingClientRectangle 会返回以后元素的视口大小.
let y =
-((event.clientY - canvas.getBoundingClientRect().top) /
canvas.offsetHeight
) *
2 +
1; // 规范设施纵坐标
let standardVector = new THREE.Vector3(x, y, 1); // 规范设施坐标
// 规范设施坐标转世界坐标
let worldVector = standardVector.unproject(that.camera);
// 射线投射方向单位向量(worldVector 坐标减相机地位坐标)
let ray = worldVector.sub(that.camera.position).normalize();
// 创立射线投射器对象
let raycaster = new THREE.Raycaster(that.camera.position, ray);
// 获取 raycaster 直线和所有模型相交的数组汇合
var intersects = raycaster.intersectObjects(that.scene.children, true);
if (intersects.length > 0) {console.log(1);
}
}
// 这个中央肯定用 renderer.domElement 千万别用 window!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!坑
that.renderer.domElement.addEventListener("click", onMouseClick, false);
},
show(){},
hide(){let a = this.groups.find( item => item.name=='dikuai')
a.children.forEach(element => {
element.material.transparent = true
element.material.opacity = 0
});
},
init () {
// set container
this.container = this.$refs.sceneContainer
// add stats
// add camera
const fov = 60 // Field of view
const aspect = this.container.clientWidth / this.container.clientHeight
const near = 20 // the near clipping plane
const far = 300 // the far clipping plane
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far)
camera.position.set(0, 50, 100)
this.camera = camera
// create scene
this.scene = new THREE.Scene()
this.scene.background = new THREE.Color('skyblue')
var hemiLight = new THREE.HemisphereLight(0xffff55, 0x00ffff, 0.6);
hemiLight.position.set(0,-100,0)
var helper = new THREE.HemisphereLightHelper(hemiLight, 5);
this.scene.add(helper);
const mainLight = new THREE.DirectionalLight(0xffffff, 4.0)
mainLight.position.set(10, 50, 10)
this.scene.add(mainLight,hemiLight)
const mainLight2 = new THREE.DirectionalLight(0xffffff, 4.0)
mainLight2.position.set(-10, -50, -10)
this.scene.add(mainLight2,hemiLight)
// add controls
this.controls = new OrbitControls(this.camera, this.container)
// create renderer
this.renderer = new THREE.WebGLRenderer({antialias: true})
this.renderer.setSize(this.container.clientWidth, this.container.clientHeight)
this.renderer.setPixelRatio(window.devicePixelRatio)
this.renderer.gammaFactor = 2.2
this.renderer.outputEncoding = THREE.sRGBEncoding
this.renderer.physicallyCorrectLights = true
this.container.appendChild(this.renderer.domElement)
// set aspect ratio to match the new browser window aspect ratio
this.camera.aspect = this.container.clientWidth / this.container.clientHeight
this.camera.updateProjectionMatrix()
this.renderer.setSize(this.container.clientWidth, this.container.clientHeight)
const loader = new GLTFLoader()
loader.load(
'/glb/aaa.glb',
gltf => {
debugger
this.models = gltf.scene
this.scene.add(this.models)
gltf.scene.traverse((child) => {if (child.isGroup) {
child.name = 'dikuai'
this.groups.push(child);
}
});
console.log(this.groups);
},
undefined,
undefined
)
this.renderer.setAnimationLoop(() => {this.rotate()
this.render()})
},
render () {this.renderer.render(this.scene, this.camera)
},
rotate() {if(!this.isRotate){return false}
// this.models.rotation.z += 0.01;
// this.models.rotation.x += 0.01;
// this.models.rotation.y += 0.01;
this.models.rotateY(0.01);
}
},
mounted () {this.init()
this.onMouseClick()}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
.main-3d{
width: 100%;
height: 100%;
.tool-box{
position: fixed;
bottom: 10px;
right: 10px;
.tool-site{
width: 48px;
height: 36px;
background: red;
cursor: pointer;
}
}
}
h3 {margin: 40px 0 0;}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {color: #42b983;}
#scene-container {height: 100%;}
</style>
正文完