/// /// /// /// /// /// /// /// (function() { function main() { // Define Constants const CIRCLE_RADIUS = 16; const GRAVITY = 9.8; const COF_OF_RESTITUITION = 0.7; // Retrieve context const lProgramContext = getContext('#collision_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 Circle-Line Collisions'); lProgramContext.load().then(function(pProgramInfo) { const mCircle = circle(lProgramContext.gl, CIRCLE_RADIUS, 30, [ { x: 1, y: 0, z: 0, w: 1 }, { x: 0, y: 1, z: 0, w: 1 }, { x: 0, y: 0, z: 1, w: 1 } ], vec2(lProgramContext.width / 2.0, lProgramContext.height / 2.0 + 100)); const mline = line2({ x: 100, y: 100 }, { x: lProgramContext.width - 100, y: 200 }, lProgramContext.gl, { x: 1, y: 0, z: 0, w: 1 }, 2.0); /** * Run the update method of a single circle * * @param {circle} pCircle * @param {number} pDeltaTimeSeconds */ function updateCircle(pCircle, pDeltaTimeSeconds) { // Same physics updates from part 1 applyForce(pCircle, vec2(0, -1.0 * (pCircle.mass * GRAVITY))); const lCurrentAcceleration = scaleVec2(pCircle.force, 1.0 / pCircle.mass); pCircle.prevVelocity = pCircle.velocity; pCircle.velocity = addVec2(pCircle.velocity, scaleVec2(lCurrentAcceleration, pDeltaTimeSeconds)); pCircle.prevPos = { ...pCircle.position }; pCircle.position = addVec2(pCircle.position, scaleVec2(pCircle.velocity, pDeltaTimeSeconds)); pCircle.force = vec2(); // Same physics updates from part 2 const lMomentOfInertia = getMomentOfInertia(pCircle); const lAngularAcceleration = pCircle.torque / lMomentOfInertia; pCircle.rotationVelocity += lAngularAcceleration * pDeltaTimeSeconds; pCircle.rotationRadians += pCircle.rotationVelocity * pDeltaTimeSeconds; pCircle.torque = 0; pCircle.model = rotateMatrix2d(translateMatrix(mat4(), pCircle.position.x, pCircle.position.y, 0), pCircle.rotationRadians); } function update(pDeltaTimeSeconds) { pDeltaTimeSeconds = pDeltaTimeSeconds; updateCircle(mCircle, pDeltaTimeSeconds); collision(pDeltaTimeSeconds); render(); } function collision(pDeltaTimeSeconds) { lineCircleCollision2(mCircle, mline); return false; } function render() { 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); renderCircle(lProgramContext.gl, pProgramInfo, mCircle); renderLine2(lProgramContext.gl, pProgramInfo, mline); } const TORQUE_MULTIPLIER = 100.0; // TODO: This may be unncessary function applyForce(pCircle, pForceVector, pPointOfApplication) { if (pPointOfApplication !== undefined) { const lOriginToPointOfApp = subVec2(vec2(), pPointOfApplication), lPerpVec = vec2(-lOriginToPointOfApp.y, lOriginToPointOfApp.x); pCircle.torque += TORQUE_MULTIPLIER * dot2(lPerpVec, pForceVector); } pCircle.force = addVec2(pCircle.force, pForceVector); } function cleanup() { lProgramContext.gl.deleteBuffer(mCircle.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(); } const lExitRequestFunc = requestUpdateLoop(update, cleanup); lProgramContext.stopButton.on('click', reset); }); } lProgramContext.playButton.on('click', run); } $(document).ready(main); })()