在THREE.js中实例化PointCloud(ParticleCloud)

时间:2017-03-14 16:21:56

标签: javascript three.js

我只是Threejs的初学者,请原谅这是一个noobie问题。但我还没有使用粒子。

如何将点(粒子)放入文本几何体的自定义几何体中? 我想要实现的是几何体或文本中的实例点然后将其爆炸到世界位置。如果有人指导我走这条路,会有很大帮助。

我知道有一个例子https://threejs.org/examples/#webgl_points_dynamic 但是我无法理解渲染循环中发生了什么。

1 个答案:

答案 0 :(得分:0)

这不是最终的解决方案,而只是一个起点。

您可以从任何类型的几何体(通常的几何体或缓冲区几何体)设置点。

enter image description here

假设您有一个THREE.TextGeometry(),那么您可以将其设置为:

textGeo = new THREE.TextGeometry("ABC", {
    font: font,
    size: 2,
    height: 0.25,
    curveSegments: 1,
    bevelEnabled: false
  });
  textGeo.computeBoundingBox();
  textGeo.computeVertexNormals();
  textGeo.center();

  fillWithPoints(textGeo, 1000); // fill our text geometry with 1000 random points

  textGeo.vertices.forEach(function(vertex){
    vertex.startPoint = vertex.clone(); // remember the starting position of a vertex
    vertex.direction = vertex.clone().normalize(); // set direction
  })
  textPoints = new THREE.Points(textGeo, new THREE.PointsMaterial({color: 0x00ff00, size: 0.1})); // all you need is to have a geometry and THREE.PointsMaterial()
  scene.add(textPoints);

为了确定一个随机点是否在我们的几何体中,我们可以通过将文本几何体的所有面投影到2D(x,y)并检查点(其x,y坐标)是否为在一个投影三角形(面)内:

function isPointInside(point, geometry) {
  var retVal = false;
  for (var i = 0; i < geometry.faces.length; i++) { //loop through faces
    face = geometry.faces[i];
    a = geometry.vertices[face.a];
    b = geometry.vertices[face.b];
    c = geometry.vertices[face.c];
    if (ptInTriangle(point, a, b, c)) {
      var retVal = true;
      break; // exit the loop if the point is in a projected triangle
    }
  }
  return retVal;
}

其中

function ptInTriangle(p, p0, p1, p2) {
    // credits: http://jsfiddle.net/PerroAZUL/zdaY8/1/
    var A = 1/2 * (-p1.y * p2.x + p0.y * (-p1.x + p2.x) + p0.x * (p1.y - p2.y) + p1.x * p2.y);
    var sign = A < 0 ? -1 : 1;
    var s = (p0.y * p2.x - p0.x * p2.y + (p2.y - p0.y) * p.x + (p0.x - p2.x) * p.y) * sign;
    var t = (p0.x * p1.y - p0.y * p1.x + (p0.y - p1.y) * p.x + (p1.x - p0.x) * p.y) * sign;

    return s > 0 && t > 0 && (s + t) < 2 * A * sign;
}

然后在动画循环中我们将使用顶点(startPoint和direction)的东西:

textGeo.vertices.forEach(function(vertex){
    vertex.copy(vertex.startPoint).addScaledVector(vertex.direction, 5 + Math.sin(Date.now() * 0.001) * 5);
});
textGeo.verticesNeedUpdate = true; // this is the most important thing, you have to set it to true after each rendering

jsfiddle示例