UNPKG

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

358 lines (229 loc) 13.1 kB
var chladni_obj = function() { // ------------- below are CONSTANTS shared with other scripts ------------------ // // https://physics.stackexchange.com/questions/90021/theory-behind-patterns-formed-on-chladni-plates // Evan Grant: Making sound visible through cymatics ... see video on ted.com var R = 0; var G = 1; var B = 2; var A = 3; var X = 0; var Y = 1; var Z = 2; var min = 3; var max = 4; var median = 5; var SIZE_DIM_3D = 3; var SIZE_DIM_COLORS = 4; var FLT_MAX = 99999.99; var FLT_MIN = -99999.99; var object_handle = {}; // holds all the various flavors of graphic object types var animals_chladni = "animals_chladni"; object_handle[animals_chladni] = {}; var all_object_labels = []; all_object_labels.push(animals_chladni); // ------------ // function init_chladni(gl, given_max_num_chladni_points) { var do_chladni = (function () { var max_num_chladni_points = null; var min_boundary = 0.0; var max_boundary = 3.0; // var max_boundary = 6.0; // var max_boundary = 10.0; // var max_boundary = 12.0; // var min_boundary = -10.0; // var max_boundary = 10.0; var maximum_acceptable_approx_to_zero = 0.4; // var maximum_acceptable_approx_to_zero = 0.1; var maximum_attempts = 100; var min_max = []; // var object_base_offset = -0.5; var object_base_offset = -0.7; var curr_chladni_vertex = 0; var curr_chladni_color_index = 0; // return function (gl, given_max_num_chladni_points) { var a1 = 3.0; var a2 = 5.0; var a3 = 9.0; var a4 = 13.0; // var manage_vars = { // a1 : 3.0, // a2 : 5.0, // a3 : 9.0, // a4 : 13.0 // }; var manage_vars = []; manage_vars.push(3.0); manage_vars.push(5.0); manage_vars.push(9.0); manage_vars.push(13.0); var incr_var_pos = 0.1; var incr_var_neg = -0.1; return { reset_chladni : function() { manage_vars[0] = 3.0; manage_vars[1] = 5.0; manage_vars[2] = 9.0; manage_vars[3] = 13.0; console.log("chladni reset"); }, recalc_vars : function(manage_vars, this_key, lastMouseX, lastMouseY) { // console.log("this_key " + this_key); var flag_subtract = true; if (this_key > 0 && this_key < 9) { var index_vars = this_key % 4; if (this_key > 4) { flag_subtract = false; } var curr_delta = (flag_subtract) ? incr_var_neg : incr_var_pos; manage_vars[index_vars] += curr_delta; // console.log("this_key " + this_key + " index_vars " + index_vars + " curr_delta " + curr_delta); } }, update_chladni : function(this_key, lastMouseX, lastMouseY) { do_chladni.recalc_vars(manage_vars, this_key, lastMouseX, lastMouseY); a1 = manage_vars[0]; a2 = manage_vars[1]; a3 = manage_vars[2]; a4 = manage_vars[3]; var x; var y; var z = 0.0; // var curr_chladni_vertex = 0; curr_chladni_vertex = 0; curr_chladni_color_index = 0; var curr_approx_to_zero; var curr_attempt; var best_approx_to_zero; do { x = Common_Utils.get_random_in_range_inclusive_float(min_boundary, max_boundary); y = Common_Utils.get_random_in_range_inclusive_float(min_boundary, max_boundary); best_approx_to_zero = FLT_MAX; curr_attempt = 0; do { // z = Common_Utils.get_random_in_range_inclusive_float(min_boundary, max_boundary); x = Common_Utils.get_random_in_range_inclusive_float(min_boundary, max_boundary); y = Common_Utils.get_random_in_range_inclusive_float(min_boundary, max_boundary); // curr_approx_to_zero = Math.sin( x * y) + Math.sin(y * z) + Math.sin(z * x); // OK nice // 0 = -(cos(x) + cos(y) + cos(z)) // curr_approx_to_zero = -Math.cos( x) + Math.cos(y) + Math.cos(z); // schwartz // chladni curr_approx_to_zero = (Math.sin( a1 * x) * Math.sin( a2 * y)) + (Math.sin( a2 * x) * Math.sin( a1 * y)) - (Math.sin( a3 * x) * Math.sin( a4 * y)) - (Math.sin( a4 * x) * Math.sin( a3 * y)); if (Math.abs(curr_approx_to_zero) < best_approx_to_zero) { best_approx_to_zero = Math.abs(curr_approx_to_zero); } } while (best_approx_to_zero > maximum_acceptable_approx_to_zero && curr_attempt++ < maximum_attempts); // fprintf(stdout, "%d %d X %f Y %f best_z_so_far %f best approx %f\n", // curr_chladni_vertex, curr_attempt, x, y, best_z_so_far, best_approx_to_zero // ); if (curr_attempt < maximum_attempts) { // console.log('curr_chladni_vertex ', curr_chladni_vertex); // console.log('SIZE_DIM_3D ', SIZE_DIM_3D); // console.log('Z ', Z); // console.log('z ', z); object_handle[animals_chladni].vertices[curr_chladni_vertex*SIZE_DIM_3D + X] = x; object_handle[animals_chladni].vertices[curr_chladni_vertex*SIZE_DIM_3D + Y] = y; object_handle[animals_chladni].vertices[curr_chladni_vertex*SIZE_DIM_3D + Z] = z; Common_Utils.populate_min_max(min_max, x, y, z); curr_chladni_vertex++; } } while (curr_chladni_vertex < max_num_chladni_points); // -------- now normalize chladni from var diff_actual = min_max[max] - min_max[min]; var offset_chladni_x = object_handle[animals_chladni].pre_translate[0] + object_base_offset; // move into translation N rotation var offset_chladni_y = object_handle[animals_chladni].pre_translate[1] + object_base_offset; var offset_chladni_z = object_handle[animals_chladni].pre_translate[2] + object_base_offset; for (var curr_normalize_point = 0; curr_normalize_point < curr_chladni_vertex; curr_normalize_point++) { object_handle[animals_chladni].colors[curr_chladni_color_index + R] = (object_handle[animals_chladni].vertices[curr_normalize_point*SIZE_DIM_3D + X] / diff_actual); object_handle[animals_chladni].colors[curr_chladni_color_index + G] = (object_handle[animals_chladni].vertices[curr_normalize_point*SIZE_DIM_3D + Y] / diff_actual); object_handle[animals_chladni].colors[curr_chladni_color_index + B] = (object_handle[animals_chladni].vertices[curr_normalize_point*SIZE_DIM_3D + Z] / diff_actual); object_handle[animals_chladni].colors[curr_chladni_color_index + A] = 1.0; object_handle[animals_chladni].vertices[curr_normalize_point*SIZE_DIM_3D + X] = (object_handle[animals_chladni].vertices[curr_normalize_point*SIZE_DIM_3D + X] / diff_actual) + offset_chladni_x; object_handle[animals_chladni].vertices[curr_normalize_point*SIZE_DIM_3D + Y] = (object_handle[animals_chladni].vertices[curr_normalize_point*SIZE_DIM_3D + Y] / diff_actual) + offset_chladni_y; object_handle[animals_chladni].vertices[curr_normalize_point*SIZE_DIM_3D + Z] = (object_handle[animals_chladni].vertices[curr_normalize_point*SIZE_DIM_3D + Z] / diff_actual) + offset_chladni_z; // console.log(object_handle[animals_chladni].vertices[curr_normalize_point*SIZE_DIM_3D + X], // object_handle[animals_chladni].vertices[curr_normalize_point*SIZE_DIM_3D + Y], // object_handle[animals_chladni].vertices[curr_normalize_point*SIZE_DIM_3D + Z] // ); curr_chladni_color_index += SIZE_DIM_COLORS; } }, init_chladni : function (gl, given_max_num_chladni_points) { max_num_chladni_points = given_max_num_chladni_points; // sin(x y) + sin(y z) + sin(z x) = 0 // was schwartz // sin(x y) + sin(y z) + sin(z x) = 0 // chladni // ------- here are others yet to be implemented : // https://developer.mozilla.org/ms/demos/detail/3d-grapher-with-fullscreen // z = cos(x*2)*cos(y*2) http://www.math.uri.edu/~bkaskosz/flashmo/graph3d/ // // ------- and another // // https://developer.mozilla.org/ms/demos/detail/implicit-equation-3d-grapher // 0 = -(cos(x) + cos(y) + cos(z)) // ---------------------- object_handle[animals_chladni].vertices = new Float32Array(max_num_chladni_points * SIZE_DIM_3D); object_handle[animals_chladni].colors = new Float32Array(max_num_chladni_points * SIZE_DIM_COLORS); // var best_approx_to_zero; // var maximum_acceptable_approx_to_zero = 0.1; // var maximum_attempts = 100; // var curr_attempt; // var min_max = []; Common_Utils.init_min_max(min_max); // var object_handle[animals_chladni] = {}; object_handle[animals_chladni].min_max = min_max; object_handle[animals_chladni].want_translate = true; // object_handle[animals_chladni].want_translate = false; // object_handle[animals_chladni].pre_translate = [ 1.5, 2.5, 1.5]; // object_handle[animals_chladni].pre_translate = [ 1.5, 2.5, 0.5]; // object_handle[animals_chladni].pre_translate = [ 1.5, 4.5, 0.5]; // object_handle[animals_chladni].pre_translate = [ 1.0, 4.5, 0.5]; // object_handle[animals_chladni].pre_translate = [ 1.0, 4.5, 0.0]; // object_handle[animals_chladni].pre_translate = [ 1.0, 3.5, 0.0]; // object_handle[animals_chladni].pre_translate = [ 2.0, 0.5, -2.0]; // object_handle[animals_chladni].pre_translate = [ 0.0, 0.0, 0.0]; // object_handle[animals_chladni].pre_translate = [ 0.0, 3.0, 0.0]; object_handle[animals_chladni].pre_translate = [ 0.0, 5.0, 0.0]; object_handle[animals_chladni].post_translate = Common_Utils.negate_array(object_handle[animals_chladni].pre_translate); // object_handle[animals_chladni].rotation_array = [0.09, 0.08, -0.11]; object_handle[animals_chladni].rotation_array = [0.19, -0.18, 0.11]; // update logic was here do_chladni.update_chladni(); // console.log("curr_chladni_vertex " + curr_chladni_vertex); // object_handle[animals_chladni].count = curr_chladni_vertex; object_handle[animals_chladni].count = max_num_chladni_points; object_handle[animals_chladni].vertex_position_buffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, object_handle[animals_chladni].vertex_position_buffer); gl.bufferData(gl.ARRAY_BUFFER, object_handle[animals_chladni].vertices, gl.STATIC_DRAW); object_handle[animals_chladni].vertex_position_buffer.itemSize = SIZE_DIM_3D; object_handle[animals_chladni].vertex_position_buffer.numItems = max_num_chladni_points; // --- object_handle[animals_chladni].vertex_color_buffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, object_handle[animals_chladni].vertex_color_buffer); gl.bufferData(gl.ARRAY_BUFFER, object_handle[animals_chladni].colors, gl.STATIC_DRAW); object_handle[animals_chladni].vertex_color_buffer.itemSize = SIZE_DIM_COLORS; object_handle[animals_chladni].vertex_color_buffer.numItems = max_num_chladni_points; } }; }()); // init_chladni var get_object_handle = function() { return object_handle; }; var get_all_object_labels = function() { return all_object_labels; }; return { // to make visible to calling reference frame list function here // init_chladni : init_chladni, do_chladni : do_chladni, get_object_handle : get_object_handle, get_all_object_labels : get_all_object_labels }; }(); // chladni_obj = function()