为了账号安全,请及时绑定邮箱和手机立即绑定

ThreeJS:将边缘几何应用到 ArrowHelper

ThreeJS:将边缘几何应用到 ArrowHelper

人到中年有点甜 2023-02-17 17:32:48
我正在尝试在 ThreeJS 中使用 ArrowHelper 创建一个箭头:let arrow = new THREE.ArrowHelper(direction.normalize(), new THREE.Vector3(), length, color, headLength, headWidth);我还想为边缘使用单独的颜色。我意识到我需要使用 THREE.EdgesGeometry,但我不太明白如何应用它。有人能帮帮我吗?更新 抱歉混淆,我认为箭头使用金字塔,而不是圆锥体。有没有办法用金字塔代替锥体并为边缘使用不同的颜色?更新谢谢大家的回答,他们真的很有帮助。我最终创建了自定义箭头类(从 ArrowHelper 复制了大部分代码):class CustomArrow extends THREE.Object3D {    constructor( dir, origin, length, color, edgeColor, headLength, headWidth ) {        super();        // dir is assumed to be normalized        this.type = 'CustomArrow';        if ( dir === undefined ) dir = new THREE.Vector3( 0, 0, 1 );        if ( origin === undefined ) origin = new THREE.Vector3( 0, 0, 0 );        if ( length === undefined ) length = 1;        if ( color === undefined ) color = 0xffff00;        if ( headLength === undefined ) headLength = 0.2 * length;        if ( headWidth === undefined ) headWidth = 0.2 * headLength;        if ( this._lineGeometry === undefined ) {            this._lineGeometry = new THREE.BufferGeometry();            this._lineGeometry.setAttribute( 'position', new THREE.Float32BufferAttribute( [ 0, 0, 0, 0, 1, 0 ], 3 ) );            this._coneGeometry = new THREE.ConeBufferGeometry( 0.5, 1, 6);            this._coneGeometry.translate( 0, - 0.5, 0 );            this._axis = new THREE.Vector3();        }        this.position.copy( origin );        this.line = new THREE.Line( this._lineGeometry, new THREE.LineBasicMaterial( { color: color, toneMapped: false, linewidth: 4 } ) );        this.line.matrixAutoUpdate = false;        this.add( this.line )        // base material                this.cone = new THREE.Mesh( this._coneGeometry, new THREE.MeshBasicMaterial( { color: color, toneMapped: false } ) );        this.add(this.cone);    }由于某种原因 linewidth 和 wireframeLinewidth 不影响线宽。知道为什么吗?
查看完整描述

2 回答

?
jeck猫

TA贡献1909条经验 获得超7个赞

编辑:金字塔是一个有 4 个径向段的圆锥体,如果需要,请查看 arrowhelper 如何根据参数构造它的圆锥体(带有锥形 CylinderGeometry)和线,并将其替换为构造如下的圆锥体几何体:

原来的:

_coneGeometry = new CylinderBufferGeometry( 0, 0.5, 1, 5, 1 );

新的:

_coneGeometry = new ConeBufferGeometry( 0.5, 1, 4);

然后您不必使用 EdgesGeometry,而是使用线框材质选项(根据 @prisoner849 的评论):

let wireframeMaterial = new THREE.MeshBasicMaterial({color: "aqua", wireframe: true});
let coneEdgeMesh = new THREE.Mesh(_coneGeometry, wireframeMaterial);

原答案:

THREE.ArrowHelper 由 2 个 Object3D 组成:一个 THREE.Line 用于直线,另一个 THREE.Mesh 用于箭头的圆锥体。Line 几何图形仅包含 2 个点并且没有边,因为它是一条线,但对于圆锥体,您可以使用:

let coneEdgeGeometry = new THREE.EdgesGeometry(arrow.cone.geometry);

然后你用你想要的边几何和颜色构造一个 LineSegments 对象:

let line = new THREE.LineSegments( coneEdgeGeometry, new THREE.LineBasicMaterial( { color: 0xffffff } ) );
arrow.add(line);

如果锥体边缘未显示,请尝试将 THREE.LineSegments 的 renderOrder 设置为 -1(这可能会产生其他问题)


查看完整回答
反对 回复 2023-02-17
?
翻过高山走不出你

TA贡献1875条经验 获得超3个赞

您可以像这样更改箭头锥体的颜色:


body {

  overflow: hidden;

  margin: 0;

}

<script type="module">

  import * as THREE from "https://threejs.org/build/three.module.js";     

  import {OrbitControls} from "https://threejs.org/examples/jsm/controls/OrbitControls.js"; 

  

  let scene = new THREE.Scene(); 

  let camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight,

  1, 100); 

  camera.position.set(0, 5, 10); 

  let renderer = new THREE.WebGLRenderer(); 

  renderer.setSize(innerWidth, innerHeight); 

  document.body.appendChild(renderer.domElement); 

  

  new OrbitControls(camera, renderer.domElement); 

  

  scene.add(new THREE.GridHelper());

  

  // different colors 

  let ah = new THREE.ArrowHelper( 

    new THREE.Vector3(0, 1, 0), 

    new THREE.Vector3(-4, 0, 0), 

    5, 

    "magenta" /* default colour */); 

  ah.cone.material.color.set("red"); // change color of cone

  scene.add(ah); 

  

  // colourful pyramid

  let cg = new THREE.SphereBufferGeometry(0.5, 4, 2).toNonIndexed();

  let pos = cg.attributes.position;

  for (let i = 0; i < pos.count; i++){

    if (pos.getY(i) < 0) pos.setY(i, 0);

  }

  console.log(cg);

  let cls = [

    new THREE.Color("red"),

    new THREE.Color("green"),

    new THREE.Color("blue"),

    new THREE.Color("yellow")

  ]

  let colors = [];

  for(let i = 0; i < 2; i++){

    cls.forEach( (c) => {

      colors.push(c.r, c.g, c.b);

      colors.push(c.r, c.g, c.b);

      colors.push(c.r, c.g, c.b);

    });

  }

  cg.setAttribute("color", new THREE.Float32BufferAttribute(colors, 3));

  

  let cm = new THREE.MeshBasicMaterial({vertexColors: true});

  let co = new THREE.Mesh(cg, cm);

  co.scale.set(1, 5, 1);

  scene.add(co);

  

  renderer.setAnimationLoop(()=>{ 

    renderer.render(scene, camera); 

  });

</script>

展开片段


查看完整回答
反对 回复 2023-02-17
  • 2 回答
  • 0 关注
  • 185 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信