diff options
Diffstat (limited to 'frontend/_shared')
-rw-r--r-- | frontend/_shared/2d/shader.js | 18 | ||||
-rw-r--r-- | frontend/_shared/math/circle.js | 2 | ||||
-rw-r--r-- | frontend/_shared/math/collision.js | 25 | ||||
-rw-r--r-- | frontend/_shared/math/line2.js | 12 | ||||
-rw-r--r-- | frontend/_shared/math/point2.js | 16 | ||||
-rw-r--r-- | frontend/_shared/math/rectangle.js | 32 | ||||
-rw-r--r-- | frontend/_shared/math/rigidbody2.js | 57 |
7 files changed, 146 insertions, 16 deletions
diff --git a/frontend/_shared/2d/shader.js b/frontend/_shared/2d/shader.js index 4deddb5..7e85a9e 100644 --- a/frontend/_shared/2d/shader.js +++ b/frontend/_shared/2d/shader.js @@ -28,7 +28,7 @@ function loadOrthographicShader(pGl) { return null; } - return { + var lRetval = { program: lShaderProgram, attributeLocations: { position: pGl.getAttribLocation(lShaderProgram, 'position'), @@ -38,7 +38,23 @@ function loadOrthographicShader(pGl) { projection: pGl.getUniformLocation(lShaderProgram, 'projection'), model: pGl.getUniformLocation(lShaderProgram, 'model') } + }; + + lRetval.renderShape = function(pShape) { + pGl.uniformMatrix4fv(lRetval.uniformLocations.model, false, pShape.model); + pGl.bindBuffer(pGl.ARRAY_BUFFER, pShape.buffer); + { + pGl.enableVertexAttribArray(lRetval.attributeLocations.position); + pGl.vertexAttribPointer(lRetval.attributeLocations.position, 2, pGl.FLOAT, false, BYTES_PER_FLOAT * 6, 0); + + pGl.enableVertexAttribArray(lRetval.attributeLocations.color); + pGl.vertexAttribPointer(lRetval.attributeLocations.color, 4, pGl.FLOAT, false, BYTES_PER_FLOAT * 6, BYTES_PER_FLOAT * 2); + } + + pGl.drawArrays(pGl.TRIANGLES, 0, pShape.vertexCount); } + + return lRetval; } return fetch('/_shared/2d/shaders/orthographic.vert').then(function(pResponse) { diff --git a/frontend/_shared/math/circle.js b/frontend/_shared/math/circle.js index 340d7dc..ba33021 100644 --- a/frontend/_shared/math/circle.js +++ b/frontend/_shared/math/circle.js @@ -71,7 +71,7 @@ function renderCircle(pGl, pProgramInfo, pCircle) { pGl.drawArrays(pGl.TRIANGLE_STRIP, 0, pCircle.vertexCount); } -function getMomentOfInertia(pCircle) { +function getCircleMomentOfInertia(pCircle) { return (Math.PI * Math.pow(pCircle.radius, 4)) / 4; } diff --git a/frontend/_shared/math/collision.js b/frontend/_shared/math/collision.js index 74ec5d8..8e4be7d 100644 --- a/frontend/_shared/math/collision.js +++ b/frontend/_shared/math/collision.js @@ -2,22 +2,25 @@ /// <reference path="line2.js" /> /// <reference path="circle.js" /> /// <reference path="mat4.js" /> +/// <reference path="point2.js" /> /** * - * @param {circle} pCricle + * @param {circle} pCircle * @param {line2} pLine */ -function lineCircleCollision2(pCricle, pLine) { - // We have a triangle formed by circle's position P and the two points of the line, A and B. - var lSlope = (pCricle.position.y - pLine.start.y) / (pCricle.position.x - pLine.start.x), - lAngle = Math.atan(lSlope), - lAngleDiff = lAngle - pLine.angle, - lPositionToStart = subVec2(pCricle.position, pLine.start), - lPosToStartLength = length2(lPositionToStart), - lHeight = lPosToStartLength * Math.sin(lAngleDiff); +function lineCircleCollision2(pCircle, pLine) { + return distanceFromPoint2ToLine2(pCircle.position, pLine) <= pCircle.radius; +} - if (Math.abs(lHeight - pCricle.radius) < pCricle.radius) { - console.log('Intersection'); +function getLineCircleCollison2Data(pCircle, pLine) { + const lCollisionNormal = pLine.normal, + lCollisionPoint = addVec2(pCircle.position, scaleVec2(negate2(lCollisionNormal), pCircle.radius)); + + return { + relativeVelocity: subVec2(pCircle.velocity, pLine.velocity), + collisionNormal: lCollisionNormal, + firstPointOfApplication: subVec2(lCollisionPoint, pCircle.position), + secondPointOfApplication: subVec2(lCollisionPoint, pLine.start) } }
\ No newline at end of file diff --git a/frontend/_shared/math/line2.js b/frontend/_shared/math/line2.js index d8ab096..a9e72be 100644 --- a/frontend/_shared/math/line2.js +++ b/frontend/_shared/math/line2.js @@ -7,7 +7,7 @@ * @param {vec2} pEnd * @param {WebGLRenderingContext} pGl */ -function line2(pStart, pEnd, pGl, pColor, pThickness) { +function line2(pStart, pEnd, pGl, pColor, pMass) { const lDiffVector = subVec2(pEnd, pStart); const lBuffer = pGl.createBuffer(); @@ -28,12 +28,18 @@ function line2(pStart, pEnd, pGl, pColor, pThickness) { start: pStart, end: pEnd, slope: lSlope, - angle: Math.atan(lSlope), + normal: normalize2(getPerp2(lDiffVector)), length: length2(lDiffVector), - direction: normalize2(lDiffVector) + mass: pMass, + direction: normalize2(lDiffVector), + velocity: vec2(0, 0) }; } +function getLine2MomentOfInertia(pLine) { + return (1.0 / 12.0) * pLine.mass * Math.pow(pLine.length, 2); +} + function renderLine2(pGl, pProgramInfo, pLine) { pGl.uniformMatrix4fv(pProgramInfo.uniformLocations.model, false, mat4()); // Model on a line is always default matrix pGl.bindBuffer(pGl.ARRAY_BUFFER, pLine.buffer); diff --git a/frontend/_shared/math/point2.js b/frontend/_shared/math/point2.js new file mode 100644 index 0000000..eeacd91 --- /dev/null +++ b/frontend/_shared/math/point2.js @@ -0,0 +1,16 @@ +function point2(x = 0, y = 0) { + return { x: x, y: y }; +} + +function distanceFromPoint2ToLine2(pPoint, pLine) { + // Check out this wikapedia article for more information: + // https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line + var x0 = pPoint.x, + y0 = pPoint.y, + x1 = pLine.start.x, + y1 = pLine.start.y, + x2 = pLine.end.x, + y2 = pLine.end.y; + + return Math.abs((x2 - x1) * (y1 - y0) - (x1 - x0) * (y2 - y1)) / Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)); +}
\ No newline at end of file diff --git a/frontend/_shared/math/rectangle.js b/frontend/_shared/math/rectangle.js new file mode 100644 index 0000000..c24fa12 --- /dev/null +++ b/frontend/_shared/math/rectangle.js @@ -0,0 +1,32 @@ +/// <reference path="rigidbody2.js" /> + +function rectangle(pGl, pData) { + var lBuffer = pGl.createBuffer(), + lColor = pData.color || { x: 1, y: 0, z: 0, w: 1 }; + + pGl.bindBuffer(pGl.ARRAY_BUFFER, lBuffer); + + var lBufferedData = [ + 0, 0, lColor.x, lColor.y, lColor.z, lColor.w, + 0, pData.height, lColor.x, lColor.y, lColor.z, lColor.w, + pData.width, pData.height, lColor.x, lColor.y, lColor.z, lColor.w, + pData.width, pData.height, lColor.x, lColor.y, lColor.z, lColor.w, + pData.width, 0, lColor.x, lColor.y, lColor.z, lColor.w, + 0, 0, lColor.x, lColor.y, lColor.z, lColor.w + ]; + + pGl.bufferData(pGl.ARRAY_BUFFER, new Float32Array(lBufferedData), pGl.STATIC_DRAW) + pGl.bindBuffer(pGl.ARRAY_BUFFER, undefined); + + pData.getMomentOfInertia = function() { + return Math.pow(pData.width * pData.height, 3.0) / 12.0; + }; + + return makeRigidBody2({ + vertexCount: 6, + buffer: lBuffer, + width: pData.width, + height: pData.height, + model: translateMatrix(mat4(), pData.position ? pData.position.x : 0, pData.position ? pData.position.y : 0, 0), + }, pData); +}
\ No newline at end of file diff --git a/frontend/_shared/math/rigidbody2.js b/frontend/_shared/math/rigidbody2.js new file mode 100644 index 0000000..0b18d0c --- /dev/null +++ b/frontend/_shared/math/rigidbody2.js @@ -0,0 +1,57 @@ +/// <reference path="vec2.js" /> +/// <reference path="mat4.js" /> +/// <reference path="circle.js" /> +/// <reference path="line2.js" /> +/// <reference path="collision.js" /> + +const GRAVITY = 9.8; +const BYTES_PER_FLOAT = 4; + +/** + * + * @param {Shape} pObject a 2D shape like a circle, rectangle, or line + * @param {Object} pData initial data for the rigidboy + */ +function makeRigidBody2(pObject, pData) { + pObject.velocity = vec2(); + pObject.prevVelocity = pObject.velocity; + pObject.position = pData.position || vec2(); + pObject.prevPosition = pObject.position; + pObject.force = vec2(); + pObject.rotationVelocity = 0; + pObject.rotationRadians = 0; + pObject.torque = 0; + pObject.mass = pData.mass !== undefined ? pData.mass : 1.0; + pObject.getMomentOfInertia = pData.getMomentOfInertia; + + return pObject; +} + +function updateRigidBody2(pRigidbody, pDeltaTimeSeconds) { + applyForceRigidbody2(pRigidbody, vec2(0, -1.0 * (pRigidbody.mass * GRAVITY))); + const lCurrentAcceleration = scaleVec2(pRigidbody.force, 1.0 / pRigidbody.mass); + pRigidbody.prevVelocity = pRigidbody.velocity; + pRigidbody.velocity = addVec2(pRigidbody.velocity, scaleVec2(lCurrentAcceleration, pDeltaTimeSeconds)); + pRigidbody.prevPos = { ...pRigidbody.position }; + pRigidbody.position = addVec2(pRigidbody.position, scaleVec2(pRigidbody.velocity, pDeltaTimeSeconds)); + pRigidbody.force = vec2(); + + const lMomentOfInertia = pRigidbody.getMomentOfInertia(pRigidbody); + const lAngularAcceleration = pRigidbody.torque / lMomentOfInertia; + pRigidbody.rotationVelocity += lAngularAcceleration * pDeltaTimeSeconds; + pRigidbody.rotationRadians += pRigidbody.rotationVelocity * pDeltaTimeSeconds; + pRigidbody.torque = 0; + + pRigidbody.model = rotateMatrix2d(translateMatrix(mat4(), pRigidbody.position.x, pRigidbody.position.y, 0), pRigidbody.rotationRadians); +} + +function applyForceRigidbody2(pRigidbody, pForceVector, pPointOfApplication) { + if (pPointOfApplication !== undefined) { + const lOriginToPointOfApp = subVec2(vec2(), pPointOfApplication), + lPerpVec = vec2(-lOriginToPointOfApp.y, lOriginToPointOfApp.x); + + pRigidbody.torque += TORQUE_MULTIPLIER * dot2(lPerpVec, pForceVector); + } + + pRigidbody.force = addVec2(pRigidbody.force, pForceVector); +} |