web-dev-qa-db-fra.com

ThreeJS: Supprimer un objet de la scène

J'utilise ThreeJS pour développer une application Web qui affiche une liste d'entités, chacune avec les boutons "View" et "Hide" correspondants; par exemple. entityName Voir Cacher . Lorsque l'utilisateur clique sur le bouton Afficher , la fonction suivante est appelée et l'entité est dessinée à l'écran avec succès.

function loadOBJFile(objFile){            
    /* material of OBJ model */                                          
    var OBJMaterial = new THREE.MeshPhongMaterial({color: 0x8888ff});
    var loader = new THREE.OBJLoader();
    loader.load(objFile, function (object){
        object.traverse (function (child){
            if (child instanceof THREE.Mesh) {
                child.material = OBJMaterial;
            }
        });
        object.position.y = 0.1;
        scene.add(object);
    });     
}

function addEntity(object) {
    loadOBJFile(object.name);
}

Et en cliquant sur le bouton Masquer , la fonction suivante est appelée:

function removeEntity(object){
    scene.remove(object.name);
}

Le problème est que l'entité n'est pas supprimée de l'écran une fois chargée lorsque le bouton est masqué est cliqué. Que puis-je faire pour que le bouton Cacher fonctionne?

J'ai fait une petite expérience. J'ai ajouté scene.remove(object.name); juste après scene.add(object); au sein de addEntity fonction et comme résultat, lorsque le bouton "Afficher" est cliqué, aucune entité n'est dessinée (comme prévu), ce qui signifie que scene.remove(object.name); a bien fonctionné dans addEntity. Mais je ne parviens toujours pas à comprendre comment l'utiliser dans removeEntity (objet).

De plus, j'ai vérifié le contenu de scene.children et cela indique: [objet Object], [objet Object], [objet Object], [objet Object], [objet Object], [objet Object]

Code complet: http://devplace.in/~harman/model_display1.php.html

S'il vous plaît demander, si plus de détails sont nécessaires. J'ai testé avec rev-59-dev et rev-60 de ThreeJS.

Merci. :)

42
harman052

Je pense que voir votre utilisation des codes addEntity et removeEntity serait utile, mais ma première pensée est de savoir si vous définissez réellement le nom d'objet.name? Essayez dans votre chargeur juste avant scene.add (objet); quelque chose comme ça:

object.name = "test_name";
scene.add(object);

Ce qui peut arriver est que le "nom" par défaut d'un Object3D est "". Par conséquent, lorsque vous appelez votre fonction removeEntity, elle échoue car le nom des objets de la scène est "".

De plus, je remarque que vous passez en object.name à votre chargeur? Est-ce là que vous stockez l'URL de la ressource? Si tel est le cas, je vous recommanderais d'utiliser la méthode .userData intégrée à Object3D pour stocker ces informations et conserver le champ de nom à des fins d'identification de la scène.

Edit: Réponse au code nouvellement ajouté

La première chose à noter est que ce n’est pas une bonne idée d’avoir "/" dans le nom de votre objet, cela semble bien fonctionner, mais vous ne savez jamais si un algorithme décidera d’échapper à cette chaîne et de casser votre projet.

Le deuxième élément est maintenant que j'ai vu votre code, c'est en fait ce qui est simple. Votre fonction de suppression essaye de supprimer par nom, vous avez besoin d'un Object3D pour le supprimer. Essaye ça:

function removeEntity(object) {
    var selectedObject = scene.getObjectByName(object.name);
    scene.remove( selectedObject );
    animate();
}

Ici vous voyez je cherche votre Object3D dans Three.js Scene en transmettant l'attribut name de votre balise d'objet. J'espère que ça t'as aidé

42
Darryl_Lehmann
clearScene: function() {
    var objsToRemove = _.rest(scene.children, 1);
    _.each(objsToRemove, function( object ) {
          scene.remove(object);
    });
},

cela utilise undescore.js pour parcourir tous les enfants (sauf le premier) dans une scène (cela fait partie du code que j'utilise pour effacer une scène). assurez-vous simplement que restituez la scène au moins une fois après suppression, car sinon la toile ne change pas! Il n’est pas nécessaire d’avoir un drapeau "spécial" ou autre.

En outre, vous ne supprimez pas l'objet par son nom, mais simplement par l'objet lui-même.

scene.remove(object); 

au lieu de scene.remove(object.name); peut suffire

PS: _.each Est une fonction de nderscore.js

10
MJB

CECI FONCTIONNE GRAND - Je l'ai testé, veuillez donc préciser le nom pour chaque objet.

donner le nom à l'objet lors de la création

    mesh.name = 'nameMeshObject';

et l'utiliser si vous devez supprimer un objet

    delete3DOBJ('nameMeshObject');



    function delete3DOBJ(objName){
        var selectedObject = scene.getObjectByName(objName);
        scene.remove( selectedObject );
        animate();
    }

ouvrez une nouvelle scène, ajoutez un objet open new scene , add object

supprimer un objet et créer un nouveau delete object and create new

3

J'ai eu le même problème que vous avez. J'essaie ce code et cela fonctionne très bien: lorsque vous créez votre objet, mettez cet objet.is_ob = true

function loadOBJFile(objFile){            
    /* material of OBJ model */                                          
    var OBJMaterial = new THREE.MeshPhongMaterial({color: 0x8888ff});
    var loader = new THREE.OBJLoader();
    loader.load(objFile, function (object){
        object.traverse (function (child){
            if (child instanceof THREE.Mesh) {
                child.material = OBJMaterial;
            }
        });
        object.position.y = 0.1;
      // add this code
        object.is_ob = true;

        scene.add(object);
    });     
}

function addEntity(object) {
    loadOBJFile(object.name);
}

Et puis vous supprimez votre objet essayez ce code:

function removeEntity(object){
    var obj, i;
            for ( i = scene.children.length - 1; i >= 0 ; i -- ) {
                obj = scene.children[ i ];
                if ( obj.is_ob) {
                    scene.remove(obj);

                }
            }
}

Essayez cela et dites-moi si cela fonctionne, il semble que trois js ne reconnaissent pas l'objet après l'avoir ajouté à la scène. Mais avec cette astuce cela fonctionne.

1
juanpscotto

Si votre élément n'est pas directement sur votre scène, retournez chez Parent pour le supprimer.

  function removeEntity(object) {
        var selectedObject = scene.getObjectByName(object.name);
        selectedObject.parent.remove( selectedObject );
    }
1
Victor Santos

J'ai commencé à enregistrer cela en tant que fonction et à l'appeler selon les besoins, quelles que soient les réactions qui l'exigent:

function Remove(){
    while(scene.children.length > 0){ 
    scene.remove(scene.children[0]); 
}
}

Maintenant, vous pouvez appeler le Remove (); fonctionner le cas échéant.

1
Alex Melluzzo