ThreeJS:将边缘几何应用到 ArrowHelper

我正在尝试在 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 不影响线宽。知道为什么吗?


人到中年有点甜
浏览 198回答 2
2回答

jeck猫

编辑:金字塔是一个有 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(这可能会产生其他问题)

翻过高山走不出你

您可以像这样更改箭头锥体的颜色:body {&nbsp; overflow: hidden;&nbsp; margin: 0;}<script type="module">&nbsp; import * as THREE from "https://threejs.org/build/three.module.js";&nbsp; &nbsp; &nbsp;&nbsp; import {OrbitControls} from "https://threejs.org/examples/jsm/controls/OrbitControls.js";&nbsp;&nbsp;&nbsp;&nbsp; let scene = new THREE.Scene();&nbsp;&nbsp; let camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight,&nbsp; 1, 100);&nbsp;&nbsp; camera.position.set(0, 5, 10);&nbsp;&nbsp; let renderer = new THREE.WebGLRenderer();&nbsp;&nbsp; renderer.setSize(innerWidth, innerHeight);&nbsp;&nbsp; document.body.appendChild(renderer.domElement);&nbsp;&nbsp;&nbsp;&nbsp; new OrbitControls(camera, renderer.domElement);&nbsp;&nbsp;&nbsp;&nbsp; scene.add(new THREE.GridHelper());&nbsp;&nbsp;&nbsp; // different colors&nbsp;&nbsp; let ah = new THREE.ArrowHelper(&nbsp;&nbsp; &nbsp; new THREE.Vector3(0, 1, 0),&nbsp;&nbsp; &nbsp; new THREE.Vector3(-4, 0, 0),&nbsp;&nbsp; &nbsp; 5,&nbsp;&nbsp; &nbsp; "magenta" /* default colour */);&nbsp;&nbsp; ah.cone.material.color.set("red"); // change color of cone&nbsp; scene.add(ah);&nbsp;&nbsp;&nbsp;&nbsp; // colourful pyramid&nbsp; let cg = new THREE.SphereBufferGeometry(0.5, 4, 2).toNonIndexed();&nbsp; let pos = cg.attributes.position;&nbsp; for (let i = 0; i < pos.count; i++){&nbsp; &nbsp; if (pos.getY(i) < 0) pos.setY(i, 0);&nbsp; }&nbsp; console.log(cg);&nbsp; let cls = [&nbsp; &nbsp; new THREE.Color("red"),&nbsp; &nbsp; new THREE.Color("green"),&nbsp; &nbsp; new THREE.Color("blue"),&nbsp; &nbsp; new THREE.Color("yellow")&nbsp; ]&nbsp; let colors = [];&nbsp; for(let i = 0; i < 2; i++){&nbsp; &nbsp; cls.forEach( (c) => {&nbsp; &nbsp; &nbsp; colors.push(c.r, c.g, c.b);&nbsp; &nbsp; &nbsp; colors.push(c.r, c.g, c.b);&nbsp; &nbsp; &nbsp; colors.push(c.r, c.g, c.b);&nbsp; &nbsp; });&nbsp; }&nbsp; cg.setAttribute("color", new THREE.Float32BufferAttribute(colors, 3));&nbsp;&nbsp;&nbsp; let cm = new THREE.MeshBasicMaterial({vertexColors: true});&nbsp; let co = new THREE.Mesh(cg, cm);&nbsp; co.scale.set(1, 5, 1);&nbsp; scene.add(co);&nbsp;&nbsp;&nbsp; renderer.setAnimationLoop(()=>{&nbsp;&nbsp; &nbsp; renderer.render(scene, camera);&nbsp;&nbsp; });</script>展开片段
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript