我正在尝试使用ArrowHelper在ThreeJS中创建一个箭头:
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);
// wire frame
this.wireframe = new THREE.Mesh( this._coneGeometry, new THREE.MeshBasicMaterial( {
color: edgeColor,
toneMapped: false,
wireframe: true,
wireframeLinewidth: 2 } ) );
this.add(this.wireframe);
this.setDirection( dir );
this.setLength( length, headLength, headWidth );
}
setDirection( dir ) {
// dir is assumed to be normalized
if ( dir.y > 0.99999 ) {
this.quaternion.set( 0, 0, 0, 1 );
} else if ( dir.y < - 0.99999 ) {
this.quaternion.set( 1, 0, 0, 0 );
} else {
this._axis.set( dir.z, 0, - dir.x ).normalize();
const radians = Math.acos( dir.y );
this.quaternion.setFromAxisAngle( this._axis, radians );
}
}
setLength( length, headLength, 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, headLength, headWidth );
this.cone.position.y = length;
this.cone.updateMatrix();
this.wireframe.scale.set( headWidth, headLength, 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不影响线宽。知道为什么吗?
发布于 2020-09-07 11:41:10
编辑:金字塔是一个包含4个径向段的圆锥,如果您想这样做的话,看看阿罗海珀如何构造它的锥(它是用锥形的CylinderGeometry构造的)和基于参数的直线,然后用如下所构造的锥几何来替换它:
原件:
_coneGeometry = new CylinderBufferGeometry( 0, 0.5, 1, 5, 1 );新:
_coneGeometry = new ConeBufferGeometry( 0.5, 1, 4);然后,您不必使用EdgesGeometry,而是使用有线框架材料选项(per @Pricer849的注释):
let wireframeMaterial = new THREE.MeshBasicMaterial({color: "aqua", wireframe: true});
let coneEdgeMesh = new THREE.Mesh(_coneGeometry, wireframeMaterial);原来的答案:
THREE.ArrowHelper由两个Object3Ds组成:一个THREE.Line表示直线,一个THREE.Mesh表示箭头锥。这条线的几何只包含两个点,没有边,因为它是一条线,但是对于圆锥,你可以使用:
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的THREE.LineSegments设置为-1 (这可能会导致其他问题)。
发布于 2020-09-07 11:33:04
你可以这样改变箭头锥的颜色:
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>
https://stackoverflow.com/questions/63776448
复制相似问题