three.js实现点击选中模型,模型描边高亮效果

  1. 射线投射器Raycaster通过.intersectObjects()判断模型是否选中
  2. EffectComposer.js进行后期处理,添加描边高亮效果
<template>
  <div class="app">
    <div ref="canvesRef" class="canvas-wrap"></div>
  </div>
</template>

<script setup>
import { ref, onMounted } from "vue";
import * as THREE from "three";
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
import Stats from "three/addons/libs/stats.module.js";
import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
// 高光
import { EffectComposer } from "three/addons/postprocessing/EffectComposer.js";
import { RenderPass } from "three/addons/postprocessing/RenderPass.js";
import { OutlinePass } from "three/addons/postprocessing/OutlinePass.js";
const canvesRef = ref(null);
const canvasWidth = window.innerWidth;
const canvasHeight = window.innerHeight;
let model = null;

// 场景
const scene = new THREE.Scene();
// 模型
const loader = new GLTFLoader();
loader.load(
  "../src/model/factory/工厂.gltf",
  function (gltf) {
    console.log("控制台查看加载gltf文件返回的对象结构", gltf);
    model = gltf;
    // console.log('gltf对象场景属性',gltf.scene);
    // 返回的场景对象gltf.scene插入到threejs场景中
    scene.add(gltf.scene);
  },
  function (val) {
    // 加载一部分,就调用函数,可做模型加载进度条
    // console.log(val);
  },
  function (err) {
    console.log(err);
  }
);

// 相机
const camera = new THREE.PerspectiveCamera(
  75,
  canvasWidth / canvasHeight,
  0.1,
  3000
);
camera.position.set(-84, 78, 1.3);
camera.lookAt(0, 0, 0);
// 点光源
const pointLight = new THREE.PointLight(0xffffff, 1.0);
pointLight.decay = 0.0; //光源光照强度不随距离改变衰减

pointLight.position.set(-100, 190, 110);
scene.add(pointLight);
// console.log(pointLight);
// 坐标辅助对象
const axesHelper = new THREE.AxesHelper(200);
scene.add(axesHelper);
// 渲染帧率
const stats = new Stats();
document.body.appendChild(stats.domElement);
// 渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(canvasWidth, canvasHeight);
// 高光
const composer = new EffectComposer(renderer);
const renderPass = new RenderPass(scene, camera);
const outlinePass = new OutlinePass(
  new THREE.Vector2(canvasWidth, canvasHeight),
  scene,
  camera
);
composer.addPass(renderPass);
composer.addPass(outlinePass);

// 动画渲染循环
function animate() {
  stats.update();
  // renderer.render(scene, camera);
  composer.render();
  requestAnimationFrame(animate);
}
animate();
// 相机轨道控制器
const cameraControls = new OrbitControls(camera, renderer.domElement);
cameraControls.addEventListener("change", function () {
  // renderer.render(scene, camera); //执行渲染操作
});
cameraControls.target.set(0, 0, 0);
cameraControls.maxPolarAngle = Math.PI / 2; // 相机不能进入地下

onMounted(() => {
  canvesRef.value.appendChild(renderer.domElement);

  renderer.domElement.addEventListener("click", (event) => {
    console.log("模型点击", model);
    // .offsetY、.offsetX以canvas画布左上角为坐标原点,单位px
    const px = event.offsetX;
    const py = event.offsetY;
    //屏幕坐标px、py转WebGL标准设备坐标x、y
    //width、height表示canvas画布宽高度
    const x = (px / canvasWidth) * 2 - 1;
    const y = -(py / canvasHeight) * 2 + 1;
    //创建一个射线投射器`Raycaster`
    const raycaster = new THREE.Raycaster();
    //.setFromCamera()计算射线投射器`Raycaster`的射线属性.ray
    // 形象点说就是在点击位置创建一条射线,用来选中拾取模型对象
    raycaster.setFromCamera(new THREE.Vector2(x, y), camera);
    const intersects = raycaster.intersectObjects(model.scene.children);
    console.log("射线器返回的对象", intersects);
    if (intersects.length > 0) {
      // 选中模型的第一个模型,设置为红色

      // intersects[0].object.material.color.set(0xff0000);
      outlinePass.selectedObjects = [intersects[0].object];
    } else {
    }
  });
});
</script>

<style lang="scss" scoped>
.app {
  position: relative;
}
</style>

在这里插入图片描述

### Three.js实现模型描边效果的方法 为了在 Three.js 场景中给特定对象添加描边效果,可以利用 `OutlinePass` 来创建轮廓渲染通道并将其集成到后期处理流程之中。这允许开发者轻松定义哪些对象应该被突出显示以及自定义这些高亮部分的颜色和其他属性。 #### 导入必要的库文件 首先需要导入用于构建后期处理管线的相关类: ```javascript import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js'; import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass.js'; import { OutlinePass } from 'three/examples/jsm/postprocessing/OutlinePass.js'; ``` 接着初始化场景、相机等基础组件之后设置 `EffectComposer` 和 `OutlinePass`[^1]。 #### 创建和配置 OutlinePass 实例 通过实例化 `OutlinePass` 并传入视口尺寸参数来启动该功能模块。同时还可以设定默认的边缘颜色以及其他视觉特性: ```javascript const outlinePass = new OutlinePass( new THREE.Vector2(window.innerWidth, window.innerHeight), scene, camera ); outlinePass.visibleEdgeColor.set("#ffffff"); // 设置可见边缘颜色为白色 outlinePass.hiddenEdgeColor.set("#00ff00"); // 隐藏区域边缘颜色设为绿色 (可根据需求调整) ``` #### 将 OutlinePass 添加至合成器 一旦完成了上述准备工作,则需把新建立好的 `OutlinePass` 加入到由 `EffectComposer` 构建起来的效果堆栈里去以便于后续执行: ```javascript composer.addPass(outlinePass); ``` 最后,在动画循环内调用 `composer.render()` 而不是直接操作 renderer 进行绘制工作即可完成整个过程。 对于想要针对单个或多个具体目标应用这种特殊样式的情况来说,只需简单地向 `selectedObjects` 属性数组里面追加相应的 Mesh 即可达成目的;如果希望移除某个已有的选中项则反之亦然。 ```javascript // 增加要描边的对象 outlinePass.selectedObjects.push(mesh); // 移除不再需要描边的对象 let index = outlinePass.selectedObjects.indexOf(mesh); if(index !== -1){ outlinePass.selectedObjects.splice(index, 1); } ``` 这样就能够在 Three.js 应用程序当中成功实现了对选定几何体进行描边的功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值