Three.JS - Particles orbiting a point in random directions forming a sphere

半腔热情 提交于 2019-12-14 03:42:36

问题


I have a particle system where all the particles are positioned at the same coordinates and one after another, in random directions, they (should) start orbiting the center of the scene forming a sphere.

What I managed to achieve until now is a group of Vector3 objects (the particles) that one after another start orbiting the center along the Z axis simply calculating their sine and cosine based on the current angle.

I'm not that good at math and I don't even know what to look for precisely.

Here's what I wrote:

var scene = new THREE.Scene();

let container = document.getElementById('container'), 
    loader = new THREE.TextureLoader(), 
    renderer, 
    camera, 
    maxParticles = 5000, 
    particlesDelay = 50, 
    radius = 50, 
    sphereGeometry, 
    sphere;

loader.crossOrigin = true;

function init() {

    let vw = window.innerWidth, 
        vh = window.innerHeight;

    renderer = new THREE.WebGLRenderer();
    renderer.setSize(vw, vh);
    renderer.setPixelRatio(window.devicePixelRatio);

    camera = new THREE.PerspectiveCamera(45, vw / vh, 1, 1000);
    camera.position.z = 200;
    camera.position.x = 30;
    camera.position.y = 30;
    camera.lookAt(scene.position);
    scene.add(camera);

    let controls = new THREE.OrbitControls(camera, renderer.domElement);

    let axisHelper = new THREE.AxisHelper(50);
    scene.add(axisHelper);

    container.appendChild(renderer.domElement);

    window.addEventListener('resize', onResize, false);

}

function onResize() {

    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();

    renderer.setSize(window.innerWidth, window.innerHeight);    

}

function draw() {

    sphereGeometry = new THREE.Geometry();
    sphereGeometry.dynamic = true;

    let particleTexture = loader.load('https://threejs.org/examples/textures/particle2.png'), 
        material = new THREE.PointsMaterial({
            color: 0xffffff, 
            size: 3, 
            transparent: true, 
            blending: THREE.AdditiveBlending, 
            map: particleTexture, 
            depthWrite: false
        });

        for ( let i = 0; i < maxParticles; i++ ) {

            let vertex = new THREE.Vector3(radius, 0, 0);
            vertex.delay = Date.now() + (particlesDelay * i);
            vertex.angle = 0;
            sphereGeometry.vertices.push(vertex);

        }

        sphere = new THREE.Points(sphereGeometry, material);
        scene.add(sphere);

}

function update() {

    for ( let i = 0; i < maxParticles; i++ ) {

        let particle = sphereGeometry.vertices[i];

        if ( Date.now() > particle.delay ) {

            let angle = particle.angle += 0.01;

            particle.x = radius * Math.cos(angle);

            if ( i % 2 === 0 ) {
                particle.y = radius * Math.sin(angle);
            } else {
                particle.y = -radius * Math.sin(angle);
            }

        }


    }

    sphere.geometry.verticesNeedUpdate = true;

}

function render() {

    update();
    renderer.render(scene, camera);
    requestAnimationFrame(render);

}

init();
draw();
render();

And here's the JSFiddle if you want to see it live: https://jsfiddle.net/kekkorider/qs6s0wv2/

EDIT: Working example

Can someone please give me a hand?

Thanks in advance!


回答1:


You want each particle to rotate around a specific random axis. You can either let them follow a parametric equation of a circle in 3D space, or you can make use of THREE.js rotation matrices.

Right now all your particles are rotating round the vector (0, 0, 1). Since your particles start off on the x-axis, you want them all to rotate around a random vector in the y-z plane (0, y, z). This can be defined during the creation of the vertices:

vertex.rotationAxis = new THREE.Vector3(0, Math.random() * 2 - 1, Math.random() * 2 - 1);
vertex.rotationAxis.normalize();

now you can just call the THREE.Vector3.applyAxisAngle(axis, angle) method on each of your particles with the random rotation axis you created each update:

particle.applyAxisAngle(particle.rotationAxis, 0.01); 

To sum up, this is how it should look like:

draw():

...
for ( let i = 0; i < maxParticles; i++ ) {

    let vertex = new THREE.Vector3(radius, 0, 0);
    vertex.delay = Date.now() + (particlesDelay * i);
    vertex.rotationAxis = new THREE.Vector3(0, Math.random() * 2 - 1, Math.random() * 2 - 1);
    vertex.rotationAxis.normalize();
    sphereGeometry.vertices.push(vertex);
}
...

update():

...
for ( let i = 0; i < maxParticles; i++ ) {

    let particle = sphereGeometry.vertices[i];

    if ( Date.now() > particle.delay ) {
        particle.applyAxisAngle(particle.rotationAxis, 0.01); 
    }
}
...


来源:https://stackoverflow.com/questions/43469555/three-js-particles-orbiting-a-point-in-random-directions-forming-a-sphere

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!