Как я могу конвертировать THREE.CatmullRomCurve3 в сетку?
Я создал линейный график в 3D, используя THREE.js и класс CatmullRomCurve3, который заботится о кривых и сглаживании, которые я хотел.
К сожалению, теперь, когда я хочу взять эту кривую и превратить ее в сетку, и, возможно, вытянуть эту сетку, кажется, я не могу. Когда я пытаюсь что-то вроде:
var geometry = new THREE.ShapeGeometry( curve );
var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
var mesh = new THREE.Mesh( geometry, material ) ;
Я получаю ошибки, которые доказывают, что кривая не совсем то, чего хочет конструктор геометрии:
three.js:27731 Uncaught TypeError: shape.extractPoints is not a function
at ExtrudeBufferGeometry.addShape (three.js:27731)
at ExtrudeBufferGeometry.addShapeList (three.js:27656)
at new ExtrudeBufferGeometry (three.js:27612)
at new ChartTest (ChartTest.js:33)
at createSceneSubjects (SceneManager.js:89)
at new SceneManager (SceneManager.js:27)
at main.js:16
Я видел примеры, когда кривая передается как параметр extrudePath, например:
var extrudeSettings = {
steps : 100,
bevelEnabled : false,
extrudePath : curve
};
но для этого требуется, чтобы фигура была передана в ExtrudeGeometry вместе с extrudeSettings, но должен быть более простой способ, чем попытка создать отдельную фигуру, когда кривая уже определяет форму, которую я хочу вытянуть. (Это также, кажется, вытесняет путь, а не форму, которую он описывает.)
Любая помощь будет принята с благодарностью!
2 ответа
ShapeGeometry
ожидает экземпляр типа THREE.Shape
как параметр, а не объект типа THREE.Curve
, Кроме того, THREE.CatmullRomCurve3
3D-кривая, тогда как THREE.Shape
является 2D-сущностью. Это означает, что ваши фигуры всегда будут плоскими. Вы можете сделать следующее, чтобы все заработало:
Образец вы кривые сначала, а затем создать экземпляр THREE.Shape
, Имейте в виду, что z-координаты заданных точек будут игнорироваться.
const points = curve.getPoints( 64 );
const shape = new THREE.Shape( points );
const geometry = new THREE.ShapeGeometry( shape );
https://jsfiddle.net/f2Lommf5/3775/
three.js R91
В случае, если вам нужна какая-то лента, вот примерное представление о том, как вы можете это сделать:
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(-0.5, 4, 5);
var renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var controls = new THREE.OrbitControls(camera, renderer.domElement);
var curve = new THREE.CatmullRomCurve3(
[
new THREE.Vector3(-2, 2, 0),
new THREE.Vector3(-1, 0.5, 0),
new THREE.Vector3(0, 1, 0),
new THREE.Vector3(1, 3, 0),
new THREE.Vector3(2, 1, 0)
]
);
var pointsCount = 50;
var pointsCount1 = pointsCount + 1;
var points = curve.getPoints(pointsCount);
var pts = curve.getPoints(pointsCount);
var width = 2;
var widthSteps = 1;
let pts2 = curve.getPoints(pointsCount);
pts2.forEach(p => {
p.z += width;
});
pts = pts.concat(pts2);
var ribbonGeom = new THREE.BufferGeometry().setFromPoints(pts);
var indices = [];
for (iy = 0; iy < widthSteps; iy++) { // the idea taken from PlaneBufferGeometry
for (ix = 0; ix < pointsCount; ix++) {
var a = ix + pointsCount1 * iy;
var b = ix + pointsCount1 * (iy + 1);
var c = (ix + 1) + pointsCount1 * (iy + 1);
var d = (ix + 1) + pointsCount1 * iy;
// faces
indices.push(a, b, d);
indices.push(b, c, d);
}
}
ribbonGeom.setIndex(indices);
ribbonGeom.computeVertexNormals();
var ribbon = new THREE.Mesh(ribbonGeom, new THREE.MeshNormalMaterial({
side: THREE.DoubleSide
}));
scene.add(ribbon);
var line = new THREE.Line(new THREE.BufferGeometry().setFromPoints(points), new THREE.LineBasicMaterial({
color: "red",
depthTest: false
}));
scene.add(line);
render();
function render() {
requestAnimationFrame(render);
renderer.render(scene, camera);
}
body {
overflow: hidden;
margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/91/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>