问题
I'm trying to animate particles along a path similar to this chrome expriement: http://armsglobe.chromeexperiments.com/
I've tried digging into the source of this project, and what I've groked so far is that they are using a built in curve method .getPoitns() to generate about 30 points on their lines.
Is there a better example on what I'm trying to accomplish? Is there a method for getting points on the line than using the .lerp() method 30 times to get 30 points? Should I just use TWEEN animations?
Any help or direction would be appreciated.
回答1:
I've figured out a solution, not sure if it's the best or not, but it works well.
You can find a demo on JsFiddle: https://jsfiddle.net/L4beLw26/
//First create the line that we want to animate the particles along
var geometry = new THREE.Geometry();
geometry.vertices.push(new THREE.Vector3(-800, 0, -800));
geometry.vertices.push(new THREE.Vector3(800, 0, 0));
var line = new THREE.Line(geometry, material);
var startPoint = line.geometry.vertices[0];
var endPoint = line.geometry.vertices[1];
scene.add(line);
//next create a set of about 30 animation points along the line
var animationPoints = createLinePoints(startPoint, endPoint);
//add particles to scene
for ( i = 0; i < numParticles; i ++ ) {
var desiredIndex = i / numParticles * animationPoints.length;
var rIndex = constrain(Math.floor(desiredIndex),0,animationPoints.length-1);
var particle = new THREE.Vector3();
var particle = animationPoints[rIndex].clone();
particle.moveIndex = rIndex;
particle.nextIndex = rIndex+1;
if(particle.nextIndex >= animationPoints.length )
particle.nextIndex = 0;
particle.lerpN = 0;
particle.path = animationPoints;
particleGeometry.vertices.push( particle );
}
//set particle material
var pMaterial = new THREE.ParticleBasicMaterial({
color: 0x00FF00,
size: 50,
map: THREE.ImageUtils.loadTexture(
"assets/textures/map_mask.png"
),
blending: THREE.AdditiveBlending,
transparent: true
});
var particles = new THREE.ParticleSystem( particleGeometry, pMaterial );
particles.sortParticles = true;
particles.dynamic = true;
scene.add(particles);
//update function for each particle animation
particles.update = function(){
// var time = Date.now()
for( var i in this.geometry.vertices ){
var particle = this.geometry.vertices[i];
var path = particle.path;
particle.lerpN += 0.05;
if(particle.lerpN > 1){
particle.lerpN = 0;
particle.moveIndex = particle.nextIndex;
particle.nextIndex++;
if( particle.nextIndex >= path.length ){
particle.moveIndex = 0;
particle.nextIndex = 1;
}
}
var currentPoint = path[particle.moveIndex];
var nextPoint = path[particle.nextIndex];
particle.copy( currentPoint );
particle.lerp( nextPoint, particle.lerpN );
}
this.geometry.verticesNeedUpdate = true;
};
function createLinePoints(startPoint, endPoint){
var numPoints = 30;
var returnPoints = [];
for(i=0; i <= numPoints; i ++){
var thisPoint = startPoint.clone().lerp(endPoint, i/numPoints);
returnPoints.push(thisPoint);
}
return returnPoints;
}
function constrain(v, min, max){
if( v < min )
v = min;
else
if( v > max )
v = max;
return v;
}
and then in the animation loop:
particles.update();
回答2:
I don't know if anyone else can't see the snippets working, but I took the answer that jigglebilly provided and put it into a full html page and is working. Just so that if you want to see a working version. ` Particle Test
<script src="../js/three.js"></script>
<script type="text/javascript">
var renderer = new THREE.WebGLRenderer( { antialias: true } );
var camera = new THREE.PerspectiveCamera( 45, (window.innerWidth) / (window.innerHeight), 100, 10000);
var container = document.getElementById("containerElement");
var numParticles = 40;
container.appendChild( renderer.domElement );
var scene = new THREE.Scene();
var material = new THREE.LineBasicMaterial({color: 0x0000ff });
//First create the line that we want to animate the particles along
var geometry = new THREE.Geometry();
geometry.vertices.push(new THREE.Vector3(-800, 0, -800));
geometry.vertices.push(new THREE.Vector3(800, 0, 0));
var line = new THREE.Line(geometry, material);
var startPoint = line.geometry.vertices[0];
var endPoint = line.geometry.vertices[1];
scene.add(line);
//next create a set of about 30 animation points along the line
var animationPoints = createLinePoints(startPoint, endPoint);
var particleGeometry = new THREE.Geometry();
//add particles to scene
for ( i = 0; i < numParticles; i ++ ) {
var desiredIndex = i / numParticles * animationPoints.length;
var rIndex = constrain(Math.floor(desiredIndex),0,animationPoints.length-1);
var particle = new THREE.Vector3();
var particle = animationPoints[rIndex].clone();
particle.moveIndex = rIndex;
particle.nextIndex = rIndex+1;
if(particle.nextIndex >= animationPoints.length )
particle.nextIndex = 0;
particle.lerpN = 0;
particle.path = animationPoints;
particleGeometry.vertices.push( particle );
}
//set particle material
var pMaterial = new THREE.ParticleBasicMaterial({
color: 0x00FF00,
size: 50,
blending: THREE.AdditiveBlending,
transparent: true
});
var particles = new THREE.ParticleSystem( particleGeometry, pMaterial );
particles.sortParticles = true;
particles.dynamic = true;
scene.add(particles);
function UpdateParticles(){
// var time = Date.now()
for( var i = 0; i < particles.geometry.vertices.length; i++ ){
var particle = particles.geometry.vertices[i];
var path = particle.path;
particle.lerpN += 0.05;
if(particle.lerpN > 1){
particle.lerpN = 0;
particle.moveIndex = particle.nextIndex;
particle.nextIndex++;
if( particle.nextIndex >= path.length ){
particle.moveIndex = 0;
particle.nextIndex = 1;
}
}
var currentPoint = path[particle.moveIndex];
var nextPoint = path[particle.nextIndex];
particle.copy( currentPoint );
particle.lerp( nextPoint, particle.lerpN );
}
particles.geometry.verticesNeedUpdate = true;
};
animate();
function createLinePoints(startPoint, endPoint){
var numPoints = 30;
var returnPoints = [];
for(i=0; i <= numPoints; i ++){
var thisPoint = startPoint.clone().lerp(endPoint, i/numPoints);
returnPoints.push(thisPoint);
}
return returnPoints;
}
function constrain(v, min, max){
if( v < min )
v = min;
else
if( v > max )
v = max;
return v;
}
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
renderer.render(scene, camera);
UpdateParticles();
}
</script>
`
This uses three.js R67.
来源:https://stackoverflow.com/questions/25898635/three-js-how-to-animate-particles-along-a-line