three.js模型贴花贴标效果DecalGeometry

2023-11-27 08:59

本文主要是介绍three.js模型贴花贴标效果DecalGeometry,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

three.js模型贴花贴标效果DecalGeometry

three.js官网很早之前就有这个案例:https://threejs.org/examples/webgl_decals.html
只是看的很神奇,没有深入研究。因为没有想到可以用到什么地方。后来想到可以给模型局部贴牌子,比如衣服贴logo,图片文字什么的,很方便。
在这里插入图片描述

DecalGeometry

贴花几何可以用来创建贴花网格,用于不同的用途,例如为模型添加独特的细节,执行动态视觉环境变化或覆盖接缝。

var geometry =  new THREE.DecalGeometry( meshOne, position, orientation, size );
var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
var mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );

构造函数:
DecalGeometry( mesh : Mesh, position : Vector3, orientation : Euler, size : Vector3 )
mesh 网格-任何网格对象。需要传入一个网格对象。
position 位置-贴花投影仪的位置。投影的位置就是网格表面的位置,用射线获取准确位置。
orientation 方向-贴花投影仪的方向。方向投影点的法线方向。
size 贴花投影仪的尺寸。

下图是我做的案例。用了一个立方图和一个球体。发现在立方体的边缘的部分添加DecalGeometry会出现问题。因为边缘部分法线突变。所以会出现错误(其实是投影原理造成的)。不过这种情况比较极端。在球体表面贴还是不成问题的。

这个贴花在opengl中叫投影纹理,可以自己百度看看原理。
ProjectiveTexturing(投影纹理)https://blog.csdn.net/qq_29523119/article/details/53001070
在这里插入图片描述
在这里插入图片描述

主要代码

投影纹理的关键点在于投影坐标和投影法线。
主要代码是在射线部分,求得点击位置的交点坐标和法线。然后用一根线可视化的表现出来。

        var mouseHelper;var line;var position = new THREE.Vector3();var orientation = new THREE.Euler();var size = new THREE.Vector3( 10, 10, 10 );var intersection = {intersects: false,point: new THREE.Vector3(),normal: new THREE.Vector3()};var mouse = new THREE.Vector2();var textureLoader = new THREE.TextureLoader();var decalDiffuse = textureLoader.load( '../img/decal/decal-diffuse.png' );var decalNormal = textureLoader.load( '../img/decal/decal-normal.jpg' );var decalMaterial = new THREE.MeshPhongMaterial( {color:0xfff000 * Math.random(),specular: 0x444444,map: decalDiffuse,normalMap: decalNormal,normalScale: new THREE.Vector2( 1, 1 ),shininess: 30,transparent: true,depthTest: true,depthWrite: false,polygonOffset: true,polygonOffsetFactor: - 4,wireframe: false} );mouseHelper = new THREE.Mesh( new THREE.BoxBufferGeometry( 1, 1, 10 ), new THREE.MeshNormalMaterial() );mouseHelper.visible = false;scene.add( mouseHelper );var geometry = new THREE.BufferGeometry();geometry.setFromPoints( [ new THREE.Vector3(), new THREE.Vector3() ] );line = new THREE.Line( geometry, new THREE.LineBasicMaterial() );scene.add( line );//贴花function decalGeo(obj) {position.copy(intersection.point);orientation.copy( mouseHelper.rotation );var material = decalMaterial.clone();material.color.setHex( Math.random() * 0xffffff );var geometry = new THREE.DecalGeometry(obj, position,orientation, new THREE.Vector3(3, 3, 3));var mesh = new THREE.Mesh(geometry, material);scene.add(mesh);}window.addEventListener('click', onClick, false);window.addEventListener('mousemove',onTouchMove);function onTouchMove(event) {var x, y;if ( event.changedTouches ) {x = event.changedTouches[ 0 ].pageX;y = event.changedTouches[ 0 ].pageY;} else {x = event.clientX;y = event.clientY;}mouse.x = ( x / window.innerWidth ) * 2 - 1;mouse.y = - ( y / window.innerHeight ) * 2 + 1;onDocumentMouseDown();}function onClick() {var obj = onDocumentMouseDown();if(!obj) return;decalGeo(obj);}function onDocumentMouseDown() {           var raycaster = new THREE.Raycaster();raycaster.setFromCamera( mouse, camera );let intersects = raycaster.intersectObjects([cube1, sphere1]);if (intersects.length > 0) {var p = intersects[ 0 ].point;mouseHelper.position.copy( p );intersection.point.copy( p );var n = intersects[ 0 ].face.normal.clone();n.transformDirection( mesh.matrixWorld );n.multiplyScalar( 10 );n.add( intersects[ 0 ].point );intersection.normal.copy( intersects[ 0 ].face.normal );mouseHelper.lookAt( n );var positions = line.geometry.attributes.position;positions.setXYZ( 0, p.x, p.y, p.z );positions.setXYZ( 1, n.x, n.y, n.z );positions.needsUpdate = true;intersection.intersects = true;return intersects[0].object;}}

