ThreeJS-3D教学十-有宽度的line

news2024/11/27 10:29:46

webgl中线是没有宽度的,现实的应用中一般做法都是将线拓宽成面来绘制。默认threejs的线宽是无法调节的,需要用有厚度的线 THREE.Line2。
先看效果图:
在这里插入图片描述

看下代码:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <style>
    body {
      width: 100%;
      height: 100%;
    }
    * {
      margin: 0;
      padding: 0;
    }
    .label {
      font-size: 20px;
      color: #000;
      font-weight: 700;
    }
  </style>
</head>
<body>
<div id="container"></div>
<script type="importmap">
  {
    "imports": {
      "three": "../three-155/build/three.module.js",
      "three/addons/": "../three-155/examples/jsm/"
    }
  }
</script>
<script type="module">
import * as THREE from 'three';
import Stats from 'three/addons/libs/stats.module.js';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { GPUStatsPanel } from 'three/addons/utils/GPUStatsPanel.js';
import { CSS2DRenderer, CSS2DObject } from 'three/addons/renderers/CSS2DRenderer.js';
import { Line2 } from 'three/addons/lines/Line2.js';
import { LineMaterial } from 'three/addons/lines/LineMaterial.js';
import { LineGeometry } from 'three/addons/lines/LineGeometry.js';
let stats, labelRenderer, gpuPanel;
let camera, scene, renderer, controls;
const group = new THREE.Group();
const matLines = [];
let once = true;
init();
initHelp();
initLight();
axesHelperWord();
animate();

let data1 = [
  {
    x: -50,
    y: 50,
    z: 0
  },
  {
    x: 50,
    y: 50,
    z: 0
  },
  {
    x: 50,
    y: -50,
    z: 0
  },
  {
    x: -50,
    y: -50,
    z: 0
  },
  {
    x: -50,
    y: 50,
    z: 0
  }
];

let data2 = [
  {
    x: -50,
    y: 0,
    z: 0
  },
  {
    x: 50,
    y: 1,
    z: 0
  }
];

let data3 = [
  {
    x: -25,
    y: 25,
    z: 0
  },
  {
    x: 25,
    y: 25,
    z: 0
  },
  {
    x: 25,
    y: -25,
    z: 0
  },
  {
    x: -25,
    y: -25,
    z: 0
  },
  {
    x: -25,
    y: 25,
    z: 0
  }
];

let positions1 = [];
let positions2 = [];
let positions3 = [];
let colors = [];
let l = data1.length;

let color = new THREE.Color();

data1.map((v, i) => {
  positions1.push(v.x, v.y, v.z);
  color.setHSL(i / l, 1.0, 0.5);
  colors.push(color.r, color.g, color.b);
});

data2.map((v, i) => {
  positions2.push(v.x, v.y, v.z);
  color.setHSL(i / l, 1.0, 0.5);
  colors.push(color.r, color.g, color.b);
});

data3.map((v, i) => {
  positions3.push(v.x, v.y, v.z);
});

draw(positions1, colors);
draw(positions2, colors);
drawSolidLine(positions3, '#f00');

function draw(positions, colors) {
  let geometry = new LineGeometry();
  // 虚线
  const matLine = new LineMaterial({
    // 只有白色 可以显示出渐变色的效果
    color: 0xffffff,
    linewidth: 10,
    vertexColors: THREE.VertexColors,   // 单独设置顶点颜色
    //resolution:  // renderer.render 时加上这个属性
    dashed: true,
    dashSize: 1,
    gapSize: 1,
    defines: {
      USE_DASH: ''
    }
  });
  let line = new Line2(geometry, matLine);
  line.scale.set(1, 1, 1);
  line.visible = true;
  scene.add(line);
  matLines.push(matLine);
  geometry.setPositions(positions);
  geometry.setColors(colors);
  line.computeLineDistances();
}

