<script src="https://cdn.jsdelivr.net/npm/p5@1.4.1/lib/p5.min.js"></script>

<style>
  html,
  body {
    margin: 0;
    padding: 0;
    overflow: hidden;
  }
</style>

<script>
  let angle = 0;
  let sides = [];
  let vertices = [];
  const len = 100;

  function setup() {
    createCanvas(windowWidth, windowHeight);
    angleMode(DEGREES);
    angleOne = createSlider(0, 89, 60);
    angleOne.position(10, 10);
    angleOne.style("width", "80px");
    angleTwo = createSlider(0, 89, 60);
    angleTwo.position(10, 30);
    angleTwo.style("width", "80px");
    rotateVel = createSlider(0, 360, 60);
    rotateVel.position(10, 50);
    rotateVel.style("width", "80px");
    iterations = createSlider(0, 20, 1);
    iterations.position(10, 70);
    iterations.style("width", "80px");
    let v1 = createVector(width / 2 - len / 2, height / 2);
    let v2 = createVector(width / 2 + len / 2, height / 2);
    sides[0] = new Side(v1.x, v1.y, v2.x, v2.y, "green");
    vertices[0] = new Vertex(v1.x, v1.y);
    vertices[1] = new Vertex(v2.x, v2.y);
  }

  function draw() {
    background(255);
    let angOne = angleOne.value();
    let angTwo = angleTwo.value();
    let rotVel = rotateVel.value();
    let numIter = iterations.value();
    fill(0);
    strokeWeight(0);
    textSize(15);
    text(angOne, 100, 25);
    text(angTwo, 100, 45);
    text(rotVel, 100, 65);
    text(numIter, 100, 85);
    let v2Offset = createVector(len * cos(-angOne), len * sin(-angOne));
    let v3Offset = createVector(-len * cos(angTwo), -len * sin(angTwo));
    vertices[2] = new Vertex(
      vertices[0].a.x + v2Offset.x,
      vertices[0].a.y + v2Offset.y
    );
    vertices[3] = new Vertex(
      vertices[1].a.x + v3Offset.x,
      vertices[1].a.y + v3Offset.y
    );
    // Update the sides
    sides[1] = new Side(
      vertices[0].a.x,
      vertices[0].a.y,
      vertices[2].a.x,
      vertices[2].a.y
    );
    sides[3] = new Side(
      vertices[1].a.x,
      vertices[1].a.y,
      vertices[3].a.x,
      vertices[3].a.y
    );
    const m1 =
      (vertices[2].a.y - vertices[0].a.y) / (vertices[2].a.x - vertices[0].a.x);
    const m2 =
      (vertices[3].a.y - vertices[1].a.y) / (vertices[3].a.x - vertices[1].a.x);
    const b2 = (vertices[1].a.x - vertices[0].a.x) * -m2;
    const xInt = b2 / (m1 - m2);
    const yInt = xInt * m1;
    point(vertices[0].a.x + xInt, vertices[0].a.y + yInt);
    vertices[4] = new Vertex(vertices[0].a.x + xInt, vertices[0].a.y + yInt);
    sides[4] = new Side(
      vertices[1].a.x,
      vertices[1].a.y,
      vertices[0].a.x + xInt,
      vertices[0].a.y + yInt,
      "blue"
    );
    sides[5] = new Side(
      vertices[0].a.x,
      vertices[0].a.y,
      vertices[0].a.x + xInt,
      vertices[0].a.y + yInt,
      "purple"
    );
    scale(4); // so I can make the triangle actually *visible*
    translate(-width / 3, -height / 3);
    sides[0].show();
    sides[4].show();
    sides[5].show();
    vertices[0].show();
    vertices[1].show();
    vertices[4].show();
    strokeWeight(1);
    stroke(255, 0, 0);
    noFill();
    arc(vertices[0].a.x, vertices[0].a.y, 40, 40, -1 * angleOne.value(), 0, PIE);
    arc(
      vertices[1].a.x,
      vertices[1].a.y,
      40,
      40,
      -180,
      -(180 - angleTwo.value()),
      PIE
    );
    stroke(255, 195, 0);
    strokeWeight(5);
    let P1x = vertices[0].a.x;
    let P1y = vertices[0].a.y;
    let P0 = createVector(P1x + 60, P1y - 40);
    push();
    let V0 = createVector(10 * cos(rotVel), 10 * sin(-rotVel));
    pop();
    point(P0.x, P0.y);
    strokeWeight(2);
    line(P0.x, P0.y, P0.x + V0.x, P0.y + V0.y);
    let hit = wallHit(P0, V0);
    // print("hit[0] is", hit[0]);
    hitPoint = createVector(P0.x + V0.x * hit[0], P0.y + V0.y * hit[0]);
    let A = createVector(
      vertices[4].a.x - vertices[1].a.x,
      vertices[4].a.y - vertices[1].a.y
    );
    stroke(0);
    let IOne = createVector(0, 0);
    let ITwo = createVector(0, 0);
    let IThree = createVector(0, 0);
    let AOne = createVector(P1x, P1y);
    let ATwo = createVector(vertices[1].a.x, vertices[1].a.y + 0.1);
    let AThree = createVector(
      (P1x + vertices[1].a.x) / 2,
      (P1y + vertices[1].a.y) / 2
    );
    let BOne = createVector(P1x, P1y);
    let BTwo = createVector(vertices[4].a.x, vertices[4].a.y + 0.1);
    let BThree = createVector(
      (P1x + vertices[4].a.x) / 2,
      (P1y + vertices[4].a.y) / 2
    );
    let COne = createVector(vertices[1].a.x, vertices[1].a.y);
    let CTwo = createVector(vertices[4].a.x, vertices[4].a.y + 0.1);
    let CThree = createVector(
      (vertices[1].a.x + vertices[4].a.x) / 2,
      (vertices[1].a.y + vertices[4].a.y) / 2
    );
    let inVec = createVector(hitPoint.x - P0.x, hitPoint.y - P0.y);
    let perp = getPerp(IOne, ITwo, IThree);
    let testOne = createVector(vertices[0].a.x + 20, vertices[0].a.y + 20);
    let testTwo = createVector(vertices[1].a.x + 20, vertices[1].a.y + 20);
    let refVec = testOne.reflect(testTwo);
    if (hit[1] == "t3") {
      perp = getPerp(AOne, ATwo, hitPoint);
      let n = createVector(AOne.y - ATwo.y, ATwo.x - AOne.x);
      refVec = inVec.reflect(n);
    } else if (hit[1] == "t1") {
      perp = getPerp(BOne, BTwo, hitPoint);
      let n = createVector(BOne.y - BTwo.y, BTwo.x - BOne.x);
      refVec = inVec.reflect(n);
    } else {
      perp = getPerp(COne, CTwo, hitPoint);
      let n = createVector(COne.y - CTwo.y, CTwo.x - COne.x);
      refVec = inVec.reflect(n);
    }
    stroke("black");
    line(hitPoint.x, hitPoint.y, hitPoint.x + refVec.x, hitPoint.y + refVec.y);
    line(P0.x, P0.y, hitPoint.x, hitPoint.y);
    let P0s = [];
    let V0s = [];
    let hits = [];
    let hitPoints = [hitPoint];
    let refs = [refVec];
    let inVecs = [];
    for (let i = 0; i < numIter; i++) {
      P0s.push(createVector(hitPoints[i].x, hitPoints[i].y));
      V0s.push(createVector(refs[i].x, refs[i].y));
      hits.push(wallHit(P0s[i], V0s[i]));
      hitPoints.push(createVector(P0s[i].x + V0s[i].x * hits[i][0], P0s[i].y + V0s[i].y * hits[i][0]));
      inVecs.push(createVector(hitPoints[i + 1].x - P0s[i].x, hitPoints[i + 1].y - P0s[i].y));
      // print(hits[0][1]);
      if (hits[i][1] == "t3") {
        perp2 = getPerp(AOne, ATwo, hitPoints[i + 1]);
        let n2 = createVector(AOne.y - ATwo.y, ATwo.x - AOne.x);
        refs.push(inVecs[i].reflect(n2));
      } else if (hits[i][1] == "t1") {
        perp2 = getPerp(BOne, BTwo, hitPoints[i + 1]);
        let n2 = createVector(BOne.y - BTwo.y, BTwo.x - BOne.x);
        refs.push(inVecs[i].reflect(n2));
      } else {
        perp2 = getPerp(COne, CTwo, hitPoints[i + 1]);
        let n2 = createVector(COne.y - CTwo.y, CTwo.x - COne.x);
        refs.push(inVecs[i].reflect(n2));
      }
      stroke("black");
      // line(hitPoint2.x, hitPoint2.y, hitPoint2.x + refVec2.x, hitPoint2.y + refVec2.y);
      // line(hitPoints[i+1].x, hitPoints[i+1].y, hitPoints[i+1].x + refs[i+1].x, hitPoints[i+1].y + refs[i+1].y);
      line(P0s[i].x, P0s[i].y, hitPoints[i + 1].x, hitPoints[i + 1].y);
    }
    //
    // let P02 = createVector(hitPoint.x, hitPoint.y);
    // let V02 = createVector(refVec.x, refVec.y);
    // let hit2 = wallHit(P02, V02);
    // hitPoint2 = createVector(P02.x + V02.x * hit2[0], P02.y + V02.y * hit2[0]);
    //
    // let inVec2 = createVector(hitPoint2.x - P02.x, hitPoint2.y - P02.y);
    // print("inVecs[0]:", inVecs[0], "inVec2:", inVec2);
    // // print(hitPoints[0].x)
    //
    // if (hit2[1] == "t3") {
    //  perp2 = getPerp(AOne, ATwo, hitPoint2);
    //  let n2 = createVector(AOne.y - ATwo.y, ATwo.x - AOne.x);
    //  refVec2 = inVec2.reflect(n2);
    // } else if (hit2[1] == "t1") {
    //  perp2 = getPerp(BOne, BTwo, hitPoint2);
    //  let n2 = createVector(BOne.y - BTwo.y, BTwo.x - BOne.x);
    //  refVec2 = inVec2.reflect(n2);
    // } else {
    //  perp2 = getPerp(COne, CTwo, hitPoint2);
    //  let n2 = createVector(COne.y - CTwo.y, CTwo.x - COne.x);
    //  refVec2 = inVec2.reflect(n2);
    // }
    //
    // stroke("black");
    // line(hitPoint2.x, hitPoint2.y, hitPoint2.x + refVec2.x, hitPoint2.y + refVec2.y);
    // line(P02.x, P02.y, hitPoint2.x, hitPoint2.y);
  }
  class Side {
    constructor(x1, y1, x2, y2, col = "black") {
      this.a = createVector(x1, y1);
      this.b = createVector(x2, y2);
      this.color = col;
    }
    show() {
      stroke(this.color);
      strokeWeight(4);
      line(this.a.x, this.a.y, this.b.x, this.b.y);
    }
  }
  class Vertex {
    constructor(x1, y1) {
      this.a = createVector(x1, y1);
    }
    show() {
      stroke(255, 0, 0);
      strokeWeight(10);
      point(this.a.x, this.a.y);
    }
  }

  function wallHit(pos, vel) {
    let P1x = vertices[0].a.x;
    let P1y = vertices[0].a.y;
    let P2x = vertices[1].a.x;
    let P2y = vertices[1].a.y;
    let P3x = vertices[4].a.x;
    let P3y = vertices[4].a.y;
    let A1 = P3y - P1y;
    let B1 = -(P3x - P1x);
    let C1 = A1 * P1x + B1 * P1y;
    let A2 = -(P3y - P2y);
    let B2 = P3x - P2x;
    let C2 = A2 * P2x + B2 * P2y;
    let A3 = -(P2y - P1y);
    let B3 = P2x - P1x;
    let C3 = A3 * P2x + B3 * P2y;
    let t1 = (C1 - A1 * pos.x - B1 * pos.y) / (A1 * vel.x + B1 * vel.y);
    let t2 = (C2 - A2 * pos.x - B2 * pos.y) / (A2 * vel.x + B2 * vel.y);
    let t3 = (C3 - A3 * pos.x - B3 * pos.y) / (A3 * vel.x + B3 * vel.y);
    let times = [t1, t2, t3];
    let posTimes = [];
    for (let i = 0; i < times.length; i++) {
      times[i] = round(times[i], 2);
    }
    // console.log("After rounding:", times);
    for (let i = 0; i < times.length; i++) {
      if (times[i] > 0) {
        posTimes.push(times[i]);
      }
    }
    let hitPoint = createVector(0, 1);
    // console.log("posTimes:", posTimes);
    trueTime = min(posTimes);
    if (trueTime == round(t1, 2)) {
      // print("Hit Purple");
      return [t1, "t1"];
      // hitPoint = createVector(P0.x + V0.x * t1, P0.y + V0.y * t1);
      // line(P0.x, P0.y, hitPoint.x, hitPoint.y);
    } else if (trueTime == round(t2, 2)) {
      // print("Hit Blue");
      return [t2, "t2"];
      // hitPoint = createVector(P0.x + V0.x * t2, P0.y + V0.y * t2);
      // line(P0.x, P0.y, hitPoint.x, hitPoint.y);
    } else {
      // print("Hit Green");
      return [t3, "t3"];
      // hitPoint = createVector(P0.x + V0.x * t3, P0.y + V0.y * t3);
      // line(P0.x, P0.y, hitPoint.x, hitPoint.y);
    }
  }

  function findNormal(pos, wall) {
    let perpVector = createVector(-wall.y, wall.x);
    strokeWeight(2);
    stroke(0);
    line(pos.x, pos.y, perpVector.x, perpVector.y);
    // line(P0.x, P0.y, hitPoint.x, hitPoint.y);
  }

  function getY(x, HP) {
    let perpY = -((vertices[4].a.x - vertices[1].a.x) / (vertices[4].a.y - vertices[1].a.y)) *
      x +
      (HP.y +
        ((vertices[4].a.x - vertices[1].a.x) / (vertices[4].a.y - vertices[1].a.y)) *
        HP.x);
    return perpY;
  }

  function getPerp(p1, p2, p3) {
    x1 = p1.x;
    y1 = p1.y;
    x2 = p2.x;
    y2 = p2.y;
    x3 = p3.x;
    y3 = p3.y;
    stroke(0);
    strokeWeight(2);
    line1 = line(x1, y1, x2, y2);
    m1 = (y2 - y1) / (x2 - x1);
    m2 = -1 / m1;
    b2 = y3 - x3 * m2;
    stroke(255, 0, 0);
    line(x3, m2 * x3 + b2, x1, m2 * x1 + b2);
    let final = createVector(m2 * x1 + b2 - (m2 * x3 + b2), x1 - x3);
    return final;
  }
</script>

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.