UNPKG

@sohale/implisolid

Version:

A Solid Modelling Kernel in Javascript based on Implicit Surfaces, for MP5 file format

1,393 lines (1,123 loc) 74.1 kB
<html> <head> <meta charset="utf-8"/> </head> <style> .stat-panel{ position:fixed; top:0px; right:0px; width:100px; /* z-index:1000; */ } </style> <body> <canvas id="my_canvas"></canvas> <!-- <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r77/three.js"> </script> --> <!--script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r73/three.js"> </script--> <!--<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r71/three.js"> </script>--> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r79/three.js"> </script> <script type="text/javascript" src="./three_r79.js"> </script> <!-- <script type="text/javascript" src="./three-r77.js"></script> --> <!--script type="text/javascript" src="https://raw.githubusercontent.com/mrdoob/three.js/69079243426506ed86d0d0ea71b4fdda9dbb2f88/examples/js/controls/OrbitControls.js"></script --> <!-- Refused to execute script '...' because its MIME type ('text/plain') is not executable, and strict MIME type checking is enabled. --> <script> function assert(cond, message) { if (!cond) { console.error(message); throw new Exception("assert ", message); } } function _expect(cond, message) { if (!cond) { console.error(message); } } </script> <script> /** Asynchronously does a series of calls to the function update_mc(). */ var callMultipleTimes = function() { // private: var last_active = 0; var intervals_counter = 0; function function_body(implisolid_, update_callback, burst_count, interval_msec) { /** Asynchronously does a series of calls to the function update_callback(). Previous name: update_mc_mul tiple() */ var BURST_COUNT = burst_count; //2; // 50; var INTERVAL_MSEC = interval_msec; //8-1; //40 // 1 // in Milliseconds // Works well on too small values of INTERVAL_MSEC (Semaphore). // The main algorithm performs much faster when this interval is larger (>100). Becasue of `gc`. var already_busy_doing_it=0; // semaphore. (Refractory). Fast x1. var burst_counter = 0; intervals_counter++; if(intervals_counter>1) //dont start if there is already one running { intervals_counter--; return; } last_active = setInterval ( function() { if(!last_active) console.error("!last_active"); burst_counter++; // mc_icounter console.error(BURST_COUNT); if(burst_counter<BURST_COUNT) //This code is amazingly similar to Bursting dyamics in neurons. { if(already_busy_doing_it<1) //removable { already_busy_doing_it++; update_callback(implisolid_, 0.2/10.*5 /5.); if(already_busy_doing_it>1) console.error(">>>already_busy_doing_it:"+already_busy_doing_it); if(!last_active) console.error("!last_active"); already_busy_doing_it--; }else{ console.log("hit"); } } else { // The interval has finished its job. Time to go. if(!last_active) console.error("!last_active"); clearInterval(last_active); // But then don't we need to wait until the last one is finished? intervals_counter--; // Allow next one in future burst_counter = 0; last_active = 0; } }, INTERVAL_MSEC ); } return function_body; }(); </script> <!--script type="text/javascript" src="./ww_geometry77.js"></script--> <script type="text/javascript" src="../js_iteration_2/geometry79.js"></script> <!--<script type="text/javascript" src="../js_iteration_2/geometry73.js"></script>--> <script> // Default (mock) OrbitControl to void breaking the program if the orbitcontrol is not found. THREE.OrbitControls = function() { this.target = new THREE.Vector3(); this.addEventListener = function(){}; } </script> <script type="text/javascript" src="./controls/OrbitControls_r79.js"></script> <!-- <script type="text/javascript" src="../js_iteration_2/bbox_calculations.js"></script> --> <!--<body>--> This file uses ImpliSolid's Geometry class. (unlike <a href="mcc2_3js.html">mcc2_3js.html</a>) <br> <script> 'use strict'; const THREEJS_R71 = "r71"; const THREEJS_R77 = "r77"; const THREEJS_R79 = "r79"; const threejs_rev = THREEJS_R79; var produce_object; var main; // Thi method creates an object which is identical to ImpliSolid object in implisolid.js // Todo: merge these two and remove this. // polygoniser_service function init_polygonizer() { //too late for pre-run //Module.preRun.push(letmeknow,memoryprofiler_add_hooks, letmeknow = function (){console.log("ok");}); //Module={preRun:[letmeknow, memoryprofiler_add_hooks]}; //main = Module.cwrap('main', 'number', []); // produce_object = Module.cwrap('produce_object_old2', null, ['number', 'number', 'number', 'number', 'number']); var s_service={}; s_service.build_geometry = Module.cwrap('build_geometry', null, [ 'string', 'string']); s_service.get_v_size = Module.cwrap('get_v_size', 'number', []); s_service.get_f_size = Module.cwrap('get_f_size', 'number', []); s_service.get_v = Module.cwrap('get_v', null, ['number']); s_service.get_f = Module.cwrap('get_f', null, ['number']); s_service.get_v_ptr = Module.cwrap('get_v_ptr', 'number', []); s_service.get_f_ptr = Module.cwrap('get_f_ptr', 'number', []); s_service.finish_geometry = Module.cwrap('finish_geometry', null, []); s_service.set_object = Module.cwrap('set_object', 'number', ['string', 'number']); s_service.unset_object = Module.cwrap('unset_object', 'number', ['number']); s_service.set_x = Module.cwrap('set_x', 'number', ['number', 'number']); s_service.unset_x = Module.cwrap('unset_x', null, []); s_service.calculate_implicit_values = Module.cwrap('calculate_implicit_values', null, []); s_service.get_values_ptr = Module.cwrap('get_values_ptr', 'number', []); s_service.get_values_size = Module.cwrap('get_values_size', 'number', []); s_service.calculate_implicit_gradients = Module.cwrap('calculate_implicit_gradients', null, []); s_service.get_gradients_ptr = Module.cwrap('get_gradients_ptr', 'number', []); s_service.get_gradients_size = Module.cwrap('get_gradients_size', 'number', []); s_service.get_pointset_ptr = Module.cwrap('get_pointset_ptr', 'number', ['string']); s_service.get_pointset_size = Module.cwrap('get_pointset_size', 'number', ['string']); s_service.about = Module.cwrap('about', null, []); s_service.init = function(){ s_service.needs_deallocation = false; } s_service.finish_with = function (){ //after the last round. if(!implisolid_.needs_deallocation) console.error("cannot `finish_geometry()`. Geometry not produced."); //todo: try-catch //d(1); implisolid_.finish_geometry(); implisolid_.needs_deallocation = false; //todo(sohail): Why implisolid_ is used here? We should use 'this'. } s_service.set_vect = function (float32Array){ if (float32Array.length % 3 != 0) {console.error("bad input array");}; var nverts = float32Array.length / 3; const _FLOAT_SIZE = Float32Array.BYTES_PER_ELEMENT; var verts_space = Module._malloc(_FLOAT_SIZE*3*nverts); Module.HEAPF32.subarray(verts_space/_FLOAT_SIZE, verts_space/_FLOAT_SIZE + 3*nverts).set(float32Array); var result = this.set_x(verts_space, nverts); console.log("set_x() result: "+result); if (!result) {console.error("Something went wrong: ", result);} Module._free( verts_space ); } s_service.update_geometry = function(geometry, ignoreNormals) { var implicit_service = this; const _FLOAT_SIZE = Float32Array.BYTES_PER_ELEMENT; const _INT_SIZE = Uint32Array.BYTES_PER_ELEMENT; const POINTS_PER_FACE = 3; var nverts = implicit_service.get_v_size(); var nfaces = implicit_service.get_f_size(); if(nfaces > 0){ var verts_address = implicit_service.get_v_ptr(); var faces_address = implicit_service.get_f_ptr(); var verts = Module.HEAPF32.subarray( verts_address/_FLOAT_SIZE, verts_address/_FLOAT_SIZE + 3*nverts); var faces = Module.HEAPU32.subarray( faces_address/_INT_SIZE, faces_address/_INT_SIZE + nfaces * POINTS_PER_FACE); } else{ console.log("empty implicit"); var verts = new Float32Array([0,0,0, 1,0,0, 1,1,0, 0,1,0, 0,0,1, 1,0,1, 1,1,1, 0,1,1 ]); var faces = new Uint32Array([0,1,2, 0,2,3, 0,4,5, 0,5,1, 1,5,6, 1,6,2, 2,6,3, 3,6,7, 4,5,6, 5,6,7]); } return geometry.update_geometry1(verts, faces, ignoreNormals, false); }; s_service.make_normals_into_geometry = function(geom, mp5_str, x, ignore_root_matrix) { var implicit_service = s_service; const _FLOAT_SIZE = Float32Array.BYTES_PER_ELEMENT; var result1 = implicit_service.set_object(mp5_str, ignore_root_matrix); console.log("SET_OBJECT() RESULTS:", result1); implicit_service.set_vect(x); // overhead implicit_service.calculate_implicit_gradients(true); // Why TRUE doe snot have any effect? var ptr = implicit_service.get_gradients_ptr(); var ptr_len = implicit_service.get_gradients_size(); var gradients = Module.HEAPF32.subarray(ptr/_FLOAT_SIZE, ptr/_FLOAT_SIZE + ptr_len); //console.log("grad len = " + ptr_len+ " grad = " + gradients); // x 4 //for( var i = 0 ; i < ptr_len; i++) { // gradients[i] += Math.random() * 0.2; //} /* for( var i = 0 ; i < ptr_len; i++) { gradients[i] += (Math.random()*2-1) * 0.2*10; } */ /* for( var i = 0 ; i < ptr_len/3; i++) { var x = gradients[i * 3 + 0 ]; var y = gradients[i * 3 + 1 ]; var z = gradients[i * 3 + 2 ]; gradients[i * 3 + 0 ] = z; gradients[i * 3 + 1 ] = x; gradients[i * 3 + 2 ] = y; } */ geom.update_normals_from_array(gradients); implicit_service.unset_x(); var result1 = implicit_service.unset_object(1); console.log("UNSET_OBJ() RESULTS:", result1); }; s_service.init(); //console.log("ok"); return s_service; } </script> <script> 'use strict'; function setShapeMatrix2Eye(shape_matrix, sz) { if (typeof sz == "undefined") sz = 1.0; for(var ii=0; ii<16; ii++) { shape_matrix[0] = 0; } shape_matrix[0] = 1 * sz; shape_matrix[5] = 1 * sz; shape_matrix[10] = 1 * sz; shape_matrix[15] = 1; shape_matrix[3] = 0; shape_matrix[7] = 0; shape_matrix[11] = 0; } </script> <script> var MP5_GENERIC_EXAMPLE_MOON = { "printerSettings":{ "name":"test", "layerThickness":0.2, "emptyLayer":0, "infillSpace":4, "topThickness":0.6, "paramSamples":75, "speedRate":1000, "circleSpeedRate":1000, "temperature":220, "inAirSpeed":7000, "flowRate":0.035, "criticalLength":35, "retractionSpeed":2400, "retractionLength":5, "shellNumber":3, "material":"PLA 2.85mm", "autoZScar":true, "zScarGap":0.5, "critLayerTime":6, "filamentDiameter":2.85 }, "mp5-version":"0.3", "root":{ "type":"root", "children":[ { "type":"Difference", "protected":false, "children":[ { "type":"cylinder", "displayColor":{ "x":0.77, "y":0.04, "z":0.18 }, "matrix":[ 42.5, 0, 0, 0, 0, 49.6, 0, 0, 0, 0, 10, 0, 0, 0, 0, 1 ], "index":652818 }, { "type":"Difference", "protected":false, "children":[ { "type":"cylinder", "displayColor":{"x":0.82, "y":0.66, "z":0.74 }, "matrix":[10, 0, 0, 0, 0, 10, 0, 0, 0, 0, 10, 0, 0, 0, 0, 1], "index":1272174 }, { "type":"cylinder", "displayColor":{"x":0.11, "y":0.076,"z":0.63 }, "matrix":[10, 0, 0, 0.66, 0, 10, 0, 6.22, 0, 0, 10, 0.00001, 0, 0, 0, 1 ], "index":2463576 } ], "displayColor":{ "x":0.66, "y":0.45, "z":0.72 }, "matrix":[2.38, 0, 0, 0.36, 0, 2.38, 0, 0.56, 0, 0, 2.38, 6.9, 0, 0, 0, 1], "index":413872 } ], "displayColor":{"x":0.55, "y":0.07, "z":0.12 }, "matrix":[ 1, 0, 0, 0.33, 0, 1, 0, 0.156, 0, 0, 1, 0.000000000000014, 0, 0, 0, 1], "index":6565922 } ] } }; var sz0 = 100.0; var HEART = '{"printerSettings":{"name":"test","layerThickness":0.2,"emptyLayer":0,"infillSpace":4,"topThickness":0.6,"paramSamples":75,"speedRate":1000,"circleSpeedRate":1000,"temperature":220,"inAirSpeed":7000,"flowRate":0.035,"criticalLength":35,"retractionSpeed":2400,"retractionLength":5,"shellNumber":3,"material":"PLA 2.85mm","autoZScar":true,"zScarGap":0.5,"critLayerTime":6,"filamentDiameter":2.85},"mp5-version":"0.3","root":{"type":"root","children":[{"type":"Union","protected":false,"children":[{"type":"cylinder","displayColor":{"x":0.9661750055896976,"y":0.8085857086202395,"z":0.41578037212168595},"matrix":[10,0,0,-3.7368777450135866,0,10,0,-1.9559832356144682,0,0,10,1.7323194345664206e-7,0,0,0,1],"index":7575510},{"type":"cube","displayColor":{"x":0.23399071378141634,"y":0.31584816496653323,"z":0.35457351563365425},"matrix":[10,0,0,1.867397834493545,0,10,0,-1.7325527119763677,0,0,10,-9.734106853898084e-10,0,0,0,1],"index":5587759},{"type":"cylinder","displayColor":{"x":0.43814645627496795,"y":0.39556472441055845,"z":0.3415798414286939},"matrix":[10,0,0,1.8694799105200275,0,10,0,3.688535947590836,0,0,10,-1.7225853365943067e-7,0,0,0,1],"index":6657333}],"initialSize":{"x":1,"y":1,"z":1},"displayColor":{"x":0.6470588235294118,"y":0.2784313725490196,"z":0.5882352941176471},"matrix":[10.0,0,0,82.63768850593796,0,10.0,0,126.37324151118989,0,0,10.0,5.000000079354265,0,0,0,1],"index":4872526}]}}'; HEART = JSON.parse(HEART); setShapeMatrix2Eye(HEART.root.children[0].matrix, sz0); HEART = JSON.stringify(HEART); var MOON = '{"printerSettings":{"name":"test","layerThickness":0.2,"emptyLayer":0,"infillSpace":4,"topThickness":0.6,"paramSamples":75,"speedRate":1000,"circleSpeedRate":1000,"temperature":220,"inAirSpeed":7000,"flowRate":0.035,"criticalLength":35,"retractionSpeed":2400,"retractionLength":5,"shellNumber":3,"material":"PLA 2.85mm","autoZScar":true,"zScarGap":0.5,"critLayerTime":6,"filamentDiameter":2.85},"mp5-version":"0.3","root":{"type":"root","children":[{"type":"Difference","protected":false,"children":[{"type":"cylinder","displayColor":{"x":0.7675997200783986,"y":0.03892568708507049,"z":0.1754374135888661},"matrix":[35,0,0,0,0,35,0,0,0,0,9,0,0,0,0,1],"index":652818},{"type":"Difference","protected":false,"children":[{"type":"cylinder","displayColor":{"x":0.8122645344236872,"y":0.657334404743416,"z":0.7357336310755096},"matrix":[10,0,0,0,0,10,0,0,0,0,10,0,0,0,0,1],"index":1272174},{"type":"cylinder","displayColor":{"x":0.11421729990684737,"y":0.07562705374348999,"z":0.6324600862122098},"matrix":[10,0,0,0.658889604636343,0,10,0,6.215549332615993,0,0,10,1.3327027659215673e-7,0,0,0,1],"index":2463576}],"initialSize":{"x":1,"y":1,"z":1},"displayColor":{"x":0.6627450980392157,"y":0.4549019607843137,"z":0.7215686274509804},"matrix":[2.381193509886417,0,0,0.3600215429489424,0,2.381193509886417,0,0.5604901669421452,0,0,2.381193509886417,6.9059681360437395,0,0,0,1],"index":413872}],"initialSize":{"x":1,"y":1,"z":1},"displayColor":{"x":0.5529411764705883,"y":0.06666666666666667,"z":0.11764705882352941},"matrix":[1,0,0,0.32938436512727,0,1,0,0.15604124684634,0,0,1,0.000000000000014,0,0,0,1],"index":6565922}]}}'; var SIMPLE_CONE = '{"printerSettings":{},"mp5-version":"0.3","root":{"type":"root","children":[{"type":"icone","displayColor":{"x":0.7,"y":0.7,"z":0.7},"matrix":[8,0,0,0,0,8,0,0,0,0,8,0,0,0,0,1],"index":9185154}]}}'; </script> <script> 'use strict'; //'use asm'; //'use strict'; //Version 1 has flaws: _free()s before returning the verts. //var CALL_VERSION = 2; //1 or 2 const VERBOSE = false; //todo: reaplce _FLOAT_SIZE with Float32Array. //const _FLOAT_SIZE = 4; //Float32Array.BYTES_PER_ELEMENT //const _INT_SIZE = 4; var global_time = 0; 'use strict'; var global_verts_copy = null; var global_gradients_copy = null; // const MESH_SCALE = 300/10; const MESH_SCALE = 1.0; const ARROWS_COUNT = 20*10; var global_mp5 = "***"; function provide_input (subjective_time, is_update_mode) { // is_update_mode: 0 => init // is_update_mode: 1 => update // is_update_mode: 2 => deprecated (used in make_geometry_old1() ) // asked for: var shape_json, polygonization_json; const DONT_CHANGE = false; // should be false if (DONT_CHANGE || is_update_mode == 0) { var r = subjective_time; // var ellipsoid_radius = 8.0 * 0.1; // r; var ellipsoid_radius = 8.0; // r; var sphere_dict1 = { type: "ellipsoid", //radius: subjective_time, matrix:[ ellipsoid_radius, 0,0, 0, 0,ellipsoid_radius, 0, 0, 0,0,ellipsoid_radius * 0.5 , 0, 0,0,0, 1] }; var sphere_dict = { type: "Union", matrix:[ 1, 0,0, 0, 0,1, 0, 0, 0,0,1, 0, 0,0,0, 1], children: [sphere_dict1, sphere_dict1] }; //global_mp5 = mp5_json_0; var mp5_json_sphere_dict= JSON.parse(JSON.stringify(MP5_GENERIC_EXAMPLE_MOON)); mp5_json_sphere_dict.root.children=[sphere_dict]; var SPHERE = JSON.stringify(mp5_json_sphere_dict); // console.log(SPHERE); var tetrahedron_dict = { type: "tetrahedron", corners: [[0, 0, 5],[0, 10, 0],[10, 0, 0],[0, 0, -5]], matrix:[ 1, 0,0, 0, 0,1, 0, 0, 0,0,1, 0, 0,0,0, 1] }; var mp5_json_tetrahedron_dict= JSON.parse(JSON.stringify(MP5_GENERIC_EXAMPLE_MOON)); mp5_json_tetrahedron_dict.root.children=[tetrahedron_dict]; var TETRAHEDRON = JSON.stringify(mp5_json_tetrahedron_dict); // Select the object to display // var mp5_json = HEART; const BB_SIZE = 9; // var mp5_json = MOON; const BB_SIZE = 9+9; // var mp5_json = TETRAHEDRON; const BB_SIZE = 9; // var mp5_json = SPHERE; const BB_SIZE = 9; var mp5_json = SIMPLE_CONE; const BB_SIZE = 12.0/10.0; var shape_dict = JSON.parse(mp5_json).root.children[0]; if(is_update_mode == 0) { var sz = 1.; } else { var sz = r; } /* HEART.root.children[0].matrix[0] = sz; HEART.root.children[0].matrix[5] = sz; HEART.root.children[0].matrix[10] = sz; */ // Scale the object shape_dict.matrix[0] = sz; shape_dict.matrix[5] = sz; shape_dict.matrix[10] = sz; /* // Move the object shape_dict.matrix[3] = 0; shape_dict.matrix[7] = 0; shape_dict.matrix[11] = 0; */ if(false) { setShapeMatrix2Eye(shape_dict.matrix); } //var bb = getBoundingBoxForTree(); mp5_json = JSON.stringify(shape_dict); global_mp5 = mp5_json; console.log(mp5_json); var x0=0, y0=0, z0=0; //var BB_SIZE = 18; //const BB_SIZE = 9; var mc_properties_json = JSON.stringify({ resolution: Math.floor(28/2*2/2*2 /4*4 /2 ), box: {xmin: x0-BB_SIZE, xmax: x0+BB_SIZE, ymin: y0-BB_SIZE , ymax: y0+BB_SIZE, zmin: z0-BB_SIZE, zmax: z0+BB_SIZE}, ignore_root_matrix: false, /* vresampl: {iters: 3, c: 1.0}, projection: {enabled: 1}, qem: {enabled: 1}, */ vresampl: {iters: 3, c: 1.0}, projection: {enabled: 1}, qem: {enabled: 1}, subdiv: {enabled: 1}, //overall_repeats: 3, overall_repeats: 3, debug: { enabled_pointsets: 0, // only_rank post_subdiv_noise: 0.0, }, // bug: When vresampl.iters is large, the centroid projection projects into 0 (0,0,0) }); shape_json = mp5_json; polygonization_json = mc_properties_json; var tuple = [shape_json, polygonization_json]; return tuple; } //Alternatively, use a growing sphere only. if(is_update_mode == 1 || is_update_mode == 2) { //d("2 G."); var x0=0, y0=0, z0=0; const BB_SIZE = 9; var r = subjective_time * 5; //var BB_SIZE = 6.; var mc_properties_json = JSON.stringify({ resolution: 14*2 / 2 * 2, // 28, box: {xmin: x0-BB_SIZE, xmax: x0+BB_SIZE, ymin: y0-BB_SIZE , ymax: y0+BB_SIZE, zmin: z0-BB_SIZE, zmax: z0+BB_SIZE}, ignore_root_matrix: false, // makes things very slow vresampl: {iters: 1, c: 1.0}, projection: {enabled: 1}, qem: {enabled: 1}, }); //implisolid_.build_geometry( 28, mc_properties_json, "sphere", subjective_time); /* var mp5_json = JSON.stringify({ type: "ellipsoid", //radius: r, //boudbl_mushroom only matrix:[ r, 0,0, x0, 0,r, 0, y0, 0,0, r, z0, 0,0,0, 1] }); shape_json = mp5_json; */ var d = JSON.parse(global_mp5); var updated_size = r / 10.; d.matrix[0] = updated_size; d.matrix[5] = updated_size; d.matrix[10] = updated_size; shape_json = JSON.stringify(d);; // shape_json = global_mp5; polygonization_json = mc_properties_json; //global_mp5 is not updated here. It is the original object before the update. var tuple = [shape_json, polygonization_json]; return tuple; } /* if(is_update_mode == 2) { //not used anymore //console.log(implisolid_); //d("2 G.."); var x0=0, y0=0, z0=0; var r = subjective_time; var mc_properties_json = JSON.stringify({ resolution: 28, box: {xmin: x0-1, xmax: x0+1, ymin: y0-1 , ymax: y0+1, zmin: z0-1, zmax: z0+1} }); var mp5_json = JSON.stringify({ type: "egg", //radius: 3.0, //double_mushroom only matrix:[ r, 0,0, x0, 0,r, 0, y0, 0,0,r, z0, 0,0,0, 1] }); shape_json = mp5_json; polygonization_json = mc_properties_json; var tuple = [shape_json, polygonization_json]; return tuple; } */ } function prepare_gradients1(implicit_service, shape_json, verts) { var ignore_root_matrix = true; const _FLOAT_SIZE = Float32Array.BYTES_PER_ELEMENT; var result1 = implicit_service.set_object(shape_json, ignore_root_matrix); console.log("SET_OBJECT() RESULTS:", result1); implicit_service.set_vect(verts); // overhead implicit_service.calculate_implicit_gradients(true); // Why TRUE doe snot have any effect? var ptr = implicit_service.get_gradients_ptr(); var ptr_len = implicit_service.get_gradients_size(); var gradients = Module.HEAPF32.subarray(ptr/_FLOAT_SIZE, ptr/_FLOAT_SIZE + ptr_len); for( var i = 0 ; i < ptr_len; i++) { // gradients[i] += (Math.random() *2 -1.0 )* 0.2; } // geom.update_normals_from_array(gradients); return gradients; } function release_gradients1(implicit_service) { implicit_service.unset_x(); var result1 = implicit_service.unset_object(1); console.log("UNSET_OBJ() RESULTS:", result1); } // DRY 6 folds! function clone_array_float(verts) { var raw_buffer = new ArrayBuffer( Float32Array.BYTES_PER_ELEMENT * verts.length); var g = new Float32Array(raw_buffer); g.subarray(0, verts.length).set(new Float32Array(verts)); return g; } function concatenate_array_float(verts1, verts2) { var n1 = verts1.length; var n2 = verts2.length; var raw_buffer = new ArrayBuffer( Float32Array.BYTES_PER_ELEMENT * (n1 + n2) ); var verts12 = new Float32Array(raw_buffer); verts12.subarray(0, n1).set(new Float32Array(verts1)); verts12.subarray(n1, (n1+n2)).set(new Float32Array(verts2)); // deliberate bug for TDD return verts12; } function make_indices_for_n1_n2(n) { var n1 = n; var raw_buffer = new ArrayBuffer( Uint32Array.BYTES_PER_ELEMENT * (n1) * 3 ); var indices12 = new Uint32Array(raw_buffer); for (var i=0; i < n1; i++) { indices12[i * 3] = i; indices12[i * 3 + 1] = i + n1; //i + n1; indices12[i * 3 + 2] = i; //i + n1; } assert(indices12.length == n1 * 3); return indices12; } /* function clone_array_int(indices) { var raw_buffer = new ArrayBuffer( Uint32Array.BYTES_PER_ELEMENT * indices.length); var g = new Uint32Array(raw_buffer); g.subarray(0, indices.length).set(new Uint32Array(indices)); return g; } */ /* Three ways: 1- make_geometry_oldold() 2- make_geometry_old1() 3- make_geometry_new2() */ function make_geometry_new2(implisolid_, shape_json, polygonization_json, reusable_geometry, re_allocate_buffers) { //console.log(shape_json); //console.log(polygonization_json); // reusable_geometry is not used; var startTime = new Date(); if(implisolid_.needs_deallocation) { // Remove data from last round. //console.log("implisolid_.needs_deallocation " + implisolid_.needs_deallocation); //d(1); implisolid_.finish_geometry(); implisolid_.needs_deallocation = false; } else{ //console.error("Should not get here"); //implisolid_.finish_geometry(); //implisolid_.needs_deallocation = false; } //implisolid_.finish_geometry(); //d("2 G"); //28*2 --> 27 sec 28->3.75--7 msec? ////////////////////// //var mp5_json = ""; //var mc_properties_json = ""; //implisolid_.build_geometry( 28, mc_properties, "sphere", subjective_time); //implisolid_.build_geometry( mp5_json , mc_properties_json); try{ implisolid_.build_geometry( shape_json , polygonization_json); } catch(e) { console.error(e); Module={}; // avoids calling Module.dynCall_vii(), etc. } //implicit_double_mushroom center will be zero. implisolid_.needs_deallocation = true; var nverts = implisolid_.get_v_size(); var nfaces = implisolid_.get_f_size(); if(VERBOSE){ console.log(nverts); } var verts_address = implisolid_.get_v_ptr(); var faces_address = implisolid_.get_f_ptr(); //no need to free anymore! const _FLOAT_SIZE = Float32Array.BYTES_PER_ELEMENT; var verts = Module.HEAPF32.subarray(verts_address/_FLOAT_SIZE, verts_address/_FLOAT_SIZE + 3*nverts); const _INT_SIZE = Uint32Array.BYTES_PER_ELEMENT; var faces = Module.HEAPU32.subarray(faces_address/_INT_SIZE, faces_address/_INT_SIZE + 3*nfaces); /* // Uncomment for visualising the mesh's normals when set according to Implicit gradients. var gradients = prepare_gradients1(implisolid_, shape_json, verts); global_verts_copy = clone_array_float(verts); global_gradients_copy = clone_array_float(gradients); */ //verts[2] -= 0.1; //verts[2 + nverts*3-3] += 0.3; //var geom = new WGeometry77(verts, faces); //var geom = new MyBufferGeometry77(verts, faces, re_allocate_buffers); if(threejs_rev === THREEJS_R71) { var geom = new LiveBufferGeometry71(verts, faces, re_allocate_buffers); } else if(threejs_rev === THREEJS_R77) { var geom = new MyBufferGeometry77(verts, faces, re_allocate_buffers); } else if(threejs_rev === THREEJS_R79) { //LiveBufferGeometry79( verts_, faces_, pre_allocate_, min_faces_capacity_, min_verts_capacity_) var min_faces_capacity_ = 0, min_verts_capacity_ = 0; var geom = new LiveBufferGeometry79( verts, faces, re_allocate_buffers, min_faces_capacity_, min_verts_capacity_); //, gradients); // Alternative: specify normals at creation of LiveGeometry. But this is fine. //geom.update_geometry(implisolid_, true); implisolid_.update_geometry(geom, true); // Alternative: specify normals at creation of LiveGeometry. But this is fine. implisolid_.make_normals_into_geometry(geom, shape_json, verts, false); /* var n = implisolid_.get_pointset_size("post_p_centroids"); var centroids = get_emc_array( implisolid_.get_pointset_ptr("post_p_centroids") , n * 3 ); implisolid_.make_normals_into_geometry(geom, shape_json, centroids, false); */ } /* release_gradients1(implisolid_); */ if(VERBOSE){ console.log("nverts : "+ nverts); console.log("nfaces : "+ nfaces); } var endTime = new Date(); var timeDiff = endTime - startTime; //console.log("Time: "+timeDiff+ " msec."); report_time(timeDiff, function(){hist();}); return geom; } // todo: should work with point_count==0 function get_emc_array(verts_address, point_count) { // var verts_address = implisolid_.get_pointset_ptr(name); // var point_count = implisolid_.get_pointset_size(name); const _FLOAT_SIZE = Float32Array.BYTES_PER_ELEMENT; var float_array = Module.HEAPF32.subarray(verts_address/_FLOAT_SIZE, verts_address/_FLOAT_SIZE + 1 * point_count); // console.error(float_array); if (point_count == 0) { console.warn("Error: zero points", point_count); //return // null; // make_empty_lines_mesh(); } return float_array; } function make_pointset(implisolid_, name, point_size, color_r, color_g, color_b) { // r79 only // var point_size = 15.0; // millimeters var scale_up = 1.0; point_size = point_size !== undefined? point_size : 15.0; color_r = color_r !== undefined? color_r : 0.9; color_g = color_g !== undefined? color_g : 0.9; color_b = color_b !== undefined? color_b : 0.9; // var dx = Math.random() * 1.0 * scale_up * 1; // var dy = Math.random() * 1.0 * scale_up * 1; // var dz = Math.random() * 1.0 * scale_up * 1; // var dx = 1.0 * scale_up * 1; // var dy = 1.0 * scale_up * 1; // var dz = 1.0 * scale_up * 1; var dx = 0, dy = 0, dz = 0; /* var verts_address = implisolid_.get_pointset_ptr(name); var point_count = implisolid_.get_pointset_size(name); const _FLOAT_SIZE = Float32Array.BYTES_PER_ELEMENT; var verts = Module.HEAPF32.subarray(verts_address/_FLOAT_SIZE, verts_address/_FLOAT_SIZE + 3 * point_count); */ var point_count = implisolid_.get_pointset_size(name); if (point_count == 0) { return make_empty_lines_mesh(); } var verts = get_emc_array(implisolid_.get_pointset_ptr(name), 3 * point_count ); // console.error(verts); var geometry = new THREE.BufferGeometry(); var positions = verts; //new Float32Array( point_count * 3 ); var colors = new Float32Array( point_count * 3 ); for ( var i = 0; i < positions.length; i += 3 ) { positions[ i ] = positions[ i ] * scale_up + dx; positions[ i + 1 ] = positions[ i + 1 ] * scale_up + dy; positions[ i + 2 ] = positions[ i + 2 ] * scale_up + dz; } for ( var i = 0; i < positions.length; i += 3 ) { colors[ i ] = color_r; colors[ i + 1 ] = color_g; colors[ i + 2 ] = color_b; } geometry.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) ); geometry.addAttribute( 'color', new THREE.BufferAttribute( colors, 3 ) ); geometry.computeBoundingSphere(); //geometry is ready var material = new THREE.PointsMaterial( { size: point_size, vertexColors: THREE.VertexColors } ); var points = new THREE.Points( geometry, material ); return points; } function make_lines_mesh_v1(verts12, indices12, color) { if (indices12.length == 0) { console.error("Warning: indices12.length =", indices12.length); } var re_allocate_buffers; //var geom = new LiveBufferGeometry79( verts12, indices12, re_allocate_buffers=true, 0, 0); var geom = new LiveBufferGeometry79( new Float32Array(new ArrayBuffer(0)), new Uint32Array(new ArrayBuffer(0)), re_allocate_buffers="Deliberately Empty", 0, 0); geom.update_geometry1(verts12, indices12, true, true); var wireframe_material = new THREE.MeshBasicMaterial( { color: color, wireframe: true, opacity:0.9, transparent: true,} ); var wire_msh = new THREE.Mesh(geom, wireframe_material); return wire_msh; } function make_empty_lines_mesh() { return new THREE.LineSegments(new THREE.BoxGeometry(0.33333,0.3333333,0.33333333)); } function make_vectorfield_flow_lines_v1(implisolid_, name1, name2, point_size) { // works! // vector field flow /* var color_r, color_g, color_b; color_r = color_r !== undefined? color_r : 0.9; color_g = color_g !== undefined? color_g : 0.9; color_b = color_b !== undefined? color_b : 0.9; */ if (implisolid_.get_pointset_ptr(name1) == 0) { } var verts1 = get_emc_array(implisolid_.get_pointset_ptr(name1)+120*3*4*0, 3 * implisolid_.get_pointset_size(name1) + 0 ); var verts2 = get_emc_array(implisolid_.get_pointset_ptr(name2)+120*3*4*0, 3 * implisolid_.get_pointset_size(name2) + 0 ); var n1 = verts1.length / 3; var n2 = verts2.length / 3; if (n1 == 0) { return make_empty_lines_mesh(); } /* n1 = 4*10; n2 = 4*10; var debug_mode = true; verts1 = verts1.subarray(0, n1 * 3); verts2 = verts2.subarray(0, n2 * 3); */ var verts12 = concatenate_array_float(verts1, verts2); /* var raw_buffer = new ArrayBuffer( Float32Array.BYTES_PER_ELEMENT * (n1 + n2) * 3); var verts12 = new Float32Array(raw_buffer); // var verts12 = new Float32Array(n1 + n2); verts12.subarray(0, n1 * 3).set(new Float32Array(verts1)); verts12.subarray(n1 * 3, (n1+n2) * 3).set(new Float32Array(verts2)); // deliberate bug for TDD */ /* for( var i=0; i<n2; i++) { var b = (i+n1)*3; verts12[b + 0] += (Math.random()*2-1)*10; verts12[b + 1] += (Math.random()*2-1)*10; verts12[b + 2] += (Math.random()*2-1)*10; } */ if (n1 !== n2) { console.error("Need to have the same number of elements."); } /* // I don't use a geometry mesh with wiredframe. I use a LineSegments that uses a BufferGeometry var raw_buffer = new ArrayBuffer( Uint32Array.BYTES_PER_ELEMENT * (n1) * 2 ); var indices12 = new Uint32Array(raw_buffer); for (var i=0; i < n1; i++) { indices12[i * 2] = i; indices12[i * 2 + 1] = i ; //+ n1; //i+1; //i + n1; // indices12[i * 2] = 0; // indices12[i * 2 + 1] = i; } */ var indices12 = make_indices_for_n1_n2(n1); /* var raw_buffer = new ArrayBuffer( Uint32Array.BYTES_PER_ELEMENT * (n1) * 3 ); var indices12 = new Uint32Array(raw_buffer); for (var i=0; i < n1; i++) { indices12[i * 3] = i; indices12[i * 3 + 1] = i + n1; //i + n1; indices12[i * 3 + 2] = i; //i + n1; } assert(indices12.length == n1 * 3); */ var wire_msh = make_lines_mesh_v1(verts12, indices12, 0xffffff); /* var line_material = new THREE.LineBasicMaterial({ vertexColors: THREE.VertexColors }); var wire_msh = new THREE.LineSegments(geom, line_material); */ return wire_msh; } function make_vectorfield_flow_lines_v2(implisolid_, name1, name2, point_size) { // vector field flow. Without using LiveGEometry (and using LineSegments) // does not work /* var color_r, color_g, color_b; color_r = color_r !== undefined? color_r : 0.9; color_g = color_g !== undefined? color_g : 0.9; color_b = color_b !== undefined? color_b : 0.9; */ /* var positions = []; var next_positions_index = 0; var colors = []; var indices_array = []; */ var verts1 = get_emc_array(implisolid_.get_pointset_ptr(name1), 3 * implisolid_.get_pointset_size(name1) ); var verts2 = get_emc_array(implisolid_.get_pointset_ptr(name2), 3 * implisolid_.get_pointset_size(name2) ); var n1 = verts1.length / 3; var n2 = verts2.length / 3; assert(n1 > 0); var verts12 = concatenate_array_float(verts1, verts2); /* var raw_buffer = new ArrayBuffer( Float32Array.BYTES_PER_ELEMENT * (n1 + n2) * 3); var verts12 = new Float32Array(raw_buffer); // var verts12 = new Float32Array(n1 + n2); verts12.subarray(0, n1 * 3).set(new Float32Array(verts1)); verts12.subarray(n1 * 3, (n1+n2) * 3).set(new Float32Array(verts2)); // deliberate bug for TDD */ if (n1 !== n2) { console.error("Need to have the same number of elements."); } // I don't use a geometry mesh with wiredframe. I use a LineSegments that uses a BufferGeometry var raw_buffer = new ArrayBuffer( Uint16Array.BYTES_PER_ELEMENT * (n1) * 2 ); var indices12 = new Uint16Array(raw_buffer); for (var i=0; i < n1; i++) { indices12[i * 2] = i; indices12[i * 2 + 1] = i + n1; //i+1; //i + n1; } var raw_buffer = new ArrayBuffer( Float32Array.BYTES_PER_ELEMENT * (n1) * 3 ); var colors_ta = new Float32Array(raw_buffer); for (var i=0; i < n1; i++) { colors_ta[i * 3] = (i/10.0) % 1.0; colors_ta[i + 3 + 1] = (i/10.0) % 1.0; colors_ta[i + 3 + 2] = (i/10.0) % 1.0; } // var indices12 = new Uint16Array( indices_array ); // var verts12 = new Float32Array( positions ); // var colors_ta = new Float32Array( colors ); var geom = new THREE.BufferGeometry(); geom.setIndex( new THREE.BufferAttribute( indices12, 1 ) ); geom.addAttribute( 'position', new THREE.BufferAttribute( verts12, 3 ) ); geom.addAttribute( 'color', new THREE.BufferAttribute( colors_ta, 3 ) ); geom.computeBoundingSphere(); // var line_material = new THREE.LineBasicMaterial({ vertexColors: THREE.VertexColors }); var line_material = new THREE.MeshBasicMaterial( { color: 0xffffff, wireframe: true, opacity:0.8, transparent: true,} ); var wire_msh = new THREE.LineSegments(geom, line_material); return wire_msh; } function hairy_object_based_on_vectors(vects, gradients, alpha1, alpha2, color) { var n = gradients.length / 3; var n1 = vects.length / 3; assert(n == n1); var arrow_tips = new Float32Array(new ArrayBuffer( n * 3 * Float32Array.BYTES_PER_ELEMENT)); var arrow_bases = new Float32Array(new ArrayBuffer( n * 3 * Float32Array.BYTES_PER_ELEMENT)); for (var i = 0; i < n; ++i) { for (var d = 0; d < 3; d++) { var j = (i * 3) + d; arrow_tips[j] = vects[j] + alpha2 * gradients[j]; arrow_bases[j] = vects[j] + alpha1 * gradients[j]; } } var verts12 = concatenate_array_float(arrow_bases, arrow_tips); /* // repeated code var raw_buffer = new ArrayBuffer( Float32Array.BYTES_PER_ELEMENT * (n + n) * 3); var verts12 = new Float32Array(raw_buffer); verts12.subarray(0, n * 3).set(new Float32Array(arrow_bases)); verts12.subarray(n * 3, (n+n) * 3).set(new Float32Array(arrow_tips)); // */ var indices12 = make_indices_for_n1_n2(n); /* //repeated code var raw_buffer = new ArrayBuffer( Uint32Array.BYTES_PER_ELEMENT * (n) * 3 ); var indices12 = new Uint32Array(raw_buffer); for (var i=0; i < n; i++) { indices12[i * 3] = i; indices12[i * 3 + 1] = i + n; //i + n; indices12[i * 3 + 2] = i + n; //i + n; } assert(indices12.length == n * 3); */ var wire_msh = make_lines_mesh_v1(verts12, indices12, color) return wire_msh; } function visualise_normals(implisolid_, shape_json, pointset_label, alpha1, alpha2, color) { /* Draws lines from alpha1*grad to alpha2*grad. alpha1,2 are the start and end of the lines parallel to the gradients. Most likely negative alpha values are used. alpha=0 means points specified from the pointset specified by label pointset_label. Using color. Example: alpha1=0.0 and alpha2=-1.0 will draw normals (outwards). color = 0x88ff00; */ // todo: refactor var n = implisolid_.get_pointset_size(pointset_label); if (n == 0) { return make_empty_lines_mesh(); } var verts = get_emc_array(implisolid_.get_pointset_ptr(pointset_label), n * 3 ); // verts = arrow_bases // see update_arrows() var ignore_root_matrix = false; var mp5_str = shape_json; // console.error(mp5_str); var result1 = implisolid_.set_object(mp5_str, ignore_root_matrix); console.log("SET_OBJECT() RESULTS:", result1); implisolid_.set_vect(verts); implisolid_.calculate_implicit_gradients(); const _FLOAT_SIZE = Float32Array.BYTES_PER_ELEMENT; var ptr = implisolid_.get_gradients_ptr(); var ptr_len = implisolid_.get_gradients_size(); var gradients = Module.HEAPF32.subarray( ptr/_FLOAT_SIZE, ptr/_FLOAT_SIZE + ptr_len); assert(ptr_len == n*3); for (var i = 0; i < n; ++i) { var r = Math.sqrt(gradients[i*3 + 0] * gradients[i*3 + 0] + gradients[i*3 + 1] * gradients[i*3 + 1] + gradients[i*3 + 2] * gradients[i*3 + 2]); gradients[i*3 + 0] /= r; gradients[i*3 + 1] /= r; gradients[i*3 + 2] /= r; } var wire_msh = hairy_object_based_on_vectors(verts, gradients, alpha1, alpha2, color); /* var raw_buffer = new ArrayBuffer( n * 3 * Float32Array.BYTES_PER_ELEMENT); var arrow_tips = new Float32Array(raw_buffer); var raw_buffer = new ArrayBuffer( n * 3 * Float32Array.BYTES_PER_ELEMENT); var arrow_bases = new Float32Array(raw_buffer); for (var i = 0; i < n; ++i) { for (var d = 0; d < 3; d++) { var j = (i * 3) + d; arrow_tips[j] = verts[j] + alpha2 * gradients[j]; arrow_bases[j] = verts[j] + alpha1 * gradients[j]; } } // repeated code var raw_buffer = new ArrayBuffer( Float32Array.BYTES_PER_ELEMENT * (n + n) * 3); var verts12 = new Float32Array(raw_buffer); verts12.subarray(0, n * 3).set(new Float32Array(arrow_bases)); verts12.subarray(n * 3, (n+n) * 3).set(new Float32Array(arrow_tips)); // //repeated code var raw_buffer = new ArrayBuffer( Uint32Array.BYTES_PER_ELEMENT * (n) * 3 ); var indices12 = new Uint32Array(raw_buffer); for (var i=0; i < n; i++) { indices12[i * 3] = i; indices12[i * 3 + 1] = i + n; //i + n; indices12[i * 3 + 2] = i + n; //i + n; } assert(indices12.length == n * 3); var wire_msh = make_lines_mesh_v1(verts12, indices12, color) */ implisolid_.unset_x(); var result1 = implisolid_.unset_object(1); console.log("UNSET_OBJ() RESULTS:", result1); return wire_msh; } function my_assert(cond, text){if(!cond){console.error("ASSERT FAILED: "); if(text) console.log(text);}} //unload function update_reused_geometry(implisolid_, mp5_json, mc_properties_json, geometry) { //console.log(mp5_json); //console.log(mc_properties_json); var startTime = new Date(); //console.log(implisolid_.needs_deallocation); if(implisolid_.needs_deallocation) { // Remove data from last round. //d(1); implisolid_.finish_geometry(); implisolid_.needs_deallocation = false; } if(implisolid_.needs_deallocation) console.error("not deallocated."); try{ implisolid_.build_geometry( mp5_json , mc_properties_json); //implicit_double_mushroom center will be zero. implisolid_.needs_deallocation = true; }catch(err){ console.error("An error occured during MCC C++") console.info(err); }finally { } var ignore_normals = false // geometry. update_geometry (implisolid_, ignore_normals); implisolid_. update_geometry (geometry, ignore_normals); var endTime = new Date(); var timeDiff = endTime - startTime; //console.log(nv3 + " , " + nf3); //console.log("Time: "+timeDiff+ " msec."); report_time(timeDiff); } 'use strict'; //*************** Arrow Functions **************************** /* function make_arrow(){ // Create an arrow and add it to the scene. var dir = new THREE.Vector3( 10, 4, 0); var origin = new THREE.Vector3(0, 0, 0); var length = 10; var hex = 0xffff00; var arrowHelper = new THREE.ArrowHelper(dir, origin, length, hex); scene.add(arrowHelper); console.log("Arrow"); return arrowHelper; } */ function make_multiple_arrows(n) { /** * Create an arrow and add it to the scene. */ var arrowHelpers = []; for(var i=0;i<n;i++) { var dir = new THREE.Vector3( 10, 4, 0); var origin = new THREE.Vector3(0, 0, 0); var length = 10; var hex = 0xffff00; var arrowHelper = new THREE.ArrowHelper(dir, origin, length, hex); scene.add(arrowHelper); arrowHelpers.push(arrowHelper); console.log("Arrow"); } return arrowHelpers; } function update_arrows(arrows, implisolid_, mp5_str, n, ignore_root_matrix) { /** * Update the arrow parameters */ var vlist = new Float32Array(n*3); for(var i=0;i<n;i++) { var x = MESH_SCALE*10 * (Math.random()*2 - 1.); var y = MESH_SCALE*10 * (Math.random()*2 - 1.); var z = MESH_SCALE*10 * (Math.random()*2 - 1.); /*vlist.push(x); vlist.push(y); vlist.push(z);*/ vlist[i*3+0] = x; vlist[i*3+1] = y; vlist[i*3+2] = z; } //var _verts = new Float32Array([x, y, z]); //var _verts = new Float32Array(vlist); var _verts = vlist; assert(_verts instanceof Float32Array); var result1 = implisolid_.set_object(mp5_str, ignore_root_matrix); console.log("SET_OBJECT() RESULTS:", result1); implisolid_.set_vect(_verts); implisolid_.calculate_implicit_gradients(); const _FLOAT_SIZE = Float32Array.BYTES_PER_ELEMENT; var ptr = implisolid_.get_gradients_ptr(); var ptr_len = implisolid_.get_gradients_size(); var g = Module.HEAPF32.subarray(ptr/_FLOAT_SIZE, ptr/_FLOAT_SIZE + ptr_len); //console.log("grad len = " + ptr_len+ " grad = " + g); // x 4 var dir = null; for(var i=0;i<n;i++) { //if not bush var x = _verts[i*3 + 0]; var y = _verts[i*3 + 1]; var z = _verts[i*3 + 2]; var gx = g[i*3 + 0]; var gy = g[i*3 + 1]; var gz = g[i*3 + 2]; //implisolid_.unset_x(); //implisolid_.unset_object(1); //console.log("*****************************************") //console.log(arrow.position); //console.log("*****************************************") //arrow.setLength(200*Math.random()); var l = Math.sqrt(gx*gx + gy*gy + gz*gz); //l = l * 100/10000; //console.log("l: "+l); var ls = MESH_SCALE*1.5; arrows[i].position.set(x, y, z); arrows[i].setLength(ls); // This can easily get broken. i.e. by multiplying ls. if (!dir) { dir = new THREE.Vector3( 0, 0, 0); } dir.set(-gx/l, -gy/l, -gz/l); arrows[i].setDirection(dir); //console.log("change_arrow"); } implisolid_.unset_x(); var result1 = implisolid_.unset_object(1); console.log("UNSET_OBJ() RESULTS:", result1); } // ************************************************************** // global variables for meshes that are accessed and updated in the render loop, etc. var mesh_solid; var mesh2_tiny_box_wireframe; var m