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

使用three.js 实现 自定义绘制平面的效果

使用three.js 实现 自定义绘制平面的效果 预览
在这里插入图片描述

import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'const box = document.getElementById('box')const scene = new THREE.Scene()const camera = new THREE.PerspectiveCamera(75, box.clientWidth / box.clientHeight, 0.1, 1000)camera.position.set(0, 3, 3)const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true, logarithmicDepthBuffer: true })renderer.setSize(box.clientWidth, box.clientHeight)box.appendChild(renderer.domElement)const controls = new OrbitControls(camera, renderer.domElement)controls.enableDamping = trueconst directionalLight = new THREE.DirectionalLight(0xffffff, 1)directionalLight.position.set(0, 20, 0)scene.add(directionalLight, new THREE.AmbientLight(0xffffff, 1))/* 增加一个面 */
const plane = new THREE.PlaneGeometry(5, 5)const material = new THREE.MeshStandardMaterial({ color: 0xffffff })const planeMesh = new THREE.Mesh(plane, material)planeMesh.rotation.x -= Math.PI / 2scene.add(planeMesh)animate()function animate() {requestAnimationFrame(animate)controls.update()renderer.render(scene, camera)}window.onresize = () => {renderer.setSize(box.clientWidth, box.clientHeight)camera.aspect = box.clientWidth / box.clientHeightcamera.updateProjectionMatrix()}// 事件
const raycaster = new THREE.Raycaster()const getPoint = event => {const mouse = new THREE.Vector2((event.offsetX / event.target.clientWidth) * 2 - 1,-(event.offsetY / event.target.clientHeight) * 2 + 1)raycaster.setFromCamera(mouse, camera)const intersects = raycaster.intersectObjects(scene.children)if (intersects.length > 0) return intersects[0].point}const setPointBox = point => {const box = new THREE.BoxGeometry(0.04, 0.04, 0.04)const material = new THREE.MeshStandardMaterial({ color: 0xff0000 })const boxMesh = new THREE.Mesh(box, material)boxMesh.position.copy(point)scene.add(boxMesh)}/* 开始绘制 */
const pointList = []; let drawMesh = null; let stop = falsebox.addEventListener('contextmenu', () => {stop = trueconst { indexGroup, faceGroup, uvGroup } = multShapeGroup(pointList)if (drawMesh) updateMultShapePlaneGeometry(drawMesh.geometry, faceGroup, indexGroup, uvGroup)})// 移动
box.addEventListener('mousemove', (event) => {if (stop) returnconst point = getPoint(event)if (!point || !drawMesh || pointList.length < 2) returnconst { indexGroup, faceGroup, uvGroup } = multShapeGroup([...pointList, point])updateMultShapePlaneGeometry(drawMesh.geometry, faceGroup, indexGroup, uvGroup)})box.addEventListener('click', (event) => {const point = getPoint(event)if (!point || stop) returnsetPointBox(point)point.y += 0.001pointList.push(point)const { indexGroup, faceGroup, uvGroup } = multShapeGroup(pointList)if (pointList.length < 3) returnif (!drawMesh) {const geometry = multShapePlaneGeometry(faceGroup, indexGroup, uvGroup)const material = new THREE.MeshStandardMaterial({ color: 0x00ff00, side: THREE.DoubleSide })drawMesh = new THREE.Mesh(geometry, material)scene.add(drawMesh)}else updateMultShapePlaneGeometry(drawMesh.geometry, faceGroup, indexGroup, uvGroup)})/* 处理顶点算法 */
function multShapeGroup(pList) {const indexGroup = pList.map((_, k) => (k >= 2) ? [0, k - 1, k] : false).filter((i) => i).reduce((i, j) => [...i, ...j], [])const faceGroup = pList.reduce((j, i) => [...j, i.x, i.y, i.z], [])const uvMaxMin = pList.reduce((p, i) => ({ x: [...p['x'], i['x']], y: [...p['y'], i['y']], z: [...p['z'], i['z']] }), { x: [], y: [], z: [] })// vu 点计算 二维面const Maxp = new THREE.Vector3(Math.max(...uvMaxMin.x), Math.max(...uvMaxMin.y), Math.max(...uvMaxMin.z))  // 最大点const Minp = new THREE.Vector3(Math.min(...uvMaxMin.x), Math.min(...uvMaxMin.y), Math.min(...uvMaxMin.z))  // 最小点const W = Maxp.x - Minp.xconst H = Maxp.y - Minp.yconst L = W > H ? W : H  // 以最大为基准// 顶点uv计算const uvGroup = pList.map(i => new THREE.Vector2((i.x - Minp.x) / L, (i.y - Minp.y) / L)).reduce((i, j) => [...i, ...j], [])return { indexGroup, faceGroup, uvGroup }}/* 根据顶点组生成物体 */
function multShapePlaneGeometry(faceGroup, indexGroup, uvGroup) {const geometry = new THREE.BufferGeometry()// 因为在两个三角面片里,这两个顶点都需要被用到。const vertices = new Float32Array(faceGroup)// itemSize = 3 因为每个顶点都是一个三元组。geometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3))// 索引组 面if (indexGroup) {// 格式化索引面组let indexs = new Uint16Array(indexGroup)// 添加索引组geometry.index = new THREE.BufferAttribute(indexs, 1)}// uv 是二维坐标相当于三维物体展开图if (uvGroup) geometry.attributes.uv = new THREE.Float32BufferAttribute(uvGroup, 2)geometry.computeVertexNormals()return geometry}/* 更新顶点 */
function updateMultShapePlaneGeometry(geometry, faceGroup, indexGroup, uvGroup) {geometry.setIndex(indexGroup)geometry.setAttribute('position', new THREE.Float32BufferAttribute(faceGroup, 3))geometry.setAttribute('uv', new THREE.Float32BufferAttribute(uvGroup, 2))delete geometry.attributes.normalgeometry.computeVertexNormals()}/*** 名称: 绘制面* 作者: 优雅永不过时 https://github.com/z2586300277
*/

相关文章:

使用three.js 实现 自定义绘制平面的效果

使用three.js 实现 自定义绘制平面的效果 预览 import * as THREE from three import { OrbitControls } from three/examples/jsm/controls/OrbitControls.jsconst box document.getElementById(box)const scene new THREE.Scene()const camera new THREE.PerspectiveCam…...

玩转Docker | 使用Docker部署捕鱼网页小游戏

玩转Docker | 使用Docker部署捕鱼网页小游戏 一、项目介绍项目简介项目预览二、系统要求环境要求环境检查Docker版本检查检查操作系统版本三、部署捕鱼网页小游戏下载镜像创建容器检查容器状态下载项目内容查看服务监听端口安全设置四、访问捕鱼网页小游戏五、总结一、项目介绍…...

第2章 Android App开发基础

第 2 章 Android App开发基础 bilibili学习地址 github代码地址 本章介绍基于Android系统的App开发常识&#xff0c;包括以下几个方面&#xff1a;App开发与其他软件开发有什么不一 样&#xff0c;App工程是怎样的组织结构又是怎样配置的&#xff0c;App开发的前后端分离设计…...

通过 SYSENTER/SYSEXIT指令来学习系统调用

SYSENTER指令—快速系统调用 指令格式没有什么重要的内容,只有opcode ,没有后面的其他字段 指令的作用: 执行快速调用到特权级别0的系统过程或例程。SYSENTER是SYSEXIT的配套指令。该指令经过优化&#xff0c;能够为从运行在特权级别3的用户代码到特权级别0的操作系统或执行过程…...

Nginx开发实战——网络通信(一)

文章目录 Nginx开发框架信号处理函数的进一步完善(避免僵尸子进程)(续&#xff09;ngx_signal.cxxngx_process_cycle.cxx 网络通信实战客户端和服务端1. 解析一个浏览器访问网页的过程2.客户端服务器角色规律总结 网络模型OSI 7层网络模型TCP/IP 4层模型3.TCP/IP的解释和比喻 最…...

w外链如何跳转微信小程序

要创建外链跳转微信小程序&#xff0c;主要有以下几种方法&#xff1a; 使用第三方工具生成跳转链接&#xff1a; 注册并登录第三方外链平台&#xff1a;例如 “W外链” 等工具。前往该平台的官方网站&#xff0c;使用手机号、邮箱等方式进行注册并登录账号。选择创建小程序外…...

获取平台Redis各项性能指标

业务场景 在XXXX项目中把A网的过车数据传到B网中&#xff0c;其中做了一个业务处理&#xff0c;就是如果因为网络或者其他原因导致把数据传到B网失败&#xff0c;就会把数据暂时先存到redis里&#xff0c;并且执行定时任务重新发送失败的。 问题 不过现场的情况比较不稳定。出…...

STM32 HAL 点灯

首先从点灯开始 完整函数如下&#xff1a; #include "led.h" #include "sys.h"//包含了stm32f1xx.h&#xff08;包含各种寄存器定义、中断向量定义、常量定义等&#xff09;//初始化GPIO口 void led_init(void) {GPIO_InitTypeDef gpio_initstruct;//打开…...

【http作业】

1.关闭防火墙 [rootlocalhost ~]# systemctl stop firewalld #关闭防火墙 [rootlocalhost ~]# setenforce 0 2.下载nginx包 [rootlocalhost ~]# mount /dev/sr0 /mnt #挂载目录 [rootlocalhost ~]# yum install nginx -y #下载nginx包 3.增加多条端口 [rootlocalhost ~]# n…...

WPF+MVVM案例实战(十一)- 环形进度条实现

文章目录 1、运行效果2、功能实现1、文件创建与代码实现2、角度转换器实现3、命名空间引用3、源代码下载1、运行效果 2、功能实现 1、文件创建与代码实现 打开 Wpf_Examples 项目,在Views 文件夹下创建 CircularProgressBar.xaml 窗体文件。 CircularProgressBar.xaml 代码实…...

简述MCU微控制器

目录 一、MCU 的主要特点&#xff1a; 二、常见 MCU 系列&#xff1a; 三、应用场景&#xff1a; MCU 是微控制器&#xff08;Microcontroller Unit&#xff09;的缩写&#xff0c;指的是一种小型计算机&#xff0c;专门用于嵌入式系统。它通常集成了中央处理器&#xff08;…...

微服务的雪崩问题

微服务的雪崩问题&#xff1a; 微服务调用链路中的某个服务故障&#xff0c;引起整个链路种的所有微服务都不可用。这就是微服务的雪崩问题。&#xff08;级联失败&#xff09;&#xff0c;具体表现出来就是微服务之间相互调用&#xff0c;服务的提供者出现阻塞或者故障&#x…...

Java基础(4)——构建字符串(干货)

今天聊Java构建字符串以及其内存原理 我们先来看一个小例子。一个是String,一个是StringBuilder. 通过结果对比&#xff0c;StringBuilder要远远快于String. String/StringBuilder/StringBuffer这三个构建字符串有什么区别&#xff1f; 拼接速度上&#xff0c;StringBuilder…...

logback日志脱敏后异步写入文件

大家项目中肯定都会用到日志打印&#xff0c;目的是为了以后线上排查问题方便&#xff0c;但是有些企业对输出的日志包含的敏感(比如&#xff1a;用户身份证号&#xff0c;银行卡号&#xff0c;手机号等)信息要进行脱敏处理。 哎&#xff01;我们最近就遇到了日志脱敏的改造。可…...

电容的基本知识

1.电容的相关公式 2.电容并联和串联的好处 电容并联的好处: 增加总电容值: 并联连接的电容器可以增加总的电容值,这对于需要较大电容值来滤除高频噪声或储存更多电荷的应用非常有用。 改善频率响应: 并联不同的电容值可以设计一个滤波器,以在特定的频率范围内提供更好的滤…...

【Axure高保真原型】分级树筛选中继器表格

今天和大家分享分级树筛选中继器表格的原型模板&#xff0c;点击树的箭头可以展开或者收起子级内容&#xff0c;点击内容&#xff0c;可以筛选出该内容及子级内容下所有的表格数据。左侧的树和右侧的表格都是用中继器制作的&#xff0c;所以使用也很方便&#xff0c;只需要在中…...

STM32 I2C通信:硬件I2C与软件模拟I2C的区别

文章目录 STM32 I2C通信&#xff1a;硬件I2C与软件模拟I2C的区别。一、硬件I2C速度快&#xff1a;实现简单&#xff1a;稳定性好&#xff1a; 二、软件模拟I2C灵活性高&#xff1a;支持多路通信&#xff1a; 三、选择哪种方式&#xff1f; STM32 I2C通信&#xff1a;硬件I2C与软…...

服务器新建用户

文章目录 前言一、步骤二、问题三、赋予管理员权限总结 前言 环境&#xff1a; 一、步骤 创建用户需要管理员权限sudo sudo useradd tang为用户设置密码 sudo passwd tang设置密码后&#xff0c;可以尝试使用 su 切换到 tang 用户&#xff0c;确保该用户可以正常使用&#…...

鸿蒙开发融云demo发送图片消息

鸿蒙开发融云demo发送图片消息 融云鸿蒙版是不带UI的&#xff0c;得自己一步步搭建。 这次讲如何发送图片消息&#xff0c;选择图片&#xff0c;显示图片消息。 还是有点难度的&#xff0c;好好看&#xff0c;好好学。 一、思路&#xff1a; 选择图片用&#xff1a;photoVie…...

音视频入门基础:AAC专题(11)——AudioSpecificConfig简介

音视频入门基础&#xff1a;AAC专题系列文章&#xff1a; 音视频入门基础&#xff1a;AAC专题&#xff08;1&#xff09;——AAC官方文档下载 音视频入门基础&#xff1a;AAC专题&#xff08;2&#xff09;——使用FFmpeg命令生成AAC裸流文件 音视频入门基础&#xff1a;AAC…...

OpenCV基本操作(python开发)——(8)实现芯片瑕疵检测

OpenCV基本操作&#xff08;python开发&#xff09;——&#xff08;1&#xff09; 读取图像、保存图像 OpenCV基本操作&#xff08;python开发&#xff09;——&#xff08;2&#xff09;图像色彩操作 OpenCV基本操作&#xff08;python开发&#xff09;——&#xff08;3&…...

聚水潭商品信息集成到MySQL的高效解决方案

聚水潭商品信息集成到MySQL的技术案例分享 在数据驱动的业务环境中&#xff0c;如何高效地实现不同系统之间的数据对接和集成&#xff0c;是每个企业面临的重要挑战。本文将聚焦于一个具体的系统对接集成案例&#xff1a;将聚水潭平台上的商品信息单集成到BI斯莱蒙的MySQL数据…...

# centos6.5 使用 yum list 报错Error Cannot find a valid baseurl for repo bas 解决方法

centos6.5 使用 yum list 报错Error Cannot find a valid baseurl for repo bas 解决方法 一、问题描述&#xff1a; centos6.5 使用 yum list 报错Error Cannot find a valid baseurl for repo bas 如下图&#xff1a; 二、问题分析&#xff1a; 官方已停止对CentOS 6的更…...

【专题】2023-2024中国保险数字化营销调研报告汇总PDF洞察(附原数据表)

原文链接&#xff1a; https://tecdat.cn/?p38063 在时代浪潮的推动下&#xff0c;中国保险行业正经历着一场波澜壮阔的变革之旅。 2023 年&#xff0c;中国经济迈向高质量发展阶段&#xff0c;保险公司纷纷聚焦队伍转型&#xff0c;专业化、职业化代理人成为行业新方向。回…...

““ 引用类型应用举例

#include <iostream> //使能cin(),cout(); #include <stdlib.h> //使能exit(); #include <iomanip> //使能setbase(),setfill(),setw(),setprecision(),setiosflags()和resetiosflags(); //setbase( char x )是设置输出数字的基数,如输出进制数则用se…...

数字图像处理 - 基于ubuntu20.04运行.NET6+OpenCVSharp项目

一、简述 上一篇Ubuntu20.04 更新Nvidia驱动 + 安装CUDA12.1 + cudnn8.9.7-CSDN博客,记录了Ubuntu20.04 更新Nvidia驱动 + 安装CUDA12.1 + cudnn8.9.7的过程,最终的目的是要这些服务器上运行.net6的程序,进行图像处理、onnxruntime推理等。 这里记录进行OpenCVSharp的安装和…...

git cherry-pick用法详解

git cherry-pick 是 Git 中一个非常有用的命令&#xff0c;它允许你选择一个特定的提交&#xff08;commit&#xff09;并将其变更应用到当前分支上。这个功能在你需要将某个分支上的某个或某些特定提交合并到另一个分支时特别有用&#xff0c;而不需要将整个分支合并过去。 基…...

HCIP-HarmonyOS Application Developer V1.0 笔记(一)

HarmonyOS的系统特性 硬件互助&#xff0c;资源共享;一次开发&#xff0c;多端部署;统一OS&#xff0c;弹性部署。 分布式软总线&#xff1a;分布式任务调度、分布式数据管理、分布式硬件虚拟化的基座 18N的独立设备 1个手机&#xff0c;8种设备&#xff08;车机&#xff0c…...

开发流程初学者指南——需求分析

目录 从零开始理解需求分析什么是需求分析&#xff1f;需求分析的目标需求分析的基本原则需求分析的各个阶段需求分析的常用方法和工具编写需求文档总结 从零开始理解需求分析 需求分析是软件开发过程中不可或缺的一环&#xff0c;它帮助我们明确用户的需求&#xff0c;确保最…...

CRM平台排名:用户体验与客户满意度的深度解析

在数字化时代&#xff0c;客户关系管理&#xff08;CRM&#xff09;系统已成为企业不可或缺的工具&#xff0c;它帮助企业优化客户互动&#xff0c;提升销售效率&#xff0c;并增强客户满意度。本文将深度解析各大CRM平台的用户体验和客户满意度&#xff0c;盘点它们的品牌介绍…...

wordpress 密码失败/深圳关键词推广

CSS3属性box-shadow使用详细教程 box-shadow&#xff1a;length length length length color length&#xff1a;阴影水平偏移值 length&#xff1a;阴影垂直偏移值 length&#xff1a;阴影模糊值 length&#xff1a;阴影边框 color&#xff1a;阴影颜色 说明&#xff1a;设置…...

开了网站建设公司 如何接业务/长春免费网上推广

文章目录一、确定慢请求是否突然暴增二、慢请求暴增可能的因素1、系统繁忙导致的慢请求2、GC导致的慢请求3、系统故障导致的慢请求4、HDFS因素三、系统负载高根因排查1、CPU 持续飙高2、IO负载持续打满3、导致 IO 负载升高的情况汇总用户请求突增Hbase在进行大量compactStoreFi…...

用什么系统做威客网站/网络推广员具体做什么的

ps&#xff1a;对go 不太熟悉&#xff0c;只因利用docker镜像golang 编译时报错&#xff0c;所以记录下 dockerfile FROM golang WORKDIR /go/src/app ADD . /go/src/app RUN go get -u -v github.com/kardianos/govendor ##安装govendor&#xff0c;govendor用来管理项目的…...

专用车网站建设/网络营销有哪些手段

一、设备节点及有关术语的含义 设备节点含义/dev/ttyS0、/dev/ttySAC0串口/dev/tty1、/dev/tty2、/dev/tty3、……虚拟终端设备节点/dev/tty0前台终端/dev/tty程序自己的终端&#xff0c;可能是串口、也可能是虚拟终端/dev/console控制台&#xff0c;又内核的cmdline参数确定 …...

企业靠网站接单/佛山关键词排名效果

由于项目需求需要做一个报表&#xff0c;选择FusionCharts作为工具使用。由于以 前没有接触过报表&#xff0c;网上也没有比较详细的fusionCharts教程&#xff0c;所以决定好好研究FusionCharts&#xff0c;同时做一个比较简单的教程提供参考。 由于能力有限(应届毕业生的菜鸟而…...

开设网站需要什么/seo关键词快速提升软件官网

异步日志 log4j2最大的特点就是异步日志&#xff0c;其性能的提升主要也是从异步日志中受益&#xff0c;我们来看看如何使用log4j2的异步日志。 同步日志 异步日志 Log4j2提供了两种实现日志的方式&#xff0c;一个是通过AsyncAppender&#xff0c;一个是通过AsyncLogger&am…...