function drawSolidLine(positions, color) {
  let geometry = new LineGeometry();
  // 虚线
  const matLine = new LineMaterial({
    // 只有白色 可以显示出渐变色的效果
    color: color,
    linewidth: 10,
    // vertexColors: THREE.VertexColors,   // 单独设置顶点颜色
    // resolution:  // renderer.render 时加上这个属性
    dashed: false
  });
  let line = new Line2(geometry, matLine);
  line.scale.set(1, 1, 1);
  line.visible = true;
  line.rotateX(Math.PI / 3);
  scene.add(line);
  matLines.push(matLine);
  geometry.setPositions(positions);
  line.computeLineDistances();
}

function init() {

  camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 10, 2000 );
  camera.up.set(0, 1, 0);
  camera.position.set(60, 40, 60);
  camera.lookAt(0, 0, 0);

  scene = new THREE.Scene();
  scene.background = new THREE.Color( '#ccc' );

  renderer = new THREE.WebGLRenderer( { antialias: true } );
  renderer.setPixelRatio( window.devicePixelRatio );
  renderer.setSize( window.innerWidth, window.innerHeight );
  document.body.appendChild( renderer.domElement );

  labelRenderer = new CSS2DRenderer();
  labelRenderer.setSize( window.innerWidth, window.innerHeight );
  labelRenderer.domElement.style.position = 'absolute';
  labelRenderer.domElement.style.top = '0px';
  labelRenderer.domElement.style.pointerEvents = 'none';
  document.getElementById( 'container' ).appendChild( labelRenderer.domElement );

  controls = new OrbitControls( camera, renderer.domElement );
  // 设置最大最小视距
  controls.minDistance = 20;
  controls.maxDistance = 1000;

  window.addEventListener( 'resize', onWindowResize );

  stats = new Stats();
  stats.setMode(1); // 0: fps, 1: ms
  document.body.appendChild( stats.dom );

  gpuPanel = new GPUStatsPanel( renderer.getContext() );
  stats.addPanel( gpuPanel );
  stats.showPanel( 0 );

  scene.add( group );
}

function initLight() {
  const AmbientLight = new THREE.AmbientLight(new THREE.Color('rgb(255, 255, 255)'));
  scene.add( AmbientLight );
}

function initHelp() {
  // const size = 100;
  // const divisions = 5;
  // const gridHelper = new THREE.GridHelper( size, divisions );
  // scene.add( gridHelper );

  // The X axis is red. The Y axis is green. The Z axis is blue.
  const axesHelper = new THREE.AxesHelper( 100 );
  scene.add( axesHelper );
}

function axesHelperWord() {
  let xP = addWord('X轴');
  let yP = addWord('Y轴');
  let zP = addWord('Z轴');
  xP.position.set(50, 0, 0);
  yP.position.set(0, 50, 0);
  zP.position.set(0, 0, 50);
}

function addWord(word) {
  let name = `<span>${word}</span>`;
  let moonDiv = document.createElement( 'div' );
  moonDiv.className = 'label';
  // moonDiv.textContent = 'Moon';
  // moonDiv.style.marginTop = '-1em';
  moonDiv.innerHTML = name;
  const label = new CSS2DObject( moonDiv );
  group.add( label );
  return label;
}

function onWindowResize() {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize( window.innerWidth, window.innerHeight );
}

function animate() {
  requestAnimationFrame( animate );
  // 这里请注意	
  // 把渲染窗口尺寸分辨率传值给材质LineMaterial的resolution属性
  // resolution属性值会在着色器代码中参与计算
  if (matLines.length && once) {
    matLines.forEach(matLine => {
      matLine.resolution.set(window.innerWidth, window.innerHeight); // resolution of the viewport
    });
    once = false;
  }

  stats.update();
  controls.update();
  labelRenderer.render( scene, camera );
  renderer.render( scene, camera );
}
</script>
</body>
</html>

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2022年03月 Python(二级)真题解析#中国电子学会#全国青少年软件编程等级考试

