105 lines
3.4 KiB
JavaScript
105 lines
3.4 KiB
JavaScript
// PendulumComponents.js
|
|
// John Breaux 2022-06-30
|
|
// Classes used by Pendulum.js
|
|
|
|
"use strict";
|
|
|
|
//
|
|
// Classes
|
|
//
|
|
|
|
// Polygon class: Construct and display a regular polygon in 2D
|
|
class Polygon extends ShapedObject {
|
|
// constructor: Make a new regular polygon
|
|
constructor({ sides = 6, radius = 1, center = { x: 0, y: 0 }, color = { r: 0, g: 0, b: 1, a: 1 } } = {}) {
|
|
super({ color: color });
|
|
// Create vertices
|
|
this.vertices = [];
|
|
for (var i = 0; i <= sides; i++) {
|
|
// Create vertices by adding center-point in Homogeneous coordinates to an offset vector generated from polar coordinates.
|
|
this.vertices[i] = new Homogeneous2D().from_polar(radius, 2 * Math.PI * i / sides, 0).add_m(new Homogeneous2D(center.x, center.y, 1));
|
|
}
|
|
}
|
|
// Wrap the init function to set the draw_primitive type to TRIANGLE_FAN
|
|
init(gl) {
|
|
this.draw_primitive = gl.TRIANGLE_FAN;
|
|
super.init(gl);
|
|
}
|
|
}
|
|
|
|
class Rod extends ShapedObject {
|
|
constructor({ anchor = { x: 0, y: 0 }, bob = { x: 0, y: 0 }, color = { r: 1.0, g: 0.0, b: 0.0, a: 1.0 } } = {}) {
|
|
super({ color: color });
|
|
// Set the object's vertices
|
|
this.vertices = [new Homogeneous2D(anchor.x, anchor.y, 1), new Homogeneous2D(bob.x, bob.y, 1)]
|
|
}
|
|
// Wrap the init function to set the draw_primitive type to LINES
|
|
init(gl) {
|
|
this.draw_primitive = gl.LINES;
|
|
super.init(gl);
|
|
}
|
|
}
|
|
|
|
class Anchor extends ShapedObject {
|
|
constructor({ center = { x: 0, y: 0 }, color = { r: 0.0, g: 1.0, b: 0.0, a: 1.0 } } = {}) {
|
|
super({ color: color });
|
|
// Set the object's vertices
|
|
this.vertices = [new Homogeneous2D(center.x, center.y, 1)];
|
|
}
|
|
// Wrap the init function to set the draw_primitive type to POINTS
|
|
init(gl) {
|
|
this.draw_primitive = gl.POINTS;
|
|
super.init(gl);
|
|
}
|
|
}
|
|
|
|
// This doesn't need to extend ShapedObject, but I love the symmetry
|
|
class Pendulum extends ShapedObject {
|
|
constructor({ angle = 60, length = PEN_LENGTH, radius = BOB_RADIUS } = {}) {
|
|
super();
|
|
this.angle_initial = angle;
|
|
this.angle = angle;
|
|
this.period = Math.sqrt(9.81 / length);
|
|
// define where anchor and bob are
|
|
var anchor = { x: 0, y: 0 }, bob = { x: 0, y: -length };
|
|
// create the components
|
|
this.components = [
|
|
new Rod({ anchor: anchor, bob: bob }),
|
|
new Anchor({ center: anchor }),
|
|
new Polygon({ sides: 4, radius: radius, center: bob })
|
|
];
|
|
}
|
|
|
|
// Initialize the pendulum
|
|
init(gl) {
|
|
// initialize the components
|
|
for (var component of this.components) {
|
|
component?.init(gl);
|
|
}
|
|
// start the clock
|
|
this.t_prev = Date.now();
|
|
}
|
|
|
|
// Draw the pendulum
|
|
draw(gl, modelMatrix, u_ModelMatrix) {
|
|
// Rotate the pendulum
|
|
modelMatrix.setIdentity();
|
|
modelMatrix.rotate(this.angle, 0, 0, 1);
|
|
// Draw each component
|
|
for (var component of this.components) {
|
|
component?.draw(gl, modelMatrix, u_ModelMatrix);
|
|
}
|
|
}
|
|
|
|
// Tick the pendulum (update and perform movement)
|
|
tick() {
|
|
if (REAL_PENDULUM_MODE) {
|
|
var now = Date.now(), elapsed = (now - this.t_prev) / 1000 * this.period;
|
|
this.angle = this.angle_initial * Math.cos(elapsed);
|
|
} else {
|
|
var now = Date.now(), elapsed = now - this.t_prev;
|
|
this.t_prev = now;
|
|
this.angle = (this.angle + (A_VELOCITY * elapsed / 1000)) % 360;
|
|
}
|
|
}
|
|
} |