summaryrefslogtreecommitdiff
path: root/frontend/_shared
diff options
context:
space:
mode:
authorMatthew Kosarek <matthew.kosarek@vention.cc>2021-02-27 17:32:32 -0500
committerMatthew Kosarek <matthew.kosarek@vention.cc>2021-02-27 17:32:32 -0500
commitd1b528b01796601c2bfea7b1a9813e5907e1c728 (patch)
tree77e2200e930fcad2166edf1e3d31d4cd1211db56 /frontend/_shared
parent026abdb98ad30209df0e88795f25b1f74556585e (diff)
Close to being done on line-circle collisions, but it appears we're running into a rotation problem. Going to work on square-line collisions in the meantime
Diffstat (limited to 'frontend/_shared')
-rw-r--r--frontend/_shared/2d/shader.js18
-rw-r--r--frontend/_shared/math/circle.js2
-rw-r--r--frontend/_shared/math/collision.js25
-rw-r--r--frontend/_shared/math/line2.js12
-rw-r--r--frontend/_shared/math/point2.js16
-rw-r--r--frontend/_shared/math/rectangle.js32
-rw-r--r--frontend/_shared/math/rigidbody2.js57
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);
+}