webgl-3d-animation
Version:
Interactive 3D animation using WebGL showing a 2D predator prey ecology on a grid which is real-time mapped onto the surface of a 3D torus. node.js server side gives access to WAV format files which are rendered using Web Audio API
1,648 lines (1,052 loc) • 58 kB
JavaScript
var webgl_3d_animation = function() {
"use strict";
var mvMatrix = mat4.create();
var mvMatrixStack = [];
var pMatrix = mat4.create();
// ------------- below are CONSTANTS shared with other scripts ------------------ //
var X = 0;
var Y = 1;
var Z = 2;
var min = 3;
var max = 4;
var median = 5;
var world_min_x = -0.5;
var world_min_y = -0.0;
var world_min_z = -2.0;
var world_max_x = 2.0;
var world_max_y = 2.0;
var world_max_z = 2.0;
var torus_matrix_rotation = [ 0.2, 0.2, -0.2];
// var fft_matrix_rotation = [ 0.6, 0.0, -0.0];
var fft_matrix_rotation = [ 0.9, 0.0, -0.0];
// var time_domain_matrix_rotation = [ -0.8, 0.0, 0.0];
var time_domain_matrix_rotation = [ -0.0, 0.0, 0.4];
var rotation_degree = {};
var rotation_grid = "grid";
var rotation_fft = "fft";
var rotation_time_domain = "time_domain";
var rotation_none = "none";
rotation_degree[rotation_grid] = 0;
rotation_degree[rotation_fft] = 0;
rotation_degree[rotation_time_domain] = 0;
rotation_degree[rotation_none] = 0;
var activity_status = {}; // stores boolean to indicate active state for each graphics flavor
var activity_siblings = {}; // key is graphics flavor value is array of its siblings to enable
// enmass on/off for entire group of graphics falvors
var activity_callback = {}; // stores pair of callbacks executed on true/false of flavor
// var curr_degree_rotation_grid = 0;
// var curr_degree_rotation_torus = 0;
var degrees_rotation_fft;
var stop_early = false;
var count_chronos = 0;
var do_output;
var do_single_step;
var last_time = 0;
var mouseDown = false;
var lastMouseX = null;
var lastMouseY = null;
var mouse_scroll_wheel_delta = 0;
var currentlyPressedKeys = {};
var moonRotationMatrix = mat4.create();
mat4.identity(moonRotationMatrix);
// var view_UI_current_state = true;
var view_UI_current_state = false;
// initialize mouse movement mat4 into nice viewing perspective
var FoV = 20.0;
var curr_pitch = -9.020000000000001;
var curr_yaw = 2.9000000000000017;
var curr_speed = 0;
var position_x = 0.6825400916557905;
var position_y = 0.4093690657292863;
var position_z = 10.021485672918804;
var curr_key_pressed = null;
var this_key = 1;
// ---
var curr_canvas;
var writable_output_pixels;
var delta_pitch = 0;
var delta_yaw = 0;
var speed = 0;
var desired_point_size = 1.0;
var shader_program_texture;
var shaderProgram_01;
var shaderProgram_02;
var shader_program_landscape;
var curr_shader_program = null;
var gl;
// ---
var xRot = 0;
var yRot = 0;
var zRot = 0;
var elapsed = 0;
// var cubeVertexPositionBuffer;
// var cubeVertexTextureCoordBuffer;
// var cubeVertexIndexBuffer;
// var neheTexture;
// var shaderProgram;
/*
function init_camera_perspectives() {
// -------- these init value define starting perspective --------- //
moonRotationMatrix = [-0.6537552205623457, -0.30087098559496206, 0.6943029284108623, 0, 0.7536820419441966, -0.3406270606507448, 0.5620569108352607, 0, 0.06739043120556161, 0.8907449831701331, 0.44945120514773496, 0, 0, 0, 0, 1];
FoV = 20.0;
curr_pitch = -9.020000000000001;
curr_yaw = 2.9000000000000017;
curr_speed = 0;
position_x = 0.6825400916557905;
position_y = 0.4093690657292863;
position_z = 10.021485672918804;
}
*/
function set_camera_perspectives() {
// -------- these init value define starting perspective --------- //
moonRotationMatrix = [0.7352716063878847, 0.27678643552261983, -0.6186537364637207, 0, -0.6667140427230679, 0.45943448572820017, -0.5868358226293043, 0, 0.12180678904838242, 0.8439628200499135, 0.5223584884859405, 0, 0, 0, 0, 1];
FoV = 20.0;
curr_pitch = 2.039999999999997;
curr_yaw = 5.920000000000003;
curr_speed = 0.01;
position_x = 0.2580853494745913;
position_y = 0.40885423701597917;
position_z = 9.181939802075272;
}
var manage_shader_program = (function() {
var local_shader_program = null;
return {
set : function(given_gl, given_shader_program) {
if (local_shader_program !== given_shader_program) {
given_gl.useProgram(given_shader_program);
local_shader_program = given_shader_program;
// console.log(".... had to toggle btw shader programs");
}
},
get : function() {
return local_shader_program;
}
};
}());
function initGL(canvas) {
try {
gl = canvas.getContext("experimental-webgl", { alpha: false });
// gl = canvas.getContext("experimental-webgl2"); // webgl2
// https://wiki.mozilla.org/Platform/GFX/WebGL2
gl.viewportWidth = canvas.width;
gl.viewportHeight = canvas.height;
// console.log(gl.getSupportedExtensions().join("\n"));
} catch (e) {}
if (!gl) {
alert("Could not initialise Webgl, go here to enable WebGL on your browser http://www.browserleaks.com/webgl");
}
}
function getShader(gl, id) {
var shaderScript = document.getElementById(id);
if (!shaderScript) {
console.error("ERROR - failed to find shader : " + id);
return null;
}
var str = "";
var k = shaderScript.firstChild;
while (k) {
if (k.nodeType == 3) {
str += k.textContent;
}
k = k.nextSibling;
}
var shader;
if (shaderScript.type == "x-shader/x-fragment") {
shader = gl.createShader(gl.FRAGMENT_SHADER);
} else if (shaderScript.type == "x-shader/x-vertex") {
shader = gl.createShader(gl.VERTEX_SHADER);
} else {
console.error("ERROR - failed to resolve type for shader : " + id);
return null;
}
gl.shaderSource(shader, str);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
console.error("ERROR - failed to compile shader : " + id);
console.error(gl.getShaderInfoLog(shader));
alert(gl.getShaderInfoLog(shader));
return null;
}
return shader;
}
function initShaders(gl) {
var curr_vertex_shader = null;
var curr_fragment_shader = null;
// --------------- shader render to texture --------------- //
curr_fragment_shader = getShader(gl, "fragment_shader_render_to_texture");
curr_vertex_shader = getShader(gl, "vertex_shader_render_to_texture");
shader_program_texture = gl.createProgram();
gl.attachShader(shader_program_texture, curr_vertex_shader);
gl.attachShader(shader_program_texture, curr_fragment_shader);
gl.linkProgram(shader_program_texture);
if (!gl.getProgramParameter(shader_program_texture, gl.LINK_STATUS)) {
alert("Could not initialise shaders");
}
gl.useProgram(shader_program_texture);
shader_program_texture.vertexPositionAttribute = gl.getAttribLocation(shader_program_texture, "aVertexPosition");
gl.enableVertexAttribArray(shader_program_texture.vertexPositionAttribute);
shader_program_texture.textureCoordAttribute = gl.getAttribLocation(shader_program_texture, "aTextureCoord");
gl.enableVertexAttribArray(shader_program_texture.textureCoordAttribute);
shader_program_texture.pMatrixUniform = gl.getUniformLocation(shader_program_texture, "uPMatrix");
shader_program_texture.mvMatrixUniform = gl.getUniformLocation(shader_program_texture, "uMVMatrix");
shader_program_texture.samplerUniform = gl.getUniformLocation(shader_program_texture, "uSampler");
/*
// --------------- shader set II ----------------- //
curr_fragment_shader = getShader(gl, "fragment_shader_02");
curr_vertex_shader = getShader(gl, "vertex_shader_02");
shaderProgram_02 = gl.createProgram();
// console.log("\n\n\n hello Corinde its 5pm today");
gl.attachShader(shaderProgram_02, curr_vertex_shader);
gl.attachShader(shaderProgram_02, curr_fragment_shader);
gl.linkProgram(shaderProgram_02);
if (!gl.getProgramParameter(shaderProgram_02, gl.LINK_STATUS)) {
alert("Could not initialise shaders");
}
gl.useProgram(shaderProgram_02);
// shaderProgram_02.vertexPositionAttribute = gl.getAttribLocation(shaderProgram_02, "aVertexPosition");
// gl.enableVertexAttribArray(shaderProgram_02.vertexPositionAttribute);
// shaderProgram_02.vertexColorAttribute = gl.getAttribLocation(shaderProgram_02, "aVertexColor");
// gl.enableVertexAttribArray(shaderProgram_02.vertexColorAttribute);
shaderProgram_02.pMatrixUniform = gl.getUniformLocation(shaderProgram_02, "uPMatrix");
shaderProgram_02.mvMatrixUniform = gl.getUniformLocation(shaderProgram_02, "uMVMatrix");
shaderProgram_02.point_size = gl.getUniformLocation(shaderProgram_02, "given_point_size");
shaderProgram_02.screen_resolution = gl.getUniformLocation(shaderProgram_02, "u_resolution");
*/
// --------------- shader_program_landscape ----------------- //
curr_fragment_shader = getShader(gl, "fragment_shader_landscape");
curr_vertex_shader = getShader(gl, "vertex_shader_landscape");
shader_program_landscape = gl.createProgram();
// console.log("\n\n\n hello Corinde its 5pm today");
gl.attachShader(shader_program_landscape, curr_vertex_shader);
gl.attachShader(shader_program_landscape, curr_fragment_shader);
gl.linkProgram(shader_program_landscape);
if (!gl.getProgramParameter(shader_program_landscape, gl.LINK_STATUS)) {
alert("Could not initialise shaders");
}
gl.useProgram(shader_program_landscape);
curr_shader_program = shader_program_landscape;
shader_program_landscape.vertexPositionAttribute = gl.getAttribLocation(shader_program_landscape, "aVertexPosition");
gl.enableVertexAttribArray(shader_program_landscape.vertexPositionAttribute);
shader_program_landscape.vertexColorAttribute = gl.getAttribLocation(shader_program_landscape, "aVertexColor");
gl.enableVertexAttribArray(shader_program_landscape.vertexColorAttribute);
shader_program_landscape.pMatrixUniform = gl.getUniformLocation(shader_program_landscape, "uPMatrix");
shader_program_landscape.mvMatrixUniform = gl.getUniformLocation(shader_program_landscape, "uMVMatrix");
shader_program_landscape.point_size = gl.getUniformLocation(shader_program_landscape, "given_point_size");
shader_program_landscape.screen_resolution = gl.getUniformLocation(shader_program_landscape, "u_resolution");
// bbb
shader_program_landscape.time = gl.getUniformLocation(shader_program_landscape, "u_time");
// --------------- shader set I ----------------- //
curr_fragment_shader = getShader(gl, "fragment_shader_01");
curr_vertex_shader = getShader(gl, "vertex_shader_01");
shaderProgram_01 = gl.createProgram();
// console.log("\n\n\n hello Corinde its 5pm today");
gl.attachShader(shaderProgram_01, curr_vertex_shader);
gl.attachShader(shaderProgram_01, curr_fragment_shader);
gl.linkProgram(shaderProgram_01);
if (!gl.getProgramParameter(shaderProgram_01, gl.LINK_STATUS)) {
alert("Could not initialise shaders");
}
gl.useProgram(shaderProgram_01);
curr_shader_program = shaderProgram_01;
shaderProgram_01.vertexPositionAttribute = gl.getAttribLocation(shaderProgram_01, "aVertexPosition");
gl.enableVertexAttribArray(shaderProgram_01.vertexPositionAttribute);
shaderProgram_01.vertexColorAttribute = gl.getAttribLocation(shaderProgram_01, "aVertexColor");
gl.enableVertexAttribArray(shaderProgram_01.vertexColorAttribute);
shaderProgram_01.pMatrixUniform = gl.getUniformLocation(shaderProgram_01, "uPMatrix");
shaderProgram_01.mvMatrixUniform = gl.getUniformLocation(shaderProgram_01, "uMVMatrix");
shaderProgram_01.point_size = gl.getUniformLocation(shaderProgram_01, "given_point_size");
shaderProgram_01.screen_resolution = gl.getUniformLocation(shaderProgram_01, "u_resolution");
} // initShaders
function mvPushMatrix() {
var copy = mat4.create();
mat4.set(mvMatrix, copy);
mvMatrixStack.push(copy);
}
function mvPopMatrix() {
if (mvMatrixStack.length === 0) {
throw "Invalid popMatrix!";
}
mvMatrix = mvMatrixStack.pop();
}
function setMatrixUniforms(given_point_size, gl, local_shader_program) {
gl.uniformMatrix4fv(local_shader_program.pMatrixUniform, false, pMatrix);
gl.uniformMatrix4fv(local_shader_program.mvMatrixUniform, false, mvMatrix);
gl.uniform1f(local_shader_program.point_size, given_point_size);
gl.uniform2f(local_shader_program.screen_resolution, gl.viewportWidth, gl.viewportHeight);
if (local_shader_program.time) { // bbb
gl.uniform1f(local_shader_program.time, elapsed);
}
}
// ---
function inner_indexed_draw(given_animal, gl, given_rotation, given_matrix_rotation, given_shader_program, given_point_size) {
manage_shader_program.set(gl, given_shader_program);
var local_shader_program = manage_shader_program.get();
mvPushMatrix();
mat4.translate(mvMatrix, [ given_animal.min_max[X][median],
given_animal.min_max[Y][median],
given_animal.min_max[Z][median]]); // OK for board 4 by 4
// ---
mat4.rotate(mvMatrix, Common_Utils.degToRad(given_rotation), given_matrix_rotation);
mat4.translate(mvMatrix, [ -given_animal.min_max[X][median],
-given_animal.min_max[Y][median],
-given_animal.min_max[Z][median]]); // OK for board 4 by 4
// ---
gl.bindBuffer(gl.ARRAY_BUFFER, given_animal.vertex_position_buffer);
gl.bufferData(gl.ARRAY_BUFFER, given_animal.vertices, gl.STATIC_DRAW);
gl.vertexAttribPointer(local_shader_program.vertexPositionAttribute, given_animal.vertex_position_buffer.itemSize, gl.FLOAT, false, 0, 0);
// -------------------------------------
gl.bindBuffer(gl.ARRAY_BUFFER, given_animal.vertex_color_buffer);
gl.bufferData(gl.ARRAY_BUFFER, given_animal.colors, gl.STATIC_DRAW);
gl.vertexAttribPointer(local_shader_program.vertexColorAttribute, given_animal.vertex_color_buffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
// --------------------------------------
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, given_animal.vertex_indices_buffer); // bbb
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, given_animal.indices, gl.STATIC_DRAW);
// setMatrixUniforms(desired_point_size, gl, local_shader_program);
setMatrixUniforms(given_point_size, gl, local_shader_program);
if (given_animal.want_lines) {
gl.drawElements(gl.LINES, given_animal.vertex_indices_buffer.numItems, gl.UNSIGNED_SHORT, 0);
} else {
gl.drawElements(gl.TRIANGLES, given_animal.vertex_indices_buffer.numItems, gl.UNSIGNED_SHORT, 0);
}
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null); // bbb
mvPopMatrix();
} // inner_indexed_draw
// ---
function inner_draw(given_animal, given_point_size, given_rotation, gl, given_shader_program, blob_tag) {
manage_shader_program.set(gl, given_shader_program);
var local_shader_program = manage_shader_program.get();
mvPushMatrix();
if (given_animal.want_translate === true) {
mat4.translate(mvMatrix, given_animal.pre_translate); // OK for board 4 by 4
}
if (given_animal.rotation_array) {
mat4.rotate(mvMatrix, Common_Utils.degToRad(given_rotation), given_animal.rotation_array);
}
if (given_animal.want_translate === true) {
mat4.translate(mvMatrix, given_animal.post_translate); // OK for board 4 by 4
}
gl.bindBuffer(gl.ARRAY_BUFFER, given_animal.vertex_position_buffer);
gl.bufferData(gl.ARRAY_BUFFER, given_animal.vertices, gl.STATIC_DRAW);
gl.vertexAttribPointer(local_shader_program.vertexPositionAttribute, given_animal.vertex_position_buffer.itemSize, gl.FLOAT, false, 0, 0);
// -------------------------------------
gl.bindBuffer(gl.ARRAY_BUFFER, given_animal.vertex_color_buffer);
gl.bufferData(gl.ARRAY_BUFFER, given_animal.colors, gl.STATIC_DRAW);
gl.vertexAttribPointer(local_shader_program.vertexColorAttribute, given_animal.vertex_color_buffer.itemSize, gl.FLOAT, false, 0, 0);
setMatrixUniforms(given_point_size, gl, local_shader_program);
gl.drawArrays(gl.POINTS, 0, given_animal.vertex_position_buffer.numItems);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
mvPopMatrix();
} // inner_draw
function setMatrixUniforms_texture(gl, local_shader_program) {
// bbb
gl.uniformMatrix4fv(local_shader_program.pMatrixUniform, false, pMatrix);
gl.uniformMatrix4fv(local_shader_program.mvMatrixUniform, false, mvMatrix);
}
// function degToRad(degrees) {
// return degrees * Math.PI / 180;
// }
/*
function texture_draw(given_animal, gl, given_shader_program) {
mvPushMatrix();
manage_shader_program.set(gl, given_shader_program);
var local_shader_program = manage_shader_program.get();
// ---
// gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
// gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
// mat4.perspective(45, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0, pMatrix);
// mat4.identity(mvMatrix);
// ---
mat4.translate(mvMatrix, [0.0, 0.0, -5.0]);
mat4.rotate(mvMatrix, Common_Utils.degToRad(xRot), [1, 0, 0]);
mat4.rotate(mvMatrix, Common_Utils.degToRad(yRot), [0, 1, 0]);
mat4.rotate(mvMatrix, Common_Utils.degToRad(zRot), [0, 0, 1]);
// gl.vertexAttribPointer(
// location, // get data from the buffer that's was last bound with gl.bindBuffer
// numComponents, // how many components per vertex (1 - 4)
// typeOfData, // what the type of data is (BYTE, FLOAT, INT, UNSIGNED_SHORT, etc...)
// normalizeFlag,
// strideToNextPieceOfData, // how many bytes to skip to get from one piece of data to next piece
// offsetIntoBuffer); // offset for how far into the buffer our data is
gl.bindBuffer(gl.ARRAY_BUFFER, given_animal.vertex_position_buffer);
gl.vertexAttribPointer( local_shader_program.vertexPositionAttribute,
given_animal.vertex_position_buffer.itemSize,
gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, given_animal.vertex_texture_coord_buffer);
gl.vertexAttribPointer( local_shader_program.textureCoordAttribute,
given_animal.vertex_texture_coord_buffer.itemSize,
gl.FLOAT, false, 0, 0);
gl.activeTexture(gl.TEXTURE0);
// gl.bindTexture(gl.TEXTURE_2D, neheTexture);
gl.bindTexture(gl.TEXTURE_2D, given_animal.texture);
gl.uniform1i(local_shader_program.samplerUniform, 0);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, given_animal.vertex_index_buffer);
setMatrixUniforms_texture(local_shader_program);
gl.drawElements(gl.TRIANGLES, given_animal.vertex_index_buffer.numItems, gl.UNSIGNED_SHORT, 0);
mvPopMatrix();
} // texture_draw
*/
// function draw_scene(gl, given_shader_program) {
function draw_scene(gl) {
/*
// console.log('count_num_draw_calls ', count_num_draw_calls);
// count_num_draw_calls++;
gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
// gl.clearColor(0.3, 0.3, 0.3, 1.0); // background color gray
// gl.clearColor(0.2, 0.2, 0.2, 1.0); // background color gray
// gl.clearColor(0.15, 0.15, 0.15, 1.0); // background color black
// gl.clearColor(0.1, 0.1, 0.1, 1.0); // background color black
gl.clearColor(0.03, 0.03, 0.03, 1.0); // background color black
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
mat4.perspective(FoV , gl.viewportWidth / gl.viewportHeight, 0.1, 100.0, pMatrix);
mat4.identity(mvMatrix);
// ---------- handle navigation
mat4.rotate(mvMatrix, Common_Utils.degToRad(-curr_pitch), [1, 0, 0]);
mat4.rotate(mvMatrix, Common_Utils.degToRad(-curr_yaw), [0, 1, 0]);
mat4.translate(mvMatrix, [-position_x, -position_y, -position_z]);
// ----------
// mat4.translate(mvMatrix, [world_min_x, world_min_y, world_min_z]); // OK for board 4 by 4
// ---
mat4.multiply(mvMatrix, moonRotationMatrix);
active_inner_draw.forEach(function(curr_element) { // ccc
if (activity_status[curr_element.object_label]) {
inner_draw( curr_element.flavor_graphics,
curr_element.point_size,
rotation_degree[curr_element.rotation_property],
gl,
curr_element.shader_program,
true);
}
});
active_inner_indexed_draw.forEach(function(curr_element) {
if (activity_status[curr_element.object_label]) {
inner_indexed_draw( curr_element.flavor_graphics,
gl,
rotation_degree[curr_element.rotation_property],
curr_element.rotation_matrix,
curr_element.shader_program);
}
});
if (true === audio_process_obj.get_display_ready_flag()) {
// pure synthesized curve based on sampled audio
inner_draw(audio_process_obj.animals_synth, 2.0, rotation_degree[rotation_grid], gl, given_shader_program, true);
inner_draw(audio_process_obj.animals_sampled, 2.0, rotation_degree[rotation_grid], gl, given_shader_program, true);
}
// ---
active_draw_texture.forEach(function(curr_element) {
if (activity_status[curr_element.object_label]) {
texture_draw( curr_element.flavor_graphics,
gl,
curr_element.shader_program);
}
});
*/
// ---
/*
gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
mat4.perspective(45, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0, pMatrix);
mat4.identity(mvMatrix);
mat4.translate(mvMatrix, [0.0, 0.0, -5.0]);
mat4.rotate(mvMatrix, Common_Utils.degToRad(xRot), [1, 0, 0]);
mat4.rotate(mvMatrix, Common_Utils.degToRad(yRot), [0, 1, 0]);
mat4.rotate(mvMatrix, Common_Utils.degToRad(zRot), [0, 0, 1]);
gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexPositionBuffer);
gl.vertexAttribPointer(shader_program_texture.vertexPositionAttribute, cubeVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexTextureCoordBuffer);
gl.vertexAttribPointer(shader_program_texture.textureCoordAttribute, cubeVertexTextureCoordBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, neheTexture);
gl.uniform1i(shader_program_texture.samplerUniform, 0);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndexBuffer);
setMatrixUniforms();
gl.drawElements(gl.TRIANGLES, cubeVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
*/
} // draw_scene
function texture_draw(given_animal, gl, given_shader_program) {
/*
gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexPositionBuffer);
gl.vertexAttribPointer(shader_program_texture.vertexPositionAttribute, cubeVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexTextureCoordBuffer);
gl.vertexAttribPointer(shader_program_texture.textureCoordAttribute, cubeVertexTextureCoordBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, neheTexture);
gl.uniform1i(shader_program_texture.samplerUniform, 0);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndexBuffer);
// setMatrixUniforms();
setMatrixUniforms_texture(shader_program_texture);
gl.drawElements(gl.TRIANGLES, cubeVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
*/
// bbb
manage_shader_program.set(gl, given_shader_program);
var local_shader_program = manage_shader_program.get();
mvPushMatrix();
// mat4.translate(mvMatrix, [0.0, 0.0, -5.0]);
mat4.translate(mvMatrix, [6.0, 4.0, 1.0]);
mat4.rotate(mvMatrix, Common_Utils.degToRad(xRot), [1, 0, 0]);
mat4.rotate(mvMatrix, Common_Utils.degToRad(yRot), [0, 1, 0]);
mat4.rotate(mvMatrix, Common_Utils.degToRad(zRot), [0, 0, 1]);
// ---
gl.bindBuffer(gl.ARRAY_BUFFER, given_animal.vertex_position_buffer);
gl.vertexAttribPointer(given_shader_program.vertexPositionAttribute, given_animal.vertex_position_buffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, given_animal.vertex_texture_coord_buffer);
gl.vertexAttribPointer(given_shader_program.textureCoordAttribute, given_animal.vertex_texture_coord_buffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, given_animal.texture);
gl.uniform1i(given_shader_program.samplerUniform, 0);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, given_animal.vertex_index_buffer);
setMatrixUniforms_texture(gl, given_shader_program);
gl.drawElements(gl.TRIANGLES, given_animal.vertex_index_buffer.numItems, gl.UNSIGNED_SHORT, 0);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
gl.bindTexture(gl.TEXTURE_2D, null);
// ---
mvPopMatrix();
} // texture_draw
function drawScene(gl) {
gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
mat4.perspective(45, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0, pMatrix);
mat4.identity(mvMatrix);
// ---
mat4.perspective(FoV , gl.viewportWidth / gl.viewportHeight, 0.1, 100.0, pMatrix);
// mat4.identity(mvMatrix);
// ---------- handle navigation
mat4.rotate(mvMatrix, Common_Utils.degToRad(-curr_pitch), [1, 0, 0]);
mat4.rotate(mvMatrix, Common_Utils.degToRad(-curr_yaw), [0, 1, 0]);
mat4.translate(mvMatrix, [-position_x, -position_y, -position_z]);
// ----------
mat4.translate(mvMatrix, [world_min_x, world_min_y, world_min_z]); // OK for board 4 by 4
// ---
mat4.multiply(mvMatrix, moonRotationMatrix);
// ---
active_draw_inner.forEach(function(curr_element) { // ccc
if (activity_status[curr_element.object_label]) {
// inner_draw(given_animal, given_point_size, given_rotation, gl, given_shader_program, blob_tag)
inner_draw( curr_element.flavor_graphics,
curr_element.point_size,
rotation_degree[curr_element.rotation_property],
gl,
curr_element.shader_program,
true);
}
});
// ---
active_draw_indexed_inner.forEach(function(curr_element) {
if (activity_status[curr_element.object_label]) {
inner_indexed_draw( curr_element.flavor_graphics,
gl,
rotation_degree[curr_element.rotation_property],
curr_element.rotation_matrix,
curr_element.shader_program,
curr_element.point_size);
}
});
// ---
active_draw_texture.forEach(function(curr_element) {
if (activity_status[curr_element.object_label]) {
texture_draw( curr_element.flavor_graphics,
gl,
curr_element.shader_program);
}
});
} // drawScene
function animate() {
var timeNow = new Date().getTime();
// Used to make us "jog" up and down as we move forward.
var joggingAngle = 0;
if (last_time !== 0) {
elapsed = timeNow - last_time;
xRot += (90 * elapsed) / 1000.0;
yRot += (90 * elapsed) / 1000.0;
zRot += (90 * elapsed) / 1000.0;
// ---
if (speed !== 0) {
position_x -= Math.sin(Common_Utils.degToRad(curr_yaw)) * speed * elapsed;
position_z -= Math.cos(Common_Utils.degToRad(curr_yaw)) * speed * elapsed;
joggingAngle += elapsed * 0.6; // 0.6 "fiddle factor" - makes it feel more realistic :-)
position_y = Math.sin(Common_Utils.degToRad(joggingAngle)) / 20 + 0.4;
curr_speed = speed;
}
rotation_degree[rotation_grid] -= (38 * elapsed) / 1000.0;
rotation_degree[rotation_time_domain] -= (98.0 * elapsed) / 1000.0;
// curr_degree_rotation_torus -= (75 * elapsed) / 1000.0;
// curr_degree_rotation_torus -= (48 * elapsed) / 1000.0;
rotation_degree[rotation_fft] -= (degrees_rotation_fft * elapsed) / 1000.0;
curr_yaw += delta_yaw * elapsed;
curr_pitch += delta_pitch * elapsed;
// --- uuu
if (view_UI_current_state) {
// console.log('delta_pitch ', delta_pitch, ' delta_yaw ', delta_yaw, ' speed ', speed);
}
}
last_time = timeNow;
}
function tick() {
requestAnimFrame(tick);
handleKeys();
// if (activity_status["animals_fish"]) {
if (activity_status.animals_fish) {
fns.update_board();
}
// if (activity_status["animals_time_curve"]) {
if (activity_status.animals_time_curve) {
audio_display_obj.update_billboard(); // refreshes time domain cylinder
}
// draw_scene(gl, shaderProgram_01);
// draw_scene(gl);
drawScene(gl);
animate(); // remove comment to engage rotation animation
// ------- write to output texture
// gl.readPixels(0, 0, CANVAS.width, CANVAS.height, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
// pixels = new Float32Array(pixels.buffer);
// gl.readPixels(0, 0, curr_canvas.width, curr_canvas.height, gl.RGBA, gl.UNSIGNED_BYTE, writable_output_pixels);
// var size_pixel_view = writable_output_pixels.length;
// console.log("size_pixel_view " + size_pixel_view);
// for (var curr_pixel = 0, size_pixel_view = writable_output_pixels.length;
// curr_pixel < size_pixel_view && curr_pixel < 10; curr_pixel += 4) {
// console.log(writable_output_pixels[curr_pixel]);
// }
// writable_output_pixels = new Float32Array(writable_output_pixels.buffer);
// writable_output_pixels now contains an array of floats, 1 float for each pixel
}
function process_a_keypress() {
// stop_early = ! stop_early; // toggle true / false
process_a_click();
}
function process_a_click() {
// do_single_step = ! do_single_step;
stop_early = ! stop_early; // toggle true / false
// do_board_update = ! do_board_update; // toggle true / false
}
// ------------ handle mouse movements
function handleMouseDown(event) {
event.preventDefault();
mouseDown = true;
lastMouseX = event.clientX;
lastMouseY = event.clientY;
}
function handleMouseUp(event) {
event.preventDefault();
mouseDown = false;
}
function handleMouseMove(event) {
event.preventDefault();
if (!mouseDown) {
return;
}
var newX = event.clientX;
var newY = event.clientY;
var deltaX = newX - lastMouseX;
var newRotationMatrix = mat4.create();
mat4.identity(newRotationMatrix);
mat4.rotate(newRotationMatrix, Common_Utils.degToRad(deltaX / 10), [0, 1, 0]);
var deltaY = newY - lastMouseY;
mat4.rotate(newRotationMatrix, Common_Utils.degToRad(deltaY / 10), [1, 0, 0]);
mat4.multiply(newRotationMatrix, moonRotationMatrix, moonRotationMatrix);
if (view_UI_current_state) {
console.log('\n', mat4.str(moonRotationMatrix), ', ', FoV, ', ', curr_pitch, ', ', curr_yaw,
', ', curr_speed,
', ', position_x, ', ', position_y, ', ', position_z);
}
lastMouseX = newX;
lastMouseY = newY;
}
// ------------- handle mouse scroll wheel
function handleMouseScrollWheel(event) {
event.preventDefault(); // prevent mouse scroll to move entire page
if (event.wheelDelta) {
// IE and Opera
mouse_scroll_wheel_delta = event.wheelDelta / 60;
} else if (event.detail) {
// W3C
mouse_scroll_wheel_delta = -event.detail / 2;
}
FoV += - 0.8 * mouse_scroll_wheel_delta;
}
// ------------ handle keyboard navigation
// http://www.cambiaresearch.com/articles/15/javascript-char-codes-key-codes
function handleKeyDown(event) {
event.preventDefault();
currentlyPressedKeys[event.keyCode] = true;
// console.log("handleKeyDown " + event.keyCode);
curr_key_pressed = event.keyCode;
}
function handleKeyUp(event) {
event.preventDefault();
currentlyPressedKeys[event.keyCode] = false;
// console.log('handleKeyUp');
}
function handleKeys() {
var key_touched = false;
var multiply_factor = 0.02;
var zoom_factor = 0.2;
if (currentlyPressedKeys[33]) { // page up
// Page Up
delta_pitch = multiply_factor;
} else if (currentlyPressedKeys[34]) { // page down
// Page Down
delta_pitch = -multiply_factor;
} else {
delta_pitch = 0;
}
if (currentlyPressedKeys[37] || currentlyPressedKeys[65]) { // left arrow OR a
// Left cursor key or A
delta_yaw = multiply_factor;
} else if (currentlyPressedKeys[39] || currentlyPressedKeys[68]) { // right arrow OR d
// Right cursor key or D
delta_yaw = -multiply_factor;
} else {
delta_yaw = 0;
}
if (currentlyPressedKeys[38] || currentlyPressedKeys[87]) { // up arrow OR w
// Up cursor key or W
speed = multiply_factor * zoom_factor;
} else if (currentlyPressedKeys[40] || currentlyPressedKeys[83]) { // down arrow OR s
// Down cursor key
speed = -multiply_factor * zoom_factor;
} else {
speed = 0;
}
if (view_UI_current_state && (0 !== delta_pitch || 0 !== delta_yaw || 0 !== speed)) {
// console.log(delta_pitch, ' ', delta_yaw, ' ', speed);
}
// ---
// if (currentlyPressedKeys[49]) { // page
// if (curr_key_pressed > 48 && curr_key_pressed < 58) {
if (currentlyPressedKeys[49] || currentlyPressedKeys[50] || currentlyPressedKeys[51] || currentlyPressedKeys[52] ||
currentlyPressedKeys[53] || currentlyPressedKeys[54] || currentlyPressedKeys[55] || currentlyPressedKeys[56]) {
this_key = curr_key_pressed - 48;
// console.log("cool seeing 1 to 9 ... as in " + this_key);
chladni_obj.do_chladni.update_chladni(this_key, lastMouseX, lastMouseY);
}
if (currentlyPressedKeys[82]) {
chladni_obj.do_chladni.reset_chladni();
}
}
// ------------
var state_animation = (function() {
var state_value = []; // true or false of given index driven by state_roster
var state_roster = []; // contains list of given_object_label values
// whos index drives state_value
var state_label_to_entry = {}; // maps key : given_object_label to value : index into state_xxx
return {
add_animation_object : function(given_object_label) {
state_roster.push(given_object_label);
var curr_object_index = state_roster.length - 1;
state_label_to_entry[given_object_label] = curr_object_index;
state_value[curr_object_index] = true; // default new additions as true
},
/*
set_state : function(given_object_label, given_value) {
var curr_index = state_label_to_entry[given_object_label];
if (true !== given_value && false !== given_value) {
throw new Error("ERROR - set_state 2nd parm must be true or false");
}
if (typeof curr_index === "undefined") {
throw new Error("set_state given invalid 1st parm ... " +
"must be object_label as previously given to add_animation_object 1st parm");
}
state_value[curr_index] = given_value;
},
*/
get_state : function(given_object_label) {
var curr_index = state_label_to_entry[given_object_label];
if (typeof curr_index === "undefined") {
return false;
}
if (typeof state_value[curr_index] === "undefined") {
throw new Error("ERROR - invalid state_value for given object label");
}
return state_value[curr_index];
}
};
}());
var active_object_handles = {};
// var active_inner_draw = [];
var active_draw_inner = [];
// var active_inner_indexed_draw = [];
var active_draw_indexed_inner = [];
var active_draw_texture = [];
var state_objects = [];
var ui_events_entry_point = function(flavor_checkbox, given_event) {
// var ui_events_entry_point = function(flavor_checkbox) {
// var given_event = this.checked;
console.log("nice ... " + flavor_checkbox + " now says " + given_event);
if (typeof activity_status[flavor_checkbox] !== "undefined") {
// console.log("cool Corinde ... here is event " + flavor_checkbox + " value " + given_event);
activity_status[flavor_checkbox] = given_event;
if (typeof activity_siblings[flavor_checkbox] !== "undefined") {
var all_siblings = activity_siblings[flavor_checkbox];
for (var curr_sibling in all_siblings) {
if (all_siblings.hasOwnProperty(curr_sibling)) {
activity_status[curr_sibling] = given_event;
}
}
}
// ---
if (typeof activity_callback[flavor_checkbox] !== "undefined") {
activity_callback[flavor_checkbox][given_event]();
}
} else {
console.log("whooa ... did not see key here is entire associative array");
console.log(activity_status);
}
};
/*
var setup_checkbox_list = function() {
var all_checkbox_ids = [
// "toggle_mute",
// "animals_audio_vis",
// "animals_fft",
// "animals_time_curve",
// "animals_borg",
// "animals_chladni",
// "animals_pasture",
"animals_trefoil_knot"
// "animals_schwartz",
// "animals_fish",
// "animals_doughnut"
];
// clear the former content of a given <div id="some_div"></div>
document.getElementById('control_checkboxes').innerHTML = '';
all_checkbox_ids.forEach(function(element) {
console.log("element " + element);
// ---
// var curr_label = element;
// create the necessary elements
// var label= document.createElement("label");
var curr_label = document.createElement("label");
// var description = document.createTextNode("pair");
var description = document.createTextNode(element);
var checkbox = document.createElement("input");
checkbox.type = "checkbox"; // make the element a checkbox
checkbox.name = "slct[]"; // give it a name we can check on the server side
// checkbox.value = "pair"; // make its value "pair"
// checkbox.onclick = ui_logic_handler.handleClick(element, this);
// checkbox.setAttribue('onclick','addRow("'+tableID+'")');
checkbox.setAttribute('onclick','ui_logic_handler.handleClick("'+element+'")');
curr_label.appendChild(checkbox); // add the box to the element
curr_label.appendChild(description);// add the description to the element
// add the label element to your div
document.getElementById('control_checkboxes').appendChild(curr_label);
});
// create the necessary elements
var label= document.createElement("label");
var description = document.createTextNode("pair");
var checkbox = document.createElement("input");
checkbox.type = "checkbox"; // make the element a checkbox
checkbox.name = "slct[]"; // give it a name we can check on the server side
// checkbox.value = "pair"; // make its value "pair"
label.appendChild(checkbox); // add the box to the element
label.appendChild(description);// add the description to the element
// add the label element to your div
document.getElementById('control_checkboxes').appendChild(label);
// document.getElementById("myCheck").checked = true;
// document.getElementById("trefoil_checkbox").checked = true;
// control_checkboxes
// var checkbox = document.createElement('input');
var checkbox = document.getElementById("control_checkboxes");
checkbox.type = "checkbox";
checkbox.name = "name";
checkbox.value = "value";
checkbox.id = "id";
var label = document.createElement('label');
label.htmlFor = "id";
label.appendChild(document.createTextNode('text for label after checkbox'));
// container.appendChild(checkbox);
// container.appendChild(label);
// document.body.appendChild(checkbox);
// document.body.appendChild(label);
// var x = document.createElement("INPUT");
// x.setAttribute("type", "checkbox");
function check() {
document.getElementById("myCheck").checked = true;
}
function uncheck() {
document.getElementById("myCheck").checked = false;
}
// ui_logic_handler.is_checked
};
*/
function add_graphics_flavor_siblings(siblings_obj, given_key, given_value) {
// console.log(" pre ------------- siblings_obj");
// console.log(siblings_obj);
// console.log(" ------------- given_key");
// console.log(given_key);
// console.log(" ------------- given_value");
// console.log(given_value);
var curr_siblings = {};
if (typeof siblings_obj[given_key] !== "undefined") {
// console.log(" cool seeing NO key for given_key " + given_key);
curr_siblings = siblings_obj[given_key];
}
curr_siblings[given_value] = 1; // placeholder for sibling of given_key
siblings_obj[given_key] = curr_siblings;
// ---
// console.log(" post ------------- siblings_obj");
// console.log(siblings_obj);
}
var internal_webGLStart = function() {
curr_canvas = document.getElementById("ecology_simulation");
initGL(curr_canvas);
initShaders(gl);
// ---
set_camera_perspectives();
var state_object_fish_and_sharks = "object_fish_and_sharks";
var state_object_landscape = "object_landscape";
var state_object_borg = "object_borg";
var state_object_schwartz = "object_schwartz";
var state_object_chladni = "object_chladni";
var state_object_trefoil = "object_trefoil";
var state_object_audio_domain = "object_audio_domain";
var state_object_toggle_mute = "toggle_mute";
var state_object_render_to_texture = "render_to_texture";
// ---
// state_animation.add_animation_object(state_object_persistance_db);
state_animation.add_animation_object(state_object_fish_and_sharks);
state_animation.add_animation_object(state_object_landscape);
state_animation.add_animation_object(state_object_borg);
state_animation.add_animation_object(state_object_schwartz);
state_animation.add_animation_object(state_object_chladni);
state_animation.add_animation_object(state_object_trefoil);
state_animation.add_animation_object(state_object_audio_domain);
state_animation.add_animation_object(state_object_render_to_texture);
// ---
activity_status[state_object_toggle_mute] = true; // toggle mute audio volume
activity_callback[state_object_toggle_mute] = {
true : webaudio_tooling_obj.do_mute,
false : webaudio_tooling_obj.un_mute
};
var curr_object_handle = null;
var curr_all_object_labels = null;
var object_label = null;
// ---------------
if (true === state_animation.get_state(state_object_render_to_texture)) {
render_to_texture_obj.init(gl);
curr_object_handle = render_to_texture_obj.get_object_handle();
curr_all_object_labels = render_to_texture_obj.get_all_object_labels();
object_label = curr_all_object_labels[0];
activity_status[object_label] = true;
active_draw_texture.push({
flavor_graphics : curr_object_handle[object_label],
object_label : object_label,
shader_program : shader_program_texture
});
}
// ------------ borg ------------ //
if (true === state_animation.get_state(state_object_borg)) {
// var MAX_BORG_POINTS = 10;
// var MAX_BORG_POINTS = 10000;
var MAX_BORG_POINTS = 50000;
// var MAX_BORG_POINTS = 100000;
// var MAX_BORG_POINTS = 300000;
borg_obj.init_borg(gl, MAX_BORG_POINTS);
curr_object_handle = borg_obj.get_object_handle();
curr_all_object_labels = borg_obj.get_all_object_labels();
object_label = curr_all_object_labels[0];
activity_status[object_label] = true;
active_draw_inner.push({
flavor_graphics : curr_object_handle[object_label],
point_size : 1.0,
rotation_property : rotation_grid,
object_label : object_label,
shader_program : shaderProgram_01
});
}
// -------------------- trefoil -------------------- //
if (true === state_animation.get_state(state_object_trefoil)) {
// var max_num_trefoil_knot_points = 1000;
var max_num_trefoil_knot_points = 5000;
trefoil_knot_obj.init_trefoil_knot(gl, max_num_trefoil_knot_points);
curr_object_handle = trefoil_knot_obj.get_object_handle();
curr_all_object_labels = trefoil_knot_obj.get_all_object_labels();
object_label = curr_all_object_labels[0];
activity_status[object_label] = true;
active_draw_inner.push({
flavor_graphics : curr_object_handle[object_label],
point_size : 5.0,
rotation_property : rotation_grid,
object_label : object_label,
shader_program : shaderProgram_01
});
}
// -------------------- schwartz -------------------- //
if (true === state_animation.get_state(state_object_schwartz)) {
// var max_num_schwartz_points = 200000;
// var max_num_schwartz_points = 100000;
// var max_num_schwartz_points = 10000;
// var max_num_schwartz_points = 20000;
var max_num_schwartz_points = 50000;
schwartz_obj.init_schwartz(gl, max_num_schwartz_points);
curr_object_handle = schwartz_obj.get_object_handle();
curr_all_object_labels = schwartz_obj.get_all_object_labels();
object_label = curr_all_object_labels[0];
activity_status[object_label] = true;
active_draw_inner.push({
flavor_graphics : curr_object_handle[object_label],
point_size : 1.0,
rotation_property : rotation_grid,
object_label : object_label,
shader_program : shaderProgram_01
});
}
// -------------------- chladni -------------------- //
if (true === state_animation.get_state(state_object_chladni)) {
// var max_num_chladni_points = 50000;
var max_num_chladni_points = 35000;
// var max_num_chladni_points = 5000;
chladni_obj.do_chladni.init_chladni(gl, max_num_chladni_points);
curr_object_handle = chladni_obj.get_object_handle();
curr_all_object_labels = chladni_obj.get_all_object_labels();
object_label = curr_all_object_labels[0];
activity_status[object_label] = true;
active_draw_inner.push({
flavor_graphics : curr_object_handle[object_label],
point_size : 1.0,
rotation_property : rotation_none,
object_label : object_label,
shader_program : shaderProgram_01
});
}
// ------------- landscape ------------- //
if (true === state_animation.get_state(state_object_landscape)) {
var MAX_LANDSCAPE_ANIMALS = 10000;
// var landscape_min_x = -1.0;
// var landscape_max_x = 1.0;
// var landscape_min_y = -1.0;
// var landscape_max_y = 1.0;
// var landscape_min_z = -1.0;
// var landscape_max_z = 1.0;
var landscape_min_x = 5.0;
var landscape_max_x = 3.0;
var landscape_min_y = -4.0;
var landscape_max_y = -2.0;
var landscape_min_z = -1.0;
var landscape_max_z = 1.0;
// var landscape_min_x = -3.0;
// var landscape_max_x = -1.0;
// var landscape_min_y = 4.0;
// var landscape_max_y = 2.0;
// var landscape_min_z = -1.0;
// var landscape_max_z = 1.0;
// var landscape_min_x = -1.0;
// var landscape_max_x = 1.0;
// var landscape_min_y = -1.0;
// var landscape_max_y = 1.0;
// var landscape_min_z = -1.0;
// var landscape_max_z = 1.0;
landscape_obj.init_landscape(gl, MAX_LANDSCAPE_ANIMALS,
landscape_min_x, landscape_max_x,
landscape_min_y, landscape_max_y,
landscape_min_z, landscape_max_z);
curr_object_handle = landscape_obj.get_object_handle();
curr_all_object_labels = landscape_obj.get_all_object_labels();
// ---
object_label = curr_all_object_labels[0];
activity_status[object_label] = true;
active_draw_inner.push({
flavor_graphics : curr_object_handle[object_label],
point_size : 1.0,
rotation_property : rotation_grid,
object_label : object_label,