【问题标题】:Draw a circle (not shaded) with Three.js用 Three.js 画一个圆(没有阴影)
【发布时间】:2012-11-25 05:16:19
【问题描述】:

我正在尝试画一个与this 网站上的轨道图案非常相似的圆圈。我想使用 Three.js 而不是纯 WebGL。

【问题讨论】:

    标签: javascript three.js geometry


    【解决方案1】:

    Three.js r50 添加了CircleGeometry。在WebGL Geometries example 中可以看到(尽管有一张脸)。

    几何中的第一个顶点是在圆的中心创建的(在 r84 中,请参阅 CircleGeometry.js line 71,在 r65 中,请参阅 CircleGeometry.js line 18),如果您要使用“完整的吃豆人”,这很不错或“信息不足的饼图”外观。哦,如果您要使用除 LineBasicMaterial / LineDashedMaterial 之外的任何材料,这似乎是必要的。

    我已验证以下代码在 r60 和 r65 中都有效:

    var radius   = 100,
        segments = 64,
        material = new THREE.LineBasicMaterial( { color: 0x0000ff } ),
        geometry = new THREE.CircleGeometry( radius, segments );
    
    // Remove center vertex
    geometry.vertices.shift();
    
    // Non closed circle with one open segment:
    scene.add( new THREE.Line( geometry, material ) );
    
    // To get a closed circle use LineLoop instead (see also @jackrugile his comment):
    scene.add( new THREE.LineLoop( geometry, material ) );
    

    PS:“文档”现在包含一个不错的 CircleGeometry 交互式示例:https://threejs.org/docs/#api/geometries/CircleGeometry

    【讨论】:

    【解决方案2】:

    在新版本的 Threejs 中,API 略有变化。

    var segmentCount = 32,
        radius = 100,
        geometry = new THREE.Geometry(),
        material = new THREE.LineBasicMaterial({ color: 0xFFFFFF });
    
    for (var i = 0; i <= segmentCount; i++) {
        var theta = (i / segmentCount) * Math.PI * 2;
        geometry.vertices.push(
            new THREE.Vector3(
                Math.cos(theta) * radius,
                Math.sin(theta) * radius,
                0));            
    }
    
    scene.add(new THREE.Line(geometry, material));
    

    根据场景需要修改segmentCount 以使圆更平滑或更锯齿状。对于小圆圈,32 段将非常平滑。对于您链接的网站上的轨道,您可能需要几百个。

    修改Vector3构造函数中三个组件的顺序以选择圆的方向。如此处给出的,圆将与 x/y 平面对齐。

    【讨论】:

    • 当我服用 THREE.Mesh 时,这不起作用......有什么想法吗?
    【解决方案3】:

    我使用了 Mr.doob 在this github post 中引用的代码。

    var resolution = 100;
    var amplitude = 100;
    var size = 360 / resolution;
    
    var geometry = new THREE.Geometry();
    var material = new THREE.LineBasicMaterial( { color: 0xFFFFFF, opacity: 1.0} );
    for(var i = 0; i <= resolution; i++) {
        var segment = ( i * size ) * Math.PI / 180;
        geometry.vertices.push( new THREE.Vertex( new THREE.Vector3( Math.cos( segment ) * amplitude, 0, Math.sin( segment ) * amplitude ) ) );         
    }
    
    var line = new THREE.Line( geometry, material );
    scene.add(line);
    

    【讨论】:

    • 当我使用 var mesh = new THREE.Mesh( geometry, material ); 这不起作用任何想法..?
    【解决方案4】:

    此示例在 Three.js 文档中:

    var material = new THREE.MeshBasicMaterial({
        color: 0x0000ff
    });
    
    var radius = 5;
    var segments = 32; //<-- Increase or decrease for more resolution I guess
    
    var circleGeometry = new THREE.CircleGeometry( radius, segments );              
    var circle = new THREE.Mesh( circleGeometry, material );
    scene.add( circle );
    

    【讨论】:

      【解决方案5】:

      我不得不这样做哈哈:

      function createCircle() {
          let circleGeometry = new THREE.CircleGeometry(1.0, 30.0);
          circleGeometry.vertices.splice(0, 1); //<= This.
          return new THREE.LineLoop(circleGeometry,
              new THREE.LineBasicMaterial({ color: 'blue' }));
      }
      let circle = createCircle();
      

      原因:否则,它不会画一个“纯”圆,有一条线从圆心到圆的边缘,即使你使用 LineLoop 而不是 Line 。从数组中拼接(删除)第一个顶点是一种技巧,但似乎可以解决问题。 :)

      (请注意,显然,根据mrienstra's answer,“哦,如果您要使用除 LineBasicMaterial / LineDashedMaterial 之外的任何材料,这似乎是必要的。”)


      不过,如果你想要厚度,you're screwed ("Due to limitations of the OpenGL Core Profile with the WebGL renderer on most platforms linewidth will always be 1 regardless of the set value.")...除非你使用:https://github.com/spite/THREE.MeshLine

      代码示例在这里:https://stackoverflow.com/a/61312721/1599699

      【讨论】:

        【解决方案6】:

        查看three.js 示例http://mrdoob.github.com/three.js/examples/webgl_lines_colors.html 了解如何绘制彩色线条。

        一个像你引用的那样的圆圈被画成一个大的#小直线段。 (其实你显示的可能是省略号)

        【讨论】:

          【解决方案7】:
          var getStuffDashCircle2 = function () {
          
          var segment = 100, radius = 100;
          
          var lineGeometry = new THREE.Geometry();
          var vertArray = lineGeometry.vertices;
          var angle = 2 * Math.PI / segment;
          for (var i = 0; i < segment; i++) {
              var x = radius * Math.cos(angle * i);
              var y = radius * Math.sin(angle * i);
              vertArray.push(new THREE.Vector3(x, y, 0));
          }
          lineGeometry.computeLineDistances();
          var lineMaterial = new THREE.LineDashedMaterial({ color: 0x00cc00, dashSize: 4, gapSize: 2 });
          var circle = new THREE.Line(lineGeometry, lineMaterial);
          
          circle.rotation.x = Math.PI / 2;
          circle.position.y = cylinderParam.trackHeight+20;
          return   circle;
          }
          

          【讨论】:

            【解决方案8】:

            我在获取其他答案时遇到了一些问题 - 特别是,CircleGeometry 在圆的中心有一个额外的点,我不喜欢尝试删除该顶点的黑客行为。

            EllipseCurve 做我想做的事(在 r135 中验证):

            const curve = new THREE.EllipseCurve(
              0.0, 0.0,            // Center x, y
              10.0, 10.0,          // x radius, y radius
              0.0, 2.0 * Math.PI,  // Start angle, stop angle
            );
            
            const pts = curve.getSpacedPoints(256);
            const geo = new THREE.BufferGeometry().setFromPoints(pts);
            
            const mat = new THREE.LineBasicMaterial({ color: 0xFF00FF });
            const circle = new THREE.LineLoop(geo, mat);
            scene.add(circle);
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多