/// /// /// /// /// (function() { function main() { // Define Constants const CIRCLE_RADIUS = 16; const GRAVITY = 9.8; // Retrieve context const lProgramContext = getContext('#rigidbody_2'); 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 2'); lProgramContext.load().then(function(pProgramInfo) { const lCircle = circle(lProgramContext.gl, CIRCLE_RADIUS, 30, [ { x: 1, y: 1, z: 0, w: 1 }, { x: 1, y: 0, z: 1, w: 1 }, { x: 0, y: 1, z: 1, w: 1 }, { x: 0, y: 1, z: 0, w: 1 } ], vec2(lProgramContext.width / 2.0, lProgramContext.height / 2.0)); function update(pDeltaTimeSeconds) { // Same physics updates from part 1 applyForce(vec2(0, -1.0 * (lCircle.mass * GRAVITY))); const lCurrentAcceleration = scaleVec2(lCircle.force, 1.0 / lCircle.mass); lCircle.velocity = addVec2(lCircle.velocity, scaleVec2(lCurrentAcceleration, pDeltaTimeSeconds)); lCircle.position = addVec2(lCircle.position, scaleVec2(lCircle.velocity, pDeltaTimeSeconds)); lCircle.force = vec2(); // Angular code starts here // Retrieve the moment of inertia for our shape (Ours is a circle by default) const lMomentOfInertia = getMomentOfInertia(lCircle); // Calculate the angular acceperation (omega = T / I) const lAngularAcceleration = lCircle.torque / lMomentOfInertia; // Calculate the rotation in radians lCircle.rotationVelocity += lAngularAcceleration * pDeltaTimeSeconds; lCircle.rotationRadians += lCircle.rotationVelocity * pDeltaTimeSeconds; lCircle.torque = 0; // Calculate the model as previously, but this time, also rotate it lCircle.model = rotateMatrix2d(translateMatrix(mat4(), lCircle.position.x, lCircle.position.y, 0), lCircle.rotationRadians); // Render Code only lProgramContext.gl.clearColor(0.0, 0.0, 0.0, 1.0); lProgramContext.gl.clearDepth(1.0); lProgramContext.gl.enable(lProgramContext.gl.DEPTH_TEST); lProgramContext.gl.depthFunc(lProgramContext.gl.LEQUAL); 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); } const TORQUE_MULTIPLIER = 100.0; // TODO: This may be unncessary function applyForce(pForceVector, pPointOfApplication) { if (pPointOfApplication !== undefined) { const lOriginToPointOfApp = subVec2(vec2(), pPointOfApplication), // The point of application is relative to the model (i.e. the center of the circle, not the scene) lPerpVec = vec2(-lOriginToPointOfApp.y, lOriginToPointOfApp.x); // Retrieve the perpendicular vector // Calculate the torque from the perp dot (T = r_perp . F) lCircle.torque += TORQUE_MULTIPLIER * dot2(lPerpVec, pForceVector); } lCircle.force = addVec2(lCircle.force, pForceVector); } 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_2_force_submit_button').unbind('submit').submit(false); } const lExitRequestFunc = requestUpdateLoop(update, cleanup); lProgramContext.stopButton.on('click', reset); $('#rigidbody_2_force_submit_button').submit(function(pEv) { pEv.preventDefault(); pEv.stopPropagation(); // Read in the force vector from the form const lForceGroup = $('#rigidbody_2_force_input'), lPositionGroup = $('#rigidbody_2_position_input'); let lForceVectorX = lForceGroup.find('.vec2_x_input').val(), lForceVectorY = lForceGroup.find('.vec2_y_input').val(); if (lForceVectorX.length === 0) { lForceVectorX = 0; } if (lForceVectorY.length === 0) { lForceVectorY = 5000; } // Read in the point of application vector from the form let lPositionGroupX = lPositionGroup.find('.vec2_x_input').val(), lPositionGroupY = lPositionGroup.find('.vec2_y_input').val(); if (lPositionGroupX.length === 0) { lPositionGroupX = -Math.sqrt(2) / 2; } if (lPositionGroupY.length === 0) { lPositionGroupY = -Math.sqrt(2) / 2; } const lForceVector = vec2(Number(lForceVectorX), Number(lForceVectorY)); const lPointOfApplication = scaleVec2(normalize2(vec2(Number(lPositionGroupX), Number(lPositionGroupY))), lCircle.radius); applyForce(lForceVector, lPointOfApplication); }); }); } lProgramContext.playButton.on('click', run); $('#rigidbody_2_force_submit_button').submit(false); } $(document).ready(main); })()