最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - three.js: Adding and replacing objects in scene - Stack Overflow

programmeradmin1浏览0评论

I am trying out the following using three.js, where I have 2 shapes: “squares” and a “sphere”.

Each object has a button associated with it. If the user clicks a button, the corresponding shape will be added to the scene however, there can only be 1 square and 1 sphere in a scene at any one time.

If the user adds a new square, it should replace the old one. I seem to be having trouble achieving this though with my code below. Currently, I can successfully add the square and sphere objects however, when I click to add another square, the current square doesn’t get replaced.

Please advise, thank you!

<html>
  <head>
    <title>My second three.js app</title>
    <style>
      body { margin: 0; }
      canvas { width: 100%; height: 100% }
    </style>
  </head>
  <body>
    <button id="button1">Square1</button>
    <button id="button2">Square2</button>
    <button id="button3">Sphere</button>
    <script src="js/three.js"></script>
    <script>
  var scene = new THREE.Scene();
  var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );

  var renderer = new THREE.WebGLRenderer();
  renderer.setSize( window.innerWidth, window.innerHeight );
  document.body.appendChild( renderer.domElement );

  loader.load( ‘square1.glb’, function ( geometry ) {

    geometry.scene.traverse( function ( node ) {

        if ( node.isMesh ){
            square = node;
            square.material.map.anisotropy = maxAnisotropy;
        }

    document.getElementById("button1").addEventListener("click", function(){
      scene.remove(square);
      scene.add(square);

    });

  });

  loader.load( ‘square2.glb’, function ( geometry ) {

    geometry.scene.traverse( function ( node ) {

      if ( node.isMesh ){
          square = node;
          square.material.map.anisotropy = maxAnisotropy;
      }

    document.getElementById("button2").addEventListener("click", function(){
      scene.remove(square);
      scene.add(square);

    });

  });

  loader.load( ‘sphere.glb’, function ( geometry ) {

    geometry.scene.traverse( function ( node ) {

      if ( node.isMesh ){
          sphere = node;
          sphere.material.map.anisotropy = maxAnisotropy;
      }

    document.getElementById("button3").addEventListener("click", function(){

    scene.add(sphere);

    });

  });

  var animate = function () {
    requestAnimationFrame( animate );
    renderer.render( scene, camera );
  };

  animate();
</script>
  </body>
</html>

I am trying out the following using three.js, where I have 2 shapes: “squares” and a “sphere”.

Each object has a button associated with it. If the user clicks a button, the corresponding shape will be added to the scene however, there can only be 1 square and 1 sphere in a scene at any one time.

If the user adds a new square, it should replace the old one. I seem to be having trouble achieving this though with my code below. Currently, I can successfully add the square and sphere objects however, when I click to add another square, the current square doesn’t get replaced.

Please advise, thank you!

<html>
  <head>
    <title>My second three.js app</title>
    <style>
      body { margin: 0; }
      canvas { width: 100%; height: 100% }
    </style>
  </head>
  <body>
    <button id="button1">Square1</button>
    <button id="button2">Square2</button>
    <button id="button3">Sphere</button>
    <script src="js/three.js"></script>
    <script>
  var scene = new THREE.Scene();
  var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );

  var renderer = new THREE.WebGLRenderer();
  renderer.setSize( window.innerWidth, window.innerHeight );
  document.body.appendChild( renderer.domElement );

  loader.load( ‘square1.glb’, function ( geometry ) {

    geometry.scene.traverse( function ( node ) {

        if ( node.isMesh ){
            square = node;
            square.material.map.anisotropy = maxAnisotropy;
        }

    document.getElementById("button1").addEventListener("click", function(){
      scene.remove(square);
      scene.add(square);

    });

  });

  loader.load( ‘square2.glb’, function ( geometry ) {

    geometry.scene.traverse( function ( node ) {

      if ( node.isMesh ){
          square = node;
          square.material.map.anisotropy = maxAnisotropy;
      }

    document.getElementById("button2").addEventListener("click", function(){
      scene.remove(square);
      scene.add(square);

    });

  });

  loader.load( ‘sphere.glb’, function ( geometry ) {

    geometry.scene.traverse( function ( node ) {

      if ( node.isMesh ){
          sphere = node;
          sphere.material.map.anisotropy = maxAnisotropy;
      }

    document.getElementById("button3").addEventListener("click", function(){

    scene.add(sphere);

    });

  });

  var animate = function () {
    requestAnimationFrame( animate );
    renderer.render( scene, camera );
  };

  animate();
</script>
  </body>
</html>
Share Improve this question edited Feb 6, 2019 at 0:06 Dacre Denny 30.4k5 gold badges51 silver badges66 bronze badges asked Feb 5, 2019 at 22:57 JamesKwonJamesKwon 531 silver badge4 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 5

Consider tracking the "current square" shape outside the scope of your <button> click handlers, to ensure that the logic for adding and removing these shape from the scene functions as expected.

Specifically, you'll want to call scene.remove() with the current square shape (if present), rather than to call it with the shape object that you subsequently call scene.add() with:

/* Current code */
document.getElementById("button1").addEventListener("click", function(){

  scene.remove(square); /* You're removing the square object here, */

  scene.add(square); /* and then adding the same square object to the scene */
});

You might find it useful to adapt your script as follows:

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );

var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );

/*
Not sure where you get your loader object from
*/
var loader = ''; // ??

/* 
Add this to track current shapes
*/
var currentSquare = '';
var currentSphere = '';

/*
Define a general, reusable method for loading geometry
*/
function loadShape(filename, onLoaded) {

  loader.load( filename, function ( geometry ) {

        var foundMesh = '';

        geometry.scene.traverse( function ( node ) {
            if ( node.isMesh ){
                foundMesh = node;
                foundMesh.material.map.anisotropy = maxAnisotropy;
            }
        });

        if(foundMesh) {
            onLoaded(foundMesh)
        }
    }
}

/*
Use the general loader method defined above
*/
loadShape('square1.glb', function(nextSquare) {

    document.getElementById("button1").addEventListener("click", function(){

        /*
        If current square exists, remove it
        */
        if(currentSquare) {
            scene.remove(currentSquare);
        }

        /*
        Add the square for the button just clicked 
        and update currentSquare
        */
        scene.add(nextSquare);  
        currentSquare = nextSquare;
    });
})

loadShape('square2.glb', function(nextSquare) {

    document.getElementById("button2").addEventListener("click", function(){

        if(currentSquare) {
            scene.remove(currentSquare);
        }

        scene.add(nextSquare);  
        currentSquare = nextSquare;
    });
})

loadShape('sphere.glb', function(nextSphere) {

    document.getElementById("button3").addEventListener("click", function(){

        if(currentSphere) {
            scene.remove(currentSphere);
        }

        scene.add(nextSphere);  
        currentSphere = nextSphere;
    });
})

var animate = function () {
  requestAnimationFrame( animate );
  renderer.render( scene, camera );
};

animate();

Hope this helps!

发布评论

评论列表(0)

  1. 暂无评论