当前位置: 首页 > news >正文

threejs:射线拾取封装

射线拾取封装代码:

import * as THREE from 'three';
// 点击事件

// 1.坐标转化(鼠标单击的屏幕坐标转标准设备坐标)

// 2.射线计算(通过鼠标单击位置+相机参数计算射线值)

// 3.射线交叉计算

// ObjectsArr是用来做射线拾取的对象数组,一个二维数组
export function rayChoose(event,width, height, camera, ObjectsArr) {
		// .offsetY、.offsetX以canvas画布左上角为坐标原点,单位px
		const px = event.offsetX;
		const py = event.offsetY;
		//屏幕坐标px、py转WebGL标准设备坐标x、y
		//width、height表示canvas画布宽高度
		const x = (px / width) * 2 - 1;
		const y = -(py / height) * 2 + 1;
		//创建一个射线投射器`Raycaster`
		const raycaster = new THREE.Raycaster();
		//.setFromCamera()计算射线投射器`Raycaster`的射线属性.ray
		// 形象点说就是在点击位置创建一条射线,射线穿过的模型代表选中
		raycaster.setFromCamera(new THREE.Vector2(x, y), camera);
		// 未选中对象返回空数组[],选中一个对象,数组1个元素,选中两个对象,数组两个元素
		const intersects = raycaster.intersectObjects(ObjectsArr);
		// intersects.length大于0说明,说明选中了模型
		let choosedObj = null;
		if (intersects.length > 0) {
			// 选中模型的第一个模型
			choosedObj = intersects[0].object;
		} else {
			choosedObj = null;
		}
		return choosedObj;
}

首先得获取射线拾取的对象集合,放在二位数组里,不同的模型,获取集合方式不同,具体要结合模型来写代码,提前跟建模师沟通好物体名称。

例如以下方法:

model.js

import * as THREE from 'three';
// 引入gltf模型加载库GLTFLoader.js
import {
	GLTFLoader
} from 'three/addons/loaders/GLTFLoader.js';

export const model = new THREE.Group();
const loader = new GLTFLoader();
export const granaryArr = []; //所有粮仓模型对象的集合,export导出用于射线拾取

loader.load("models/粮仓.glb", function(gltf) {
	//把gltf.scene中的所有模型添加到model组对象中
	model.add(gltf.scene);
	
	// 所有粮仓模型的父对象名称:'粮仓'
	const group = gltf.scene.getObjectByName('粮仓');
	//console.log('粮仓', group);
	group.traverse(function(obj) {
		if (obj.type === 'Mesh') {
			granaryArr.push(obj);
		}
	})
});

在vue文件里,rayChoose要放在addEventListener里使用。

index.vue

<template>
	<!-- 封装射线拾取案例 -->
</template>

<script setup>
	import {
		model,granaryArr
	} from './model.js'; //模型对象
	import {
		renderer,scene,camera,width,height
	} from './init.js';
	import {
		rayChoose
	} from '../../utils/rayChoose.js';
	scene.add(model); //模型对象添加到场景中
	renderer.domElement.addEventListener('click', function(event) {
		// choosedObj只能放在addEventListener内部使用
		const choosedObj = rayChoose(event, width,height,camera,granaryArr);
		console.log(choosedObj);
	})
</script>


<style>
</style>

获取到choosedObj后,可以对其进一步处理,比如高光描边,弹出一个信息框等等。

相关文章:

  • 计算机毕业设计 ——jspssm518Springboot 的影视影院订票选座管理系统
  • unity使用PICO Neo3开发,XR环境配置
  • 异常(2)
  • Java高频面试之SE-23
  • 27.[前端开发-JavaScript基础]Day04-函数基本使用-递归-变量作用域-函数式编程
  • 结构型模式 - 代理模式 (Proxy Pattern)
  • 利用python进行数据分析(重点、易忘点)---第八章数据规整:聚合、合并和重塑
  • Linux查看和处理文件内容
  • 【网络编程】网络套接字和使用案例
  • 数学与计算生物学:生物系统的数学建模
  • vs code默认主题修改配置
  • 大白话JavaScript如何深拷贝一个对象或数组?JSON.parse (JSON.stringify ()) 这种方法有什么局限性?
  • ss命令——查看网络连接信息
  • vue+qrcode2批量生成二维码
  • 【Python爬虫(74)】用Python爬虫解锁法律条文数据的宝库
  • C语言 --- 经典习题1
  • 使用 C# 以api的形式调用 DeepSeek
  • 千峰React:案例一
  • IDEA 使用codeGPT+deepseek
  • 绕过【information_schema】,【order by】过滤
  • 做像淘宝网的网站/企业如何进行网络推广
  • 农村电商网站建设方案/电脑版百度入口
  • 南昌有做网站的吗/网站优化及推广
  • 珠海华中建设工程有限公司网站/百度推广代理公司广州
  • 美食 网站模板/优化设计答案
  • 网站建设公司是干嘛的/一键建站