在ThreeJS中设置贝塞尔曲线的动画

时间:2017-01-18 20:14:51

标签: javascript three.js

我想在ThreeJS中为bezier曲线制作动画。开始,结束和控制点将更新。最终我需要一次制作许多曲线动画。最有效的方法是什么?

如果您运行下面的代码段,您会看到我每次渲染帧时都会创建Bezier对象,几何和直线。我从场景中删除了上一行,然后添加了新的更新行。有没有更好的办法?也许只更新几何体而不再添加线?



var camera, scene, renderer, geometry, material, mesh;

init();
animate();

/**
 Create the scene, camera, renderer
*/
function init() {
  scene = new THREE.Scene();
  camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 10000);
  camera.position.z = 500;
  scene.add(camera);
  addCurve();
  renderer = new THREE.WebGLRenderer();
  renderer.setSize(window.innerWidth, window.innerHeight);
  document.body.appendChild(renderer.domElement);
}

/**
 Add the initial bezier curve to the scene
*/
function addCurve() {
  testPoint = 0;
  curve = new THREE.CubicBezierCurve3(
    new THREE.Vector3( testPoint, 0, 0 ),
    new THREE.Vector3( -5, 150, 0 ),
    new THREE.Vector3( 20, 150, 0 ),
    new THREE.Vector3( 10, 0, 0 )
  );
  curveGeometry = new THREE.Geometry();
  curveGeometry.vertices = curve.getPoints( 50 );
  curveMaterial = new THREE.LineBasicMaterial( { color : 0xff0000 } );
  curveLine = new THREE.Line( curveGeometry, curveMaterial );
  scene.add(curveLine);
}

/**
 On each frame render, remove the old line, create new curve, geometry and add the new line
*/
function updateCurve() {
  testPoint ++;
  scene.remove(curveLine);
  curve = new THREE.CubicBezierCurve3(
    new THREE.Vector3( testPoint, 0, 0 ),
    new THREE.Vector3( -5, 150, 0 ),
    new THREE.Vector3( 20, 150, 0 ),
    new THREE.Vector3( 10, 0, 0 )
  );
  curveGeometry = new THREE.Geometry();
  curveGeometry.vertices = curve.getPoints( 50 );
  curveLine = new THREE.Line( curveGeometry, curveMaterial );
  scene.add(curveLine);
}

function animate() {
  requestAnimationFrame(animate);
  render();
}

function render() {
  updateCurve();
  renderer.render(scene, camera);
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r83/three.min.js"></script>
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:3)

每帧创建新行是非常广泛的操作。

创建动画曲线的最佳方法是什么?

可能使用shaders。但是实施起来需要花费更多的时间,所以如果我的下一个建议对你来说足够了,那就是他们。

改善代码中的曲线更新

我尽量不改变你的很多代码。使用“// EDITED”注释标记已修改的地点。我添加了一个数组,因为你说会有很多曲线。

<强>解释

  • 正如@WestLangley所述,尽量避免在动画循环中使用new关键字。
  • CubicBezierCurve3具有v0v1v2v3属性。那些是你从一开始就提供的THREE.Vector3.getPoints()使用它们返回顶点数组。因此,您只需更改它们即可,无需new个关键字。 See this line for more details.
  • 而不是重新创建线条,在您的情况下,您可以简单地更新几何体。因为你有一个THREE.Line - 你的几何只需要顶点。更改顶点后,您应设置geometry.verticesNeedUpdate = true或Three.js将忽略您的更改。

var camera, scene, renderer, geometry, material, mesh, curves = [];

init();
animate();

/**
 Create the scene, camera, renderer
*/
function init() {
  scene = new THREE.Scene();
  camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 10000);
  camera.position.z = 500;
  scene.add(camera);
  addCurve();
  renderer = new THREE.WebGLRenderer();
  renderer.setSize(window.innerWidth, window.innerHeight);
  document.body.appendChild(renderer.domElement);
}

/**
 Add the initial bezier curve to the scene
*/
function addCurve() {
  testPoint = 0;
  curve = new THREE.CubicBezierCurve3(
    new THREE.Vector3( testPoint, 0, 0 ),
    new THREE.Vector3( -5, 150, 0 ),
    new THREE.Vector3( 20, 150, 0 ),
    new THREE.Vector3( 10, 0, 0 )
  );
  curveGeometry = new THREE.Geometry();
  curveGeometry.vertices = curve.getPoints( 50 );
  curveMaterial = new THREE.LineBasicMaterial( { color : 0xff0000 } );
  curveLine = new THREE.Line( curveGeometry, curveMaterial );
  scene.add(curveLine);
  
  // EDITED
  curves.push(curveLine); // Add curve to curves array
  curveLine.curve = curve; // Link curve object to this curveLine
}

/**
 On each frame render, remove the old line, create new curve, geometry and add the new line
*/
function updateCurve() {
  testPoint ++;
  
  // EDITED
  for (var i = 0, l = curves.length; i < l; i++) {
    var curveLine = curves[i];
    
    // Update x value of v0 vector
    curveLine.curve.v0.x = testPoint;
    // Update vertices
    curveLine.geometry.vertices = curveLine.curve.getPoints( 50 ); 
    // Let's three.js know that vertices are changed
    curveLine.geometry.verticesNeedUpdate = true;
  }
}

function animate() {
  requestAnimationFrame(animate);
  render();
}

function render() {
  updateCurve();
  renderer.render(scene, camera);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r83/three.min.js"></script>