Как преобразовать 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, но должен быть более простой способ, чем попытка создать отдельную форму, когда кривая уже определяет форму, которую я хочу выдавить. (Это также, кажется, выдавливает путь, а не форму, которую он описывает.)

Любая помощь будет принята с благодарностью!


person sands    schedule 25.03.2018    source источник
comment
Немного непонятно, в чем у вас проблема. Вы пытаетесь создать ленту или реальное тело? Похоже, у вас есть решение, но вам не нравится, как оно реализовано?   -  person manthrax    schedule 25.03.2018
comment
Кроме того, вы можете добавить фотографии того, что у вас есть и чего вы хотите достичь.   -  person prisoner849    schedule 25.03.2018


Ответы (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

person Mugen87    schedule 25.03.2018
comment
Привет, кажется, это не работает с более новыми версиями (0.106.2). Вы знаете, как это делается в более новой версии, пожалуйста? - person wassx; 19.07.2019
comment
Что значит не работать? Скрипка по-прежнему работает с последней версией R106. - person Mugen87; 20.07.2019
comment
Извините, я перепутал в своем коде с THREE.Geometry. - person wassx; 21.07.2019

В случае, если вам нужна лента, вот примерное представление о том, как вы можете это сделать:

введите здесь описание изображения

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>

person prisoner849    schedule 25.03.2018