diff --git a/Pendulum/Pendulum.js b/Pendulum/Pendulum.js index 4c89a71..480c395 100644 --- a/Pendulum/Pendulum.js +++ b/Pendulum/Pendulum.js @@ -18,9 +18,11 @@ const vertex_shader = ` const fragment_shader = ` + precision mediump float; + uniform vec4 u_Color; void main() { - gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); + gl_FragColor = u_Color; } `; // Point size of the anchor @@ -53,7 +55,7 @@ function main() { // create a pendulum object var pendulum = new Pendulum({ angle: 0, length: PEN_LENGTH, radius: BOB_RADIUS }); - init(gl, pendulum); + pendulum.init(gl); // Specify the color for clearing gl.clearColor(0, 0, 0, 1); @@ -82,10 +84,6 @@ function main() { tick(); } -function init(gl, pendulum) { - pendulum.init(gl); -} - function draw(gl, pendulum, modelMatrix, u_ModelMatrix) { // Clear gl.clear(gl.COLOR_BUFFER_BIT); diff --git a/Pendulum/PendulumComponents.js b/Pendulum/PendulumComponents.js index 414e753..2fd57a6 100644 --- a/Pendulum/PendulumComponents.js +++ b/Pendulum/PendulumComponents.js @@ -16,7 +16,7 @@ function acquire_buffer(gl) { return vertexBuffer; } -function acquire_VAO(gl, name, size, type) { +function acquire_attribute(gl, name, size, type) { // Acquire a reference to named attr var ret = gl.getAttribLocation(gl.program, name); if (ret < 0) { @@ -26,10 +26,19 @@ function acquire_VAO(gl, name, size, type) { gl.vertexAttribPointer(ret, size, type, false, 0, 0); return ret; } +function acquire_uniform(gl, name) { + // Acquire a reference to named attr + var ret = gl.getUniformLocation(gl.program, name); + if (!ret) { + console.log(`Failed to get the storage location of ${name}`); + return -1; + } + return ret; +} // Classes // homo2: Stores a 2d vector or point in homog. coords -class homog2 { +class Homogeneous2D { constructor(x = 0, y = 0, w = 0) { this.x = x; this.y = y; @@ -57,7 +66,7 @@ class homog2 { } // copy copy() { - return new homog2(this.x, this.y, this.w); + return new Homogeneous2D(this.x, this.y, this.w); } // create vector/point from 2d polar coordinates from_polar(r = 0, theta = 0, w = 0) { @@ -68,12 +77,78 @@ class homog2 { } } +class Rod { + constructor({ anchor = { x: 0, y: 0 }, bob = { x: 0, y: 0 }, color = { r: 1.0, g: 0.0, b: 0.0, a: 1.0 } } = {}) { + // Set the object's vertices + this.vertices = [ new Homogeneous2D(anchor.x, anchor.y, 1), + new Homogeneous2D(bob.x, bob.y, 1)] + // Set object's color + this.color = [color.r, color.g, color.b, color.a]; + } + // Convert to Float32Array [x, y] + 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; + } + // Initialize the object's drawing parameters + 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); + + // 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 the object + draw(gl, modelMatrix, u_ModelMatrix) { + // Bind the buffers + gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); + + // Set the object's color + var u_Color = acquire_uniform(gl, 'u_Color'); + gl.uniform4fv(u_Color, this.color); + + // get a_Position + var a_Position = acquire_attribute(gl, 'a_Position', 2, gl.FLOAT); + // Enable the assignment to a_Position variable + gl.enableVertexAttribArray(a_Position); + + // Pass the rotation matrix to the vertex shader + gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrix.elements); + // Draw the Anchor + gl.drawElements(gl.LINES, 2, gl.UNSIGNED_BYTE, 0); + } +} class Anchor { - constructor({ center = { x: 0, y: 0 } } = {}) { - this.position = new homog2(center.x, center.y, 1); + constructor({ center = { x: 0, y: 0 }, color = { r: 0.0, g: 1.0, b: 0.0, a: 1.0 } } = {}) { + this.position = new Homogeneous2D(center.x, center.y, 1); + // Set object color + this.color = [color.r, color.g, color.b, color.a]; } - // Convert to Float32Array [center, v0, v1, ...] + // Convert to Float32Array [x, y] vertex_array() { // allocate space for center.xy + vertices.xy var ret = new Float32Array(2); @@ -89,7 +164,7 @@ class Anchor { console.log(ret); return ret; } - + // Initialize the object's drawing parameters init(gl) { // Make the buffers this.vertexBuffer = acquire_buffer(gl); @@ -103,14 +178,18 @@ class Anchor { gl.bufferData(gl.ARRAY_BUFFER, this.vertex_array(), gl.STATIC_DRAW); gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.index_array(), gl.STATIC_DRAW); } - + // Draw the object draw(gl, modelMatrix, u_ModelMatrix) { // Bind the buffers gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); + // Set the object's color + var u_Color = acquire_uniform(gl, 'u_Color'); + gl.uniform4fv(u_Color, this.color); + // get a_Position - var a_Position = acquire_VAO(gl, 'a_Position', 2, gl.FLOAT); + var a_Position = acquire_attribute(gl, 'a_Position', 2, gl.FLOAT); // Enable the assignment to a_Position variable gl.enableVertexAttribArray(a_Position); @@ -121,18 +200,21 @@ class Anchor { } } -// hexagon2 class: Holds vertices and a center point. Only constructs regular polygons +// Polygon 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 } } = {}) { + constructor({ sides = 6, radius = 1, rotation = 0, center = { x: 0, y: 0 }, color = { r: 0, g: 0, b: 1, a: 1 } } = {}) { this.length = 0; - // vertices + // Mark center point + this.center = new Homogeneous2D(center.x, center.y, 1); + // Create 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++; + this.vertices[i] = new Homogeneous2D().from_polar(radius, rotation + (i * 2 * Math.PI / sides)).add_m(this.center); + this.length++; } + // Set object color + this.color = [color.r, color.g, color.b, color.a]; } // Convert to Float32Array [center, v0, v1, ...] vertex_array() { @@ -155,7 +237,7 @@ class Polygon { ret[this.vertices.length] = 0; return ret; } - + // Initialize the object's drawing parameters init(gl) { // Make the buffers this.vertexBuffer = acquire_buffer(gl); @@ -169,14 +251,18 @@ class Polygon { gl.bufferData(gl.ARRAY_BUFFER, this.vertex_array(), gl.STATIC_DRAW); gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.index_array(), gl.STATIC_DRAW); } - + // Draw the object draw(gl, modelMatrix, u_ModelMatrix) { // Bind the buffers gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); + // Set the object's color + var u_Color = acquire_uniform(gl, 'u_Color'); + gl.uniform4fv(u_Color, this.color); + // get a_Position - var a_Position = acquire_VAO(gl, 'a_Position', 2, gl.FLOAT); + var a_Position = acquire_attribute(gl, 'a_Position', 2, gl.FLOAT); // Enable the assignment to a_Position variable gl.enableVertexAttribArray(a_Position); @@ -190,7 +276,9 @@ class Polygon { class Pendulum { constructor({ angle = 0, length = PEN_LENGTH, radius = BOB_RADIUS, anchor = { x: 0, y: 0 } } = {}) { this.angle = angle; + var bob = {x: 0, y: -length}; this.components = [ + new Rod({ anchor: anchor, bob: bob}), new Anchor({ center: anchor }), new Polygon({ radius: radius, center: { x: 0, y: -length } }) ]; @@ -206,7 +294,7 @@ class Pendulum { // Initialize the pendulum init(gl) { // initialize the components - for(var component of this.components) { + for (var component of this.components) { component?.init(gl); } // start the clock