如何删除合并的几何

时间:2016-04-08 20:04:59

标签: performance three.js geometry

出于性能原因,我合并了几何体。我有成千上万的立方体要显示。我有合理的表现。

现在我必须处理删除一些问题。我几乎拥有它,但无法弄清楚如何使这项工作,所以我削减了我的代码,以完成这个完整的样本。

在单击多维数据集的onDocumentMouseDown函数中,我尝试将其删除。它确实如此。但是,它不是删除一个多维数据集,而是删除两个。 (然后它基本上更糟糕)它删除了我指出的那个和我添加的下一个。

 <!DOCTYPE html>
<html>
 <head>
  <meta charset=utf-8>
  <title>Measurement</title>
  <style>
   body { margin: 0; }


  </style>
 </head>
 <body>
  <div id="canvas_container" style="position: absolute; left:0px; top:0px; touch-action:none;"></div>

  <div id="MessageDisplay1" style="position: absolute; top: 50px; left: 50px;  background-color: black; opacity: 0.8; color:white; touch-action:none;"></div>

  <div id="MessageDisplay" style="position: absolute; top: 50px; left: 200px;  background-color: black; opacity: 0.8; color:white; touch-action:none;"></div>

    <script src="js/three.js"></script>

    <script>


   // player motion parameters
   var motioncontrol = {
    airborne: false,
    bumpposition: 5.0,
    bumpdegrees: 4.0,
    rotationanglezx: 0,
    tiltangle: 0,
    distancePointZ : 10000.0,
    distancePointY: 100.0,

    position : new THREE.Vector3(), velocity : new THREE.Vector3(),
    rotation: new THREE.Vector3(), spinning: new THREE.Vector2(),
    prevposition : new THREE.Vector3(),
    prevrotation : new THREE.Vector3()
   };

  var mouseDown = 0;
  var mouse = new THREE.Vector2();
  var raycaster = new THREE.Raycaster();
  var INTERSECTED;

  motioncontrol.position.y = 15;
  motioncontrol.position.x = 0;
  motioncontrol.position.z = 0;
  motioncontrol.rotation.x = 0;

  motioncontrol.rotation.z = motioncontrol.distancePointZ * Math.cos(0);
  motioncontrol.rotation.x = motioncontrol.distancePointZ * Math.sin(0);

  motioncontrol.prevposition.copy(motioncontrol.position);
  motioncontrol.prevrotation.copy(motioncontrol.rotation);

  // Our Javascript will go here.
  var domContainer = null;
  domContainer = document.getElementById("canvas_container");           
  var camera = new THREE.PerspectiveCamera( 50, window.innerWidth/window.innerHeight, 0.1, 5000 );
  var aspectratio = window.innerWidth/window.innerHeight;
  var renderer = new THREE.WebGLRenderer();
  renderer.setSize( window.innerWidth, window.innerHeight );
  domContainer.appendChild(renderer.domElement);

  var materials = THREE.ImageUtils.loadTexture('texture/sky.jpg');

  addEventListener('mousemove', onDocumentMouseMove, false);
  domContainer.addEventListener('mousedown', onDocumentMouseDown, false);
  domContainer.addEventListener('mouseup', onDocumentMouseUp, false);

  var scene = new THREE.Scene();

  scene.add(camera);
  window.addEventListener('resize', resize, false);
  camera.position.x = 0;
  camera.position.y = 100;
  camera.position.z = -100;
  camera.rotation.y = Math.PI / 180.0 * 90;


  var directionalLight = new THREE.DirectionalLight(0xffffff, 1.0);
  directionalLight.position.set(0, -10, 0);
  scene.add(directionalLight);


  directionalLight = new THREE.DirectionalLight(0xffffff, 3.0);
  directionalLight.position.set(0, -50,-1000);
  scene.add(directionalLight);

  directionalLight = new THREE.DirectionalLight(0xffffff, 3.0);
  directionalLight.position.set(0, -50, 1000);
  scene.add(directionalLight);


  directionalLight = new THREE.DirectionalLight(0xffffff, 3.0);
  directionalLight.position.set(-200, -10, 0);
  scene.add(directionalLight);


  directionalLight = new THREE.DirectionalLight(0xffffff, 3.0);
  directionalLight.position.set(200, -10, 0);
  scene.add(directionalLight);


  addGround(scene);

  // array of unsorted geometries.
  var CubeGeometryArray = new Array();
  var CubeGeometryTier1 = new THREE.Geometry();
  var CubeGeometryTier2 = new THREE.Geometry();
  var CubeGeometryTier3 = new THREE.Geometry();
  var CubeGeometryTier4 = new THREE.Geometry();
  var CubeGeometryTier5 = new THREE.Geometry();

  // array of materials
  var CubeMaterials = new Array();

  // array of meshes used for hit testing. 
  var CubeArray = new Array();
  var cMaterialCount = 0;
  var Cube20Mesh;
  var Cube40Mesh;
  var CubesLoaded = false;

  LoadCubeMaterial();
  LoadCubeMeshs();
  var controls;


  function resize()
   {
    renderer.setSize(window.innerWidth, window.innerHeight);
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
   };

  function onMouseWheel(event)
   {
    var delta = 0;

    if ( event.wheelDelta !== undefined ) {
     // WebKit / Opera / Explorer 9
     delta = event.wheelDelta;

    } else if ( event.detail !== undefined ) {
     // Firefox
     delta = - event.detail;
    }

    if ( delta > 0 ) {  // forward  

      var angle = Math.atan2(motioncontrol.rotation.x, motioncontrol.rotation.z);        
      motioncontrol.position.z += motioncontrol.bumpposition * Math.cos(angle);
      motioncontrol.position.x += motioncontrol.bumpposition * Math.sin(angle);                            

    } else if ( delta < 0 ) {

      var angle = Math.atan2(motioncontrol.rotation.x, motioncontrol.rotation.z);
      angle += Math.PI;
      motioncontrol.position.z += motioncontrol.bumpposition * Math.cos(angle);
      motioncontrol.position.x += motioncontrol.bumpposition * Math.sin(angle);

    }
   };

  function onDocumentMouseMove(event)
   {
    event.preventDefault();
    if (mouseDown > 0) {
     if (((event.clientX / window.innerWidth) * 2 - 1) > mouse.x) {
      motioncontrol.rotationanglezx -= motioncontrol.bumpdegrees;
      if (motioncontrol.rotationanglezx < 0)
       motioncontrol.rotationanglezx += 360;

      var angle = (Math.PI / 180.0) * motioncontrol.rotationanglezx;
      motioncontrol.rotation.x = motioncontrol.distancePointZ * Math.cos(angle) - motioncontrol.distancePointZ * Math.sin(angle);
      motioncontrol.rotation.z = motioncontrol.distancePointZ * Math.sin(angle) + motioncontrol.distancePointZ * Math.cos(angle);

     }

     if (((event.clientX / window.innerWidth) * 2 - 1) < mouse.x) {
      motioncontrol.rotationanglezx += motioncontrol.bumpdegrees;
      if (motioncontrol.rotationanglezx > 360)
       motioncontrol.rotationanglezx -= 360;

      var angle = (Math.PI / 180.0) * motioncontrol.rotationanglezx;
      motioncontrol.rotation.x = motioncontrol.distancePointZ * Math.cos(angle) - motioncontrol.distancePointZ * Math.sin(angle);
      motioncontrol.rotation.z = motioncontrol.distancePointZ * Math.sin(angle) + motioncontrol.distancePointZ * Math.cos(angle);
     }
    }
   };

  function onDocumentMouseDown(event)
   {
    ++mouseDown;
    event.preventDefault();
    var mouse = new THREE.Vector2();

    mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
    mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;

    raycaster.setFromCamera(mouse, camera);

    intersects = raycaster.intersectObjects(CubeArray);
    if(intersects.length > 0)
     {
      if(intersects[0].object.name != null)
       {
        var offset = intersects[0].object.name * 8;
        var offsetfaces = intersects[0].object.name * 12;
        var index = intersects[0].object.name;
        var selectedObject = scene.getObjectByName("Tier1");
        scene.remove(selectedObject);

        CubeArray.splice(index, 1);
        CubeGeometryTier1 = CubeGeometryArray[0];
        CubeGeometryTier1.vertices.splice(offset, 8);
        CubeGeometryTier1.faces.splice(offsetfaces, 12);
        CubeGeometryTier1.faceVertexUvs[0].splice(offsetfaces, 12);

        CubeGeometryArray[0] = CubeGeometryTier1.clone();

        CubeGeometryTier1.sortFacesByMaterialIndex();
        var cmesh = new THREE.Mesh(CubeGeometryTier1,   new THREE.MeshFaceMaterial(CubeMaterials));
        cmesh.matrixAutoUpdate = false;
        cmesh.updateMatrix();
        cmesh.name = "Tier1";
        scene.add(cmesh);
       }
      else
       INTERSECTED = null;
     }
   };

   function onDocumentMouseUp(event) {
       mouseDown = 0;
       event.preventDefault();                       
   }

  function addGround(scene1)
   {
    var materialg =  new THREE.MeshBasicMaterial( { color: 0x333333 , side: THREE.BackSide } );    
    var groundmesh = new THREE.Mesh(new THREE.PlaneGeometry(9000, 4500, 1), materialg);
    groundmesh.receiveShadow = true;
    groundmesh.rotation.x = Math.PI / 180.0 * 90;
    groundmesh.position.set(0, 0, 0);
    groundmesh.name = "asphalt";
    scene1.add(groundmesh);
  };

  function writeToScreen(message)
   {
    var pre = document.getElementById("MessageDisplay");
    pre.style.wordWrap = "break-word";
    pre.innerHTML = message;
   }


  function writeToScreen2(message)
   {
    var pre = document.getElementById("MessageDisplay1");
    pre.style.wordWrap = "break-word";
    pre.innerHTML = message;
   }


  function addCube20(name, x1,z1,azimuth,height,add)
   {
    var cube;
    if (add)
     {
       if (height > 5)
        height = 5;
       cube = Cube20Mesh.clone();
       cube.visible = true;
       cube.receiveShadow = true;
       cube.position.set(x1, ((height - 1) * 8.5) + 4.25, z1);
       cube.rotation.y = (Math.PI / 180.0) * azimuth;
       cube.name = name;
       cube.updateMatrix();
       AddCubeGeometry(cube.geometry, cube.matrix, height);
       cube.matrixWorld = cube.matrix;
       CubeArray.push(cube); // kept for hit test
      }
   };

  function addCube40(name, x1, z1, azimuth,height,add)
   {
     var cube;
     if (add)
     {
       if (height > 5)
         height = 1;
        cube = Cube40Mesh.clone();
        cube.visible = true;
        cube.receiveShadow = true;
        cube.position.set(x1, ((height - 1) * 8.5) + 4.25, z1);
        cube.rotation.y = (Math.PI / 180.0) * azimuth;
        cube.name = name;
        cube.updateMatrix();
        AddCubeGeometry(cube.geometry, cube.matrix, height + 5);
        cube.matrixWorld = cube.matrix;
        CubeArray.push(cube); // kept for hit test
       }
    };

  function LoadCubeMeshs()
  {
   var CubeGeometry20 = new THREE.BoxGeometry(20, 8.5, 9.5);
   var CubeGeometry40 = new THREE.BoxGeometry(40, 8.5, 9.5);
   Cube20Mesh  = new THREE.Mesh(CubeGeometry20);
   Cube40Mesh =  new THREE.Mesh(CubeGeometry40); 
   CubesLoaded = true;
  };


  function LoadCubeMaterial()
  {
   CubeMaterials[0] = new THREE.MeshBasicMaterial({color:0xff0000 });
   cMaterialCount++;
   CubeMaterials[1] = new THREE.MeshBasicMaterial({color:0xffff00 });
   cMaterialCount++;
   CubeMaterials[2] = new THREE.MeshBasicMaterial({color:0xffffff });
   cMaterialCount++;
   CubeMaterials[3] = new THREE.MeshBasicMaterial({color:0x0000ff });
   cMaterialCount++;
   CubeMaterials[4] = new THREE.MeshBasicMaterial({color:0x00ffff });
   cMaterialCount++;
   CubeMaterials[5] = new THREE.MeshBasicMaterial({color:0x772255 });
   cMaterialCount++;
   CubeMaterials[6] = new THREE.MeshBasicMaterial({color:0x552277 });
   cMaterialCount++;
   CubeMaterials[7] = new THREE.MeshBasicMaterial({color:0x222299 });
   cMaterialCount++;
   CubeMaterials[8] = new THREE.MeshBasicMaterial({color:0x992222 });
   cMaterialCount++;
   CubeMaterials[9] = new THREE.MeshBasicMaterial({color:0x000000 });
   cMaterialCount++;
   };


       function DisplayCubes(scene1)
        {
          if(CubeGeometryTier1.faces.length > 0)
          {
           var material = new THREE.MeshNormalMaterial();
            // save the unsorted geometry. 
            CubeGeometryArray.push(CubeGeometryTier1.clone());
            CubeGeometryTier1.sortFacesByMaterialIndex();
            var Cubemesh = new THREE.Mesh(CubeGeometryTier1, new THREE.MeshFaceMaterial(CubeMaterials)); 
            Cubemesh.matrixAutoUpdate = false;
            Cubemesh.updateMatrix();
            Cubemesh.name = "Tier1";
            scene1.add(Cubemesh);
           }

          if(CubeGeometryTier2.faces.length > 0)
           {
            // save the unsorted geometry. 
            CubeGeometryArray.push(CubeGeometryTier2.clone());
            // sorting is a HUGE performance boost 
            CubeGeometryTier2.sortFacesByMaterialIndex();
            var Cubemesh = new THREE.Mesh(CubeGeometryTier2,  CubeMaterials); 
            Cubemesh.matrixAutoUpdate = false;
            Cubemesh.updateMatrix();
            Cubemesh.name = "Tier2";
            scene1.add(Cubemesh);
           }

          if(CubeGeometryTier3.faces.length > 0)
           {
             CubeGeometryArray.push(CubeGeometryTier3.clone());
             CubeGeometryTier3.sortFacesByMaterialIndex();
             var Cubemesh = new THREE.Mesh(CubeGeometryTier3, CubeMaterials); 
             Cubemesh.matrixAutoUpdate = false;
             Cubemesh.updateMatrix();
             Cubemesh.name = "Tier3";
             scene1.add(Cubemesh);
            }

          if(CubeGeometryTier4.faces.length > 0)
          {
             CubeGeometryArray.push(CubeGeometryTier4.clone());
             CubeGeometryTier4.sortFacesByMaterialIndex();
             var Cubemesh = new THREE.Mesh(CubeGeometryTier4,   CubeMaterials); 
             Cubemesh.matrixAutoUpdate = false;
             Cubemesh.updateMatrix();
             Cubemesh.name = "Tier4";
             scene1.add(Cubemesh);
            }

          if(CubeGeometryTier5.faces.length > 0)
          {
             CubeGeometryArray.push(CubeGeometryTier5.clone());
             CubeGeometryTier5.sortFacesByMaterialIndex();
             var Cubemesh = new THREE.Mesh(CubeGeometryTier5,   CubeMaterials); 
             Cubemesh.matrixAutoUpdate = false;
             Cubemesh.updateMatrix();
             Cubemesh.name = "Tier5";
             scene1.add(Cubemesh);
          }
       };

       // merging geometry for improved performance. 
       function AddCubeGeometry(geom, matrix,tier)
       {
        switch(tier)
          {
           case 1:
            //CubeGeometryTier1.merge(geom, matrix, tier - 1);
            CubeGeometryTier1.merge(geom, matrix);
             break;
           case 2:
             CubeGeometryTier2.merge(geom, matrix,tier - 1);
             break;
           case 3:
             CubeGeometryTier3.merge(geom, matrix,tier - 1);
             break;

           case 4:
             CubeGeometryTier4.merge(geom, matrix,tier - 1);
             break;

           case 5:
             CubeGeometryTier5.merge(geom, matrix,tier - 1);
             break;
            // forty footers 
           case 6:
            //             CubeGeometryTier1.merge(geom, matrix,tier - 1);
             CubeGeometryTier1.merge(geom, matrix);
             break;

           case 7:
             CubeGeometryTier2.merge(geom, matrix,tier - 1);
             break;

           case 8:
             CubeGeometryTier3.merge(geom, matrix,tier - 1);
             break;

           case 9:
             CubeGeometryTier4.merge(geom, matrix,tier - 1);
             break;

           case 10:
             CubeGeometryTier5.merge(geom, matrix,tier - 1);
             break;

           default:
             CubeGeometryTier1.merge(geom, matrix,0);
             break;           
         }
        };





   motioncontrol.position.y = 10;
   motioncontrol.position.x = -50;
   motioncontrol.position.z = 0;
   motioncontrol.rotation.x = 0;

   motioncontrol.rotation.z = motioncontrol.distancePointZ * Math.cos(0);
   motioncontrol.rotation.x = motioncontrol.distancePointZ * Math.sin(0);




  function LoadCubes()
   {
     var cnt = 0;
     for(var x = 0; x < 5; x++)
      {
       addCube20(cnt, 0, x * 23.0, 90, 1, true);
       cnt++;
       addCube40(cnt, 10, x * 43, 90, 1, true);
       cnt++;
      }

    };


   // game systems code

   var keyboardControls = (function() {

    var keys = { SP : 32, Q:81, E:69, W : 87, A : 65, S : 83, D : 68, UP : 38, LT : 37, DN : 40, RT : 39 };

    var keysPressed = {};

    (function( watchedKeyCodes ) {
     var handler = function( down ) {
      return function( e ) {
       var index = watchedKeyCodes.indexOf( e.keyCode );
       if( index >= 0 ) {
        keysPressed[watchedKeyCodes[index]] = down; e.preventDefault();
       }
      };
     };
     window.addEventListener( "keydown", handler( true ), false );
     window.addEventListener( "keyup", handler( false ), false );
    })([
     keys.SP, keys.Q, keys.E, keys.W, keys.A, keys.S, keys.D, keys.UP, keys.LT, keys.DN, keys.RT
    ]);


    return function() {

      // look around                    

     if (keysPressed[keys.Q])
     {
         motioncontrol.tiltangle += motioncontrol.bumpdegrees;
         if (motioncontrol.tiltangle < 0)
           motioncontrol.tiltangle += 360;
        var angle = (Math.PI / 180.0) * motioncontrol.tiltangle;
        motioncontrol.rotation.y =  motioncontrol.distancePointZ * Math.sin(angle);
       }  

      if (keysPressed[keys.E])
       {
         motioncontrol.tiltangle -= motioncontrol.bumpdegrees;
         if (motioncontrol.tiltangle < 0)
          motioncontrol.tiltangle += 360;
           var angle = (Math.PI / 180.0) * motioncontrol.tiltangle;
        motioncontrol.rotation.y =  motioncontrol.distancePointZ * Math.sin(angle);
       }


     if (keysPressed[keys.W])
       {
        motioncontrol.position.y += motioncontrol.bumpposition;
        if (motioncontrol.position.y > 1000.0)
         motioncontrol.position.y = 1000.0;
       }  

      if (keysPressed[keys.S])
       {
       motioncontrol.position.y += -motioncontrol.bumpposition;
       if (motioncontrol.position.y < 1.0)
        motioncontrol.position.y = 1;
       }




      if(keysPressed[keys.A])
      {
        var angle = Math.atan2(motioncontrol.rotation.x, motioncontrol.rotation.z);
        angle += Math.PI / 180.0 * 90;
        var message = "Angle " + angle * 180/Math.PI;
        motioncontrol.position.z += motioncontrol.bumpposition * Math.cos(angle);
        motioncontrol.position.x += motioncontrol.bumpposition * Math.sin(angle);
       }

      if(keysPressed[keys.D])
      {
        var angle = Math.atan2(motioncontrol.rotation.x, motioncontrol.rotation.z);
        angle += Math.PI / 180.0 * -90;
        var message = "Angle " + angle * 180/Math.PI;
        motioncontrol.position.z += motioncontrol.bumpposition * Math.cos(angle);
        motioncontrol.position.x += motioncontrol.bumpposition * Math.sin(angle);
       }

      // forward  
      if (keysPressed[keys.UP])
      {
        var angle = Math.atan2(motioncontrol.rotation.x, motioncontrol.rotation.z);

        var message = "Angle " + angle * 180/Math.PI;
        motioncontrol.position.z += motioncontrol.bumpposition * Math.cos(angle);
        motioncontrol.position.x += motioncontrol.bumpposition * Math.sin(angle);
       }

      // backward 
      if(keysPressed[keys.DN])
       {
        var deltaX = motioncontrol.rotation.z - motioncontrol.position.z;
        var deltaY = motioncontrol.rotation.x - motioncontrol.position.x;
        // var angle = Math.atan2(deltaY, deltaX);
        var angle = Math.atan2(motioncontrol.rotation.x, motioncontrol.rotation.z);
        angle += Math.PI;
       var message = "Angle " + angle * 180/Math.PI;
        motioncontrol.position.z += motioncontrol.bumpposition * Math.cos(angle);
        motioncontrol.position.x += motioncontrol.bumpposition * Math.sin(angle);
       }

      if(keysPressed[keys.LT])
      {
         motioncontrol.rotationanglezx -= motioncontrol.bumpdegrees;
         if (motioncontrol.rotationanglezx < 0)
          motioncontrol.rotationanglezx += 360;

         var angle = (Math.PI / 180.0) * motioncontrol.rotationanglezx;
         motioncontrol.rotation.x =  motioncontrol.distancePointZ * Math.cos(angle) - motioncontrol.distancePointZ * Math.sin(angle);
         motioncontrol.rotation.z =  motioncontrol.distancePointZ * Math.sin(angle) + motioncontrol.distancePointZ * Math.cos(angle);

        }
      if(keysPressed[keys.RT])
        {
         motioncontrol.rotationanglezx += motioncontrol.bumpdegrees;
         if (motioncontrol.rotationanglezx > 360)
          motioncontrol.rotationanglezx -= 360;

         var angle = (Math.PI / 180.0) * motioncontrol.rotationanglezx;
         motioncontrol.rotation.x =  motioncontrol.distancePointZ * Math.cos(angle) - motioncontrol.distancePointZ * Math.sin(angle);
         motioncontrol.rotation.z = motioncontrol.distancePointZ * Math.sin(angle) + motioncontrol.distancePointZ * Math.cos(angle);

        }
    };

   })();


   var updateCamera = (function() {

    return function() {

     camera.position.copy(motioncontrol.position);

     camera.lookAt(motioncontrol.rotation);
     var message = "Rotation " + motioncontrol.rotationanglezx + "<BR>";
     message += "X " + motioncontrol.position.x + "<BR>";
     message += "Y " + motioncontrol.position.y + "<BR>";
     message += "Z " + motioncontrol.position.z + "<BR>";

     message += "X " + motioncontrol.rotation.x + "<BR>";
     message += "Y " + motioncontrol.rotation.y + "<BR>";
     message += "Z " + motioncontrol.rotation.z + "<BR>";
     var angle = Math.atan2(motioncontrol.rotation.x, motioncontrol.rotation.z);
     message += "Angle " + angle * 180 / Math.PI + "<BR>";
     message += "Use Arrows w,s,e,d,q,a to navigate<BR>";

     writeToScreen2(message);

    };
   })();


  function render() {
    if(cMaterialCount > 9 && cMaterialCount < 200 && CubesLoaded)
      {
       cMaterialCount = 200;
       LoadCubes();
       DisplayCubes(scene);
      }
     keyboardControls();           
     updateCamera();

     renderer.render( scene, camera );
     requestAnimationFrame( render ); 
   };

  render();

   </script>
 </body>
