Experiencia en la creación de múltiples escenas 3D sin recargar la página (three.js)

Qué debo hacer



Para un proyecto personal, necesitaba encontrar una solución para trabajar con varios modelos diferentes de gltf.



Tenía un poco de experiencia con three.js, así que después de leer los ejemplos de GLTFLoader, se eligió esta biblioteca en particular.



Los datos de la escena se almacenan en un archivo json separado y contienen información sobre la ruta a la escena, la iluminación, la ruta de la cámara, etc. pero en este material nos interesan en menor medida.



En teoría, era necesario dibujar varias escenas seguidas. En la práctica, todo resultó algo más complicado.



Cómo puedo



Cámara



La primera dificultad fue trazar una ruta para que la cámara se moviera. De los requisitos para la

cámara y el movimiento:



  • La cámara debe moverse por puntos clave, completando los intermedios;
  • la cámara debe depender del desplazamiento de la rueda del mouse (hacia adelante y hacia atrás, respectivamente);
  • la cámara debería "frenar" suavemente y suavizar su movimiento.


Para construir e interpolar la ruta, CatmullRomCurve3 creó el método getPoint (), que construyó una curva bastante suave. El resto de las clases de curvas, como Curve o CubicBezierCurve3, no dibujaron los puntos intermedios con la suficiente fluidez. Esto debe tenerse en cuenta.



. , ( ). ( ). , , , ( ) . , , .



. TrackballControls (0, 0, 0). (W, S, D, A ), , , ( ).





, fps . , - . . . .







, . , . , , . , GPU , .



three.js SPA ( ) , .



for (let i = mScene.scene.children.length - 1; i >= 0; i--) {
    mScene.scene.remove(mScene.scene.children[i]); //  ,    
}


. . dispose() :



In general, there is no definite recommendation for this. It highly depends on the specific use case when calling dispose() is appropriate. It's important to highlight that it's not always necessary to dispose objects all the time. A good example for this is a game which consists of multiple levels.


, dispose. ? ( ):



dispose_scene() {
    let self = this;
    self.scroll_timer_stop();
    this.scene.traverse(function (object) {
    self.scroll_timer_stop();
        if (object.type === "Mesh" || object.type === "Group") {
            self.dispose_hierarchy(object, self.dispose_node);
            self.scene.remove(object);
            object = null;
       }
    });
}

dispose_hierarchy(node, callback) {
    for (var i = node.children.length - 1; i >= 0; i--) {
        var child = node.children[i];
        this.dispose_hierarchy(child, callback);
        callback(child);
    }
}

dispose_node(node) {
        if (node.constructor.name === "Mesh") {
            node.parent = undefined;
            if (node.geometry) {
                node.geometry.dispose();
            }
            if (node.geometry) {
                node.geometry.dispose();
            }
            let material = node.material;
            if (material) {
                if (material.map) {
                    material.map.dispose();
                }
                if (material.lightMap) {
                    material.lightMap.dispose();
                }
                ...
                material.dispose();
                material = undefined;
            }
        } else if (node.constructor.name === "Object3D") {
            node.parent.remove(node);
            node.parent = null;
        }
}

dispose_postprocessing() { 
        this.postprocessing.rtTextureColors.dispose();
        this.postprocessing.rtTextureDepth.dispose();
        ...
        this.postprocessing.materialGodraysDepthMask.dispose();
        this.postprocessing.materialGodraysGenerate.dispose();
        ...
}




, three.js . this.postprocessing.dispose() , , dispose() , , . , , . . . Geforce 2070 super , :







. . !




All Articles