如何解决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 举报,一经查实,本站将立刻删除。