Python编程&#xff08;1~6级&#xff09;全部真题・点这里 C/C编程&#xff08;1~8级&#xff09;全部真题・点这里 一、单选题&#xff08;共25题&#xff0c;每题2分&#xff0c;共50分&#xff09; 第1题 关于Python中的列表&#xff0c;下列描述错误的是?&#xff08; …

BUUCTF在线评测简介

1、网站 BUUCTF在线评测简介 BUUCTF在线评测 BUUCTF在线评测BUUCTF 是一个 CTF 竞赛和训练平台&#xff0c;为各位 CTF 选手提供真实赛题在线复现等服务。https://buuoj.cn/challenges 2、介绍 3、学习步骤 学习从这里开始&#xff01;

深入剖析 深度学习中 __init()__函数和forward()函数

目录 前言1. __init()__函数2. forward()函数3. 两者关系 前言 再看代码时&#xff0c;发现init函数和forward函数都有参数&#xff0c;具体是怎么传参的呢&#xff1f; 为了更方便的讲解&#xff0c;会举简单的代码例子结合讲解。 forward() 和 __init__() 是神经网络模型类…

甘特图:如何制定一个有效的项目计划?需要考虑这些方面

一个清晰、可行的计划能够为团队提供明确的方向&#xff0c;确保项目顺利执行&#xff0c;缺乏明确的计划可能导致项目偏离轨道。 甘特图是一种通过条状图形来表示项目和进度的工具&#xff0c;由于其具有视觉化的优点&#xff0c;使得管理者能够更容易地掌握项目进展情况。因…

安捷伦N8485A射频传感器26.5GHz

安捷伦N8485A射频传感器 N8485A 是 Agilent 使用的 26.5 GHz 0.1 瓦射频传感器。电子测试设备传感器测量波形的功率&#xff0c;例如多音和调制射频 (RF) 波形。传感器使用二极管检测器收集高度精确的调制测量值。 用于存储校准系数的 EEPROM 消除了手动输入 10 MHz 至 26.5 GH…

lombok保姆教学

初始化准备工作 所有的环境如下&#xff1a; jdk1.8或者jdk11Springboot2.xmysql5.7或者mysql8.0 首先创建Springboot工程&#xff0c;初次创建初始化速度慢 如果想指定单个项目的maven中央仓库&#xff0c;pom中的配置如下&#xff1a; <!-- 代码库 --><reposito…

BUUCTF学习(一):SQL注入,万能密码

1、场景 2、题目 3、解题 用户名&#xff1a;admin or 11# 密码&#xff1a;123456 4、解析SQL注入 “SQL注入是一种常见的Web应用程序漏洞&#xff0c;攻击者可以通过注入的SQL语句获取数据库的敏感信息&#xff0c;对网站用户的数据安全造成威胁。SQL注入的特点包括广泛性、隐…

如何将领导发的jar包安装到本地的maven仓库

第一步&#xff1a;打开idea右侧的maven功能选择这个图标 第二步&#xff1a;输入maven指令 这个的pom文件的maven管理 1.这个是同一个文件夹下面导入两个jar包。如jdk16和javadoc mvn install:install-file -DfileD:\java\maven\myDepot\aspose-words-16.8.0-jdk16.jar -D…

websocket+node+vite(vue)实现一个简单的聊天

1.前端逻辑 本项目基于之前搭建的vite环境&#xff1a;https://blog.csdn.net/beekim/article/details/128083106?spm1001.2014.3001.5501 新增一个登录页和聊天室页面 <template><div>登录页</div><div>用户名:<input type"text" pl…

uniapp开发H5微信公众号,使用微信的扫一扫等Api试错

记录使用uniapp开发H5微信公众号,有些业务需要用到一些API&#xff0c;比如扫码&#xff0c;h5和微信小程序&#xff0c;app在使用过程中有有些不同&#xff0c;h5使用需要单独引入微信的jsdk,才能使用否则会报错无法使用 引入微信jsdk npm安装 npm install jweixin-module -…

一款优秀的文件外发控制软件 具备哪些优势?

