three.js Raycaster(鼠标点击选中模型)

效果:

代码:

<template><div><el-container><el-main><div class="box-card-left"><div id="threejs" style="border: 1px solid red"></div><div class="box-right" style="text-align: left; padding: 10px"><div style="text-align: left">标准设备坐标系:</div><div>three.js Canvas画布具有一个标准设备坐标系,该坐标系的坐标原点是在canvas画布的中间位置,x轴水平向右,y轴竖直向上,标准设备坐标系的坐标值不是绝对值,是相对值,范围是[-1,1],也就是说canvas画布上任何一个位置的坐标,如果用标准设备坐标取衡量,那么坐标的所有值都在-1和 1之间;</div><div style="text-align: left; margin-top: 10px">屏幕坐标转为 标准设备坐标:</div><div style="text-align: left"><pre>// 坐标转化公式addEventListener('click',function(event){const px = event.offsetX;const py = event.offsetY;//屏幕坐标px、py转标准设备坐标x、y//width、height表示canvas画布宽高度const x = (px / width) * 2 - 1;const y = -(py / height) * 2 + 1;})</pre></div></div></div></el-main></el-container></div>
</template>
<script>
// 引入轨道控制器扩展库OrbitControls.js
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
// 效果制作器
import { EffectComposer } from "three/examples/jsm/postprocessing/EffectComposer.js";
// 渲染通道
import { RenderPass } from "three/examples/jsm/postprocessing/RenderPass.js";
// 发光描边OutlinePass
import { OutlinePass } from "three/examples/jsm/postprocessing/OutlinePass.js";export default {data() {return {name: "",scene: null,camera: null,renderer: null,effectComposer: null,mesh: null,geometry: null,group: null,material: null,texture: null,position: null,outlinePass: null,canvasWidth: 1000,canvasHeight: 800,color: [],meshArr: [],};},created() {},mounted() {this.name = this.$route.query.name;const numbers = Array.from({ length: 255 }, (_, i) => i);// const uppercaseLetters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');this.color = [...numbers];this.init();},methods: {goBack() {this.$router.go(-1);},addEventListenerFn() {// canvas画布添加监听事件document.getElementById("threejs").addEventListener("click", (event) => {// 1,坐标转换const point_x = event.offsetX; // 获取x方向当前点击点距离原点的距离;向右为正(原点是当前元素的左上角点)const point_y = event.offsetY; // 获取y方向当前点击点距离原点的距离;向下为正(原点是当前元素的左上角点)const x = (point_x / this.canvasWidth) * 2 - 1;const y = -(point_y / this.canvasHeight) * 2 + 1;// 2,创建射线投射器对象,const raycaster = new this.$three.Raycaster();// 3,射线计算,(参数是鼠标点击位置,相机参数)raycaster.setFromCamera(new this.$three.Vector2(x, y), this.camera);// 4,射线交叉计算// const mesh_arr = []// if(!this.scene)return;// this.scene.traverse(m => {//   console.log('m',m);//   if(m.isMesh != undefined && m.isMesh) {//     mesh_arr.push(m);//   }// })const intersects = raycaster.intersectObjects(this.meshArr);if (intersects.length > 0) {if (this.effectComposer) {// intersects[0].object.material.color.set(0xff0000);this.outlinePass.selectedObjects = [intersects[0].object];this.renderFun();}}});},// 随机颜色randomColor() {// 要生成min-max之间的随机数,公式为:Math.random()*(max-min+1)+minlet i = Math.floor(Math.random() * (this.color.length - 0 + 1) + 0);let j = Math.floor(Math.random() * (this.color.length - 0 + 1) + 0);let k = Math.floor(Math.random() * (this.color.length - 0 + 1) + 0);this.position = new this.$three.Vector3(i, j, k);return new this.$three.Color("rgb(" +this.color[i] +", " +this.color[j] +", " +this.color[k] +")");},init() {// 创建场景对象this.scene = new this.$three.Scene();// 创建立方缓存几何体对象for (let i = 0; i < 3; i++) {this.boxGeometry();}// 创建辅助坐标轴对象const axesHelper = new this.$three.AxesHelper(200);this.scene.add(axesHelper);// 创建正交投影相机对象// this.camera = new this.$three.PerspectiveCamera(60,1,0.01,1000);// this.camera.position.set(600,600,600);// this.camera.lookAt(0,0,0);// 创建透视投影相机对象this.camera = new this.$three.OrthographicCamera(-500,500,400,-400,0,1000);this.camera.position.set(200, 200, 200);this.camera.lookAt(0, 0, 0);// const helper = new this.$three.CameraHelper( this.camera );// this.scene.add( helper );// 创建渲染器对象this.renderer = new this.$three.WebGLRenderer();this.renderer.setSize(this.canvasWidth, this.canvasHeight);this.renderer.render(this.scene, this.camera);window.document.getElementById("threejs").appendChild(this.renderer.domElement);// 创建相机空间轨道控制器const controls = new OrbitControls(this.camera, this.renderer.domElement);controls.addEventListener("change", () => {// this.renderer.render(this.scene, this.camera);this.effectComposer.render();});// 调用后处理方法this.effectComposerFn();// 调用 监听  点击事件的方法this.addEventListenerFn();},// 创建盒模型的方法boxGeometry() {// 创建网格基础材质对象const material = new this.$three.MeshBasicMaterial({color: this.randomColor(),});// 创建立方几何体对象const geometry = new this.$three.BoxGeometry(this.position.x,this.position.y,this.position.z);// 创建网格模型对象const mesh = new this.$three.Mesh(geometry, material);if (this.position) {// 网格模型设置位置mesh.position.set(this.position.x, this.position.y, this.position.z);}this.meshArr.push(mesh);this.scene.add(mesh);},// 后处理方法effectComposerFn() {// 创建后处理对象this.effectComposer = new EffectComposer(this.renderer);// 创建后处理渲染器通道对象const renderPass = new RenderPass(this.scene, this.camera);// 后处理对象 添加渲染器通道this.effectComposer.addPass(renderPass);// 创建发光描边对象this.outlinePass = new OutlinePass(new this.$three.Vector2(this.canvasWidth, this.canvasHeight),this.scene,this.camera);// 设置发光描边颜色this.outlinePass.visibleEdgeColor.set(0xE0F409);// 设置发光描边厚度this.outlinePass.edgeThickness = 5;// 描边亮度this.outlinePass.edgeStrength = 20;// 设置发光描边频率this.outlinePass.pulsePeriod = 2;this.effectComposer.addPass(this.outlinePass);},renderFun() {// 调用后处理对象的render方法进行渲染,this.effectComposer.render();window.requestAnimationFrame(this.renderFun);},},
};
</script>
//
<style lang="less" scoped>
.box-card-left {display: flex;align-items: flex-start;flex-direction: row;width: 100%;.box-right {}
}
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/321074.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【模拟电路】非接触测电笔绘制、电子琴NE555

一、非接触测电笔原理图绘制 二、非接触测电笔PCB绘制 三、电子琴NE555制作过程及元器件选型 四、电子琴NE555原理图绘制 五、电子琴NE555PCB绘制 六、电子琴NE555最终效果 点击跳转 一、非接触测电笔原理图绘制 材料 电池 2032 电池底座 适用电池:CR2032 白色 C964762 NPN三…

googlecode.log4jdbc慢sql日志,格式化sql

前言 无论使用原生JDBC、mybatis还是hibernate&#xff0c;使用log4j等日志框架可以看到生成的SQL&#xff0c;但是占位符和参数总是分开打印的&#xff0c;不便于分析&#xff0c;显示如下的效果: googlecode Log4jdbc 是一个开源 SQL 日志组件&#xff0c;它使用代理模式实…

JSUDO|加速度与阿里云合作云产品

电讯&#xff1a;深圳市加速度软件开发有限公司【加速度jsudo】&#xff0c;与阿里云计算有限公司&#xff08;简称“阿里云”&#xff09;达成合作&#xff0c;双方将在电商、企业管理等应用软件领域就云产品和应用软件更深层次合作。 加速度软件长期以来&#xff0c;一直与阿…

JavaWeb——后端之maven

三、后端Web开发 1. Maven 1.1 概念 概念&#xff1a; 一款用于管理和构建java项目的工具&#xff0c;是apache下的一个开源项目 作用&#xff1a; 依赖管理&#xff1a;jar包&#xff0c;避免版本冲突问题——不用手动导jar包&#xff0c;只需要在配置文件&#xff08;pom…

确定转角起始扭矩值的方法有哪些

在预紧螺栓时&#xff0c;扭矩加角度法是一种常用的方法。这种方法需要确定转角起始扭矩值&#xff0c;以确保螺栓能够被正确地预紧。确定转角起始扭矩值的方法如下&#xff0c;SunTorque智能扭矩系统带大家一起了解。1. 确定螺栓规格和性能参数 在预紧螺栓之前&#xff0c;需要…

显著提升VMware虚拟机运行速度的技巧

最主要是要把CPU核心减少到2&#xff0c;以前设置为4非常卡。因为我的电脑一个就4个CPU。

技术学习|CDA level I 描述性统计分析(数据的描述性统计分析)

技术学习|CDA level I 描述性统计分析&#xff08;数据的描述性统计分析&#xff09; 数据的描述性统计分析常从数据的集中趋势、离散程度和分布形态3个方面进行。 一、集中趋势 集中趋势是指数据向其中心值靠拢的趋势。测量数据的集中趋势&#xff0c;主要是寻找其中心值。…

直播获奖(live)CSP2020

描述 NOI2130 即将举行。 为了增加观赏性&#xff0c;CCF 决定逐一评出每个选手的成绩&#xff0c;并直播即时的获奖分数线。 本次竞赛的获奖率为w&#xff0c;即当前排名前w 的选手的最低成绩就是即时的分数线。 更具体地&#xff0c;若当前已评出了 p 个选手的成绩&#…

INT201各种题型收集

汇总一下 FA 有穷自动机 - RL正则语言 DFA M (Q, Σ, δ, q, F) Q 是有限状态集合&#xff08;Finite Set of States&#xff09;&#xff1a; 这表示自动机中存在一个有限数量的不同状态。每个状态代表了自动机在某个特定时刻的内部状态。这些状态可以用符号或名称表示。 …

python学完之后可以做什么,python学完可以做什么

大家好&#xff0c;小编来为大家解答以下问题&#xff0c;python学完可以做哪些工作&#xff0c;python学完之后可以做什么&#xff0c;今天让我们一起来看看吧&#xff01; Python是一种全栈的开发语言&#xff0c;你如果能学好Python&#xff0c;前端&#xff0c;后端&#x…

jmeter断言-三种

1.响应断言 substring是指包含就行 不用完全相等 2.json断言 3.持续时间断言

【ModelScope】部署一个属于自己的AI服务

前言 技术栈是Fastapi。 FastAPI 是一个现代、快速&#xff08;基于 Starlette 和 Pydantic&#xff09;、易于使用的 Python web 框架&#xff0c;主要用于构建 RESTful API。以下是 FastAPI 的一些优势&#xff1a; 性能卓越&#xff1a; FastAPI 基于 Starlette 框架&…