我可以通过指定三个坐标,即 - start,mid和end,在three.js中绘制样条线。在这样做时,曲线从“开始”的坐标开始,一直上升到中间并下降到“结束”的坐标。这是同一个jsbin。
但是,我现在只想绘制样条的下半部分,即仅从'mid'到'end'的部分。
编辑:添加以下代码
<html>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r75/three.js"></script>
<script>
// global variables
var renderer;
var scene;
var camera;
var geometry;
var control;
var count = 0;
var animationTracker;
init();
drawSpline();
function init()
{
// create a scene, that will hold all our elements such as objects, cameras and lights.
scene = new THREE.Scene();
// create a camera, which defines where we're looking at.
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
// create a render, sets the background color and the size
renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0x000000, 1.0);
renderer.setSize(window.innerWidth, window.innerHeight);
// position and point the camera to the center of the scene
camera.position.x = 0;
camera.position.y = 40;
camera.position.z = 40;
camera.lookAt(scene.position);
// add the output of the renderer to the html element
document.body.appendChild(renderer.domElement);
}
function drawSpline(numPoints)
{
var numPoints = 100;
// var start = new THREE.Vector3(-5, 0, 20);
var start = new THREE.Vector3(-5, 0, 20);
var middle = new THREE.Vector3(0, 35, 0);
var end = new THREE.Vector3(5, 0, -20);
var curveQuad = new THREE.QuadraticBezierCurve3(start, middle, end);
var tube = new THREE.TubeGeometry(curveQuad, numPoints, 0.5, 20, false);
var mesh = new THREE.Mesh(tube, new THREE.MeshNormalMaterial({
opacity: 0.9,
transparent: true
}));
scene.add(mesh);
renderer.render(scene, camera);
}
</script>
</body>
</html>
我提到过只想要掉落部分来“适应场景”。我的意思是,只有下降部分应该占据整个图像占据的空间。否则,如果仅从样条曲线的'mid'之后修剪掉顶点,那么样条曲线的部分将非常小,就像在下面的第二张图片中一样(使用绘画裁剪掉)。
答案 0 :(得分:1)
我在下面展示了绘制三维二次贝塞尔曲线的一半(或任何比例)的一种方法。数学基于DeCasteljau的算法(如果我理解正确的话)。数学显示在代码中包含的额外函数中,即splitQuadraticBezierCurve
和getPointAtT
。 THREE.js有一些与getPointAtT
类似的功能,特别是getPoint
,还有一个getTangent
函数。但是,我还不知道如何使用getTangent
,所以我最终只是自己实现数学。反正这并不困难。
使用下图可以更好地理解分割曲线的基本原理:
v
代表向量(或点),v0
,v1
和v2
是从您的初始二次曲线中检索到的,并且是您的原始start
},middle
和end
点。 v01
和v12
沿指示的行距离为t
(在您的情况下为0.5),而v012
距t
之间的距离v01
}和v12
。该函数返回一个2元素数组,其中原始二次曲线的第一个(元素0)和第二个(元素1)“一半”。第一个“半”曲线的起点,中点和终点为v0
,v01
&amp; v012
。第二个“半”曲线的起点,中点和终点为v012
,v12
&amp; v2
。
代码为第二个“半”曲线生成以下图像:
手动裁剪此图像。获得形状“填充”屏幕是手动完成的。要以编程方式执行“填充”取决于您对更改和/或愿意和/或能够更改感兴趣的内容:相机的位置?相机的角度?相机的视野?对象的位置?视图宽度/高度/比例?因此,我在这里没有提到这一点。但是,我希望这个答案至少能告诉你如何分割二次贝塞尔曲线。
// global variables
var renderer;
var scene;
var camera;
var geometry;
var control;
var count = 0;
var animationTracker;
init();
drawSpline();
function init()
{
// create a scene, that will hold all our elements such as objects, cameras and lights.
scene = new THREE.Scene();
// create a camera, which defines where we're looking at.
camera = new THREE.PerspectiveCamera(20, window.innerWidth / window.innerHeight, 0.1, 1000);
// create a render, sets the background color and the size
renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0x000000, 1.0);
renderer.setSize(window.innerWidth, window.innerHeight);
// position and point the camera to the center of the scene
camera.position.set(0, 40, 40);
camera.lookAt(new THREE.Vector3(0, 15, 0));
// add the output of the renderer to the html element
document.body.appendChild(renderer.domElement);
}
function getPointAtT(vA, vB, t) {
return new THREE.Vector3(
vA.x + (vB.x - vA.x) * t,
vA.y + (vB.y - vA.y) * t,
vA.z + (vB.z - vA.z) * t
);
}
function splitQuadraticBezierCurve(quad, t) {
var v0 = quad.v0;
var v1 = quad.v1;
var v2 = quad.v2;
var v01 = getPointAtT(v0, v1, t);
var v12 = getPointAtT(v1, v2, t);
var v012 = getPointAtT(v01, v12, t);
var firstHalf = new THREE.QuadraticBezierCurve3(v0, v01, v012);
var secondHalf = new THREE.QuadraticBezierCurve3(v012, v12, v2 );
return [firstHalf, secondHalf];
}
function drawSpline()
{
var numPoints = 100;
var start = new THREE.Vector3(-5, 0, 20);
var middle = new THREE.Vector3(0, 30, 0);
var end = new THREE.Vector3(5, 0, -20);
var curveQuad = new THREE.QuadraticBezierCurve3(start, middle, end);
var FIRST_HALF = 0;
var SECOND_HALF = 1;
var curveProportion = 0.5;
var secondHalfCurveQuad = splitQuadraticBezierCurve(curveQuad, curveProportion)[SECOND_HALF];
var tube = new THREE.TubeGeometry(secondHalfCurveQuad, numPoints, 0.5, 20, false);
var mesh = new THREE.Mesh(tube, new THREE.MeshNormalMaterial({
opacity: 0.9,
transparent: true
}));
scene.add(mesh);
renderer.render(scene, camera);
}