diff --git a/javascript/PhysicsEngine/Polygon.js b/javascript/PhysicsEngine/Polygon.js new file mode 100644 index 0000000..3f02433 --- /dev/null +++ b/javascript/PhysicsEngine/Polygon.js @@ -0,0 +1,30 @@ +import {Vector2} from "./Vector2.js" + +export class Face { + constructor(from, to) { + this.from = from.clone() + this.to = to.clone() + + let delta = to.clone().subtract(from).normal() + this.normal = new Vector2(-delta.y, delta.x) + } + + center() { + let delta = this.to.clone().subtract(this.from).normal() + return this.from.clone().add(delta.scale(delta.magnitude() / 2)) + } +} + +export class Polygon { + constructor(points) { + console.log(points) + this.points = points; + this.sides = []; + for (let i = 0; i < points.length - 1; i++) { + this.sides.push(new Face(points[i], points[i + 1])) + console.log(this.sides[i].center()) + console.log(this.sides[i].from) + } + this.sides.push(new Face(points[points.length-1], points[0])) + } +} \ No newline at end of file diff --git a/javascript/PhysicsEngine/Vector2.js b/javascript/PhysicsEngine/Vector2.js new file mode 100644 index 0000000..49ffa95 --- /dev/null +++ b/javascript/PhysicsEngine/Vector2.js @@ -0,0 +1,59 @@ +export class Vector2 { + constructor(x, y) { + this.x = x; + this.y = y; + } + + normal() { + let mag = this.magnitude() + return new Vector2(this.x / mag, this.y / mag); + } + + magnitude() { + return Math.sqrt(this.x*this.x + this.y*this.y); + } + + add(vector) { + this.x += vector.x; + this.y += vector.y; + return this; + } + + subtract(vector) { + this.x -= vector.x; + this.y -= vector.y; + return this; + } + + multiply(vector) { + this.x *= vector.x; + this.y *= vector.y; + return this; + + } + + divide(vector) { + this.x /= vector.x; + this.y /= vector.y; + return this; + + } + + scale(scalar) { + this.x *= scalar; + this.y *= scalar; + return this; + } + + clone() { + return new Vector2(this.x, this.y) + } + + dot(vector) { + return this.x*vector.x + this.y*vector.y + } + + cross(vector) { + return this.x * vector.y - this.y * vector.x + } +} \ No newline at end of file diff --git a/javascript/PhysicsEngine/index.html b/javascript/PhysicsEngine/index.html new file mode 100644 index 0000000..cf3ee7a --- /dev/null +++ b/javascript/PhysicsEngine/index.html @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javascript/PhysicsEngine/main.js b/javascript/PhysicsEngine/main.js new file mode 100644 index 0000000..43f9d14 --- /dev/null +++ b/javascript/PhysicsEngine/main.js @@ -0,0 +1,14 @@ +import { Vector2 } from "./Vector2.js"; +import * as polyModule from "./Polygon.js" + +let newPoly = new polyModule.Polygon([ + new Vector2(-1, 1), + new Vector2(1, 1), + new Vector2(1, -1), + new Vector2(-1, -1) +]) + +console.log(newPoly) + +let vector = new Vector2(1, 1); +let vector2 = new Vector2(5, 3) diff --git a/javascript/polygonCollision/script.js b/javascript/polygonCollision/script.js index 75df64b..895b945 100644 --- a/javascript/polygonCollision/script.js +++ b/javascript/polygonCollision/script.js @@ -127,17 +127,7 @@ class Box { let axis2Mag = Math.sqrt(axis2.x * axis2.x + axis2.y * axis2.y) axis2.x = axis2.x / axis2Mag axis2.y = axis2.y / axis2Mag - - // let axis3 = { x: points[3].x - points[2].x, y: points[3].y - points[2].y } - // let axis3Mag = Math.sqrt(axis3.x * axis3.x + axis3.y * axis3.y) - // axis3.x = axis3.x / axis3Mag - // axis3.y = axis3.y / axis3Mag - - // let axis4 = { x: points[0].x - points[3].x, y: points[0].y - points[3].y } - // let axis4Mag = Math.sqrt(axis4.x * axis4.x + axis4.y * axis4.y) - // axis4.x = axis4.x / axis4Mag - // axis4.y = axis4.y / axis4Mag - return [axis1, axis2]//, axis3, axis4] + return [axis1, axis2] } toWorldSpace(x, y) { @@ -159,10 +149,22 @@ class Box { return [tl, tr, br, bl] } + getFaces() { + let faces = [] + let coords = this.getWorldCoordinates() + coords.array.forEach(element, index, array => { + if (index < array.length - 1) { + faces.push({element - array[index + 1], 1}) + } else { + faces.push() + } + }); + } + render(ctx) { ctx.fillStyle = this.color ctx.fillRect(this.x - 1.5, this.y - 1.5, 3, 3) - +ls`` let coords = this.getWorldCoordinates() ctx.strokeStyle = this.color @@ -196,6 +198,10 @@ function round(value, decimals) { return Number(Math.round(value + 'e' + decimals) + 'e-' + decimals); } +function getPointsBelow() { + +} + function getCollidingPoint(box1, box2, normal) { let mag = Math.sqrt((box2.x - box1.x) ** 2 + (box2.y - box1.y) ** 2) let delta = { x: (box2.x - box1.x) / mag, y: (box2.y - box1.y) / mag } @@ -268,46 +274,18 @@ function projectVectorToLine(x, y, lx, ly) { return { x: projX, y: projY } } -function projectToAxis(axisX, axisY, box, color) { - let axis = { x: axisX, y: axisY } - let axisMag = Math.sqrt(axis.x * axis.x + axis.y * axis.y) - axis = { x: axis.x / axisMag, y: axis.y / axisMag } - let boxProj = box.getProjection(axis.x, axis.y) - - if (color != undefined) { - // ctx.fillStyle = color - // ctx.fillRect(axis.x * boxProj.max - 2.5, axis.y * boxProj.max - 2.5, 5, 5) - // ctx.fillRect(axis.x * boxProj.min - 2.5, axis.y * boxProj.min - 2.5, 5, 5) - // ctx.strokeStyle = color - // ctx.beginPath() - // ctx.moveTo(axis.x * boxProj.max, axis.y * boxProj.max) - // ctx.lineTo(boxProj.maxPoint.x, boxProj.maxPoint.y) - // ctx.stroke() - // ctx.beginPath() - // ctx.moveTo(axis.x * boxProj.min, axis.y * boxProj.min) - // ctx.lineTo(boxProj.minPoint.x, boxProj.minPoint.y) - // ctx.stroke() - } - return boxProj -} - function testBoxCollision(box1, box2) { - let satAxis = box1.getCollisionAxis() - let satAxis2 = box2.getCollisionAxis() - satAxis = satAxis.concat(box2.getCollisionAxis()) + let satAxisBox1 = box1.getCollisionAxis() + let satAxisBox2 = box2.getCollisionAxis() var colliding = true let mvt = Number.MAX_VALUE let normal = undefined + let satShape = undefined // true: box1, false: box2 - // ctx.strokeStyle = "rgb(0,255,0)" - - for (axis of satAxis) { - // ctx.moveTo(width / 2, height / 2) - // ctx.lineTo(width / 2 + 50 * axis.x, height / 2 + 50 * axis.y) - - let box1Proj = projectToAxis(axis.x, axis.y, box1) - let box2Proj = projectToAxis(axis.x, axis.y, box2) + for (axis of satAxisBox1) { + let box1Proj = box1.getProjection(axis.x, axis.y) + let box2Proj = box2.getProjection(axis.x, axis.y) let overlap = testProjectionOverlap(box1Proj, box2Proj) @@ -316,37 +294,39 @@ function testBoxCollision(box1, box2) { } else if (overlap < mvt) { mvt = overlap normal = axis + satShape = true } + } - // ctx.fillStyle = box1.color - // ctx.fillRect(box1Proj.max * axis.x / 2 + width / 2 - 1.5, box1Proj.max * axis.y / 2 + height / 2 - 1.5, 3, 3) - // ctx.fillRect(box1Proj.min * axis.x / 2 + width / 2 - 1.5, box1Proj.min * axis.y / 2 + height / 2 - 1.5, 3, 3) + for (axis of satAxisBox2) { + let box1Proj = box1.getProjection(axis.x, axis.y) + let box2Proj = box2.getProjection(axis.x, axis.y) - // ctx.fillStyle = box2.color - // ctx.fillRect(box2Proj.max * axis.x / 2 + width / 2 - 1.5, box2Proj.max * axis.y / 2 + height / 2 - 1.5, 3, 3) - // ctx.fillRect(box2Proj.min * axis.x / 2 + width / 2 - 1.5, box2Proj.min * axis.y / 2 + height / 2 - 1.5, 3, 3) + let overlap = testProjectionOverlap(box1Proj, box2Proj) + if (!overlap) { + colliding = false + } else if (overlap < mvt) { + mvt = overlap + normal = axis + satShape = false + } } - // ctx.stroke() - if (colliding) { - // box2.color = "rgb(255,0,255)" let dot = normal.x * (box2.x - box1.x) + normal.y * (box2.y - box1.y) - // ctx.beginPath() - // ctx.strokeStyle = "rgb(0,0,255)" - // ctx.moveTo(width / 2, height / 2) - // ctx.lineTo(width / 2 + 50 * normal.x, height / 2 + 50 * normal.y) - - // ctx.moveTo(box1.x, box1.y) - // ctx.lineTo(box1.x + normal.x * mvt, box1.y + normal.y * mvt) - if (dot < 0) { normal.x = -normal.x normal.y = -normal.y } + if (satShape) { //axis is from box1 + for + } else { //axis is from box2 + + } + ctx.beginPath() ctx.strokeStyle = "rgb(255,0,0)" ctx.moveTo(box1.x, box1.y) @@ -365,7 +345,7 @@ function testBoxCollision(box1, box2) { // ctx.stroke() - return { colliding: true, mtx: mvt, normal: normal } + return { colliding: true, mtx: mvt, normal: normal, incidentFace: {} } } else { box2.color = "rgb(255,255,255)" return { colliding: false } @@ -518,8 +498,8 @@ function loop(t) { closestBox.dy = mouseDelta.y * 50 } - for (let c = 0; c < 8; c++) { - let cdt = dt / 8 + for (let c = 0; c < 1; c++) { + let cdt = dt / 1 calculatePhysics(cdt) for (let i = 0; i < boxes.length; i++) { @@ -554,38 +534,38 @@ function loop(t) { function startup() { console.log("Starting simulation") - let newBox = new Box( - Math.random() * width, - Math.random() * height, - 25 + Math.random() * 55, - 25 + Math.random() * 55, - 360 * Math.random(), - 150 - Math.random() * 300, - 150 - Math.random() * 300, - 150 - Math.random() * 300) - - newBox.m = 0 - newBox.anchored = true - - boxes.push(newBox) - - for (let i = 0; i < 35; i++) { - boxes.push(new Box( - Math.random() * width, - Math.random() * height, - 25 + Math.random() * 55, - 25 + Math.random() * 55, - 360 * Math.random(), - 150 - Math.random() * 300, - 150 - Math.random() * 300, - 150 - Math.random() * 300)) - } - - // let boxa = new Box(width / 2, height / 2, 1000, 50, 0) - // boxa.anchored = true - // let boxb = new Box(width / 2, height / 2, 50, 50, 0) - - // boxes.push(boxa, boxb) + // let newBox = new Box( + // Math.random() * width, + // Math.random() * height, + // 25 + Math.random() * 55, + // 25 + Math.random() * 55, + // 360 * Math.random(), + // 150 - Math.random() * 300, + // 150 - Math.random() * 300, + // 150 - Math.random() * 300) + + // newBox.m = 0 + // newBox.anchored = true + + // boxes.push(newBox) + + // for (let i = 0; i < 35; i++) { + // boxes.push(new Box( + // Math.random() * width, + // Math.random() * height, + // 25 + Math.random() * 55, + // 25 + Math.random() * 55, + // 360 * Math.random(), + // 150 - Math.random() * 300, + // 150 - Math.random() * 300, + // 150 - Math.random() * 300)) + // } + + let boxa = new Box(width / 2, height / 2, 500, 50, 0) + boxa.anchored = true + let boxb = new Box(width / 2, height / 2, 50, 50, 0) + + boxes.push(boxa, boxb) window.requestAnimationFrame(loop) }