为网格删除写一个反向函数

时间:2017-06-28 13:20:57

标签: javascript function three.js mesh

我有一个在你点击另一个时创建网格的功能。在点击上,创建2或3个网格并转到它们的位置。知道我想做反向功能:当部署网格时,你点击网格上的anoter时间,先前创建的网格会返回并从场景中移除。

这是我的第一个功能:

function sortiSphere(element, obj) {


    var matStdParams = {
        roughness: 1,
        metalness: 0.8,
        color: element.group,
        emissive: element.group,
        emissiveIntensity: 0.5
    };


    var sphereMaterial2 = new THREE.MeshStandardMaterial(matStdParams);

    var mesh = new THREE.Mesh(sphereGeometry, sphereMaterial2);

    mesh.position.x = x;
    mesh.position.y = y;
    mesh.position.z = z;

    mesh.userData.children = element.children;
    mesh.userData.name = element.label;
    mesh.userData.rang = element.rang;
    mesh.userData.def = element.définition;
    mesh.userData.posx = element.posx;
    mesh.userData.posy = element.posy;
    mesh.userData.posz = element.posz;
    mesh.userData.parent = obj;
    mesh.userData.cartabs = element.cartabs;
    mesh.position.normalize();
    mesh.position.multiplyScalar(1 / element.rang);
    mesh.scale.set(1 / (element.rang / 2), 1 / (element.rang / 2), 1 / (element.rang / 2))

    mesh.position.x = obj.position.x;
    mesh.position.y = obj.position.y;
    mesh.position.z = obj.position.z;

    var x = element.posx;
    var y = element.posy;
    var z = element.posz;


    new TWEEN.Tween(mesh.position).to({
            x: x,
            y: y,
            z: z
        }, 1000)
        .easing(TWEEN.Easing.Elastic.Out).start();


    console.log(mesh);

    scene.add(mesh);
    lesMesh.push(mesh)


    // lines
    var material = new THREE.LineBasicMaterial({
        color: 0xffffff
    });

    var geometry = new THREE.Geometry();
    geometry.vertices.push(
        obj.position,
        new THREE.Vector3(x, y, z)
    );

    var line = new THREE.Line(geometry, material);
    scene.add(line);

    gen1 = [];
    gen2 = [];
    gen3 = [];
    gen4 = [];
    gen5 = [];


    obj.userData.bool = true;

};

请注意,网格包含有关其状态的信息:userData.bool(如果已部署,则为true,否则为false)

现在,我该如何告诉他们回去?

以下是我现在所得到的:

    function deleteSphere(element, obj) {
    console.log("--- deleteSphere / debut fonction")



    for (i = 0; gen1.length > i; i++) {

        if (gen1[i].userData.children) {


            for (j = 0; gen1[i].userData.children.length > j; j++) {

                console.log(gen2[i][j]);
                scene.remove(gen2[i][j]);}

        } else {

            scene.remove(gen1[i])

           console.log(gen1[i].userData.children)
        }
    }
};

感谢您的时间

1 个答案:

答案 0 :(得分:0)

当您使用tween.js时,您可以使用其.onUpdate().onComplete()方法。

这不是最终的解决方案,这只是一个从头开始的例子。

让我们的基础对象有一个容器:

var bases = new THREE.Group();
scene.add(bases);

现在我们需要一个事件,我们将创建我们的基础对象,让它点击一个按钮:

btnAdd.addEventListener("click", setBase);

我们的setBase()函数将如下所示:

var rndBase = function() {
  return THREE.Math.randFloatSpread(10);
}

function setBase() {
  var base = new THREE.Mesh(new THREE.SphereGeometry(.5, 8, 4), new THREE.MeshBasicMaterial({
    color: Math.random() * 0xffffff
  }));
  base.position.set(rndBase(), rndBase(), rndBase());
  bases.add(base);
}

一切准备就绪,我们可以从点击基础对象开始。让它成为mousedown的事件监听器:

window.addEventListener("mousedown", setOrRemove, false);

var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
var intersects;
var obj;

function setOrRemove(event) {
  mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
  mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
  raycaster.setFromCamera(mouse, camera);
  intersects = raycaster.intersectObjects(bases.children);
  if (intersects.length > 0) {
    obj = intersects[0].object;
    if (obj.children.length != 0) { // simple check for existence of children
      removeObj(obj); // if children were deployed, then remove them and their parent (base object)
    } else {
      setChildren(obj); // otherwise, as a base object has no children, then we'll add some
    }
  }
}

最有趣的部分从这里开始。

让我们设置孩子们:

function setChildren(parent) {
  let radius = Math.random() + 1;
  for (let i = 0; i < THREE.Math.randInt(2, 3); i++) { //as you said there are 2 or 3 children
    var child = new THREE.Mesh(new THREE.BoxGeometry(.25, .25, .25), new THREE.MeshBasicMaterial({
      color: parent.material.color,
      wireframe: true
    }));
    child.userData.direction = new THREE.Vector3(rndBase(), rndBase(), rndBase()).normalize(); // random direction (must be a normalized vector)
    child.userData.radius = radius;
    parent.add(child);
  }
  let start = { val: 0 };
  let end = { val: 1 };
  new TWEEN.Tween(start).to(end, 1000) // we simply change from 0 to 1 during 1 second
    .easing(TWEEN.Easing.Elastic.Out)
    .onUpdate( // here we'll update position of each children in accordance to direction and radius
      function() {
        parent.children.forEach((child) => {
          child.position.copy(child.userData.direction).multiplyScalar(child.userData.radius * this.val);
        })
      }
    )
    .start();
}

删除基础对象及其子对象是:

function removeObj(baseObj) { // very similar to how we created children
  let start = { val: 1 };
  let end = { val: 0 };
  new TWEEN.Tween(start).to(end, 1000)
    .easing(TWEEN.Easing.Elastic.In)
    .onUpdate(
        function(){
        baseObj.children.forEach((child) => {
          child.position.copy(child.userData.direction).multiplyScalar(child.userData.radius * this.val);
          })
      }
    )
    .onComplete( // but the difference is here, it allow us to perform something when our tweening is completed
      function() { 
        for (let i = baseObj.children - 1; i = 0; i--) {
          baseObj.remove(baseObj.children[i]); //and here we simply delete children in reverse order
        }
        bases.remove(baseObj); //and then we remove the base object itself
      }
    )
    .start()
}

所以,就是这样。别忘了把TWEEN.update();放在我们的动画循环中:)

jsfiddle示例r86。