2017-01-18 95 views
1

ThreeJSでベジェ曲線をアニメーション化したいと思います。開始点、終了点、および制御点が更新されます。最終的には、一度に多くのカーブをアニメーション化する必要があります。これを行う最も効率的な方法は何ですか?ThreeJSでベジェ曲線をアニメーション化する

以下のコードスニペットを実行すると、フレームがレンダリングされるたびに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>

+1

(1)コンソールにrenderer.info' '入力。ジオメトリを正しく処分しないでください。代わりに、1つの 'Line'を作成し、頂点を更新します。 http://stackoverflow.com/questions/31399856/drawing-a-line-with-three-js-dynamically/31411794#31411794を参照してください(2)タイトなループでは 'new'を避けてください。オブジェクトを作成して再利用する。 – WestLangley

答えて

1

非常にexepnsive opertationです。

アニメーションカーブを作成する最もよい方法は何ですか?

おそらくshadersを使用します。しかし、実装にはもっと時間がかかることがありますので、私の次の提案があなたのために十分であれば、それだけで十分です。

はあなたのコード

私はあなたのコードの多くを変えないようにしたの曲線の更新を改善します。編集した場所を「// EDITED」とコメントしました。私は多くの曲線があると言ったので、配列を追加しました。 @WestLangleyが言ったように

説明

  • 、アニメーションループの内部newキーワードを使用しないようにしてみてください。
  • CubicBezierCurve3は、v0,v1,v2およびv3の属性を有する。あなたが最初から提供しているのは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>

関連する問題