diff options
Diffstat (limited to 'frontend/2d/_collisions')
-rw-r--r-- | frontend/2d/_collisions/circle_line.html (renamed from frontend/2d/_collisions/part_1.html) | 22 | ||||
-rw-r--r-- | frontend/2d/_collisions/circle_line.js | 178 | ||||
-rw-r--r-- | frontend/2d/_collisions/collisions_1.js | 125 | ||||
-rw-r--r-- | frontend/2d/_collisions/rectangle_line.html | 52 | ||||
-rw-r--r-- | frontend/2d/_collisions/rectangle_line.js | 105 |
5 files changed, 340 insertions, 142 deletions
diff --git a/frontend/2d/_collisions/part_1.html b/frontend/2d/_collisions/circle_line.html index 06a4b3d..038c759 100644 --- a/frontend/2d/_collisions/part_1.html +++ b/frontend/2d/_collisions/circle_line.html @@ -13,10 +13,11 @@ <script src="/_shared/math/mat4.js"></script> <script src="/_shared/math/circle.js"></script> <script src="/_shared/math/line2.js"></script> + <script src="/_shared/math/point2.js"></script> <script src="/_shared/math/collision.js"></script> <script src="/_shared/2d/shader.js"></script> <script src="/_shared/2d/program_common.js"></script> - <script src="collisions_1.js"></script> + <script src="circle_line.js"></script> </head> <body> <header> @@ -26,28 +27,15 @@ <nav> </nav> <section> - <h1>Part 1: Circle-Line</h1> + <h1>Circle-Line</h1> <article> <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. </p> - <div id="collision_1" class="opengl_canvas_container"> + <div id="circle_line_collision" class="opengl_canvas_container"> <canvas width="640" height="480"></canvas> <div class="opengl_canvas_sidebar"> - <ul class="opengl_value_tracker"> - <li><b>Linear Force:</b><span id="rigidbody_1_force_field">N/A</span></li> - <li><b>Linear Acceleration:</b><span id="rigidbody_1_acceleration_field">N/A</span></li> - <li><b>Linear Velocity:</b><span id="rigidbody_1_velocity_field">N/A</span></li> - <li><b>Linear Position:</b><span id="rigidbody_1_position_field">N/A</span></li> - </ul> - <form id="rigidbody_1_force_submit_button" style="text-align: right; padding: 0.5rem;"> - <div class="vec2_input_group"> - <label>Force Vector</label> - <input class="vec2_x_input" type="number" placeholder="X (Default 0)"/> - <input class="vec2_y_input" type="number" placeholder="Y (Default 5000 N)"/> - </div> - <input type="submit" value="Apply Force"></input> - </form> + </div> <button class="play_button"> Play diff --git a/frontend/2d/_collisions/circle_line.js b/frontend/2d/_collisions/circle_line.js new file mode 100644 index 0000000..e5898f0 --- /dev/null +++ b/frontend/2d/_collisions/circle_line.js @@ -0,0 +1,178 @@ +/// <reference path="../../scripts/jquery-3.5.1.min.js"/> +/// <reference path="../../_shared/math/vec2.js" /> +/// <reference path="../../_shared/math/mat4.js" /> +/// <reference path="../../_shared/2d/shader.js" /> +/// <reference path="../../_shared/math/circle.js" /> +/// <reference path="../../_shared/math/line2.js" /> +/// <reference path="../../_shared/math/collision.js" /> +/// <reference path="../../_shared/2d/program_common.js" /> + +(function() { + // Define Constants + const CIRCLE_RADIUS = 16; + const GRAVITY = 20.0; + const COF_OF_RESTITUITION = 0.75; + const TORQUE_MULTIPLIER = 100.0; // TODO: This may be unncessary + + var programContext, + circleObject, + lineObjectList, + programInfo, + exitRequestFunc; + + function main() { + programContext = getContext('#circle_line_collision'); + + if (programContext.gl === null) { + console.error('Unable to initialize WebGL. Your browser or machine may not support it.'); + return; + } + + programContext.gl.clearColor(0.1, 0.15, 0.2, 1.0); + programContext.gl.clear(programContext.gl.COLOR_BUFFER_BIT); + programContext.playButton.on('click', run); + } + + function run() { + console.log('Running Circle-Line Collisions'); + programContext.load().then(function(pProgramInfo) { + programInfo = pProgramInfo; + circleObject = circle(programContext.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(programContext.width * (3.0 / 4.0), programContext.height / 2.0 + 100)); + + circleObject.velocity = vec2(0, -50); + + lineObjectList = []; + + lineObjectList.push(line2({ x: 100, y: 100 }, { x: programContext.width - 100, y: 200 }, programContext.gl, + { x: 1, y: 0, z: 0, w: 1 }, 2.0)); + + lineObjectList.push(line2({ x: 100, y: 200 }, { x: programContext.width - 100, y: 100 }, programContext.gl, + { x: 1, y: 1, z: 0, w: 1 }, 2.0)); + + lineObjectList.push(line2({ x: 100, y: 0 }, { x: 100, y: programContext.height }, programContext.gl, + { x: 0, y: 1, z: 0, w: 1 }, 2.0)); + + lineObjectList.push(line2({ x: programContext.width - 100, y: 0 }, { x: programContext.width - 100, y: programContext.height }, programContext.gl, + { x: 0, y: 1, z: 0, w: 1 }, 2.0)); + + + exitRequestFunc = requestUpdateLoop(update, cleanup); + programContext.stopButton.on('click', reset); + }); + } + + function update(pDeltaTimeSeconds) { + pDeltaTimeSeconds = pDeltaTimeSeconds; + updateCircle(circleObject, pDeltaTimeSeconds); + collision(pDeltaTimeSeconds); + render(); + } + + function updateCircle(pCircle, pDeltaTimeSeconds) { + 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(); + + const lMomentOfInertia = getCircleMomentOfInertia(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 collision(pDeltaTimeSeconds) { + lineObjectList.forEach(function(lineObject) { + if (!lineCircleCollision2(circleObject, lineObject)) { + return; + } + + var lSubdividedDeltaTime = pDeltaTimeSeconds, + lSubdividedCircle = undefined; + + do { + lSubdividedCircle = JSON.parse(JSON.stringify(circleObject)); + lSubdividedCircle.position = {...circleObject.prevPos}; + lSubdividedCircle.velocity = {...circleObject.prevVelocity}; + lSubdividedDeltaTime = lSubdividedDeltaTime / 2.0; + updateCircle(lSubdividedCircle, lSubdividedDeltaTime); + if (lSubdividedDeltaTime === 0) { + console.error('This should NOT be happening'); + break; + } + } while (lineCircleCollision2(lSubdividedCircle, lineObject)) + + const lIntersectionResult = getLineCircleCollison2Data(lSubdividedCircle, lineObject), + lRelativeVelocity = lIntersectionResult.relativeVelocity, + lCollisionNormal = lIntersectionResult.collisionNormal, + lFirstPerp = getPerp2(lIntersectionResult.firstPointOfApplication), + lSecondPerp = getPerp2(lIntersectionResult.secondPointOfApplication); + + const lNumerator = dot2(scaleVec2(lRelativeVelocity, -(1.0 + COF_OF_RESTITUITION)), lCollisionNormal); + const lLinearDenomPart = dot2(lCollisionNormal, (scaleVec2(lCollisionNormal, 1 / circleObject.mass))); + const lRotationalDenomPart = (Math.pow(dot2(lFirstPerp, lCollisionNormal), 2) / getCircleMomentOfInertia(circleObject)); + + const lImpulseMagnitude = lNumerator / (lLinearDenomPart + lRotationalDenomPart); + + circleObject.position = lSubdividedCircle.position; + circleObject.velocity = addVec2(lSubdividedCircle.velocity, scaleVec2(lCollisionNormal, lImpulseMagnitude / circleObject.mass)); + circleObject.rotationVelocity = lSubdividedCircle.rotationVelocity + dot2(lFirstPerp, scaleVec2(lCollisionNormal, lImpulseMagnitude)); + + updateCircle(circleObject, pDeltaTimeSeconds - lSubdividedDeltaTime); + + return; + }) + } + + 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 render() { + programContext.gl.clearColor(0.1, 0.15, 0.2, 1.0); + programContext.gl.clearDepth(1.0); + programContext.gl.enable(programContext.gl.DEPTH_TEST); + programContext.gl.depthFunc(programContext.gl.LEQUAL); + programContext.gl.clear(programContext.gl.COLOR_BUFFER_BIT | programContext.gl.DEPTH_BUFFER_BIT); + programContext.gl.useProgram(programInfo.program); + programContext.gl.uniformMatrix4fv(programInfo.uniformLocations.projection, false, programContext.perspective); + + renderCircle(programContext.gl, programInfo, circleObject); + lineObjectList.forEach(function(lineObject) { + renderLine2(programContext.gl, programInfo, lineObject); + }); + } + + function cleanup() { + programContext.gl.deleteBuffer(circleObject.buffer); + lineObjectList.forEach(function(lineObject) { + programContext.gl.deleteBuffer(lineObject.buffer); + }); + programContext.gl.deleteProgram(programInfo.program); + programContext.gl.clearColor(0.1, 0.15, 0.2, 1.0); + programContext.gl.clear(programContext.gl.COLOR_BUFFER_BIT); + } + + function reset() { + exitRequestFunc(); + programContext.reset(); + } + + $(document).ready(main); +})()
\ No newline at end of file diff --git a/frontend/2d/_collisions/collisions_1.js b/frontend/2d/_collisions/collisions_1.js deleted file mode 100644 index ac325c2..0000000 --- a/frontend/2d/_collisions/collisions_1.js +++ /dev/null @@ -1,125 +0,0 @@ -/// <reference path="../../scripts/jquery-3.5.1.min.js"/> -/// <reference path="../../_shared/math/vec2.js" /> -/// <reference path="../../_shared/math/mat4.js" /> -/// <reference path="../../_shared/2d/shader.js" /> -/// <reference path="../../_shared/math/circle.js" /> -/// <reference path="../../_shared/math/line2.js" /> -/// <reference path="../../_shared/math/collision.js" /> -/// <reference path="../../_shared/2d/program_common.js" /> - -(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); -})()
\ No newline at end of file diff --git a/frontend/2d/_collisions/rectangle_line.html b/frontend/2d/_collisions/rectangle_line.html new file mode 100644 index 0000000..5db958c --- /dev/null +++ b/frontend/2d/_collisions/rectangle_line.html @@ -0,0 +1,52 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <meta charset="utf-8"> + <script src="/scripts/jquery-3.5.1.min.js"></script> + <script src="/index.js"></script> + <link rel="stylesheet" href="/index.css"> + <link rel="shortcut icon" href="/favicon/favicon.ico" type="image/x-icon"> + <link href="https://fonts.googleapis.com/css?family=Open+Sans:400,600,300" rel="stylesheet" type="text/css"> + <title>Physics for Games</title> + + <script src="/_shared/math/vec2.js"></script> + <script src="/_shared/math/mat4.js"></script> + <script src="/_shared/math/rectangle.js"></script> + <script src="/_shared/math/line2.js"></script> + <script src="/_shared/math/point2.js"></script> + <script src="/_shared/math/collision.js"></script> + <script src="/_shared/math/rigidbody2.js"></script> + <script src="/_shared/2d/shader.js"></script> + <script src="/_shared/2d/program_common.js"></script> + <script src="rectangle_line.js"></script> + </head> + <body> + <header> + <h1>Physics for Games</h1> + </header> + <main> + <nav> + </nav> + <section> + <h1>Rectangle-Line</h1> + <article> + <p> + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. + </p> + <div id="rectangle_line_collision" class="opengl_canvas_container"> + <canvas width="640" height="480"></canvas> + <div class="opengl_canvas_sidebar"> + + </div> + <button class="play_button"> + Play + </button> + <button class="stop_button"> + Stop + </button> + </div> + </article> + </section> + </main> + </body> +</html>
\ No newline at end of file diff --git a/frontend/2d/_collisions/rectangle_line.js b/frontend/2d/_collisions/rectangle_line.js new file mode 100644 index 0000000..ac73f71 --- /dev/null +++ b/frontend/2d/_collisions/rectangle_line.js @@ -0,0 +1,105 @@ +/// <reference path="../../scripts/jquery-3.5.1.min.js"/> +/// <reference path="../../_shared/math/vec2.js" /> +/// <reference path="../../_shared/math/mat4.js" /> +/// <reference path="../../_shared/2d/shader.js" /> +/// <reference path="../../_shared/math/rectangle.js" /> +/// <reference path="../../_shared/math/line2.js" /> +/// <reference path="../../_shared/math/collision.js" /> +/// <reference path="../../_shared/2d/program_common.js" /> + +(function() { + var programContext, + rectangleObject, + lineObjectList, + programInfo, + exitRequestFunc; + + function main() { + programContext = getContext('#rectangle_line_collision'); + + if (programContext.gl === null) { + console.error('Unable to initialize WebGL. Your browser or machine may not support it.'); + return; + } + + programContext.gl.clearColor(0.1, 0.15, 0.2, 1.0); + programContext.gl.clear(programContext.gl.COLOR_BUFFER_BIT); + programContext.playButton.on('click', run); + } + + function run() { + console.log('Running Rectangle-Line Collisions'); + programContext.load().then(function(pProgramInfo) { + programInfo = pProgramInfo; + + rectangleObject = rectangle(programContext.gl, { + width: 50, + height: 25, + color: { x: 0.3, y: 0.5, z: 0.1, w: 0.7 }, + position: vec2(programContext.width / 2.0 - 100, programContext.height / 2.0 + 100) + }); + rectangleObject.velocity = vec2(0, -50); + + lineObjectList = []; + + lineObjectList.push(line2({ x: 100, y: 100 }, { x: programContext.width - 100, y: 200 }, programContext.gl, + { x: 1, y: 0, z: 0, w: 1 }, 2.0)); + + lineObjectList.push(line2({ x: 100, y: 200 }, { x: programContext.width - 100, y: 100 }, programContext.gl, + { x: 1, y: 1, z: 0, w: 1 }, 2.0)); + + lineObjectList.push(line2({ x: 100, y: 0 }, { x: 100, y: programContext.height }, programContext.gl, + { x: 0, y: 1, z: 0, w: 1 }, 2.0)); + + lineObjectList.push(line2({ x: programContext.width - 100, y: 0 }, { x: programContext.width - 100, y: programContext.height }, programContext.gl, + { x: 0, y: 1, z: 0, w: 1 }, 2.0)); + + + exitRequestFunc = requestUpdateLoop(update, cleanup); + programContext.stopButton.on('click', reset); + }); + } + + function update(pDeltaTimeSeconds) { + pDeltaTimeSeconds = pDeltaTimeSeconds; + updateRigidBody2(rectangleObject, pDeltaTimeSeconds); + collision(pDeltaTimeSeconds); + render(); + } + + function collision(pDeltaTimeSeconds) { + + } + + function render() { + programContext.gl.clearColor(0.1, 0.15, 0.2, 1.0); + programContext.gl.clearDepth(1.0); + programContext.gl.enable(programContext.gl.DEPTH_TEST); + programContext.gl.depthFunc(programContext.gl.LEQUAL); + programContext.gl.clear(programContext.gl.COLOR_BUFFER_BIT | programContext.gl.DEPTH_BUFFER_BIT); + programContext.gl.useProgram(programInfo.program); + programContext.gl.uniformMatrix4fv(programInfo.uniformLocations.projection, false, programContext.perspective); + + programInfo.renderShape(rectangleObject); + lineObjectList.forEach(function(lineObject) { + renderLine2(programContext.gl, programInfo, lineObject); + }); + } + + function cleanup() { + programContext.gl.deleteBuffer(rectangleObject.buffer); + lineObjectList.forEach(function(lineObject) { + programContext.gl.deleteBuffer(lineObject.buffer); + }); + programContext.gl.deleteProgram(programInfo.program); + programContext.gl.clearColor(0.1, 0.15, 0.2, 1.0); + programContext.gl.clear(programContext.gl.COLOR_BUFFER_BIT); + } + + function reset() { + exitRequestFunc(); + programContext.reset(); + } + + $(document).ready(main); +})()
\ No newline at end of file |