let globalScaleVar = 200; class RotatingOnion { constructor(angles, scale) { this.angles = { ...angles }; // Destructure this.scale = scale; this.orbitingObjects = []; // Array to hold orbiting objects // Onion oscillation this.oscillationOffset = random(1000); // Tracks the time or phase for oscillation this.xOscillationAmplitude = 10; // Amplitude for angle.x oscillation this.zOscillationAmplitude = 10; // Amplitude for angle.z oscillation this.xBase = angles.x; // Base value for angle.y oscillation this.zBase = angles.z; // Base value for angle.z oscillation } // Add an orbiting object to the onion addOrbitingObject(orbitRadius, speed, scale, tiltAngleX, tiltAngleY) { const tiltAngle = { x: tiltAngleX, y: tiltAngleY }; // Pass both X and Y tilt angles this.orbitingObjects.push(new OrbitingObject(this, orbitRadius, speed, scale, tiltAngle)); } update() { // Increment the angles as needed per frame this.angles.y += 0.1; this.oscillationOffset += 1; // Increment the oscillation phase this.angles.x = this.xBase + this.xOscillationAmplitude * sin(this.oscillationOffset*0.7); this.angles.z = this.zBase + this.zOscillationAmplitude * cos(this.oscillationOffset*0.4); // Update each orbiting object for (let obj of this.orbitingObjects) { obj.update(); } } display() { push(); rotateX(this.angles.x); rotateY(this.angles.y); rotateZ(this.angles.z); scale(this.scale); model(onion); // Display all orbiting objects for (let obj of this.orbitingObjects) { obj.display(); this.displayTorus(obj.orbitRadius, obj.tiltAngle); } pop(); } // Function to display a torus representing the orbit path displayTorus(orbitRadius, tiltAngle) { push(); stroke(150, 150, 150); // Set the color of the orbit path strokeWeight(0.5); noFill(); // Apply the tilt before rendering the torus rotateY(-tiltAngle.y); // Apply Y-axis tilt for the torus rotateX(90-tiltAngle.x); // Apply the tilt angle to rotate the orbit plane torus(orbitRadius, 0.001); // Radius and tube radius of the torus pop(); } } class OrbitingObject { constructor(parent, orbitRadius, speed, scale, tiltAngle) { this.parent = parent; // The parent object (Onion) this.orbitRadius = orbitRadius; this.speed = speed; // Orbiting speed (angular speed) this.scale = scale; this.angle = random(360); // Start at a random position in the orbit this.tiltAngle = tiltAngle; } update() { // Update the angle to simulate rotation around the parent this.angle += this.speed; // Calculate the position of the orbiting object in the un-tilted plane const x = this.orbitRadius * cos(this.angle); const z = this.orbitRadius * sin(this.angle); const y = 0; // Or any base y value if it's not 0 // Apply the tilt transformation around both the X and Y axes const tiltXCos = cos(this.tiltAngle.x); const tiltXSin = sin(this.tiltAngle.x); const tiltYCos = cos(this.tiltAngle.y); const tiltYSin = sin(this.tiltAngle.y); // Tilt transformation around the X-axis (first) let newX = x; let newY = y * tiltXCos + z * tiltXSin; let newZ = z * tiltXCos - y * tiltXSin; // Tilt transformation around the Y-axis (second) this.x = newX * tiltYCos - newZ * tiltYSin; this.y = newY; this.z = newZ * tiltYCos + newX * tiltYSin; } display() { push(); translate(this.x, this.y, this.z); // Move to the correct orbit position sphere(this.scale); // Display the object (could be another model or shape) pop(); } } function preload() { onion = loadModel('./assets/onion.obj'); font = loadFont('./assets/jgs5.ttf'); } function setup() { createCanvas(windowWidth, windowHeight, WEBGL); angleMode(DEGREES); ambientMaterial(0, 0, 0, 0); stroke(255); strokeWeight(0.5); textFont(font, 60); textAlign(CENTER, CENTER); randomSeed() // Initialize the onion object with radius, angles, and scale onionObj = new RotatingOnion({ x: 0, y: random(360), z: 180 }, globalScaleVar); // Add orbiting objects to the onion for (let i = 1.8; i <= 4.8; i += 0.6) { onionObj.addOrbitingObject( i, random(0.1, 0.8), globalScaleVar * 0.0001 * random(1, 6), random(0, 30), random(0, 30) ); } } function draw() { background(0); noFill(); orbitControl(); // Update the onion object onionObj.update(); // Display the onion and its orbiting objects onionObj.display(); fill(255, 255, 255); text('PLACEHOLDER', 0, 350); } function windowResized() { resizeCanvas(windowWidth, windowHeight); }