</html>

1 个答案:

答案 0 :(得分:0)

TLDR 阵列突变和静态偏移是一种危险的混合

首先,我建议您发布某种代码的小提琴。我做了一个here你的例子。其次,您可以使用一些DRYing来缩短和澄清您的代码。第三,在这个大小的代码中,我建议以某种方式分离和分组代码(文件,任务,甚至注释块)。最后,在这样的演示中,我认为没有理由推出自己的控件。查看THREE.js提供的Orbit Camera之类的内容。

无论如何,我收集到你收集大量的立方体到10层&#39; of THREE.Geometry用于渲染目的。然后单击(〜第180行),光线投射,并尝试从几何体中仅删除该立方体。这是您的相关代码:

intersects = raycaster.intersectObjects(CubeArray);
if(intersects.length > 0)
 {
  if(intersects[0].object.name != null)
   {
    var offset = intersects[0].object.name * 8;
    var offsetfaces = intersects[0].object.name * 12;
    var index = intersects[0].object.name;
    var selectedObject = scene.getObjectByName("Tier1");
    scene.remove(selectedObject);

    CubeArray.splice(index, 1);
    CubeGeometryTier1 = CubeGeometryArray[0];
    CubeGeometryTier1.vertices.splice(offset, 8);
    CubeGeometryTier1.faces.splice(offsetfaces, 12);
    CubeGeometryTier1.faceVertexUvs[0].splice(offsetfaces, 12);

    CubeGeometryArray[0] = CubeGeometryTier1.clone();

    CubeGeometryTier1.sortFacesByMaterialIndex();
    var cmesh = new THREE.Mesh(CubeGeometryTier1,   new THREE.MeshFaceMaterial(CubeMaterials));
    cmesh.matrixAutoUpdate = false;
    cmesh.updateMatrix();
    cmesh.name = "Tier1";
    scene.add(cmesh);
   }
  else
   INTERSECTED = null;
 }

