So i am trying to make some particles follow a path I’ve managed to this but the particles seem to be duplicated twice so there are a few particles in the middle of the screen that do not move that should not be there I’ve also noticed the animation rotation of the “particle box” jumps … here is a code pen
i am trying to create one of these particle paths from this example but with the above path as you can see It’s not going to well
You use getPoint to get a position along the path, this is completely sufficient. You need to have shorter clouds. Then place every cloud on its own position long the curve, so, newPosition and tangent must be recalculated for each cloud. All clouds’ positions are based on t but with different offset (thus the left cloud is at position t, the next cloud is a little bit ahead of time, the next to the next is more ahead of time and so on). This is a simplified illustration of 5 clouds on a path.
The full JS code of the last video, that I posted, is at the bottom. As a general advice, not related to your questions, try to keep the code tidy and well formatted. This is very helpful for debugging and understanding the fabrics of what the code does. There are several code formatting styles, any of them is better than having no style.
As for the code, there is no need to calculate different positions in different variables. This can be done on-the-fly in the cycle where clouds have their rotation set. Like this:
for (var i = 0; i < scene.children.length; i++) {
// get position and tangent of i-th cloud
newPosition = pointsPath.getPoint((fraction+i/50)%1);
tangent = pointsPath.getTangent((fraction+i/50)%1);
var object = scene.children[i];
if (object instanceof THREE.Points) {
var time = Date.now() * 0.0009;
// set position of i-th cloud
object.position.copy(newPosition);
// set rotation of i-th cloud
object.rotation.y = Math.atan2( tangent.x, tangent.z );
object.rotation.z = time * (i < 1 ? i + 2 : -(i + 1));
} // if
} // for
Show the full source code
import * as THREE from "https://jokertattoo.co.uk/game-lesson-1/js/three.module.js";
import TWEEN from "https://jokertattoo.co.uk/game-lesson-1/js/tween.esm.js";
import { RGBELoader } from "https://jokertattoo.co.uk/game-lesson-1/js/RGBELoader.js";
import { OrbitControls } from "https://jokertattoo.co.uk/game-lesson-1/js/OrbitControls.js";
import { GLTFLoader } from "https://jokertattoo.co.uk/game-lesson-1/js/GLTFLoader.js";
import { RoughnessMipmapper } from "https://jokertattoo.co.uk/game-lesson-1/js/RoughnessMipmapper.js";
import { CSS2DRenderer, CSS2DObject } from "https://jokertattoo.co.uk/game-lesson-1/js/CSS2DRenderer.js";
var container, controls;
var camera, scene, renderer, loaderGL, time, mixer, mixer2, mixer3, mixer4, mixer6, mixer7, mixer8, mixer9, clock, labelRenderer;
var raycaster, mouse, tween;
var model, model2, model3, model4, model5, model6, model7, model8, model9;
var cubefix, cube, cube2, cube3, cube4, cube5, character, Characterm, Monster0, score, gltfPlayer, gltfMonster, isZoomed, gltfC1, gltfC2, gltfC3, gltfC4, gltfC5;
var action, action3, action0, action2, action4, action5, action6;
var nearFog, farFog, densityFog, colorFog, colorFog2;
var hotspotLabel1, hotspotLabel2, hotspotLabel3, hotspotLabel4;
var materials = [],
parameters;
var mouseX = 0,
mouseY = 0;
var timerAnimate;
var CH0, CH, CH3, CH4;
var game_loader_count = 0;
var observer, text, checkText, partcount, StartButton, ButtonStart;
var fov, aspect, near, far;
var fraction, pointsPath, char, axis, up, newPosition, tangent, radians, particles, loaderSprite;
var materials = [];
var parameterse =[];
init();
animate();
function init() {
renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(devicePixelRatio);
document.body.appendChild(renderer.domElement);
var pmremGenerator = new THREE.PMREMGenerator(renderer);
pmremGenerator.compileEquirectangularShader();
fov = { value: 45};
aspect = window.innerWidth / window.innerHeight;
near = { value: 1};
far = { value: 10000};
camera = new THREE.PerspectiveCamera(fov.value, aspect, near.value, far.value);
camera.position.set(-8, 10, 25.1);
camera.lookAt(0,0,0);
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000000);
fraction = 0;
up = new THREE.Vector3( 0,0,1 );
axis = new THREE.Vector3( );
pointsPath = new THREE.CurvePath();
const curve = new THREE.CatmullRomCurve3( [
new THREE.Vector3( 0, 0, -0 ),
new THREE.Vector3( -2, 0, 7 ),
new THREE.Vector3( -8, 0, 12 ),
new THREE.Vector3( -14, 0, 8 ),
new THREE.Vector3( 10, 0, 5 ),
new THREE.Vector3( -5, 0, -14 ),
new THREE.Vector3( 5, 0, -15 ),
new THREE.Vector3( 0, 0, -0 ),
const bezierLine = new THREE.CubicBezierCurve3(
//originals
new THREE.Vector3( 13, 0, -1 ),
new THREE.Vector3( 500, 0, 100 ),
new THREE.Vector3( -14, 0, -73 ),
new THREE.Vector3( 0, 0, 0 ),
const bezierLine2 = new THREE.CubicBezierCurve3(
new THREE.Vector3( 0, 0, -1 ),
new THREE.Vector3( -50, 0, 10 ),
new THREE.Vector3( -14, 0, -73 ),
new THREE.Vector3( 0, 0, 0 ),
pointsPath.add(curve);
// pointsPath.add(bezierLine2);
const material = new THREE.MeshNormalMaterial();
const coneGeom = new THREE.ConeGeometry(1, 2, 10);
coneGeom.translate(0, 24.5, 0);
const cone = new THREE.Mesh(coneGeom, material);
const cylinder = new THREE.CylinderGeometry(0.4, 0.6, 3, 10);
cylinder.merge(cone.geometry, cone.matrix);
cylinder.scale(0.5, 0.5, 0.5);
char = new THREE.Mesh(cylinder, material);
max = 2,
high = Math.floor(Math.random() * (max - min) + min);
for (var i = 0; i < partcount; i++) { var x = (Math.random() * 2 - 1) * 1; var y = (Math.random() * 2 - 1) * 1; var z = (Math.random() * 2 - 1) * 2;
vertices.push(x, y, z); }
geometryParticle.setAttribute("position", new THREE.Float32BufferAttribute(vertices, 3));
parameterse = [ [[0.8, 0, 0.5], sprite1, 1], [[0.8, 0, 0.5], sprite1, 2], [[0.8, 0, 0.5], sprite1, 1], [[0.8, 0, 0.5], sprite1, 2], [[0.8, 0, 0.5], sprite1, 3], ];
for (var i = 0; i < parameterse.length; i++) { var color = parameterse[i][2]; var sprite = parameterse[i][1]; var size = parameterse[i][2];
materials[i] = new THREE.PointsMaterial({ size: size, map: sprite, blending: THREE.AdditiveBlending,
depthWrite: false, transparent: true, fog: false, toneMapped: false});
materials[i].toneMapped = false; materials[i].color.setHSL(color[0], color[1], color[2]);
particles = new THREE.Points(geometryParticle, materials[i]);
// particles.rotation.x = Math.random()
scene.add(particles);
color: 0x9132a8
const points = pointsPath.curves.reduce((p, d)=> [...p, ...d.getPoints(60)], []);
const geometry2 = new THREE.BufferGeometry().setFromPoints( points );
var liner = new THREE.Line( geometry2, material2 );
scene.add(liner);
clock = new THREE.Clock();
const axesHelper = new THREE.AxesHelper( 0.5 );
axesHelper.translateX(1);
scene.add( axesHelper );
controls = new OrbitControls(camera, renderer.domElement);
controls.enableKeys = false;
controls.enableZoom = false;
controls.enableDamping = true;
controls.maxPolarAngle = 1.4;
controls.minPolarAngle = 1.2;
controls.dampingFactor = 0.04;
controls.autoRotate = false;
controls.rotateSpeed = 0.015;
controls.minDistance = 2;
controls.enabled = false;
function animate() {
fraction +=0.0004;
// if (fraction > 1) fraction = 0;
for (var i = 0; i < scene.children.length; i++) {
newPosition = pointsPath.getPoint((fraction+i/50)%1);
tangent = pointsPath.getTangent((fraction+i/50)%1);
var object = scene.children[i];
if (object instanceof THREE.Points) {
const pos = object.position.copy(newPosition);
var time = Date.now() * 0.0009;
object.rotation.y = Math.atan2( tangent.x, tangent.z );
object.rotation.z = time * (i < 1 ? i + 2 : -(i + 1));
for (var i = 0; i < materials.length; i++) {
var color = parameterse[i][0];
var h = ((360 * (color[0] + time)) % 360) / 360;
materials[i].color.setHSL(h, color[1], color[2]);