2017-01-18 2 views
1

Ich möchte eine Bezier-Kurve in ThreeJS animieren. Start, Ende und Kontrollpunkte werden aktualisiert. Schließlich muss ich viele Kurven gleichzeitig animieren. Was ist der effizienteste Weg, dies zu tun?Animieren einer Bezier-Kurve in ThreeJS

Wenn Sie das Code-Snippet unten ausführen, sehen Sie, dass ich jedes Mal, wenn der Frame gerendert wird, das Bezier-Objekt, die Geometrie und die Linie erstellen. Ich entferne die vorherige Zeile aus der Szene und füge dann die neue, aktualisierte Zeile hinzu. Gibt es einen besseren Weg? Vielleicht nur die Geometrie aktualisieren und die Zeile nicht erneut hinzufügen?

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) Geben Sie 'in die Konsole renderer.info'. Sie entledigen sich nicht Ihrer Geometrien. Erstellen Sie stattdessen eine "Linie" und aktualisieren Sie die Scheitelpunkte. Siehe http://stackoverflow.com/questions/31399856/drawing-a-line-with-three-js-dynamically/31411794#31411794 (2) Vermeiden Sie "neue" in engen Schleifen. Objekte erstellen und wiederverwenden. – WestLangley

Antwort

1

Erstellen neuer Linien für jeden Rahmen ist sehr exepnsive Opertation.

Was ist der beste Weg, animierte Kurven zu erstellen?

Wahrscheinlich mit shaders. Aber es kann viel mehr Zeit zur Implementierung brauchen, also wenn meine nächsten Vorschläge für dich ausreichen werden, nur sie.

verbessern Kurve Aktualisierung im Code

Ich versuchte, nicht viel Code zu ändern. Markierte bearbeitete Orte mit "// EDITED" Kommentar. Ich habe ein Array hinzugefügt, weil Sie gesagt haben, dass es viele Kurven geben wird.

Erklärung

  • Wie @WestLangley sagte, prüfen Sie die Animationsschleife mit new Schlüsselwort zu vermeiden.
  • CubicBezierCurve3 hat v0, v1, v2 und v3 Attribute. Das sind THREE.Vector3 `s, die Sie von Anfang an bereitstellen. .getPoints() verwendet sie, um das Vertices-Array zurückzugeben. So können Sie sie einfach ändern und kein new Schlüsselwort wird benötigt. See this line for more details.
  • Anstatt die Linie neu zu erstellen, können Sie in Ihrem Fall einfach die Geometrie aktualisieren. Wie Sie eine THREE.Line haben - Ihre Geometrie benötigt nur Scheitelpunkte. Nach dem Ändern der Scheitelpunkte sollten Sie geometry.verticesNeedUpdate = true oder Three.js werden Ihre Änderungen ignorieren.

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>