2016-05-05 12 views
1

Wir beschäftigen uns mit großen Three.js Szenen mit vielen einzelnen Objekten. Es ist leicht, mit Szenen zu enden, die 25k bis 50k Object3D Instanzen haben. Ja, das ist viel, aber wir sehen derzeit keinen einfachen Weg, diese Zahl zu senken. Das Löschen einer solchen Szene durch Entfernen aller Objekte dauert normalerweise etwa zwei Minuten. Dies ist der Fall, wenn Sie jedes Element einzeln mit scene.remove(element); entfernen und alle Elemente zuerst sammeln und scene.remove(element1, element2, ...); aufrufen. Wir haben auch versucht, die komplette Szeneninstanz zu ersetzen, aber ohne Erfolg: Es war immer noch langsam.Entfernen vieler Objekte aus Three.js Szene langsam

Wir haben einige Unterschiede zwischen verschiedenen Grafikkarten gesehen und vermuten, dass dies mit der Verwendung vieler Puffergeometrien zu tun hat, die vermutlich von der Grafikkarte entfernt werden müssten (was dann die Leistung beeinflussen würde).

Da der Browser während der Entfernung des Objekts blockiert, wird die Website für diesen Zeitraum unbrauchbar. Sehen Sie eine Möglichkeit, die Leistung der Objektentfernung zu verbessern oder nicht blockierend zu machen (ohne setTimeout() zum Entfernen einzelner Elemente)?

Dies zeigt das Problem in einer vereinfachten Art und Weise (mit 50k Würfel, nach dem ersten Rahmen entfernt, aber einige unserer Objekte sind viel komplexer): http://jsfiddle.net/ua2mg5ty/

+0

Huch. Vielleicht sollten Sie 'InstancedBufferGeometry' verwenden. Siehe zum Beispiel [this] (http://threejs.org/examples/webgl_buffergeometry_instancing.html) und [this] (http://threejs.org/examples/webgl_buffergeometry_instancing_dynamic.html). – WestLangley

+0

Danke für den Zeiger! Wenn ich mich nicht irre, impliziert die Verwendung von 'InstanceBufferGeometry', dass die einzelnen Objektinstanzen ähnlich sind. Wir zeigen viele große Neuronen, die alle sehr unterschiedlich sind. Sie basieren derzeit auf 'LineSegments' mit regulären 'Geometry'-Instanzen. Ich nehme an, ich könnte 'InstanceBufferGeometry' verwenden, um nur ein einzelnes Liniensegment zu speichern und ein Offset-Array zu verwenden, um einzelne Liniensegmente an der richtigen Position zu instanzieren. Macht das Sinn? – tomka

+0

Vielleicht. Oder verwende 'BufferGeometry'. Vermeiden Sie regelmäßige Geometrie. Achten Sie darauf, 'dispose()' beim Entfernen von Objekten aufzurufen. – WestLangley

Antwort

4

Try Mesh merge und Entfernen eines einzelnen Netzes.

http://jsfiddle.net/2t8j5caj/

Removal Zeit: 0.13500000000021828ms, Renderzeit: 3.6000000000012733ms

var mesh = new THREE.Mesh(singleGeometry, material); 
for (var i = 0; i < nCubes; i++) { 
    var box = new THREE.BoxGeometry(1, 1, 1); 
    var cube = new THREE.Mesh(box); 
    cube.position.x = (Math.random() - 0.5) * 5; 
    cube.position.y = (Math.random() - 0.5) * 5; 
    cube.position.z = (Math.random() - 0.5) * 5; 
    cube.scale.set((Math.random() - 1 * cubeSize), (Math.random() - 1 * cubeSize), (Math.random() - 1 * cubeSize)) 
    cube.updateMatrix(); 

    singleGeometry.merge(cube.geometry, cube.matrix); 
} 
var mesh = new THREE.Mesh(singleGeometry, material); 
scene.add(mesh); 
+0

Danke, das ist ein weiterer guter Vorschlag. Ich muss noch herausfinden, ob das in meinem Anwendungsfall funktioniert: Logische Objekte (in meinem Fall Neuronen) enthalten mehrere Meshes, die ich einzeln ein- und ausblenden möchte, verschiedene Shader anwenden und ein anderes Mauspickverhalten haben. Ich würde wahrscheinlich all dies verlieren, wenn alle Netze in einem logischen Objekt zusammengeführt werden. – tomka

+0

Prost. Möglicherweise können Sie vor dem Zusammenführen auf bestimmte Flächen im Netz Shader anwenden und das spezifische Material zum Anzeigen/Ausblenden bestimmter Flächen ändern. Ray Picking ist bereits Gesicht basiert. Stellen Sie sich das Mesh als Ansammlung von Gesichtern und nicht als einzelne Mesh-Objekte vor. Letzteres ist vorzuziehen - es fühlt sich an wie Freiheit, aber JS kann einfach nicht mit einem Satz umgehen, der in seinem einzelnen Thread groß ist. Denken Sie auch daran, dass Flächen und Eckpunkte Klassenobjekte sind, denen Eigenschaften zugewiesen werden können, die die drei Entwickler nicht beabsichtigt haben. Drei basiert auf einem Prototyp. Das richtige Erweitern einer Three-Klasse beeinträchtigt die Klassenintegrität nicht. – Radio

+1

Entschuldigung, ich habe diese Antwort nicht angenommen. Ich habe nicht getan, was Sie vorgeschlagen haben, aber Ihre Antwort sowie die Kommentare von WestLangley zu meiner Frage haben mich in die richtige Richtung geführt: Ich konstruiere jetzt 'InstanceBufferGeometry'-Objekte und Shader manuell, was in wenigen Millisekunden Entfernung resultiert. – tomka

Verwandte Themen