随着越来越多的公司在网上开展业务&#xff0c;网络安全漏洞也相应增加。因此&#xff0c;企业需要保护自己的数据&#xff0c;防止数据泄露&#xff0c;给企业带来损失。近几年来&#xff0c;企业数据泄露事件频发&#xff0c;给许多企业都带来巨大创伤。 乌克兰电力公司在201…

【python入门篇】元组、字典和集合(3)

先来介绍下这三种数据类型&#xff0c;第一个&#xff1a;元组&#xff08;tuple&#xff09;是 python中另一个重要的序列结构&#xff0c;和列表类似&#xff0c;元组也是由一系列按特定顺序排序的元素组成。第二个&#xff1a;python 字典&#xff08;dict&#xff09;是一种…

AIGC|数字时代巨变,创新潮流涌现,万亿市值风口已开!

“2021年至2023年7月期间&#xff0c;AIGC赛道共发生280笔投融资&#xff0c;展现了其高热度与高成长性。在获投的应用与模型层创业项目中&#xff0c;文本、影像、语音平分秋色。”艾瑞咨询在其《2023年中国AIGC产业全景报告》披露国内AIGC的最新投融资情况&#xff0c;这让我…

关于IOC与IOA的学习

[TOC]IOC与IOA学习 IoC 和 IoA&#xff1a;两者有什么区别&#xff1f; IoC 和 IoA 可通过以下四种简单的方法进行区分&#xff1a; 具体工具与动机&#xff1a; IoC 专注于攻击者为实现其意图而使用的特定文件和采取的行动&#xff0c;而 IoA 则专注于这些意图本身。IoC 关…

QT 串口编程 QSerialPort

//创建串口对象QSerialPort s new QSerialPort("/dev/ttySAC2", this);//配置串口信息s->setBaudRate(QSerialPort::Baud9600);//波特率s->setDataBits(QSerialPort::Data8);//数据位s->setStopBits(QSerialPort::OneStop);//奇偶校验s->setParity(QSer…

《向量数据库指南》——Milvus Cloud向量数据库的优势

大禹智库: 随着大模型的爆火,向量数据库也越发成为开发者关注的焦点。为了方便大家更好地了解向量数据库,我们特地推出了《Hello, VectorDB》系列,本文将从宏观角度、向量数据库与其他算法库的区别、技术难点及如何选择向量数据库等方面,带大家认识真正的向量数据库。 在…

simulink创建全局变量MATLAB function引用

matlab版本&#xff1a;2022a 在库浏览器中找到Data Store Memory并放置 双击打开Data Store Memory模块设置变量名 在信号属性中设置初始值、数据类型和信号类型&#xff0c;数据类型和信号类型不能为auto 在记录中勾选“记录数据存储数据” 打开引用该变量的MATLAB function模…

数字时代,VR虚拟展会打造全渠道同步营销新模式

随着经济的快速发展&#xff0c;VR虚拟展会逐步完善&#xff0c;对线下实体展会也产生了重大的影响&#xff0c;在这个数字化时代&#xff0c;展会展览也需要寻找新的表达方式&#xff0c;VR虚拟展会以一种全新的魅力吸引越来越多的观展者。 传统展厅的局限性&#xff1b; 1、…

更新 | 持续开源迅为RK3568驱动指南-驱动基础进阶篇

《iTOP-RK3568开发板驱动开发指南》更新&#xff0c;本次更新内容对应的是驱动&#xff08;第一期_驱动基础-进阶篇&#xff09;视频&#xff0c;后续资料会不断更新&#xff0c;不断完善&#xff0c;帮助用户快速入门&#xff0c;大大提升研发速度。 文档教程更新至驱动基础进…

安捷伦N8482A射频传感器6GHz

安捷伦N8482A射频传感器 N8482A 是 Agilent 使用的 6 GHz 0.1 瓦射频传感器。电子测试设备传感器测量波形的功率&#xff0c;例如多音和调制射频 (RF) 波形。传感器使用二极管检测器收集高度精确的调制测量值。 用于存储校准系数的 EEPROM 消除了手动输入 100 kHz 至 6 GHz 的宽…