以下是我阅读此代码段的方法:

  • 反对CubeArray
  • 如果没有命中或没有名称,请返回
  • Implict将一些字符串名称(!)转换为数字以计算Tier中的位置
  • 通过名称&#34; Tier1&#34;从场景中删除对象,而不管其他任何输入
  • 将CubeGeometryTier1设置为CubeGeometryArray的第一个索引,无论是否为raycast
  • 现在覆盖CubeGeometryTier1以删除几何
  • 使用CubeGeometryTier1的更改对象重新分配CubeGeometryArray [0]
  • 基于CubeGeometryTier1构建一个新网格,将其称为&#34; Tier1&#34;并将其转储回场景

我承认我还没有完全追踪你建造立方体的数百条线,但这对我来说毫无意义。假设您使用CubeGeometry [Tier | Array]和硬编码的名称和索引是正确的,那么真正让我感到震惊的是当您改变数组时使用静态偏移。

你拼接CubeArray去除那个&#39;幽灵&#39;多维数据集再次被挑选,但没有其他的鬼&#39;更改了多维数据集,特别是它们的偏移名称,而重建为Tier1的几何图形则更改了。通过拼接的多维数据集,所有索引名称都将错误

以下是更简单形式的示例:

&#13;
&#13;
//set up
var baseArray = [0, 1, 2, 3, 4, 5].map(i => '' + i);
const getRandomInt = (min, max) => {
  return Math.floor(Math.random() * (max - min)) + min;
};
const pickRandomElementFrombaseArray = () => {
  const pickedIndex = getRandomInt(0, baseArray.length);
  return baseArray[pickedIndex];
};


