2013-08-21 12 views
37

ich ThreeJS bin mit einer Web-Anwendung zu entwickeln, die eine Liste von Einheiten zeigen, die jeweils mit entsprechender „Ansicht“ und Taste „Hide“; z.B. entityName Ansicht Ausblenden. Wenn der Benutzer auf Schaltfläche klickt, wird die folgende Funktion aufgerufen und die Entität erfolgreich auf dem Bildschirm gezeichnet. ThreeJS: Entfernen Objekt aus Szene

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

Das Problem ist, Einheit nicht von Bildschirm geladen einmal entfernt wird, wenn ausblenden Schaltfläche geklickt wird

:

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); 
} 

Und klicken ausblenden Taste wird folgende Funktion aufgerufen. Was kann ich tun, um zu verstecken Schaltfläche zu arbeiten?

Ich habe kleines Experiment. Ich habe scene.remove(object.name); direkt nach scene.add(object); innerhalb addEntity Funktion und als Ergebnis, wenn „Ansicht“ Schaltfläche geklickt, keine Einheit gezogen (wie erwartet), was bedeutet, dass scene.remove(object.name); innerhalb addEntity ganz gut gearbeitet. Aber ich kann immer noch nicht herausfinden, wie man es in removeEntity (object) verwendet.

Auch überprüfte ich Inhalte von scene.children und es zeigt: [object Object], [object Object], [object Object], [object Object], [object Object], [object Object]

vollständige Code: http://devplace.in/~harman/model_display1.php.html

Bitte fragen Sie, wenn Sie mehr Details benötigt wird. Ich habe mit rev-59-dev und rev-60 von ThreeJS getestet.

Danke. :)

+0

Vielleicht hast du update scene vergessen (render it)? Gibt es Renderupdate vorhanden (requestAnimationFrame loop oder renderer.render (...))? –

+0

Ich versuchte durch Aufruf von animate() (update() und render() werden innerhalb von animate()) nach 'scene.remove (Objektname);' in 'removeEntity (Objekt)', aber keine Änderung aufgerufen. :( – harman052

Antwort

34

Ich denke, Ihre Nutzung für addEntity und removeEntity Code zu sehen wäre hilfreich, aber mein erster Gedanke ist, sind Sie tatsächlich die object.name Einstellung? Versuchen Sie in Ihrem Loader kurz vor scene.add (object); so etwas wie diese:

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

Was passiert sein könnte ist die Voreinstellung „Name“ für einen Object3D ist „“, also, wenn Sie dann Ihre removeEntity Funktion nennen es aufgrund der Szene Objekte nicht, Namen zu sein „“

Außerdem merke ich, dass Sie object.name an Ihren Loader übergeben? Speichern Sie hier die URL der Ressource? In diesem Fall würde ich empfehlen, die integrierte .userData-Methode von Object3D zu verwenden, um diese Informationen zu speichern und das Namensfeld für Szenenidentifikationszwecke beizubehalten.

Edit: Antwort auf neu hinzugefügten Code

Das erste, was zu beachten ist, ist es nicht eine gute Idee zu haben „/“ in Ihrem Objektnamen, es scheint gut zu funktionieren, aber man weiß ja nie, wenn einige Algorithmus entscheiden entkomme dieser Schnur und brich dein Projekt.

Zweiter Punkt ist jetzt, dass ich Ihren Code gesehen habe, seine eigentlich gerade nach vorne, was los ist. Ihre Löschfunktion versucht, nach Namen zu löschen, Sie benötigen ein Objekt3D zum Löschen. Versuchen Sie folgendes:

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

Hier sehen Sie, ich Nachschlag Ihre Object3D in den Three.js Scene indem Sie in Ihrem Objekt-Tag des name Attribut übergeben.Hoffe, dass hilft

+0

Eigentlich ist das Argument "object" an "addEntity" übergeben und "removeEntity" ist ein JavaScript-Standard-Schlüsselwort, das den "Namen" der Entität wählt, deren entsprechende Schaltfläche "Ansicht" angeklickt (addEntity und removeEntity sind onclick callee Funktionen) 'object.name' enthält eigentlich den Namen der Entity scene.add (Objekt) funktioniert gut, da ich Objekte auf dem Bildschirm gezeichnet sehen kann Problem ist nur mit scene.remove (object.name) als weder es zeigt keine Fehler noch irgendwelche Ergebnisse. – harman052

+0

Ich sehe, ich bin mir nicht sicher, das genaue Problem, aber die Funktion scene.remove in Three.js sucht nach einem Object3D.name, die gleich oder nicht sein kann. Leider denke ich, dass ein bisschen mehr Code benötigt wird, um die Objektkonstruktion und die Verwendung Ihres add remove Objektcodes zu sehen. Andernfalls würde ich den Mesh.name in der Add-Funktion "console.log" schreiben und die Funktion entfernen und sehen, welche Ausgaben Sie erhalten. –

+0

Ich habe gerade die Frage bearbeitet, indem ich mehr Details hinzugefügt und den Link zum vollständigen Code erwähnt habe. Bitte prüfe. Vielen Dank. – harman052

1

Ich hatte das gleiche Problem wie Sie haben. Ich versuche, diesen Code und es funktioniert gut: Wenn Sie Ihr Objekt setzen erstellen Diesen object.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); 
} 

