ThreeJS中的曲线应用
曲线运动
// 从一系列的点创建一条平滑的三维样条曲线。
curve = new THREE.CatmullRomCurve3(
[
new THREE.Vector3(-10, 0, 10),
new THREE.Vector3(-5, 5, 5),
new THREE.Vector3(0, 0, 5),
new THREE.Vector3(5, -5, 5),
new THREE.Vector3(10, 0, 10),
],
true
);
// 使用getPoint(t)返回一组divisions+1的点
const points = curve.getPoints(500);
// 通过点队列设置该 BufferGeometry 的 attribute。
const geometry = new THREE.BufferGeometry().setFromPoints(points);
const material = new THREE.LineBasicMaterial({ color: 0xff0000 });
const curveObject = new THREE.Line(geometry, material);
scene.add(curveObject);
function animate(){
renderer.render(scene, camera);
const elapsed = clock.getElapsedTime();
const time = elapsed/10%1;
const point = curve.getPoint(time);
moon.position.copy(point);
camera.position.copy(point);
camera.lookAt(earth.position)
requestAnimationFrame(animate)
}
const curveHandles = []; // 曲线控制点数组
// 初始化曲线控制点,设置成立方样条曲线
const initialPoints = [
{ x: 1, y: 0, z: -1 },
{ x: 1, y: 0, z: 1 },
{ x: -1, y: 0, z: 1 },
{ x: -1, y: 0, z: -1 },
];
const boxGeometry = new THREE.BoxGeometry(0.1, 0.1, 0.1);
const boxMaterial = new THREE.MeshBasicMaterial();
for (const handlePos of initialPoints) {
const handle = new THREE.Mesh(boxGeometry, boxMaterial);
handle.position.copy(handlePos);
curveHandles.push(handle);
scene.add(handle);
}
// 创建立方样条曲线
const curve = new THREE.CatmullRomCurve3(
curveHandles.map((handle) => handle.position)
);
curve.curveType = "centripetal"; // 曲线类型(切向加速调整)
curve.closed = true; // 是否封闭
// 创建曲线并根据关键点更新线条
const points = curve.getPoints(50);
const line = new THREE.LineLoop(
new THREE.BufferGeometry().setFromPoints(points),
new THREE.LineBasicMaterial({ color: 0x00ff00 })
);
scene.add(line);
// 加载字体并创建 3D 文本
const loader = new FontLoader();
loader.load("fonts/helvetiker_regular.typeface.json", function (font) {
const geometry = new TextGeometry("Hello three.js!", {
font: font,
size: 0.2,
height: 0.05,
curveSegments: 12,
bevelEnabled: true,
bevelThickness: 0.02,
bevelSize: 0.01,
bevelOffset: 0,
bevelSegments: 5,
});
geometry.rotateX(Math.PI);
const material = new THREE.MeshStandardMaterial({
color: 0x99ffff,
});
const objectToCurve = new THREE.Mesh(geometry, material);
/*
*/
flow = new Flow(objectToCurve);
flow.updateCurve(0, curve);
scene.add(flow.object3D);
});
// 创建射线对象
rayCaster = new THREE.Raycaster();
// 创建变换控制器对象
control = new TransformControls(camera, renderer.domElement);
control.addEventListener("dragging-changed", function (event) {
if (!event.value) {
const points = curve.getPoints(50);
line.geometry.setFromPoints(points);
flow.updateCurve(0, curve);
}
});
// 逐帧动画函数
function animate() {
requestAnimationFrame(animate);
// 判断是否点击场景
if (action === ACTION_SELECT) {
rayCaster.setFromCamera(mouse, camera);
action = ACTION_NONE;
const intersects = rayCaster.intersectObjects(curveHandles, false);
if (intersects.length) {
const target = intersects[0].object;
control.attach(target);
scene.add(control);
}
}
// 曲线模拟器运动
if (flow) {
flow.moveAlongCurve(0.001);
}
// 渲染场景
render();
}
Powered by Waline v2.13.0