// operationally equivilent to splicing your Tiers of their geometry
const yankIndex = (value) => {
  //value is a string in this case
  const index = +value;
  if (index < 0 || index > baseArray.length - 1) {
    throw `Unable to remove invalid index ${index}`
  } else {
    baseArray.splice(index, 1);
  }
};


// Run the test until empty or failure
var messages = [`Starting with ${baseArray}`];
while (baseArray.length > 0) {
  const pickedValue = pickRandomElementFrombaseArray();
  messages.push(`Picked element ${pickedValue} to remove`);
  try {
    yankIndex(pickedValue);
    messages.push(`Now array is ${baseArray}`);
  } catch (e) {
    messages.push(`ALERT: ${e}`);
    break;
  }
}

messages.push('Test complete');
const div = $('#div');
messages.map(msg => `<p>${msg}</p>`).forEach(msg => div.append(msg))
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title></title>
</head>

<body>
  <h2>Results</h2>
  <div id="div"></div>
</body>

</html>
&#13;
&#13;
&#13;

尝试几次。在发生错误之前,阵列只有0.8%的可能性耗尽。

当你处理数组的变异时,偷偷摸摸的错误会蔓延到代码中。忽略完全重构代码,让人想起的选择:

  1. 维护每次删除时的偏移地图。基本上,重建每个立方体的每个动作的偏移量。您可以在CubeArray中执行此操作,或者,如果创建/更改10k重的THREE.js对象不符合您的喜好,则将每个多维数据集ID映射到层中的偏移量的另一级间接

  2. 不可见对象永远不要真正删除几何体(即不要拼接层数组),只需将其隐藏即可。将面部缩放为0,隐形垫,无论如何。这意味着您预先生成的所有偏移都将保留。缺点是看不见的地理位置是免费的,如果您需要以其他方式更改场景,这将不会有帮助,并且您必须从thee.raycast扫描其他点击