///
///
///
///
///
///
(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 = getCircleMomentOfInertia(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);
})()