From a315509189073cdaf4172bcfd4e4a54e5c8c87eb Mon Sep 17 00:00:00 2001 From: Matthew Kosarek Date: Tue, 2 Mar 2021 20:03:02 -0500 Subject: Updated stylings and very nearly have square collisions complete and proper --- frontend/2d/_collisions/circle_line.js | 3 +- frontend/2d/_collisions/rectangle_line.js | 105 ++++++++++++++++++++++++++++-- 2 files changed, 102 insertions(+), 6 deletions(-) (limited to 'frontend/2d') diff --git a/frontend/2d/_collisions/circle_line.js b/frontend/2d/_collisions/circle_line.js index e5898f0..0736e2c 100644 --- a/frontend/2d/_collisions/circle_line.js +++ b/frontend/2d/_collisions/circle_line.js @@ -125,7 +125,8 @@ circleObject.position = lSubdividedCircle.position; circleObject.velocity = addVec2(lSubdividedCircle.velocity, scaleVec2(lCollisionNormal, lImpulseMagnitude / circleObject.mass)); - circleObject.rotationVelocity = lSubdividedCircle.rotationVelocity + dot2(lFirstPerp, scaleVec2(lCollisionNormal, lImpulseMagnitude)); + circleObject.rotationVelocity = lSubdividedCircle.rotationVelocity + + dot2(lFirstPerp, scaleVec2(lCollisionNormal, lImpulseMagnitude)) / getCircleMomentOfInertia(circleObject); updateCircle(circleObject, pDeltaTimeSeconds - lSubdividedDeltaTime); diff --git a/frontend/2d/_collisions/rectangle_line.js b/frontend/2d/_collisions/rectangle_line.js index ac73f71..dec5108 100644 --- a/frontend/2d/_collisions/rectangle_line.js +++ b/frontend/2d/_collisions/rectangle_line.js @@ -34,7 +34,8 @@ rectangleObject = rectangle(programContext.gl, { width: 50, - height: 25, + height: 50, + mass: 1, color: { x: 0.3, y: 0.5, z: 0.1, w: 0.7 }, position: vec2(programContext.width / 2.0 - 100, programContext.height / 2.0 + 100) }); @@ -43,16 +44,16 @@ lineObjectList = []; lineObjectList.push(line2({ x: 100, y: 100 }, { x: programContext.width - 100, y: 200 }, programContext.gl, - { x: 1, y: 0, z: 0, w: 1 }, 2.0)); + { x: 1, y: 0, z: 0, w: 1 }, 10000000.0)); lineObjectList.push(line2({ x: 100, y: 200 }, { x: programContext.width - 100, y: 100 }, programContext.gl, - { x: 1, y: 1, z: 0, w: 1 }, 2.0)); + { x: 1, y: 1, z: 0, w: 1 }, 10000000.0)); lineObjectList.push(line2({ x: 100, y: 0 }, { x: 100, y: programContext.height }, programContext.gl, - { x: 0, y: 1, z: 0, w: 1 }, 2.0)); + { x: 0, y: 1, z: 0, w: 1 }, 10000000.0)); lineObjectList.push(line2({ x: programContext.width - 100, y: 0 }, { x: programContext.width - 100, y: programContext.height }, programContext.gl, - { x: 0, y: 1, z: 0, w: 1 }, 2.0)); + { x: 0, y: 1, z: 0, w: 1 }, 10000000.0)); exitRequestFunc = requestUpdateLoop(update, cleanup); @@ -68,7 +69,101 @@ } function collision(pDeltaTimeSeconds) { + for (var lineIdx = 0; lineIdx < lineObjectList.length; lineIdx++) { + var lLine = lineObjectList[lineIdx]; + + if (areIntersecting(rectangleObject, lLine, pDeltaTimeSeconds)) { + break; + } + } + } + + function doesPointIntersect(pPoint, pLine) { + const EPSILON = 0.98; + return distanceFromPoint2ToLine2(pPoint, pLine) <= EPSILON; + } + + function getIntersectionInformation(pRectangle, pCollisionPoint, pLine) { + var lCollisionNormal = pLine.normal, + lRectCollisionPoint_WorldCoords = multMat4ByVec2(pRectangle.model, pCollisionPoint), + lRectPosition = pRectangle.position, + lTrueRectCollisionPoint = normalize2(subVec2(lRectPosition, lRectCollisionPoint_WorldCoords)); + + console.log(lTrueRectCollisionPoint); + + return { + relativeVelocity: subVec2(pRectangle.velocity, pLine.velocity), + collisionNormal: lCollisionNormal, + rectangleCollisionPoint: lTrueRectCollisionPoint + } + } + + function areIntersecting(pRectangle, pLine, pDeltaTimeSeconds) { + var lCollisionPoint = undefined, + lCheckCollision = function(pRectangle) { + var lLowerLeft = multMat4ByVec2(pRectangle.model, vec2(-pRectangle.width / 2.0, -pRectangle.height / 2.0)), + lUpperLeft = multMat4ByVec2(pRectangle.model, vec2(-pRectangle.width / 2.0, pRectangle.height / 2.0)), + lUpperRight = multMat4ByVec2(pRectangle.model, vec2(pRectangle.width / 2.0, pRectangle.height / 2.0)), + lLowerRight = multMat4ByVec2(pRectangle.model, vec2(pRectangle.width / 2.0, -pRectangle.height / 2.0)); + + if (doesPointIntersect(lLowerLeft, pLine)) { + console.log('Lwer left'); + lCollisionPoint = vec2(-pRectangle.width / 2.0, -pRectangle.height / 2.0); + return true; + } else if (doesPointIntersect(lUpperLeft, pLine)) { + console.log('Upper left'); + lCollisionPoint = vec2(-pRectangle.width / 2.0, pRectangle.height / 2.0); + return true; + } else if (doesPointIntersect(lUpperRight, pLine)) { + console.log('Upepr right'); + lCollisionPoint = vec2(pRectangle.width / 2.0, pRectangle.height / 2.0); + return true; + } else if (doesPointIntersect(lLowerRight, pLine)) { + console.log('Lower right'); + lCollisionPoint = vec2(pRectangle.width / 2.0, -pRectangle.height / 2.0); + return true; + } + + return false; + }; + + if (!lCheckCollision(pRectangle)) { + return; + } + + // Subdivide until we find the exact moment where we intersected + var lSubdividedDeltaTime = pDeltaTimeSeconds, + lSubRectangle = undefined; + do { + lSubRectangle = JSON.parse(JSON.stringify(pRectangle)); + lSubRectangle.position = {...pRectangle.prevPos}; + lSubRectangle.velocity = {...pRectangle.prevVelocity}; + lSubRectangle.getMomentOfInertia = pRectangle.getMomentOfInertia; + lSubdividedDeltaTime = lSubdividedDeltaTime / 2.0; + updateRigidBody2(lSubRectangle, lSubdividedDeltaTime); + if (lSubdividedDeltaTime === 0) { + console.error('This should NOT be happening'); + break; + } + } while (lCheckCollision(lSubRectangle)); + var lIntersectionResult = getIntersectionInformation(lSubRectangle, lCollisionPoint, pLine), + lRelativeVelocity = lIntersectionResult.relativeVelocity, + lCollisionNormal = lIntersectionResult.collisionNormal, + lRectPerp = getPerp2(lIntersectionResult.rectangleCollisionPoint); + + const lNumerator = dot2(scaleVec2(lRelativeVelocity, -(1.0 + 1.0)), lCollisionNormal); + const lLinearDenomPart = dot2(lCollisionNormal, (scaleVec2(lCollisionNormal, 1.0 / pRectangle.mass))); + const lRotationalDenomPart = (Math.pow(dot2(lRectPerp, lCollisionNormal), 2) / pRectangle.getMomentOfInertia()); + + const lImpulseMagnitude = lNumerator / (lLinearDenomPart + lRotationalDenomPart); + + pRectangle.position = lSubRectangle.position; + pRectangle.velocity = addVec2(lSubRectangle.velocity, scaleVec2(lCollisionNormal, lImpulseMagnitude / pRectangle.mass)); + pRectangle.rotationVelocity = lSubRectangle.rotationVelocity + dot2(lRectPerp, scaleVec2(lCollisionNormal, lImpulseMagnitude)) / pRectangle.getMomentOfInertia(); + + updateRigidBody2(pRectangle, pDeltaTimeSeconds - lSubdividedDeltaTime); + return true; } function render() { -- cgit v1.2.1