当前位置:网站首页>Three.js 点击模型,高亮发光模型外轮廓
Three.js 点击模型,高亮发光模型外轮廓
2022-08-05 11:45:00 【GIS开发者】
最近在开发一个功能,在三维场景里有很多模型,需要点击模型,高亮对应的模型,代表选中了该模型。做起来还是稍微麻烦一些的。
具体效果
实现流程
主要的流程还是,
关键代码
在Vue项目中,所以参考时需要注意下:
- 鼠标点击模型
import * as THREE from 'three'
//添加监听
window.addEventListener('click',event=>{
this.clickEvent(event)
})
clickEvent(event){
//获取在射线上的接触点
//获取鼠标坐标
let mouse=new THREE.Vector2();
let raycaster=new THREE.Raycaster();
mouse.x=(event.clientX/window.innerWidth)*2-1;
mouse.y=-(event.clientY/window.innerHeight)*2+1;
raycaster.setFromCamera(mouse, this.camera);
let intersects = raycaster.intersectObjects(this.scene.children);
if(intersects&&intersects.length>0){
console.log("点击模型")
}
},;
- 高亮发光模型外轮廓
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"
import {
ShaderPass } from "three/examples/jsm/postprocessing/ShaderPass.js"
import {
FXAAShader } from "three/examples/jsm/shaders/FXAAShader.js"
//渲染场景
let animate = () =>{
requestAnimationFrame(animate);
//渲染外发光
renderer.render(scene, camera);
if (this.composer) {
this.composer.render()
}
};
animate();
//高亮显示模型(呼吸灯)
outlineObj (selectedObjects) {
// 创建一个EffectComposer(效果组合器)对象,然后在该对象上添加后期处理通道。
this.composer = new EffectComposer(this.renderer)
// 新建一个场景通道 为了覆盖到原理来的场景上
this.renderPass = new RenderPass(this.scene, this.camera)
this.composer.addPass(this.renderPass);
// 物体边缘发光通道
this.outlinePass = new OutlinePass(new THREE.Vector2(window.innerWidth, window.innerHeight), this.scene, this.camera, selectedObjects)
this.outlinePass.selectedObjects = selectedObjects
this.outlinePass.edgeStrength = 15.0 // 边框的亮度
this.outlinePass.edgeGlow = 2// 光晕[0,1]
this.outlinePass.usePatternTexture = false // 是否使用父级的材质
this.outlinePass.edgeThickness = 1.0 // 边框宽度
this.outlinePass.downSampleRatio = 1 // 边框弯曲度
this.outlinePass.pulsePeriod = 5 // 呼吸闪烁的速度
this.outlinePass.visibleEdgeColor.set(parseInt(0xff0000)) // 呼吸显示的颜色
this.outlinePass.hiddenEdgeColor = new THREE.Color(0, 0, 0) // 呼吸消失的颜色
this.outlinePass.clear = true
this.composer.addPass(this.outlinePass)
// 自定义的着色器通道 作为参数
let effectFXAA = new ShaderPass(FXAAShader)
effectFXAA.uniforms.resolution.value.set(1 / window.innerWidth, 1 / window.innerHeight)
effectFXAA.renderToScreen = true
this.composer.addPass(effectFXAA)
},
完整代码
<template>
<div id="app">
<div id="map"></div>
</div>
</template>
<script>
import {
Scene,
PerspectiveCamera,
WebGLRenderer,
DirectionalLight,
MeshBasicMaterial,
Mesh,
TextureLoader,
CylinderGeometry,
RepeatWrapping
} from 'three';
import {
OBJLoader} from "@/lib/OBJLoader"
import * as THREE from 'three'
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"
import {
ShaderPass } from "three/examples/jsm/postprocessing/ShaderPass.js"
import {
FXAAShader } from "three/examples/jsm/shaders/FXAAShader.js"
import {
OrbitControls } from "three/examples/jsm/controls/OrbitControls.js"
export default {
name: 'App',
components: {
},
data(){
return{
baseY:-20,
composer: null,
outlinePass: null,
renderPass: null,
}
},
mounted() {
let scene = new Scene();
let camera = new PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
// fov — 摄像机视锥体垂直视野角度
// aspect — 摄像机视锥体长宽比
// near — 摄像机视锥体近端面
// far — 摄像机视锥体远端面
let renderer = new WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
let app = document.getElementById("map")
app.appendChild(renderer.domElement);
//加载场景控制插件
let controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.enableZoom = true;
controls.autoRotate = false;
controls.autoRotateSpeed = 3;
controls.enablePan = true;
controls.enableKeys = true;
controls.keyPanSpeed = 7;
controls.keys = {
LEFT: 37,
UP: 38,
RIGHT: 39,
BOTTOM: 40
}
this.controls = controls;
//添加一个光源
let light = new DirectionalLight(0xffffff);//光源颜色
light.position.set(200, 100, 1305);//光源位置
scene.add(light);//光源添加到场景中
camera.position.y = 30;
camera.position.z = 100;
this.scene=scene;
this.camera=camera;
this.renderer=renderer;
window.addEventListener('click',event=>{
this.clickEvent(event)
});
this.addBottom(scene)
//渲染场景
let animate = () =>{
requestAnimationFrame(animate);
//渲染外发光
renderer.render(scene, camera);
if (this.composer) {
this.composer.render()
}
};
animate();
},
methods: {
clickEvent(event){
//获取在射线上的接触点
//获取鼠标坐标
let mouse=new THREE.Vector2();
let raycaster=new THREE.Raycaster();
mouse.x=(event.clientX/window.innerWidth)*2-1;
mouse.y=-(event.clientY/window.innerHeight)*2+1;
raycaster.setFromCamera(mouse, this.camera);
let intersects = raycaster.intersectObjects(this.scene.children);
if(intersects&&intersects.length>0){
this.outlineObj([intersects[0].object])
}
},
//高亮显示模型(呼吸灯)
outlineObj (selectedObjects) {
// 创建一个EffectComposer(效果组合器)对象,然后在该对象上添加后期处理通道。
this.composer = new EffectComposer(this.renderer)
// 新建一个场景通道 为了覆盖到原理来的场景上
this.renderPass = new RenderPass(this.scene, this.camera)
this.composer.addPass(this.renderPass);
// 物体边缘发光通道
this.outlinePass = new OutlinePass(new THREE.Vector2(window.innerWidth, window.innerHeight), this.scene, this.camera, selectedObjects)
this.outlinePass.selectedObjects = selectedObjects
this.outlinePass.edgeStrength = 15.0 // 边框的亮度
this.outlinePass.edgeGlow = 2// 光晕[0,1]
this.outlinePass.usePatternTexture = false // 是否使用父级的材质
this.outlinePass.edgeThickness = 1.0 // 边框宽度
this.outlinePass.downSampleRatio = 1 // 边框弯曲度
this.outlinePass.pulsePeriod = 5 // 呼吸闪烁的速度
this.outlinePass.visibleEdgeColor.set(parseInt(0xff0000)) // 呼吸显示的颜色
this.outlinePass.hiddenEdgeColor = new THREE.Color(0, 0, 0) // 呼吸消失的颜色
this.outlinePass.clear = true
this.composer.addPass(this.outlinePass)
// 自定义的着色器通道 作为参数
let effectFXAA = new ShaderPass(FXAAShader)
effectFXAA.uniforms.resolution.value.set(1 / window.innerWidth, 1 / window.innerHeight)
effectFXAA.renderToScreen = true
this.composer.addPass(effectFXAA)
},
addBottom(scene) {
let loader = new TextureLoader()
let texture = loader.load('./bottom.jpg', function (texture) {
texture.wrapS = texture.wrapT = RepeatWrapping;
texture.offset.set(0, 0);
texture.repeat.set(1.57, 1);
});
let material = new MeshBasicMaterial({
map: texture // 通过map 属性引入图片
})
let bar = new CylinderGeometry(20, 20, 20, 40, 40, false);
// THREE.CylinderGeometry(radiusTop, radiusBottom, height, radiusSegments, heightSegments, openEnded)
// radiusTop:顶面的半径;
// radiusBottom:底面的半径;
// height:是圆柱体的高度;
// radiusSegments:两底面的分段切片;
// heightSegments:侧面的分段切片;
// openEnded:是一个布尔值,表示是否没有顶面和底面,缺省值为false,表示有顶面和底面。
let cubeBar = new Mesh(bar, material);
cubeBar.position.x = 0
cubeBar.position.y = this.baseY
scene.add(cubeBar);
},
}
}
</script>
<style>
body, html, #app {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
overflow: hidden;
}
#map {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
z-index: 1;
}
</style>
边栏推荐
- 提问题进不去。想问大家一个关于返回值的问题(图的遍历),求给小白解答啊
- 五大理由告诉你为什么开发人员选择代码质量静态分析工具Klocwork来实现软件安全
- Discover the joy of C language
- 多业务模式下的交易链路探索与实践
- 碘乙酰胺在Desthiobiotin-Iodoacetamide试剂中的作用?
- 623. Add a row to a binary tree: Simple binary tree traversal problems
- 解决2022Visual Studio中scanf返回值被忽略问题
- How about Ping An Mengwa Card Insurance?Let parents read a few ways to identify products
- A woman is the most beautiful life in the world
- 小红的aba子序列(离散化、二分、dp维护区间最短)
猜你喜欢
随机推荐
Four, kubeadm single master
Version Control | Longzhi invites you to go to the GOPS Global Operation and Maintenance Conference to explore the road of large-scale, agile, high-quality and open software development and operation
Android 开发用 Kotlin 编程语言 二 条件控制
hdu4545 魔法串
Security Issues and Prevention in Web3
并非富人专属,一文让你对NFT改观
平安萌娃卡保险怎么样?让父母读懂几个识别产品的方法
TiDB 6.0 Placement Rules In SQL 使用实践
Byte Qiu Zhao confused me on both sides, and asked me under what circumstances would the SYN message be discarded?
Hands-on Deep Learning_GoogLeNet / Inceptionv1v2v3v4
Zhihu asks: Can China still achieve great national rejuvenation?
5G NR 系统消息
Introduction to the Evolution of Data Governance System
学生信息管理系统(第一次.....)
安全软件Avast与赛门铁克诺顿NortonLifeLock合并获英国批准
“蘑菇书”是怎样磨出来的?
女人是这个世界上最美丽的生命
微信小程序标题栏封装
再获殊荣 | 赛宁网安入选2022年度“培育独角兽”企业榜单
.NET深入解析LINQ框架(六:LINQ执行表达式)