上面的代码有个地方有个问题,就是n.transformDirection( mesh.matrixWorld );这个里面的mesh应该改成intersects[0].object,否则当模型发生旋转之后他的法线没有更新就会出现错误。
这段代码是求当前点击面的法线。

  1. 克隆旧的法线

  2. 旧法线乘以模型的世界矩阵得到归一化后的法线

  3. 和一个标量相乘,放大10倍。

  4. 加上点击点的坐标,进行平移。

            var n = intersects[ 0 ].face.normal.clone();n.transformDirection( intersects[0].object.matrixWorld );n.multiplyScalar( 10 );n.add( intersects[ 0 ].point );                mouseHelper.lookAt( n );
    

最后得到的n点就是线段一个顶点的坐标。
在这里插入图片描述
在这里插入图片描述

这篇关于three.js模型贴花贴标效果DecalGeometry的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/427399

相关文章

详解如何使用Python从零开始构建文本统计模型

《详解如何使用Python从零开始构建文本统计模型》在自然语言处理领域,词汇表构建是文本预处理的关键环节,本文通过Python代码实践,演示如何从原始文本中提取多尺度特征,并通过动态调整机制构建更精确... 目录一、项目背景与核心思想二、核心代码解析1. 数据加载与预处理2. 多尺度字符统计3. 统计结果可

SpringBoot整合Sa-Token实现RBAC权限模型的过程解析

《SpringBoot整合Sa-Token实现RBAC权限模型的过程解析》:本文主要介绍SpringBoot整合Sa-Token实现RBAC权限模型的过程解析,本文给大家介绍的非常详细,对大家的学... 目录前言一、基础概念1.1 RBAC模型核心概念1.2 Sa-Token核心功能1.3 环境准备二、表结

使用Python获取JS加载的数据的多种实现方法

《使用Python获取JS加载的数据的多种实现方法》在当今的互联网时代,网页数据的动态加载已经成为一种常见的技术手段,许多现代网站通过JavaScript(JS)动态加载内容,这使得传统的静态网页爬取... 目录引言一、动态 网页与js加载数据的原理二、python爬取JS加载数据的方法(一)分析网络请求1

Kotlin Compose Button 实现长按监听并实现动画效果(完整代码)

《KotlinComposeButton实现长按监听并实现动画效果(完整代码)》想要实现长按按钮开始录音,松开发送的功能,因此为了实现这些功能就需要自己写一个Button来解决问题,下面小编给大... 目录Button 实现原理1. Surface 的作用(关键)2. InteractionSource3.

使用WPF实现窗口抖动动画效果

《使用WPF实现窗口抖动动画效果》在用户界面设计中,适当的动画反馈可以提升用户体验,尤其是在错误提示、操作失败等场景下,窗口抖动作为一种常见且直观的视觉反馈方式,常用于提醒用户注意当前状态,本文将详细... 目录前言实现思路概述核心代码实现1、 获取目标窗口2、初始化基础位置值3、创建抖动动画4、动画完成后

uniapp小程序中实现无缝衔接滚动效果代码示例

《uniapp小程序中实现无缝衔接滚动效果代码示例》:本文主要介绍uniapp小程序中实现无缝衔接滚动效果的相关资料,该方法可以实现滚动内容中字的不同的颜色更改,并且可以根据需要进行艺术化更改和自... 组件滚动通知只能实现简单的滚动效果,不能实现滚动内容中的字进行不同颜色的更改,下面实现一个无缝衔接的滚动

Java实现图片淡入淡出效果

《Java实现图片淡入淡出效果》在现代图形用户界面和游戏开发中,**图片淡入淡出(FadeIn/Out)**是一种常见且实用的视觉过渡效果,它可以用于启动画面、场景切换、轮播图、提示框弹出等场景,通过... 目录1. 项目背景详细介绍2. 项目需求详细介绍2.1 功能需求2.2 非功能需求3. 相关技术详细

使用animation.css库快速实现CSS3旋转动画效果

《使用animation.css库快速实现CSS3旋转动画效果》随着Web技术的不断发展,动画效果已经成为了网页设计中不可或缺的一部分,本文将深入探讨animation.css的工作原理,如何使用以及... 目录1. css3动画技术简介2. animation.css库介绍2.1 animation.cs

VSCode中配置node.js的实现示例

《VSCode中配置node.js的实现示例》本文主要介绍了VSCode中配置node.js的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着... 目录一.node.js下载安装教程二.配置npm三.配置环境变量四.VSCode配置五.心得一.no

Flutter实现文字镂空效果的详细步骤

《Flutter实现文字镂空效果的详细步骤》:本文主要介绍如何使用Flutter实现文字镂空效果,包括创建基础应用结构、实现自定义绘制器、构建UI界面以及实现颜色选择按钮等步骤,并详细解析了混合模... 目录引言实现原理开始实现步骤1:创建基础应用结构步骤2:创建主屏幕步骤3:实现自定义绘制器步骤4:构建U