Проблем със събирането на отпадъци на ThreeJS

Създадох приложение ThreeJS, използвайки рендеринга на платното (поради изискванията на проекта), с който се сблъсках с проблем с паметта/събирането на боклука.

Част от логиката на приложението създава много мрежи за постигане на анимации върху сегменти на плоска 2d поничка/пръстен. При всяко преминаване на анимация ние премахваме всички предишни мрежи и генерираме нови.

Когато обектите се премахнат от сцената, те не се изтриват от паметта, а вместо това се преместват в масив, наречен __objectsRemoved. Това се съхранява за неопределено време - предполагам, че има някакво събиране на боклук, което се случва да изчисти всичко в крайна сметка, но не знам как да задействам това. Използването на паметта на приложението непрекъснато се покачва, докато не спре браузъра в рамките на 30-40 секунди.

Не успяхме да разрешим този проблем и отчаяно търсим съвет. Този проект трябва да стартира много скоро, така че всички незабавни насоки/съвети са високо оценени.

Ето една цигулка, която илюстрира проблема. http://jsfiddle.net/729sv/

var camera, scene, renderer;
var base = 0;

init();
animate();

function init() {
    renderer = new THREE.CanvasRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);

    scene = new THREE.Scene();

    camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 1000);
    camera.position.z = 100;

    document.addEventListener('mousedown', update, false);

    update();
}

function update() {

    if (base) scene.remove(base);

    base = new THREE.Object3D();
    scene.add(base);

    for (var j = 0; j < 10; ++j) {

        var geometry = new THREE.IcosahedronGeometry(50, 3);
        var material = new THREE.MeshNormalMaterial()
        var mesh = new THREE.Mesh(geometry, material);
        base.add(mesh);
    }
}

function animate() {
    requestAnimationFrame(animate);
    console.log(scene.__objectsRemoved.length);
    renderer.render(scene, camera);
}

Работим с ThreeJS R62

Благодаря ти!


person Funkmyer    schedule 21.12.2013    source източник
comment
Защо държите предмети наоколо за неопределено време? Вярвам, че проблемът ви може да идва от факта, че съхранявате „премахнатите“ обекти завинаги. Тъй като непрекъснато пишете в масива, той никога няма да премахне нищо от него. Или презапишете вашите ценности, или просто изхвърлете нещата.   -  person Justin Wood    schedule 21.12.2013
comment
Не създавайте/премахвайте обекти при всяко преминаване на анимация. Вместо това създайте набор от обекти и ги използвайте повторно. Вижте например threejs.org/examples/webgl_particles_shapes.html   -  person WestLangley    schedule 21.12.2013
comment
Здравейте момчета, благодаря за отговорите. Джъстин, всъщност премахвам обекти и библиотеката изглежда задържа изтрити елементи в масив. Това е проблемът, който се опитвам да заобиколя. @WestLangley, генерирам персонализирана геометрия на фигура за всеки tween от сегментите на поничката, докато растат или се свиват. Не съм сигурен за по-ефективен метод за постигане на това, но приветствам всякакви предложения.   -  person Funkmyer    schedule 21.12.2013
comment
Ако имаше метод за създаване на тези сегменти веднъж и след това просто анимиране на върховете за разширяване на свиването, това би било много по-ефективно от текущия метод. Мога да публикувам този конкретен код тук или в друга публикация на SO, ако искате да го видите.   -  person Funkmyer    schedule 21.12.2013
comment
Ще направя всичко възможно да отговоря на конкретни въпроси относно three.js.   -  person WestLangley    schedule 21.12.2013
comment
@WestLangley, благодаря ти. Публикувах този въпрос в собствената тема. stackoverflow.com/questions/20722655/   -  person Funkmyer    schedule 21.12.2013


Отговори (1)


Това е грешка в библиотеката. Съжалявам за това :(

Не мога да повярвам, че не сме улучили това досега... __objectsAdded и __objectsRemoved бяха добавени за WebGLRenderer от съображения за ефективност. Обаче забравихме за страничните ефекти, които това създава при други програми за изобразяване (виждам, че използвате CanvasRenderer...)

Като заобиколно решение... Можете да опитате да замените тези масиви:

scene = new THREE.Scene();

if ( renderer instanceof THREE.CanvasRenderer ) {

    scene.__lights = { length: 0, push: function(){}, indexOf: function (){ return -1 }, splice: function(){} }
    scene.__objectsAdded = { length: 0, push: function(){}, indexOf: function (){ return -1 }, splice: function(){} }
    scene.__objectsRemoved = { length: 0, push: function(){}, indexOf: function (){ return -1 }, splice: function(){} }

}
person mrdoob    schedule 22.12.2013
comment
Благодаря ти! Ще опитам това и ще видя дали ще оправи нещата. - person Funkmyer; 22.12.2013
comment
Това проработи, благодаря отново за помощта за това и за цялата ви работа по една фантастична библиотека. - person Funkmyer; 22.12.2013
comment
Това коригирано ли е в three.js R66? Заобиколното решение създаде някои проблеми за мен. - person Sam Stainsby; 28.04.2014
comment
Още не... Какви проблеми създаде? - person mrdoob; 29.04.2014