59

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

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

非表示ボタンをクリックすると、次の関数が呼び出されます。

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

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

小さな実験をしました。関数内のscene.remove(object.name);直後に追加した結果、「表示」ボタンをクリックすると、(予想どおり) エンティティが描画されず、内でうまく機能したことを意味します。しかし、まだ removeEntity(object) で使用する方法がわかりません。scene.add(object);addEntityscene.remove(object.name);addEntity

また、scene.children の内容を確認したところ、[オブジェクト オブジェクト]、[オブジェクト オブジェクト]、[オブジェクト オブジェクト]、[オブジェクト オブジェクト]、[オブジェクト オブジェクト]、[オブジェクト オブジェクト] が表示されます。

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

詳細が必要な場合はお尋ねください。ThreeJSのrev-59-devとrev-60でテストしました。

ありがとう。:)

4

12 に答える 12

55

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、Three.jsであなたを検索していることがわかります。それが役立つことを願っていますScenename

于 2013-08-21T15:12:27.727 に答える
10
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:underscore.js_.eachの機能です

于 2013-12-24T01:34:19.797 に答える
1

removeObject3D の Ibrahim コードを改善し、ジオメトリまたはマテリアルのチェックを追加しました

removeObject3D(object) {
    if (!(object instanceof THREE.Object3D)) return false;
    // for better memory management and performance
    if (object.geometry) {
        object.geometry.dispose();
    }
    if (object.material) {
        if (object.material instanceof Array) {
            // for better memory management and performance
            object.material.forEach(material => material.dispose());
        } else {
            // for better memory management and performance
            object.material.dispose();
        }
    }
    if (object.parent) {
        object.parent.remove(object);
    }
    // the parent might be the scene or another Object3D, but it is sure to be removed this way
    return true;
}
于 2021-07-14T14:49:28.483 に答える
0

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

于 2013-09-09T01:19:51.337 に答える
-9

これを使用できます

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
  }   
于 2013-09-21T09:03:59.747 に答える