colorMode(HSB, 360, 100, 100, 1.0);
topBeam = new Beam(0.49, 500, 50,
topBeam.offsetX = width / 2;
createBeams(topBeam, 0.8, 500, 100, 30, 5);
function createBeams(parentBeam, p, l, yo, w, n) {
const lb = new Beam(p, p * l, p * yo, p * w);
lb.color = color(280, 100, 70, 0.2);
const rb = new Beam(p, p * l, p * yo, p * w);
rb.color = color(280 * p, 100, 70, 0.2);
parentBeam.attach(lb, 0);
parentBeam.attach(rb, 1);
createBeams(lb, p, l, yo, w, n - 1);
createBeams(rb, p, l, yo, w, n - 1);
constructor(pivot, length, offsetY, mass, weights, initialAngle) {
weights = weights || [0, 0];
this.stopAtPointsLimit = true;
this.attachments = [null, null];
length * (1 - this.pivot)
this.offsetX = -this.length[0];
mass * this.pivot + weights[0],
mass * (1 - this.pivot) + weights[1]
this.calculateMomentOfInertia();
this.angle = initialAngle || 0;
this.angularVelocity = 0;
this.angularAccelaration = 0;
this.color = color(130,100,70,0.5);
calculateMomentOfInertia() {
this.I = rodMomentOfInertia(this.mass[0], this.length[0]) +
rodMomentOfInertia(this.mass[1], this.length[1]);
if (this.attachments[0] !== null) {
this.I += pointMassMomentOfInertia(this.attachments[0].totalMass(), this.length[0]);
if (this.attachments[1] !== null) {
this.I += pointMassMomentOfInertia(this.attachments[1].totalMass(), this.length[1]);
return this.mass[0] + this.mass[1];
const lF = cos(this.angle) * force(this.mass[0], g);
const rF = cos(this.angle) * force(this.mass[1], g);
const totalTorque = torque(rF, this.length[1]) - torque(lF, this.length[0]);
this.angularAcceleration = angularAcceleration(totalTorque, this.I);
this.angularVelocity = this.angularVelocity + (this.angularAcceleration * this.dt);
this.angle = this.angle + (this.angularVelocity * this.dt);
if (this.attachments[0] !== null) {
this.attachments[0].offsetX = this.startPt().x;
this.attachments[0].update();
if (this.attachments[1] !== null) {
this.attachments[1].offsetX = this.endPt().x;
this.attachments[1].update();
this.startPoints.push(this.startPt());
if (this.startPoints.length > this.pointsLimit) {
if (this.stopAtPointsLimit) {
this.startPoints.splice(0, 1);
this.endPoints.push(this.endPt());
if (this.endPoints.length > this.pointsLimit) {
if (this.stopAtPointsLimit) {
this.endPoints.splice(0, 1);
this.parent.attach(this, this.side);
this.attachments[side] = obj;
this.mass[side] = this.mass[side] + obj.totalMass();
y += this.parent.startPt().y;
y += this.parent.endPt().y;
return createVector(this.offsetX, y);
const pivot = this.pivotXY();
pivot.x + -this.length[0] * cos(this.angle),
pivot.y + -this.length[0] * sin(this.angle)
const pivot = this.pivotXY();
pivot.x + this.length[1] * cos(this.angle),
pivot.y + this.length[1] * sin(this.angle)
if (this.parent !== null) {
const pivot = this.pivotXY();
for (let p = 0; p < this.startPoints.length; p++) {
const pt = this.startPoints[p];
for (let p = 0; p < this.endPoints.length; p++) {
const pt = this.endPoints[p];
if (this.attachments[0] !== null) {
this.attachments[0].drawPoints();
if (this.attachments[1] !== null) {
this.attachments[1].drawPoints();
const pivot = this.pivotXY();
translate(pivot.x, pivot.y);
line(-this.length[0], 0, this.length[1], 0);
if (this.attachments[0] !== null) {
this.attachments[0].draw();
line(this.startPt().x, this.startPt().y,
this.attachments[0].pivotXY().x,
this.attachments[0].pivotXY().y);
if (this.attachments[1] !== null) {
this.attachments[1].draw();
line(this.endPt().x, this.endPt().y,
this.attachments[1].pivotXY().x,
this.attachments[1].pivotXY().y);
circle(this.startPt().x, this.startPt().y, 8);
circle(this.endPt().x, this.endPt().y, 8);