summaryrefslogtreecommitdiff
path: root/frontend/2d/_collisions/collisions_1.js
blob: ac325c206cc0e40b858e3977e38ec16cf964fbf0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/// <reference path="../../scripts/jquery-3.5.1.min.js"/>
/// <reference path="../../_shared/math/vec2.js" />
/// <reference path="../../_shared/math/mat4.js" />
/// <reference path="../../_shared/2d/shader.js" />
/// <reference path="../../_shared/math/circle.js" />
/// <reference path="../../_shared/math/line2.js" />
/// <reference path="../../_shared/math/collision.js" />
/// <reference path="../../_shared/2d/program_common.js" />

(function() {

    function main() {
        // Define Constants
        const CIRCLE_RADIUS = 16;
        const GRAVITY = 9.8;
        const COF_OF_RESTITUITION = 0.7;
    
        // Retrieve context
        const lProgramContext = getContext('#collision_1');
    
        if (lProgramContext.gl === null) {
            console.error('Unable to initialize WebGL. Your browser or machine may not support it.');
            return;
        }
    
        lProgramContext.gl.clearColor(0.0, 0.0, 0.0, 1.0);
        lProgramContext.gl.clear(lProgramContext.gl.COLOR_BUFFER_BIT);
    
        function run() {
            console.log('Running Circle-Line Collisions');
            lProgramContext.load().then(function(pProgramInfo) {
                const mCircle = circle(lProgramContext.gl, CIRCLE_RADIUS, 30, [
                        { x: 1, y: 0, z: 0, w: 1 },
                        { x: 0, y: 1, z: 0, w: 1 },
                        { x: 0, y: 0, z: 1, w: 1 }
                    ], vec2(lProgramContext.width / 2.0, lProgramContext.height / 2.0 + 100));

                const mline = line2({ x: 100, y: 100 }, { x: lProgramContext.width - 100, y: 200 }, lProgramContext.gl,
                    { x: 1, y: 0, z: 0, w: 1 }, 2.0);
    
                /**
                 * Run the update method of a single circle
                 * 
                 * @param {circle} pCircle 
                 * @param {number} pDeltaTimeSeconds 
                 */
                function updateCircle(pCircle, pDeltaTimeSeconds) {
                    // Same physics updates from part 1
                    applyForce(pCircle, vec2(0, -1.0 * (pCircle.mass * GRAVITY)));
                    const lCurrentAcceleration = scaleVec2(pCircle.force, 1.0 / pCircle.mass);
                    pCircle.prevVelocity = pCircle.velocity;
                    pCircle.velocity = addVec2(pCircle.velocity, scaleVec2(lCurrentAcceleration, pDeltaTimeSeconds));
                    pCircle.prevPos = { ...pCircle.position };
                    pCircle.position = addVec2(pCircle.position, scaleVec2(pCircle.velocity, pDeltaTimeSeconds));
                    pCircle.force = vec2();
    
                    // Same physics updates from part 2
                    const lMomentOfInertia = getMomentOfInertia(pCircle);
                    const lAngularAcceleration = pCircle.torque / lMomentOfInertia;
                    pCircle.rotationVelocity += lAngularAcceleration * pDeltaTimeSeconds;
                    pCircle.rotationRadians += pCircle.rotationVelocity * pDeltaTimeSeconds;
                    pCircle.torque = 0;
    
                    pCircle.model = rotateMatrix2d(translateMatrix(mat4(), pCircle.position.x, pCircle.position.y, 0), pCircle.rotationRadians);
                }
    
                function update(pDeltaTimeSeconds) {
                    pDeltaTimeSeconds = pDeltaTimeSeconds;
                    updateCircle(mCircle, pDeltaTimeSeconds);
                    collision(pDeltaTimeSeconds);
                    render();
                }
    
                function collision(pDeltaTimeSeconds) {
                    lineCircleCollision2(mCircle, mline);
                    return false;
                }
    
                function render() {
                    lProgramContext.gl.clearColor(0.0, 0.0, 0.0, 1.0);
                    lProgramContext.gl.clearDepth(1.0);
                    lProgramContext.gl.enable(lProgramContext.gl.DEPTH_TEST);
                    lProgramContext.gl.depthFunc(lProgramContext.gl.LEQUAL);
                    lProgramContext.gl.clear(lProgramContext.gl.COLOR_BUFFER_BIT | lProgramContext.gl.DEPTH_BUFFER_BIT);
                    lProgramContext.gl.useProgram(pProgramInfo.program);
                    lProgramContext.gl.uniformMatrix4fv(pProgramInfo.uniformLocations.projection, false, lProgramContext.perspective);
    
                    renderCircle(lProgramContext.gl, pProgramInfo, mCircle);
                    renderLine2(lProgramContext.gl, pProgramInfo, mline);
                }
    
                const TORQUE_MULTIPLIER = 100.0; // TODO: This may be unncessary
                function applyForce(pCircle, pForceVector, pPointOfApplication) {
                    if (pPointOfApplication !== undefined) {
                        const lOriginToPointOfApp = subVec2(vec2(), pPointOfApplication),
                            lPerpVec = vec2(-lOriginToPointOfApp.y, lOriginToPointOfApp.x);
        
                            pCircle.torque += TORQUE_MULTIPLIER * dot2(lPerpVec, pForceVector);
                    }
    
                    pCircle.force = addVec2(pCircle.force, pForceVector);
                }
    
                function cleanup() {
                    lProgramContext.gl.deleteBuffer(mCircle.buffer);
                    lProgramContext.gl.deleteProgram(pProgramInfo.program);
                    lProgramContext.gl.clearColor(0.0, 0.0, 0.0, 1.0);
                    lProgramContext.gl.clear(lProgramContext.gl.COLOR_BUFFER_BIT);
                }
    
                function reset() {
                    lExitRequestFunc();
                    lProgramContext.reset();
                }
    
                const lExitRequestFunc = requestUpdateLoop(update, cleanup);
                lProgramContext.stopButton.on('click', reset);
            });
        }
        
        lProgramContext.playButton.on('click', run);
    }
    
    $(document).ready(main);
})()