cebulacamp_3D_scene/sketch.js

250 lines
7.2 KiB
JavaScript

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(model, orbitRadius, speed, scale, tiltAngleX, tiltAngleY) {
const tiltAngle = { x: tiltAngleX, y: tiltAngleY }; // Pass both X and Y tilt angles
this.orbitingObjects.push(new OrbitingObject(this, model, 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_stroke);
push()
emissiveMaterial(backgroundColor)
model(onion_fill);
pop()
// 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, model, orbitRadius, speed, scale, tiltAngle) {
this.parent = parent; // The parent object (Onion)
this.model = model
this.orbitRadius = orbitRadius;
this.speed = speed; // Orbiting speed (angular speed)
this.scale = scale;
this.rotationAngle_x = random(360);
this.rotationAngle_y = random(360);
this.rotationAngle_z = random(360);
this.rotationSpeed_x = random(0.5, 2);
this.rotationSpeed_y = random(0.5, 2);
this.rotationSpeed_z = random(0.5, 2);
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;
// Rotate in place
this.rotationAngle_x += this.rotationSpeed_x;
this.rotationAngle_y += this.rotationSpeed_y;
this.rotationAngle_z += this.rotationSpeed_z;
// 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
// Apply in-place rotation
rotateX(this.rotationAngle_x)
rotateY(this.rotationAngle_y);
rotateZ(this.rotationAngle_z)
scale(this.scale);
model(this.model);
pop();
}
}
class Text3D {
constructor(fromColor, toColor, textString, position_x, position_y) {
this.position_x = position_x
this.position_y = position_y
this.fromColor = fromColor;
this.toColor = toColor;
this.textString = textString;
this.depth = 30; // Number of layers for 3D effect
this.depthSpacing = 0.60; // Depth spacing between layers
this.rotationY = 0;
}
display() {
// Apply rotation toward the camera
rotateY(this.rotationY);
push();
for (let i = 0; i < this.depth; i++) {
let r = map(i, 0, this.depth - 1, this.fromColor[0], this.toColor[0]);
let g = map(i, 0, this.depth - 1, this.fromColor[1], this.toColor[1]);
let b = map(i, 0, this.depth - 1, this.fromColor[2], this.toColor[2]);
fill(r, g, b);
translate(0, 0, this.depthSpacing);
text(this.textString, this.position_x, this.position_y);
}
pop();
}
update() {
// Get the camera position
let camX = camera.eyeX;
let camZ = camera.eyeZ;
// Get the camera position
let targetRotY = atan2(camX, camZ); // Calculate target Y rotation
// Ensure shortest rotation path by normalizing angles
let delta = (targetRotY - this.rotationY + 540) % 360 - 180; // Keeps within -180 to 180 range
this.rotationY += delta * 0.05; // Interpolate rotation smoothly
}
}
function preload() {
onion_stroke = loadModel('./assets/onion_stroke.obj');
onion_fill = loadModel('./assets/onion_fill.obj');
font = loadFont('./assets/jgs5.ttf');
}
function setup() {
createCanvas(windowWidth, windowHeight, WEBGL);
angleMode(DEGREES);
noStroke();
textFont(font, 60);
textAlign(CENTER, CENTER);
randomSeed()
// Background color
backgroundColor = [0, 0, 0];
// Initialize camera to get its position
camera = createCamera();
// Initialize 3D text
startGradient = [210, 0, 255]; // Start color
endGradient = [0, 255, 180]; // End color
text3D = new Text3D(startGradient, endGradient, "PLACEHOLDER", 0, 350);
// 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(
onion_fill,
i,
random(0.1, 0.8),
globalScaleVar * 0.0001 * random(1, 6),
random(0, 30),
random(0, 30)
);
}
}
function draw() {
background(backgroundColor);
orbitControl();
ambientLight(100);
shininess(0);
specularMaterial(255, 255, 255);
directionalLight(
startGradient[0], startGradient[1], startGradient[2], // color
-180, 180, 0 // direction
);
directionalLight(
endGradient[0], endGradient[1], endGradient[2], // color
180, -180, 0 // direction
);
// Update objects
onionObj.update();
text3D.update();
// Display the onion, orbiting objects and the 3D text
onionObj.display();
text3D.display();
}
function windowResized() {
resizeCanvas(windowWidth, windowHeight);
}