ThreeJs入门47-粒子系统-生成多个粒子系统

695 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天,点击查看活动详情

示例代码采用three.js-r73版本: github.com/mrdoob/thre…

我们现在可以通过geometry生成粒子系统了,我们如何通过加载不同的模型,生成多个粒子系统呢?让我们来看看吧。

封装生成粒子系统的方法

  • 基于上节课的代码,我们继续开发我们的功能。
  • 为了方便操作生成粒子系统,我们需要封装一个方法createMesh
  • 我们需要一些参数
    • geometry:加载的几何体
    • scene:场景
    • scale:模型缩放,用来改变模型大小
    • x、y、z:表示模型位置
    • color:粒子颜色
    • dynamic:粒子是否运动,我们的粒子模型可以是动态的或者静态的
/**
 * 创建mesh
 * @param {*} originalGeometry 从模型中加载的几何体
 * @param {*} scene 场景
 * @param {*} scale 模型缩放
 * @param {*} x 表示把模型放到什么位置
 * @param {*} y 
 * @param {*} z 
 * @param {*} color 粒子颜色
 * @param {*} dynamic 粒子是否运动起来
 */
function createMesh(originalGeometry, scene, scale, x, y, z, color, dynamic) {

}
  • 封装这个方法,主要需要以下几步
    • 获取顶点的位置
    • 设置几何体对象和相关属性
    • 判断模型是静态还是动态,分别对物体做一些设置
    • 将所有物体管理起来,初始化一些参数,为后面粒子运动做准备

获取顶点的位置

  • 对顶点和顶点的数量进行存储
var vertices = originalGeometry.vertices;
var vl = vertices.length; // 顶点数量

设置几何体对象和相关属性

  • 我们要保留原有的Geometry,所以需要对几何体进行克隆,并且添加一些新的属性
// 几何体对象和相关属性
var geometry = new THREE.Geometry();
var vertices_tmp = []; //缓存数组 x,y,z,down,up
// 把原Geometry的顶点复制到新的geometry中
for (var i = 0; i < vl; i++) {
  p = vertices[i];
  geometry.vertices[i] = p.clone();
  vertices_tmp[i] = [p.x, p.y, p.z, 0, 0];
}
  • 我们设置了新的几何体,把原几何体的顶点复制到新的几何体中
  • 并且添加了缓存数组,用来存储顶点信息和向上向下运动,默认都是0,也就是静止

判断模型是静态还是动态,分别对物体做一些设置

  // 判断模型是动态的还是静态的,生成粒子系统
  if(dynamic) {
		// 动态的物体
  }else {  
  	// 静态的物体
  }

设置静态物体的显示

  • 静态物体的显示比较简单,我们先做这一部分
  • 我们直接创建粒子系统,根据传递的参数设置材质颜色,物体大小和位置
// 静态的物体
mesh = new THREE.Points( geometry, new THREE.PointsMaterial({ color, size: 3 }) );
mesh.scale.x = mesh.scale.y = mesh.scale.z = scale;
mesh.position.x = x;
mesh.position.y = y;
mesh.position.z = z;
parent.add(mesh);
  • 在车模型上进行使用
binaryLoader.load(
    `${base_url}/models/binary/veyron/VeyronNoUv_bin.js`,
    function (geometry) {
      createMesh(geometry, scene, 6.8, 2200, -200, -100, 0x0055ff, false);
    }
  );

image.png

  • 这样我们的粒子车模型就展示完成了

设置动态物体的显示

  • 由于我们每创建一个人(自定义颜色的),就需要复制出7个克隆人(统一颜色的),一共是8个模型,展示在不同的位置,所以我们先定义这些人的位置
// 人的位置
var clones = [
  [2000, 0, -2000],
  [2000, 0, 0],
  [1000, 0, 500],
  [1000, 0, -5000],
  [3000, 0, 2000],
  [-4000, 0, 1000],
  [-4500, 0, -3000],
  [0, 0, 0], // 原点位置的人设置自定义颜色
];
  • 遍历这些人的位置,根据位置创建不同的物体,然后添加到分组中
// 动态的物体
for(var i = 0; i < clones; i++) {
  // 当i不是最后一个点位时,赋值默认颜色0x252525,最后一个点位给传入的颜色
  var c = (i < clones.length - 1) ? 0x656565 : color;
  mesh = new THREE.Points(geometry,new THREE.PointsMaterial({ color: c, size: 3 }));
  mesh.scale.x = mesh.scale.y = mesh.scale.z = scale;
  // 给物体不同的点位,传入的点位+默认的点位
  mesh.position.x = x + clones[i][0];
  mesh.position.y = y + clones[i][1];
  mesh.position.z = z + clones[i][2];
  parent.add(mesh)
}
  • 在人模型上进行使用
createMesh(geometry, scene, 4.05, -500, -350, 600, 0xff7744, true);

image.png

  • 这样我们就创建了1个人和7个克隆人的粒子模型

将所有物体管理起来

  • 我们把物体缓存起来,设置好需要的参数,为后面的粒子运动做准备
// 将所有的对象管理起来,设置一些初始化参数
meshes.push({
  mesh, // 物体
  vertices: geometry.vertices,// 顶点
  vertices_tmp, // 顶点缓存
  vl, // 顶点数组长度
  down: 0, // 向下顶点数
  up: 0, // 向上顶点数
  direction: 0, // 向上/向下运动 -1向下 1向上
  speed: 60, // 运动速度
  started: false, // 是否开始运动
  start: Math.floor(100 + 200 * Math.random()), // 开始时间
  delay: Math.floor(200 + 200 * Math.random()), //停留时间
  dynamic, // 物体是否运动
});

codepen示例代码