如何将THREE.CatmullRomCurve3转换为网格?

时间:2018-03-25 04:09:41

标签: javascript three.js geometry catmull-rom-curve

我使用THREE.js和 CatmullRomCurve3 类在3D中创建了一个折线图,它可以处理我想要的曲线和平滑。

不幸的是,现在我想把这条曲线变成一个网格,并且可能挤出那个网格,看起来我不能。当我尝试这样的事情时:

    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 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:1)

在这种情况下,如果你想要一种功能区,这里有一个关于你如何做到这一点的粗略概念:

enter image description here

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>