Threejs,粒子沿随机线移动

上次拿了一个小球实验,小球和随机线的相依相恋

这次捉来了几只粒子,效果嘛,有点魔幻,不过也还行。效果在这里0.0

刚开始的粒子会比较紧密一点,像这样
在这里插入图片描述

这是运行一段时间比较稳定的样子

在这里插入图片描述
套个半透明的管子模拟个水流啥的应该也还行

主要的代码总结一下:

主要变量:

//粒子
 var particles;//粒子系统,new Point类型
 var pointsGomtry = new THREE.Geometry(); //粒子顶点信息
 var particlesNum = 60; //粒子数量
 var particlesPos = []; //粒子位置
 var posLocal = []; // 随机线在粒子坐标系内的位置
 var posIndex = []; // 粒子所在的随机点索引
 var colors = []; //粒子的颜色们
 var color = new THREE.Color();
 var colorde = 3; // 粒子颜色的衰减值,减少亮度和饱和度

粒子的位置是在一个圆内随机生成的:

for ( var i = 0; i < particlesNum; i ++ ) {

 var x = Math.sin(6 * i * 2 * Math.PI/ 180) * Math.random(0,1);
 var z = 0;
 var y = Math.cos(6 * i * 2 * Math.PI/ 180) * Math.random(0,1);

 particlesPos.push( x, y, z );
 // colors 彩色
 /*var vx = ( x / colorde ) + 0.5; 
 var vy = ( y / colorde ) + 0.5;
 var vz = ( z / colorde ) + 0.5;*/
 //天蓝色
 var vx = 0; 
 var vy = 174;
 var vz = 255;
 color.setRGB( vx, vy, vz );
 colors.push( color.r, color.g, color.b );
 posIndex.push(0);
 }

有了点就可以生成BufferGeometry和Geometry了,如果只是生成粒子的话, BufferGeometry 就可以了, BufferGeometry 里面的位置信息是 Float32Array ,变换和操作起来都有一些难度,转换为 Geometry 的话,有v3类型的vertices,操作要方便很多。

var pointsGeometry = new THREE.BufferGeometry();
pointsGeometry.addAttribute( 'position', new THREE.Float32BufferAttribute( particlesPos, 3 ) );
pointsGeometry.addAttribute( 'color', new THREE.Float32BufferAttribute( colors, 3 ) );
pointsGeometry.computeBoundingSphere();

pointsGomtry = pointsGomtry.fromBufferGeometry(pointsGeometry);

默认的粒子系统里面粒子是方形,我想要圆形的,所以要自己配一下材质,材质配置说明详见

var material = new THREE.PointsMaterial( 
{ 
 size: 6, 
 vertexColors: THREE.VertexColors,
 map:new THREE.TextureLoader().load( "dot.png"),
 //blending:THREE.MultiplyBlending,
 transparent:true,
 opacity:1.0,
 depthTest: false,
 });
particles = new THREE.Points( pointsGomtry, material );
scene.add( particles );

放一个坐标轴方便定位

var axes2 = new THREE.AxesHelper( 5 );
axes.name = "AxesHelper2";
particles.add( axes2 );

把粒子系统放到随机线的初始位置,

particles.position.set(pointsV3[0].x,pointsV3[0].y,pointsV3[0].z); 
particles.lookAt(pointsV3[1]);
particles.updateMatrixWorld(true,true);

计算随机线上的点在粒子系统里的坐标位置

for(let i = 0;i < pointsV3.length; i++)
{
posLocal.push(particles.worldToLocal(pointsV3[i].clone()));
}

在animate()里面定时给每个点变换一下位置,线的走向就是每个点应该走的方向,把方向normalize一下,乘一个类似速度的偏随机的数字就是每个点的下一个位置

var vs = particles.geometry.vertices;
for(var i = 0; i < vs.length; i++) {

let pos = vs[i];
n=posLocal[posIndex[i]+1].clone().sub(posLocal[posIndex[i]].clone()).normalize().multiplyScalar(Math.random(0,1) * 1);

let vv = posLocal[posIndex[i]+1].clone().sub(vs[i].clone());
if(vv.length() < 1 || vv.clone().dot(n.clone()) < 0 )
{
   vs[i].add(vv.clone().projectOnVector(n.clone()));
   if(posIndex[i] < posLocal.length - 2)
         posIndex[i]+=1; 
   else
   {
       posIndex[i]=0; 
       let r = (Math.random(0,1) - 0.5)*360;
       let x = Math.sin(r * Math.PI/ 180);
       let z = 0;
       let y = Math.cos(r * Math.PI/ 180);
       vs[i] = new THREE.Vector3(x,y,z);
    }
 }
 else
 { 
     vs[i].add(n);
 }

}
particles.geometry.verticesNeedUpdate = true; 

有些临时变量名字起的随意了一些,不过也不难理解。

分割线更一波,上面的粒子有的时候操作着会产生突然看不见的问题,我知道应该是相机裁剪的问题,调了一下参数还是不行,今天发现一个函数可以解决这个问题,就是直接把裁剪关了。

particles = new THREE.Points( pointsGomtry, material );
particles.frustumCulled = false;
scene.add( particles );
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值