Und dann dann löschen Sie Ihr Objekt diesen Code versuchen:

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); 

       } 
      } 
} 

Versuchen Sie das mal und sagen Sie mir, wenn das funktioniert, scheint es, dass drei js das Objekt nicht erkennen, nachdem es der Szene hinzugefügt wurde. Aber mit diesem Trick funktioniert es.

+1

Ich bin nicht sicher, was das tun soll, Sie fügen nur eine zufällige Flagge hinzu. – MJB

+0

Sie können das Namensattribut verwenden, das in allen Objekten vorhanden ist und standardmäßig ''. Es muss nicht eindeutig sein und Sie können auf diese Weise viele Klassen von Objekten haben. –

-7

können Sie diese

function removeEntity(object) { 
    var scene = document.querySelectorAll("scene");        //clear the objects from the scene 
    for (var i = 0; i < scene.length; i++) {         //loop through to get all object in the scene 
    var scene =document.getElementById("scene");         
    scene.removeChild(scene.childNodes[0]);          //remove all specified objects 
    } 
11
clearScene: function() { 
    var objsToRemove = _.rest(scene.children, 1); 
    _.each(objsToRemove, function(object) { 
      scene.remove(object); 
    }); 
}, 

diese verwendet undescore.js verwenden, um alle Kinder iterrate über (außer dem ersten) in einer Szene (es ist Teil des Codes verwende ich eine Szene löschen). stell einfach sicher, dass du die Szene mindestens einmal nach löschst, weil sonst die Leinwand sich nicht ändert! Es gibt keine Notwendigkeit für eine "spezielle" obj Flagge oder ähnliches.

auch löschen Sie nicht das Objekt mit Namen, nur durch das Objekt selbst, so ruft

scene.remove(object); 

statt scene.remove(object.name); kann

PS genug sein: _.each ist eine Funktion der underscore.js

+3

Was ist los mit einem regulären für (let x of foo)? oder eine reguläre for-Schleife? – shinzou

+0

natürlich können Sie eine einfache for-Schleife verwenden, nichts falsch daran, ich habe nur zufällig verwendet _.each, das ist alles. – MJB

1

Wenn Ihr Element nicht direkt in Ihrer Szene ist, gehen Sie zurück zum übergeordneten Element, um es zu entfernen.

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

dieses große Werk - ich teste es so wenden Sie sich bitte für jedes Objekt Name SET

den Namen für das Objekt geben, wenn

mesh.name = 'nameMeshObject'; 

erstellen und diese verwenden, wenn Sie Objekt

löschen,
delete3DOBJ('nameMeshObject'); 



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

öffnen neue Szene, fügen Objekt open new scene , add object

Objekt löschen und neu erstellen delete object and create new