ThreeJS:将边缘几何形状应用于ArrowHelper

如何解决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,edgeColor,headWidth ) {

        super();
        // dir is assumed to be normalized

        this.type = 'CustomArrow';

        if ( dir === undefined ) dir = new THREE.Vector3( 0,1 );
        if ( origin === undefined ) origin = new THREE.Vector3( 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,1,0 ],3 ) );
            this._coneGeometry = new THREE.ConeBufferGeometry( 0.5,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);

        // wire frame
        this.wireframe = new THREE.Mesh( this._coneGeometry,new THREE.MeshBasicMaterial( { 
            color: edgeColor,wireframe: true,wireframeLinewidth: 2 } ) );
        this.add(this.wireframe);

        this.setDirection( dir );
        this.setLength( length,headWidth );
    }

    setDirection( dir ) {

        // dir is assumed to be normalized

        if ( dir.y > 0.99999 ) {

            this.quaternion.set( 0,1 );

        } else if ( dir.y < - 0.99999 ) {

            this.quaternion.set( 1,0 );

        } else {

            this._axis.set( dir.z,- dir.x ).normalize();

            const radians = Math.acos( dir.y );

            this.quaternion.setFromAxisAngle( this._axis,radians );

        }

    }

    setLength( length,headWidth ) {

        if ( headLength === undefined ) headLength = 0.2 * length;
        if ( headWidth === undefined ) headWidth = 0.2 * headLength;

        this.line.scale.set( 1,Math.max( 0.0001,length - headLength ),1 ); // see #17458
        this.line.updateMatrix();
        
        this.cone.scale.set( headWidth,headWidth );
        this.cone.position.y = length;
        this.cone.updateMatrix();
        
        this.wireframe.scale.set( headWidth,headWidth );
        this.wireframe.position.y = length;
        this.wireframe.updateMatrix();
    }

    setColor( color ) {
        this.line.material.color.set( color );
        // this.cone.material.color.set( color );
        // this.wireframe.material.color.set( color );
    }

    copy( source ) {
        super.copy( source,false );
        this.line.copy( source.line );
        this.cone.copy( source.cone );
        this.wireframe.copy( source.wireframe );
        return this;
    }
}

由于某些原因,线宽和wireframeLinewidth不会影响线宽。知道为什么吗?

解决方法

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

原始

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

新:

_coneGeometry = new ConeBufferGeometry( 0.5,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。线几何仅包含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 {
  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,100); 
  camera.position.set(0,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,0),new THREE.Vector3(-4,"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.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,1);
  scene.add(co);
  
  renderer.setAnimationLoop(()=>{ 
    renderer.render(scene,camera); 
  });
</script>

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-