Pendulum: Shit's fucked
This commit is contained in:
parent
3b4b277871
commit
465954d3dd
@ -17,6 +17,7 @@
|
||||
<script src="../lib/webgl-debug.js"></script>
|
||||
<script src="../lib/cuon-utils.js"></script>
|
||||
<script src="../lib/cuon-matrix.js"></script>
|
||||
<script src="PendulumComponents.js"></script>
|
||||
<script src="Pendulum.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,4 +1,9 @@
|
||||
// RotatingTranslatedTriangle.js (c) 2012 matsuda
|
||||
|
||||
// Pendulum.js
|
||||
// John Breaux 2022-06-30
|
||||
// Simulates a pendulum in a frictionless vacuum with no gravity
|
||||
|
||||
"use strict"
|
||||
|
||||
const vertex_shader = `
|
||||
@ -8,6 +13,7 @@ const vertex_shader = `
|
||||
void main()
|
||||
{
|
||||
gl_Position = u_ModelMatrix * a_Position;
|
||||
gl_PointSize = 5.0;
|
||||
} `;
|
||||
|
||||
|
||||
@ -26,92 +32,16 @@ var PEN_LENGTH = 0.8;
|
||||
// Rotation angle (degrees/second)
|
||||
var A_VELOCITY = 45.0;
|
||||
|
||||
// Classes
|
||||
// homo2: Stores a 2d vector or point in homog. coords
|
||||
class homog2 {
|
||||
constructor(x = 0, y = 0, w = 0) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.w = w;
|
||||
}
|
||||
// Add with modify
|
||||
add_m(rhs) {
|
||||
if (rhs) {
|
||||
this.x += rhs.x;
|
||||
this.y += rhs.y;
|
||||
this.w += rhs.w;
|
||||
return this;
|
||||
}
|
||||
else return null;
|
||||
}
|
||||
// scalar multiply with modify
|
||||
smul_m(scalar) {
|
||||
if (typeof(rhs) === "number") {
|
||||
this.x *= rhs;
|
||||
this.y *= rhs;
|
||||
this.w *= rhs;
|
||||
return this;
|
||||
}
|
||||
else return null;
|
||||
}
|
||||
// copy
|
||||
copy() {
|
||||
return new homog2(this.x, this.y, this.w);
|
||||
}
|
||||
// create vector/point from 2d polar coordinates
|
||||
from_polar(r = 0, theta = 0, w = 0) {
|
||||
this.x = r * Math.cos(theta);
|
||||
this.y = r * Math.sin(theta);
|
||||
this.w = w;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
// hexagon2 class: Holds 6 vertices and a center point. Only constructs perfect hexagons.
|
||||
class hexagon2 {
|
||||
// constructor: Make a new regular polygon
|
||||
constructor({sides = 6, radius = 0, rotation = 0, center = { x: 0, y: 0 } } = {}) {
|
||||
// lenth is center + sides
|
||||
this.length = 1;
|
||||
this.center = new homog2(center.x, center.y, 1);
|
||||
this.v = [];
|
||||
for (var i = 0; i <= sides; i++) {
|
||||
this.v[i] = new homog2().from_polar(radius, rotation + (i*2*Math.PI / sides)).add_m(this.center);
|
||||
this.length++;
|
||||
}
|
||||
}
|
||||
// Convert to Float32Array [center, v0, v1, ...]
|
||||
to_array() {
|
||||
// allocate space for center.xy + vertices.xy
|
||||
var ret = new Float32Array((1 + this.v.length) * 2);
|
||||
// save the center
|
||||
ret[0] = this.center.x;
|
||||
ret[1] = this.center.y;
|
||||
// save the vertices
|
||||
for (var i = 0; i < this.v.length; i++) {
|
||||
var j = 2 * (i + 1);
|
||||
ret[j] = this.v[i].x;
|
||||
ret[j+1] = this.v[i].y;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
draw(gl, n, currentAngle, modelMatrix, u_ModelMatrix) {
|
||||
// Set the rotation matrix
|
||||
modelMatrix.setRotate(currentAngle, 0, 0, 1);
|
||||
// Pass the rotation matrix to the vertex shader
|
||||
gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrix.elements);
|
||||
// Clear <canvas>
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
// Draw the pendulum
|
||||
gl.drawArrays(gl.TRIANGLE_FAN, 0, n);
|
||||
}
|
||||
}
|
||||
|
||||
class pendulum2 {
|
||||
constructor({angle = 0, length = PEN_LENGTH, radius = BOB_RADIUS} = {}) {
|
||||
this.bob = new hexagon2({radius: radius, center: {x: 0, y: -length}});
|
||||
console.log(this);
|
||||
// Common functions:
|
||||
// acquire_buffer: Get a vertex buffer object from gl
|
||||
function acquire_buffer(gl) {
|
||||
// Create a buffer object
|
||||
var vertexBuffer = gl.createBuffer();
|
||||
if (!vertexBuffer) {
|
||||
console.log('Failed to create the buffer object');
|
||||
return -1;
|
||||
}
|
||||
return vertexBuffer;
|
||||
}
|
||||
|
||||
function main() {
|
||||
@ -132,14 +62,8 @@ function main() {
|
||||
}
|
||||
|
||||
// create a pendulum object
|
||||
var pendulum = new pendulum2({angle: 0, length: 0});
|
||||
|
||||
// Write the positions of vertices to a vertex shader
|
||||
var n = initVertexBuffers(gl, pendulum);
|
||||
if (n < 0) {
|
||||
console.log('Failed to set the positions of the vertices');
|
||||
return;
|
||||
}
|
||||
var pendulum = new Pendulum({ angle: 0, length: PEN_LENGTH, radius: BOB_RADIUS });
|
||||
init(gl, pendulum);
|
||||
|
||||
// Specify the color for clearing <canvas>
|
||||
gl.clearColor(0, 0, 0, 1);
|
||||
@ -151,81 +75,32 @@ function main() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Current rotation angle
|
||||
var currentAngle = 0.0;
|
||||
|
||||
// Model matrix
|
||||
var modelMatrix = new Matrix4();
|
||||
// Set it to the I matrix
|
||||
modelMatrix.setIdentity();
|
||||
|
||||
// Start drawing
|
||||
var tick = function () {
|
||||
currentAngle = animate(currentAngle); // Update the rotation angle
|
||||
pendulum.bob.draw(gl, n, currentAngle, modelMatrix, u_ModelMatrix); // Draw the triangle
|
||||
requestAnimationFrame(tick, canvas); // Request that the browser ?calls tick
|
||||
// Tick the pendulum
|
||||
pendulum.tick();
|
||||
// Draw the pendulum
|
||||
draw(gl, pendulum, modelMatrix, u_ModelMatrix);
|
||||
// Request that the browser ?calls tick
|
||||
requestAnimationFrame(tick, canvas);
|
||||
};
|
||||
tick();
|
||||
}
|
||||
|
||||
function initVertexBuffers(gl, pendulum) {
|
||||
// var vertices = new Float32Array([
|
||||
// 0, 0.5, -0.5, -0.5, 0.5, -0.5
|
||||
// ]);
|
||||
// var n = 3; // The number of vertices
|
||||
var vertices = pendulum.bob.to_array();
|
||||
var n = pendulum.bob.length;
|
||||
|
||||
// Create a buffer object
|
||||
var vertexBuffer = gl.createBuffer();
|
||||
if (!vertexBuffer) {
|
||||
console.log('Failed to create the buffer object');
|
||||
return -1;
|
||||
function init(gl, pendulum) {
|
||||
pendulum.init(gl);
|
||||
}
|
||||
|
||||
// Bind the buffer object to target
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
|
||||
|
||||
// Write date into the buffer object
|
||||
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
|
||||
|
||||
// Assign the buffer object to a_Position variable
|
||||
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
|
||||
if (a_Position < 0) {
|
||||
console.log('Failed to get the storage location of a_Position');
|
||||
return -1;
|
||||
}
|
||||
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
|
||||
|
||||
// Enable the assignment to a_Position variable
|
||||
gl.enableVertexAttribArray(a_Position);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
function draw(gl, n, currentAngle, modelMatrix, u_ModelMatrix) {
|
||||
// Set the rotation matrix
|
||||
modelMatrix.setRotate(currentAngle, 0, 0, 1);
|
||||
modelMatrix.translate(0.35, 0, 0);
|
||||
|
||||
// Pass the rotation matrix to the vertex shader
|
||||
gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrix.elements);
|
||||
|
||||
function draw(gl, pendulum, modelMatrix, u_ModelMatrix) {
|
||||
// Clear <canvas>
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
|
||||
// Draw the rectangle
|
||||
gl.drawArrays(gl.TRIANGLES, 0, n);
|
||||
}
|
||||
|
||||
// Last time that this function was called
|
||||
var g_last = Date.now();
|
||||
function animate(angle) {
|
||||
// Calculate the elapsed time
|
||||
var now = Date.now();
|
||||
var elapsed = now - g_last;
|
||||
g_last = now;
|
||||
// Update the current rotation angle (adjusted by the elapsed time)
|
||||
var newAngle = angle + (A_VELOCITY * elapsed) / 1000.0;
|
||||
return newAngle %= 360;
|
||||
// Draw the pendulum
|
||||
pendulum.draw(gl, modelMatrix, u_ModelMatrix);
|
||||
}
|
||||
|
||||
function up() {
|
||||
|
210
Pendulum/PendulumComponents.js
Normal file
210
Pendulum/PendulumComponents.js
Normal file
@ -0,0 +1,210 @@
|
||||
// PendulumComponents.js
|
||||
// John Breaux 2022-06-30
|
||||
// Classes and data structures for Pendulum.js
|
||||
|
||||
"use strict"
|
||||
|
||||
// Classes
|
||||
// homo2: Stores a 2d vector or point in homog. coords
|
||||
class homog2 {
|
||||
constructor(x = 0, y = 0, w = 0) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.w = w;
|
||||
}
|
||||
// Add with modify
|
||||
add_m(rhs) {
|
||||
if (rhs) {
|
||||
this.x += rhs.x;
|
||||
this.y += rhs.y;
|
||||
this.w += rhs.w;
|
||||
return this;
|
||||
}
|
||||
else return null;
|
||||
}
|
||||
// scalar multiply with modify
|
||||
smul_m(scalar) {
|
||||
if (typeof (rhs) === "number") {
|
||||
this.x *= rhs;
|
||||
this.y *= rhs;
|
||||
this.w *= rhs;
|
||||
return this;
|
||||
}
|
||||
else return null;
|
||||
}
|
||||
// copy
|
||||
copy() {
|
||||
return new homog2(this.x, this.y, this.w);
|
||||
}
|
||||
// create vector/point from 2d polar coordinates
|
||||
from_polar(r = 0, theta = 0, w = 0) {
|
||||
this.x = r * Math.cos(theta);
|
||||
this.y = r * Math.sin(theta);
|
||||
this.w = w;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class Anchor {
|
||||
constructor({ center = { x: 0, y: 0 } } = {}) {
|
||||
this.position = new homog2(center.x, center.y, 1);
|
||||
}
|
||||
// Convert to Float32Array [center, v0, v1, ...]
|
||||
vertex_array() {
|
||||
// allocate space for center.xy + vertices.xy
|
||||
var ret = new Float32Array(2);
|
||||
// save the vertices
|
||||
ret[0] = this.position.x, ret[1] = this.position.y;
|
||||
console.log(ret);
|
||||
return ret;
|
||||
}
|
||||
// Generate the index_array for the shape
|
||||
index_array() {
|
||||
var ret = new Uint8Array(1);
|
||||
ret[0] = 0;
|
||||
console.log(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
init(gl) {
|
||||
// Make the buffers
|
||||
this.vertexBuffer = acquire_buffer(gl);
|
||||
this.indexBuffer = acquire_buffer(gl);
|
||||
|
||||
// Bind the buffers
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
|
||||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
|
||||
|
||||
// Acquire a reference to a_Position
|
||||
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
|
||||
if (a_Position < 0) {
|
||||
console.log('Failed to get the storage location of a_Position');
|
||||
return -1;
|
||||
}
|
||||
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
|
||||
|
||||
// Enable the assignment to a_Position variable
|
||||
gl.enableVertexAttribArray(a_Position);
|
||||
|
||||
// Write date into the buffers
|
||||
gl.bufferData(gl.ARRAY_BUFFER, this.vertex_array(), gl.STATIC_DRAW);
|
||||
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.index_array(), gl.STATIC_DRAW);
|
||||
}
|
||||
|
||||
draw(gl, modelMatrix, u_ModelMatrix) {
|
||||
// Bind the buffers
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
|
||||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
|
||||
// Pass the rotation matrix to the vertex shader
|
||||
gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrix.elements);
|
||||
// Draw the Anchor
|
||||
gl.drawElements(gl.POINTS, 1, gl.UNSIGNED_BYTE, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// hexagon2 class: Holds vertices and a center point. Only constructs regular polygons
|
||||
class Polygon {
|
||||
// constructor: Make a new regular polygon
|
||||
constructor({ sides = 6, radius = 1, rotation = 0, center = { x: 0, y: 0 }, color = { r: 0, g: 0, b: 1 } } = {}) {
|
||||
this.length = 0;
|
||||
// vertices
|
||||
this.vertices = [];
|
||||
this.center = new homog2(center.x, center.y, 1);
|
||||
for (var i = 0; i <= sides; i++) {
|
||||
this.vertices[i] = new homog2().from_polar(radius, rotation + (i * 2 * Math.PI / sides)).add_m(this.center);
|
||||
this.length++;
|
||||
}
|
||||
}
|
||||
// Convert to Float32Array [center, v0, v1, ...]
|
||||
vertex_array() {
|
||||
// allocate space for center.xy + vertices.xy
|
||||
var ret = new Float32Array((this.vertices.length) * 2);
|
||||
// save the vertices
|
||||
for (var i = 0; i < this.vertices.length; i++) {
|
||||
var j = 2 * i;
|
||||
ret[j] = this.vertices[i].x;
|
||||
ret[j + 1] = this.vertices[i].y;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
// Generate the index_array for the shape
|
||||
index_array() {
|
||||
var ret = new Uint8Array(this.vertices.length + 1);
|
||||
for (var i = 0; i < this.vertices.length; i++) {
|
||||
ret[i] = i
|
||||
}
|
||||
ret[this.vertices.length] = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
init(gl) {
|
||||
// Make the buffers
|
||||
this.vertexBuffer = acquire_buffer(gl);
|
||||
this.indexBuffer = acquire_buffer(gl);
|
||||
|
||||
// Bind the buffers
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
|
||||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
|
||||
|
||||
// Acquire a reference to a_Position
|
||||
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
|
||||
if (a_Position < 0) {
|
||||
console.log('Failed to get the storage location of a_Position');
|
||||
return -1;
|
||||
}
|
||||
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
|
||||
|
||||
// Enable the assignment to a_Position variable
|
||||
gl.enableVertexAttribArray(a_Position);
|
||||
|
||||
// Write date into the buffers
|
||||
gl.bufferData(gl.ARRAY_BUFFER, this.vertex_array(), gl.STATIC_DRAW);
|
||||
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.index_array(), gl.STATIC_DRAW);
|
||||
}
|
||||
|
||||
draw(gl, modelMatrix, u_ModelMatrix) {
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
|
||||
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
|
||||
// Pass the rotation matrix to the vertex shader
|
||||
gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrix.elements);
|
||||
// Draw the shape
|
||||
gl.drawElements(gl.TRIANGLE_FAN, this.length, gl.UNSIGNED_BYTE, 0);
|
||||
}
|
||||
}
|
||||
|
||||
class Pendulum {
|
||||
constructor({ angle = 0, length = PEN_LENGTH, radius = BOB_RADIUS, anchor = { x: 0, y: 0 } } = {}) {
|
||||
this.angle = angle;
|
||||
this.components = [
|
||||
new Anchor({ center: anchor }),
|
||||
new Polygon({ radius: radius, center: { x: 0, y: -length } })
|
||||
];
|
||||
}
|
||||
|
||||
// Tick the pendulum (update and perform movement)
|
||||
tick() {
|
||||
var now = Date.now(), elapsed = now - this.t_prev;
|
||||
this.t_prev = now;
|
||||
this.angle = (this.angle + (A_VELOCITY * elapsed / 1000)) % 360;
|
||||
}
|
||||
|
||||
// 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.setRotate(this.angle, 0, 0, 1);
|
||||
// Draw each component
|
||||
for (var component of this.components) {
|
||||
component?.draw(gl, modelMatrix, u_ModelMatrix);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user