/// /// /// /// /// /// function main() { // Define Constants const CIRCLE_RADIUS = 16; const GRAVITY = 9.8; // Retrieve context const lProgramContext = getContext('#rigidbody_1'); if (lProgramContext.gl === null) { console.error('Unable to initialize WebGL. Your browser or machine may not support it.'); return; } lProgramContext.gl.clearColor(0.0, 0.0, 0.0, 1.0); lProgramContext.gl.clear(lProgramContext.gl.COLOR_BUFFER_BIT); function run() { console.log('Running Rigid Body 1'); lProgramContext.load().then(function(pProgramInfo) { const lCircle = circle(lProgramContext.gl, CIRCLE_RADIUS, 30, [{ x: 0.3, y: 0.3, z: 0.3, w: 1 }], vec2(lProgramContext.width / 2.0, lProgramContext.height / 2.0)); function update(pDeltaTimeSeconds) { // Physics updates const lGravityForce = vec2(0, -1.0 * (lCircle.mass * GRAVITY)); // Add up the forces acting on the circle lCircle.force = addVec2(lCircle.force, lGravityForce); // Figure out acceleration (a = F / m) const lCurrentAcceleration = scaleVec2(lCircle.force, 1.0 / lCircle.mass); // Calculate the new velocity: v = v0 + a * t lCircle.velocity = addVec2(lCircle.velocity, scaleVec2(lCurrentAcceleration, pDeltaTimeSeconds)); // Update the position based on velocity: x = x0 + v * t lCircle.position = addVec2(lCircle.position, scaleVec2(lCircle.velocity, pDeltaTimeSeconds)); // Update the model matrix accordingly lCircle.model = translateMatrix(mat4(), lCircle.position.x, lCircle.position.y, 0); // Report the current state to the frontend $('#rigidbody_1_force_field').text(vec2str(lCircle.force)); $('#rigidbody_1_acceleration_field').text(vec2str(lCurrentAcceleration)); $('#rigidbody_1_velocity_field').text(vec2str(lCircle.velocity)); $('#rigidbody_1_position_field').text(vec2str(lCircle.position)); // Reset the circle's force vector lCircle.force = vec2(); // Render Code only lProgramContext.gl.clearColor(0.0, 0.0, 0.0, 1.0); // Clear to black, fully opaque lProgramContext.gl.clearDepth(1.0); // Clear everything lProgramContext.gl.enable(lProgramContext.gl.DEPTH_TEST); // Enable depth testing lProgramContext.gl.depthFunc(lProgramContext.gl.LEQUAL); // Near things obscure far things lProgramContext.gl.clear(lProgramContext.gl.COLOR_BUFFER_BIT | lProgramContext.gl.DEPTH_BUFFER_BIT); lProgramContext.gl.useProgram(pProgramInfo.program); lProgramContext.gl.uniformMatrix4fv(pProgramInfo.uniformLocations.projection, false, lProgramContext.perspective); lProgramContext.gl.uniformMatrix4fv(pProgramInfo.uniformLocations.model, false, lCircle.model); renderCircle(lProgramContext.gl, pProgramInfo, lCircle); } function addForce(ev) { ev.preventDefault(); ev.stopPropagation(); let lXValue = $(this).find('.vec2_x_input').val(), lYValue = $(this).find('.vec2_y_input').val(); if (lXValue.length === 0) { lXValue = 0; } if (lYValue.length === 0) { lYValue = 5000; } console.log('Applying force: ' + lXValue + ', ' + lYValue); lCircle.force = addVec2(lCircle.force, vec2(Number(lXValue), Number(lYValue))); } function cleanup() { lProgramContext.gl.deleteBuffer(lCircle.buffer); lProgramContext.gl.deleteProgram(pProgramInfo.program); lProgramContext.gl.clearColor(0.0, 0.0, 0.0, 1.0); lProgramContext.gl.clear(lProgramContext.gl.COLOR_BUFFER_BIT); } function reset() { lExitRequestFunc(); lProgramContext.reset(); $('#rigidbody_1_force_submit_button').unbind('submit').submit(false); } const lExitRequestFunc = requestUpdateLoop(update, cleanup); lProgramContext.stopButton.on('click', reset); $('#rigidbody_1_force_submit_button').submit(addForce); }); } lProgramContext.playButton.on('click', run); $('#rigidbody_1_force_submit_button').submit(false); } $(document).ready(main);