diff options
author | Matthew Kosarek <mattkae@protonmail.com> | 2021-02-07 19:22:56 -0500 |
---|---|---|
committer | Matthew Kosarek <mattkae@protonmail.com> | 2021-02-07 19:22:56 -0500 |
commit | cc6d3871008a89fcf48814596d7bfec05f2706e4 (patch) | |
tree | 993ce66cc5a3c96841dc52fea60df873ff2f3469 | |
parent | 376e1a7f9207fffb1ec3027ac1e7f32db5de4922 (diff) |
Added rotational dynamics to the examples
-rw-r--r-- | frontend/_rigidbody/circle.js | 2 | ||||
-rw-r--r-- | frontend/_rigidbody/rigidbody_1.js | 10 | ||||
-rw-r--r-- | frontend/_rigidbody/rigidbody_2.js | 77 | ||||
-rw-r--r-- | frontend/index.css | 11 | ||||
-rw-r--r-- | frontend/rigidbody.html | 25 |
5 files changed, 111 insertions, 14 deletions
diff --git a/frontend/_rigidbody/circle.js b/frontend/_rigidbody/circle.js index c044597..194a772 100644 --- a/frontend/_rigidbody/circle.js +++ b/frontend/_rigidbody/circle.js @@ -33,7 +33,9 @@ function circle(pGl, pRadius, pSegments, pColorList, pInitialPosition) { position: pInitialPosition || vec2(), velocity: vec2(), force: vec2(), + torque: 0, mass: 1, + rotationVelocity: 0, rotationRadians: 0, model: mat4(), radius: pRadius diff --git a/frontend/_rigidbody/rigidbody_1.js b/frontend/_rigidbody/rigidbody_1.js index 5021162..c5e4f0a 100644 --- a/frontend/_rigidbody/rigidbody_1.js +++ b/frontend/_rigidbody/rigidbody_1.js @@ -72,9 +72,17 @@ function main() { ev.preventDefault(); ev.stopPropagation(); - const lXValue = $(this).find('.vec2_x_input').val(), + 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))); } diff --git a/frontend/_rigidbody/rigidbody_2.js b/frontend/_rigidbody/rigidbody_2.js index b41fa92..c41461e 100644 --- a/frontend/_rigidbody/rigidbody_2.js +++ b/frontend/_rigidbody/rigidbody_2.js @@ -24,23 +24,29 @@ function main() { 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)); + { 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 previously - const lGravityForce = vec2(0, -1.0 * (lCircle.mass * GRAVITY)); - lCircle.force = addVec2(lCircle.force, lGravityForce); + 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.rotationRadians += Math.PI * pDeltaTimeSeconds; - lCircle.model = rotateMatrix2d(translateMatrix(mat4(), lCircle.position.x, lCircle.position.y, 0), lCircle.rotationRadians); lCircle.force = vec2(); + // Calculate rotation + const lMomentOfInertia = getMomentOfInertia(lCircle); + const lAngularAcceleration = lCircle.torque / lMomentOfInertia; + + lCircle.rotationVelocity += lAngularAcceleration * pDeltaTimeSeconds; + lCircle.rotationRadians += lCircle.rotationVelocity * pDeltaTimeSeconds; + lCircle.model = rotateMatrix2d(translateMatrix(mat4(), lCircle.position.x, lCircle.position.y, 0), lCircle.rotationRadians); + lCircle.torque = 0; + // Render Code only lProgramContext.gl.clearColor(0.0, 0.0, 0.0, 1.0); lProgramContext.gl.clearDepth(1.0); @@ -55,6 +61,19 @@ function main() { 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); + + 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); @@ -65,14 +84,52 @@ function main() { 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);
\ No newline at end of file diff --git a/frontend/index.css b/frontend/index.css index 9139963..a718784 100644 --- a/frontend/index.css +++ b/frontend/index.css @@ -89,6 +89,8 @@ section > p { Helpful inputs */ .vec2_input_group { + position: relative; + margin-top: 1rem; display: flex; flex-direction: row; width: 100%; @@ -96,6 +98,15 @@ section > p { padding: 0.25rem; } +.vec2_input_group > label { + position: absolute; + top: -1rem; + left: 0rem; + font-size: 0.8rem; + font-weight: bold; + text-align: left; +} + .vec2_input_group > input { width: 45%; } diff --git a/frontend/rigidbody.html b/frontend/rigidbody.html index 510c667..2cc32b7 100644 --- a/frontend/rigidbody.html +++ b/frontend/rigidbody.html @@ -113,8 +113,9 @@ </ul> <form id="rigidbody_1_force_submit_button" style="text-align: right; padding: 0.5rem;"> <div class="vec2_input_group"> - <input class="vec2_x_input" type="number" value="0"/> - <input class="vec2_y_input" type="number" value="5000"/> + <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> @@ -135,7 +136,25 @@ <div id="rigidbody_2" class="opengl_canvas_container"> <canvas width="640" height="480"></canvas> <div class="opengl_canvas_sidebar"> - + <ul class="opengl_value_tracker"> + <li><b>Force:</b><span id="rigidbody_1_force_field">N/A</span></li> + <li><b>Acceleration:</b><span id="rigidbody_2_acceleration_field">N/A</span></li> + <li><b>Velocity:</b><span id="rigidbody_2_velocity_field">N/A</span></li> + <li><b>Position:</b><span id="rigidbody_2_position_field">N/A</span></li> + </ul> + <form id="rigidbody_2_force_submit_button" style="text-align: right; padding: 0.5rem;"> + <div id="rigidbody_2_force_input" 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> + <div id="rigidbody_2_position_input" class="vec2_input_group"> + <label>Point of Application (Unit Vector)</label> + <input class="vec2_x_input" type="number" placeholder="X (Default 2 Root 2)"/> + <input class="vec2_y_input" type="number" placeholder="Y (Default 2 Root 2)"/> + </div> + <input type="submit" value="Apply Force"></input> + </form> </div> <button class="play_button"> Play |