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


    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>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
  • 相关阅读:
    关于java业务层是否抛异常
    数字电路基础02(用2选1MUX实现与、或、非、与非、或非、异或、同或)
    Django模型的使用
    英语四级XYZ字母开头单词+托福高频单词
    无线传感器网络(Wireless Sensor Networks)概述
    Linux的子shell
    PMP备考敏捷考题的五点应对策略
    SpringCLoud——服务的拆分和远程调用
    改进YOLOv7系列:首发最新结合多种X-Transformer结构新增小目标检测层,让YOLO目标检测任务中的小目标无处遁形
    数据结构——C++实现二叉搜索树,前中后序、层序迭代遍历配合仿函数
  • 原文地址:https://blog.csdn.net/weixin_44384273/article/details/133854118