web-dev-qa-db-ja.com

ThreeJS:シーンからオブジェクトを削除する

ThreeJSを使用して、エンティティのリストを表示するWebアプリケーションを開発しています。各エンティティには、対応する[表示]ボタンと[非表示]ボタンがあります。例えばentityName表示HideユーザーがViewボタンをクリックすると、次の関数が呼び出され、エンティティが画面に正常に描画されます。

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

そして、Hideボタンをクリックすると、次の関数が呼び出されます:

_function removeEntity(object){
    scene.remove(object.name);
}
_

問題は、Hideボタンがクリックされたときに、エンティティが画面から削除されないことです。 非表示ボタンを機能させるにはどうすればよいですか?

ちょっとした実験をしました。 addEntity関数内のscene.remove(object.name);の直後にscene.add(object);を追加し、その結果、[表示]ボタンがクリックされたときに、エンティティが描画されない(予想どおり)scene.remove(object.name);addEntity内でうまく機能しました。しかし、それでもremoveEntity(object)でそれを使用する方法を理解することはできません。

また、scene.childrenの内容を確認したところ、[object Object]、[object Object]、[object Object]、[object Object]、[object Object]、[object Object]が表示されます。

完全なコード: http://devplace.in/~harman/model_display1.php.html

詳細が必要な場合は、お問い合わせください。 ThreeJSのrev-59-devおよびrev-60でテストしました。

ありがとう。 :)

42
harman052

AddEntityとremoveEntityのコードの使用法を見ることは役立つと思いますが、私の最初の考えは実際にobject.nameを設定することですか? scene.add(object);の直前にローダーで試してください。このようなもの:

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

何が起こっているのかは、Object3Dのデフォルトの「名前」が「」であるため、removeEntity関数を呼び出すと、シーンオブジェクト名が「」であるために失敗します

また、あなたはあなたのローダーにobject.nameを渡すことに気付きましたか?これはリソースへのURLを保存する場所ですか?その場合、Object3Dに組み込まれた.userDataメソッドを使用してその情報を保存し、シーン識別のために名前フィールドを保持することをお勧めします。

編集:新しく追加されたコードへの応答

最初に注意することは、オブジェクト名に「/」を含めることは素晴らしい考えではありません、それはうまくいくようですが、アルゴリズムがその文字列をエスケープしてプロジェクトを壊すことを決定するかどうかはわかりません。

2番目の項目は、あなたのコードを見たということです。実際には、何が起こっているのかわかりません。削除機能は名前で削除しようとしています。削除するにはObject3Dが必要です。これを試して:

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

ここで、Object3Dは、オブジェクトタグのScene属性を渡すことにより、Three.js nameで。役立つことを願っています

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

これはundescore.jsを使用して、シーン内のすべての子(最初の子を除く)を反復処理します(シーンをクリアするために使用するコードの一部です)。 レンダリングシーンを少なくとも1回削除してから削除してください。それ以外の場合、キャンバスは変更されません! 「特別な」objフラグやこのようなものは必要ありません。

また、オブジェクト自体を削除するだけで、名前でオブジェクトを削除しないので、

_scene.remove(object); 
_

代わりにscene.remove(object.name);で十分です

PS:__.each_は nderscore.js の関数です

10
MJB

この作品は素晴らしい-私はそれをテストしたので、すべてのオブジェクトの名前を設定してください

作成時にオブジェクトに名前を付けます

    mesh.name = 'nameMeshObject';

オブジェクトを削除する必要がある場合に使用します

    delete3DOBJ('nameMeshObject');



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

新しいシーンを開き、オブジェクトを追加します open new scene , add object

オブジェクトを削除して新規作成 delete object and create new

私はあなたと同じ問題を抱えていました。私はこのコードを試してみて、うまく動作します:オブジェクトを作成するとき、この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);
}

次に、オブジェクトを削除して次のコードを試してください:

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

                }
            }
}

それを試して、それが機能するかどうか教えてください、3つのjsはシーンに追加された後、オブジェクトを認識しないようです。しかし、このトリックではうまくいきます。

1
juanpscotto

要素がシーンに直接ない場合は、親に戻って削除します

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

私はこれを関数として保存し始め、どのような反応がそれを必要とする場合でも必要に応じて呼び出しました:

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

これで、Remove()を呼び出すことができます。必要に応じて機能します。

1
Alex Melluzzo