diff options
Diffstat (limited to 'frontend/_shared/math/circle.js')
-rw-r--r-- | frontend/_shared/math/circle.js | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/frontend/_shared/math/circle.js b/frontend/_shared/math/circle.js new file mode 100644 index 0000000..340d7dc --- /dev/null +++ b/frontend/_shared/math/circle.js @@ -0,0 +1,112 @@ +/// <reference path="mat4.js" /> +/// <reference path="vec2.js" /> + +const BYTES_PER_FLOAT = 4; + +/** + * Initializes a new circle object for the WebGL context. + * + * @param {WebGLRenderingContext} pGl + * @param {number} pRadius + * @param {number} pSegments + * @param {Array<Vector4>} pColorList + * @param {vec2} pInitialPosition + * @param {number} pMass + */ +function circle(pGl, pRadius, pSegments, pColorList, pInitialPosition, pMass) { + const lBuffer = pGl.createBuffer(); + + pGl.bindBuffer(pGl.ARRAY_BUFFER, lBuffer); + + var lBufferedData = []; + vertexCount = 0; + + const lAngleIncrements = (360.0 / pSegments) * (Math.PI / 180.0); + for (let lSegIdx = 0; lSegIdx < pSegments; lSegIdx++) { + const lAngle = lAngleIncrements * lSegIdx, + lNextAngle = lAngleIncrements * (lSegIdx + 1), + lColorIndex = Math.floor(pColorList.length * (lSegIdx / pSegments)), + lColor = pColorList[lColorIndex]; // TODO: Calculate which one to use + + lBufferedData = lBufferedData.concat([ + 0, 0, lColor.x, lColor.y, lColor.z, lColor.w, + pRadius * Math.sin(lAngle), pRadius * Math.cos(lAngle), lColor.x, lColor.y, lColor.z, lColor.w, + pRadius * Math.sin(lNextAngle), pRadius * Math.cos(lNextAngle), lColor.x, lColor.y, lColor.z, lColor.w + ]); + + vertexCount += 3; + } + + pGl.bufferData(pGl.ARRAY_BUFFER, new Float32Array(lBufferedData), pGl.STATIC_DRAW) + pGl.bindBuffer(pGl.ARRAY_BUFFER, undefined); + + return { + buffer: lBuffer, + vertexCount: vertexCount, + prevPos: vec2(), + position: pInitialPosition || vec2(), + prevVelocity: vec2(), + velocity: vec2(), + force: vec2(), + torque: 0, + mass: pMass === undefined ? 1 : pMass, + rotationVelocity: 0, + rotationRadians: 0, + model: translateMatrix(mat4(), pInitialPosition ? pInitialPosition.x : 0, pInitialPosition ? pInitialPosition.y : 0, 0), + radius: pRadius + }; +} + +function renderCircle(pGl, pProgramInfo, pCircle) { + pGl.uniformMatrix4fv(pProgramInfo.uniformLocations.model, false, pCircle.model); + pGl.bindBuffer(pGl.ARRAY_BUFFER, pCircle.buffer); + { + pGl.enableVertexAttribArray(pProgramInfo.attributeLocations.position); + pGl.vertexAttribPointer(pProgramInfo.attributeLocations.position, 2, pGl.FLOAT, false, BYTES_PER_FLOAT * 6, 0); + + pGl.enableVertexAttribArray(pProgramInfo.attributeLocations.color); + pGl.vertexAttribPointer(pProgramInfo.attributeLocations.color, 4, pGl.FLOAT, false, BYTES_PER_FLOAT * 6, BYTES_PER_FLOAT * 2); + } + + pGl.drawArrays(pGl.TRIANGLE_STRIP, 0, pCircle.vertexCount); +} + +function getMomentOfInertia(pCircle) { + return (Math.PI * Math.pow(pCircle.radius, 4)) / 4; +} + +function doCirclesIntersect(pFirst, pSecond) { + const lDistanceBetween = Math.pow(pFirst.position.x - pSecond.position.x, 2) + + Math.pow(pFirst.position.y - pSecond.position.y, 2) + return lDistanceBetween <= Math.pow(pFirst.radius + pSecond.radius, 2); +} + +/** + * Returns intersection information about the intersecting circles. + * + * Warning! Only use this if doCirclesIntersect returned true for these circles. + * + * @param {circle} pFirst + * @param {circle} pSecond + */ +function getIntersectionDataForCircles(pFirst, pSecond) { + // The collision normal is simply the difference between the two current positions + const lCollisionNormal = normalize2(subVec2(pFirst.position, pSecond.position)); + const lCollisionPoint = vec2( + ((pFirst.position.x * pSecond.radius) + (pSecond.position.x * pFirst.radius)) / (pFirst.radius + pSecond.radius), + ((pFirst.position.y * pSecond.radius) + (pSecond.position.y * pFirst.radius)) / (pFirst.radius + pSecond.radius) + ); + + return { + relativeVelocity: subVec2(pFirst.velocity, pSecond.velocity), + collisionNormal: lCollisionNormal, + //firstPointOfApplication: addVec2(scaleVec2(normalize2(pFirst.velocity), pFirst.radius), pFirst.position), + //secondPointOfApplication: addVec2(scaleVec2(normalize2(pSecond.velocity), pSecond.radius), pSecond.position) + firstPointOfApplication: subVec2(lCollisionPoint, pFirst.position), + secondPointOfApplication: subVec2(lCollisionPoint, pSecond.position) + } +} + +function freeCircle(pGl, pCircle) { + pGl.deleteBuffer(pCircle.buffer); +}
\ No newline at end of file |