summaryrefslogtreecommitdiff
path: root/frontend/2d/_rigidbody/rigidbody_1.js
blob: e49c7c9e2c2dfb2712a4d92b900007b741648128 (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
/// <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/2d/program_common.js" />

(function() {

    function main() {
        // Define Constants
        const CIRCLE_RADIUS = 16;
        const GRAVITY = 9.8;
    
        // Retrieve context
        const lProgramContext = getContext('#rigidbody_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 Rigid Body 1');
            lProgramContext.load().then(function(pProgramInfo) {
                const lCircle = circle(lProgramContext.gl, CIRCLE_RADIUS, 30, [{ x: 0.3, y: 0.3, z: 0.3, w: 1 }], vec2(lProgramContext.width / 2.0, lProgramContext.height / 2.0));
                
                function update(pDeltaTimeSeconds) {
                    // Physics updates
                    const lGravityForce = vec2(0, -1.0 * (lCircle.mass * GRAVITY));
    
                    // Add up the forces acting on the circle
                    lCircle.force = addVec2(lCircle.force, lGravityForce);
    
                    // Figure out acceleration (a = F / m)
                    const lCurrentAcceleration = scaleVec2(lCircle.force, 1.0 / lCircle.mass);
    
                    // Calculate the new velocity: v = v0 + a * t
                    lCircle.velocity = addVec2(lCircle.velocity, scaleVec2(lCurrentAcceleration, pDeltaTimeSeconds));
    
                    // Update the position based on velocity: x = x0 + v * t
                    lCircle.position = addVec2(lCircle.position, scaleVec2(lCircle.velocity, pDeltaTimeSeconds));
    
                    // Update the model matrix accordingly
                    lCircle.model = translateMatrix(mat4(), lCircle.position.x, lCircle.position.y, 0);
    
                    // Report the current state to the frontend
                    $('#rigidbody_1_force_field').text(vec2str(lCircle.force));
                    $('#rigidbody_1_acceleration_field').text(vec2str(lCurrentAcceleration));
                    $('#rigidbody_1_velocity_field').text(vec2str(lCircle.velocity));
                    $('#rigidbody_1_position_field').text(vec2str(lCircle.position));
    
                    // Reset the circle's force vector
                    lCircle.force = vec2();
    
                    // Render Code only
                    lProgramContext.gl.clearColor(0.0, 0.0, 0.0, 1.0);  // Clear to black, fully opaque
                    lProgramContext.gl.clearDepth(1.0);                 // Clear everything
                    lProgramContext.gl.enable(lProgramContext.gl.DEPTH_TEST);           // Enable depth testing
                    lProgramContext.gl.depthFunc(lProgramContext.gl.LEQUAL);            // Near things obscure far things
                    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);
                    lProgramContext.gl.uniformMatrix4fv(pProgramInfo.uniformLocations.model, false, lCircle.model);
    
                    renderCircle(lProgramContext.gl, pProgramInfo, lCircle);
                }
    
                function addForce(ev) {
                    ev.preventDefault();
                    ev.stopPropagation();
    
                    let lXValue = $(this).find('.vec2_x_input').val(),
                        lYValue = $(this).find('.vec2_y_input').val();
    
                    if (lXValue.length === 0) {
                        lXValue = 0;
                    }
    
                    if (lYValue.length === 0) {
                        lYValue = 5000;
                    }
    
                    console.log('Applying force: ' + lXValue + ', ' + lYValue);
                    lCircle.force = addVec2(lCircle.force, vec2(Number(lXValue), Number(lYValue)));
                }
    
                function cleanup() {
                    lProgramContext.gl.deleteBuffer(lCircle.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();
                    $('#rigidbody_1_force_submit_button').unbind('submit').submit(false);
                }
    
                const lExitRequestFunc = requestUpdateLoop(update, cleanup);
                lProgramContext.stopButton.on('click', reset);
                $('#rigidbody_1_force_submit_button').submit(addForce);
            });
        }
    
        lProgramContext.playButton.on('click', run);
        $('#rigidbody_1_force_submit_button').submit(false);
    
    }
    
    $(document).ready(main);
})()