UNPKG

@sohale/implisolid

Version:

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

1,475 lines (1,177 loc) 50.4 kB
<html> <head> <meta charset="utf-8"/> </head> <style> .stat-panel{ position:fixed; top:0px; right:0px; width:100px; /* z-index:1000; */ } .mycanvas { /* width: 100%; */ /* Will not work ion canvas, because the size is later changed by JS code. Note that "width=" attriute and css width are independent: one is the pixels resolution and the other one is appearance onle, regarless of the actual pixels (resolution). */ } </style> <body> <canvas class=mycanvas id="my_canvas"></canvas> <!-- To show the histogram: Uncomment the following <div> to reveal the histogram graph, also uncomment the line that says: //hist_delayed(); --> <div id="chart_div" class="stat-panel" no_style="width: 900px; height: 500px;"> </div> This file uses ImpliSolid's Geometry class. (unlike <a href="mcc2_3js.html">mcc2_3js.html</a>). <br/> Press SHIFT to animate. * </body> <!-- <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> // 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> function my_assert(cond, text){ if (!cond) { console.error("ASSERT FAILED: "); if(text) console.log(text); } } function my_assert(cond, message) { if (!cond) { if (message) console.error("assert failed: ", message); else console.error("assert failed"); throw new Error("assert failed: ", message); } } assert = my_assert; function _expect(cond, message) { if (!cond) { console.error(message); } } </script> <!-- function callMultipleTimes (implisolid_, update_callback, burst_count, interval_msec): --> <script type="text/javascript" src="../js_iteration_2/js/call_multiple_times.js"></script> <!--script type="text/javascript" src="./legacy/geometry77.js"></script--> <script type="text/javascript" src="../js_iteration_2/geometry79.js"></script> <!--<script type="text/javascript" src="../js_iteration_2/js/geometry73.js"></script>--> <!-- <script type="text/javascript" src="../js_iteration_2/bbox_calculations.js"></script> --> <script type="text/javascript" src="../js_iteration_2/implisolid_main.js"></script> <script type="text/javascript" src="../js_iteration_2/examples/js/example_objects.js"></script> <script type="text/javascript" src="../js_iteration_2/js/js_utils.js"></script> <!-- stuff used by pointset_utils.js --> <script type="text/javascript" src="../js_iteration_2/js/pointset_utils.js"></script> <script type="text/javascript" src="../js_iteration_2/js/arrow_utils.js"></script> <script type="text/javascript" src="../js_iteration_2/examples/js/example_materials.js"></script> <script type="text/javascript" src="../js_iteration_2/examples/js/performance_graphs.js"></script> <script type="text/javascript" src="../js_iteration_2/examples/js/misc_props.js"></script> <!-- Graph --> <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script> <!--<div id="chart_div" style="width: 900px; height: 500px;"></div>--> <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; </script> <!-- <script> // This 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={}; //destroying. for test s_service.__update_geometry = function(geometry, ignoreNormals) { // refactor as: get_latest_vf() 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={}; //destroying. for test s_service.init(); //console.log("ok"); //return s_service; return {}; } </script> --> <script> 'use strict'; </script> <script> </script> <script> 'use strict'; //'use asm'; //Version 1 has flaws: _free()s before returning the verts. //var CALL_VERSION = 2; //1 or 2 const VERBOSE = false; 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; //globals.global_mp5 = "***"; // some code moved into js_utils.js /* Three ways: 1- make_geometry_oldold() 2- make_geometry_old1() 3- make_geometry_new2() */ /* function ___make_geometry_new2(implisolid_, shape_json, polygonization_json, re_allocate_buffers, geom_callback) { //console.log(shape_json); //console.log(polygonization_json); // reusable_geometry =null, 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); var geom = geom_callback(verts,faces, re_allocate_buffers); var endTime = new Date(); var timeDiff = endTime - startTime; //console.log("Time: "+timeDiff+ " msec."); report_time(timeDiff, function(){hist();}); return geom; } */ var geom_callback__1 = function (verts, faces, re_allocate_buffers) { /* // 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. */ var min_faces_capacity_ = 0, min_verts_capacity_ = 0; // force zero initial allocation var geom = new LiveBufferGeometry79( verts, faces, re_allocate_buffers, min_faces_capacity_, min_verts_capacity_); //geom.update_geometry(implisolid_, true); //implisolid_.update_geometry(geom, true); IMPLICIT.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); IMPLICIT.make_normals_into_geometry(geom, shape_json, verts, false); /* var n = implisolid_.get_pointset_size("post_p_centroids"); var centroids = PS_UTILS.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); } return geom; } //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); // called after build_geometry() 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'; // ************************************************************** // global variables for meshes that are accessed and updated in the render loop, etc. var globals = {}; globals.mesh_solid = null; globals.mesh_wireframe = null; globals.normals = null; globals.arrows = null; globals.chosen_matrial = null; globals.global_mp5 = "***"; var mesh2_tiny_box_wireframe; var materials_list; //, material_f; var material_wireframe; //var last_geometry = null; // DEMO CONFIGURATIONS const CHOSEN_MATERIAL_INDEX = 2; //14; //2; nice //3; // 7 = colourful // 3 = ? //1: grayscale boring phong. //2: faceted. (good for debug / shape study) //3: colorful //4: semi opaque (good for debug / shape study) //6: striped //7: rainbow //8 is wireframe //9: plain white? //10: changing peach //11: changing cyan //12: ??? white? //13: proper Phong (As in WeDesign.Live) //14: Phong but semi-transparent const SHOW_WIREFRAME = false; const SHOW_SOLID = true; const PERSPECTIVE = false; function init_scene(IMPLICIT, shape_json, polygonization_json) { // determins the size & location of the grid, the location of the camera, and the size of the small cube in center (reference cube). var GRID_CELL_SIZE = 1.0; scene = new THREE.Scene(); //var WIDTH = 300, HEIGHT = 300; var WIDTH = window.innerWidth, HEIGHT = window.innerHeight - 0*200; //for memory profiler if (PERSPECTIVE) { camera = new THREE.PerspectiveCamera( 75, WIDTH / HEIGHT, 1, 10000 ); // ( fov, aspect, near, far ) } else { // Use Orthogaphic camera var span_per_pixel = 1.0/800.0*2000.0/30.0; var x0 = WIDTH/2.0*span_per_pixel; var y0 = HEIGHT/2.0*span_per_pixel; camera = new THREE.OrthographicCamera( -x0, +x0, -y0, +y0, 1, 10000 ); // ( left, right, top, bottom, near, far ) } camera.position.set(0, 0, 40*GRID_CELL_SIZE); // 40*25; //1000; // Grid var grid = grid_bed(GRID_CELL_SIZE); scene.add( grid ); materials_list = look_nice(); globals.chosen_matrial = materials_list[CHOSEN_MATERIAL_INDEX]; //globals.chosen_matrial = new THREE.MeshBasicMaterial( { // color: 0xaaffff, wireframe: false, opacity:0.5, transparent: true, // side:THREE.DoubleSide } ); //THREE.FrontSide or THREE.BackSide or THREE.DoubleSide. material_wireframe = new THREE.MeshBasicMaterial( { color: 0xff0000, wireframe: true, opacity:0.3, transparent: true,} ); // //if(delta_t === undefined) // var delta_t = 0.2; // // Subjective time! // global_time += delta_t; var geometry = null; //geometry = new THREE.BoxGeometry( 200, 200, 200 ); /* if(CALL_VERSION==1){ //geometry = make_geometry_oldold(shape_json, polygonization_json); } else */ { /* OLD geometry = make_geometry_new2(implisolid_, shape_json, polygonization_json, true, geom_callback__1); */ var ignore_root_matrix = false; console.warn("bad: ignore_root_matrix not known", ignore_root_matrix); geometry = IMPLICIT.getLiveGeometry_from_json(shape_json, polygonization_json, true, geom_callback__1, ignore_root_matrix); } //last_geometry = geometry; if(SHOW_WIREFRAME){ globals.mesh_wireframe = new THREE.Mesh( geometry, material_wireframe ); globals.mesh_wireframe.position.set( 0, 0, 0 ); globals.mesh_wireframe.scale.set( MESH_SCALE, MESH_SCALE, MESH_SCALE ); scene.add( globals.mesh_wireframe ); } //this.fromBufferGeometry( new THREE.SphereBufferGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) ); //material_f = new THREE.MeshBasicMaterial( { color: 0xffffff, wireframe: false, opacity:0.4, transparent: true } ); if(SHOW_SOLID){ //globals.mesh_solid = new THREE.Mesh( geometry, material_f ); //nice ones: 2, 3, (checked until 4) globals.mesh_solid = new THREE.Mesh( geometry, globals.chosen_matrial ); globals.mesh_solid.position.set( 0, 0, 0 ); globals.mesh_solid.scale.set( MESH_SCALE, MESH_SCALE, MESH_SCALE ); scene.add( globals.mesh_solid ); } /* var points2 = PS_UTILS.make_pointset("pre_resampling_vertices", 8.0 / 4.0, 0.9, 0.0, 0.0); // Red: before scene.add( points2 ); var points1 = PS_UTILS.make_pointset("post_resampling_vertices", 10.0 / 4.0, 0.9, 0.9, 0.0); // Yellow: after scene.add( points1 ); */ /* var points2 = PS_UTILS.make_pointset("pre_qem_verts", 2.0 / 30.0, 0.9, 0.0, 0.0); // Red: before scene.add( points2 ); */ /* var points1q = PS_UTILS.make_pointset("post_qem_verts", 2.5 / 30.0 * 6.0, 0.9, 0.9, 0.0); // Yellow: after scene.add( points1q ); */ var alpha1 = -0.3, alpha2 = -0.6; var norms_ = PS_UTILS.visualise_normals(shape_json, "post_p_centroids", alpha1, alpha2, 0x009900); // 0x00ff00 // 0x88ff00 if (norms_) { scene.add(norms_); } globals.normals = norms_; var points2 = PS_UTILS.make_pointset("pre_p_centroids", 8.0 / 4.0*2 / 30.0, 0.9, 0.0, 0.0); // Red: before // scene.add( points2 ); var points1 = PS_UTILS.make_pointset("post_p_centroids", 10.0 / 4.0 / 30.0, 0.9, 0.9, 0.0); // Yellow: after scene.add( points1 ); /* // "Centroid Projection"'s result. var vectorfield = PS_UTILS.make_vectorfield_flow_lines_v1("pre_p_centroids", "post_p_centroids"); scene.add( vectorfield ); */ // "QEM"'s result. var vectorfield = PS_UTILS.make_vectorfield_flow_lines_v1("pre_qem_verts", "post_qem_verts"); scene.add( vectorfield ); // Visualising the normal vectors as queried and applied on t geometry. Normal vector for vertices is a bad idea. Need to see how normal vectors can be specified for facets of BufferGeometry. if ( global_verts_copy && global_gradients_copy ) { var hairy_m = PS_UTILS.hairy_object_based_on_vectors(global_verts_copy, global_gradients_copy, 0.0, 1.0, 0x777700); scene.add( hairy_m ); } // choose what is visible and what is not // globals.mesh_solid.visible = false; // points1.visible = false; //points2.visible = false; // globals.mesh_wireframe.visible = false; // vectorfield.visiable = false; // norms_.visible = false; // globals.normals.visible = false; /* var points2 = PS_UTILS.make_pointset("pre_qem_verts", 8.0 / 4.0, 0.9, 0.0, 0.0); // Red: before scene.add( points2 ); var points1 = PS_UTILS.make_pointset("post_qem_verts", 10.0 / 4.0, 0.9, 0.9, 0.0); // Yellow: after scene.add( points1 ); */ // Show a cube in center var geo2 = new THREE.BoxGeometry( GRID_CELL_SIZE, GRID_CELL_SIZE, GRID_CELL_SIZE ); mesh2_tiny_box_wireframe = new THREE.Mesh( geo2, material_wireframe ); mesh2_tiny_box_wireframe .position.set( 0, 0, 0 ); scene.add( mesh2_tiny_box_wireframe ); //mesh2_tiny_box_wireframe .scale.set( 10, 10, 10 ); var dirLight = new THREE.DirectionalLight(0xffffff, 1); dirLight.position.set(100, 100, 50); scene.add(dirLight); var dirLight2 = new THREE.DirectionalLight(0x00ffff, 1); dirLight2.position.set(-100, -100, -50); scene.add(dirLight2); //var arrow = make_arrow(); //global_arrow = arrow; var arrows__ = make_multiple_arrows(ARROWS_COUNT); globals.arrows = arrows__; if(VERBOSE){ console.log("RENDERER"); } var render_canvas = document.getElementById( 'my_canvas' ); my_assert(render_canvas); console.log(render_canvas); renderer = new THREE.WebGLRenderer( { antialias: true, canvas: render_canvas } ); //renderer.setSize( window.innerWidth, window.innerHeight ); renderer.setSize( WIDTH, HEIGHT ); document.body.appendChild( renderer.domElement ); /* function callMultipleTimes() { var mc_icounter=0; setInterval(function(){ if(mc_icounter<10) update_mc(implisolid_, 0.2/10.*5); mc_icounter++; }, 30); } */ function doKeyDownListener(event) { const CONTROL_KEY = 17; const SHIFT_KEY = 16; if ( event.keyCode == SHIFT_KEY ) { var BURST_COUNT = 5; // 50; var INTERVAL_MSEC = 100; // 8-1; //40 // 1 // in Milliseconds //update_mc(implisolid_); callMultipleTimes (BURST_COUNT, INTERVAL_MSEC, function(){ update_mc(IMPLICIT, 0.2/10.*5 /5.); }); //change_arrow(arrow, implisolid_, globals.global_mp5); } else console.log("\"keydown\" code", event.keyCode); } window.addEventListener( "keydown", doKeyDownListener, false ); // keydown keypress // CONTROLS //see https://github.com/mrdoob/three.js/blob/master/examples/webgl_geometry_teapot.html var cameraControls = new THREE.OrbitControls( camera, renderer.domElement ); cameraControls.rotateSpeed = 1.5; cameraControls.zoomSpeed = 1.2; cameraControls.panSpeed = 0.8; cameraControls.enableZoom = true; cameraControls.enablePan = true; cameraControls.enableDamping = true; cameraControls.dampingFactor = 0.6; //0.9; // 1.0; //motile: 0.3; /* cameraControls.constraint.smoothZoom = true; cameraControls.constraint.zoomDampingFactor = 0.2; cameraControls.constraint.smoothZoomSpeed = 5.0; */ cameraControls.target.set( 0, 0, 0 ); cameraControls.addEventListener( 'change', function () {;} ); } function update_mc(implisolid_, delta_t){ if(delta_t === undefined) delta_t = 0.2; // Subjective time! global_time += delta_t; var tuple = provide_input(global_time, 1, globals); var shape_json = tuple.shape_json; var polygonization_json = tuple.polygonization_json; assert(typeof polygonization_json !== "string"); //Three modes of speed here for (UPDATE_SAME_GEOM_OBJECT, EVEN_REUSE_MESH_OBJECT): // (false, false) // Creates a new Geometry object at each loop iteration. // (true, false) // Keeps geometry object instance // (true, true) // Keeps mesh instance (as well as geometry) var UPDATE_SAME_GEOM_OBJECT = true; //Will not even call the constructor var EVEN_REUSE_MESH_OBJECT = true; if( EVEN_REUSE_MESH_OBJECT && ! UPDATE_SAME_GEOM_OBJECT) console.error("Wrong condition."); if(SHOW_SOLID){ var p1 = [globals.mesh_solid.position, globals.mesh_solid.rotation]; } if(SHOW_WIREFRAME){ var p2 = [globals.mesh_wireframe.position, globals.mesh_wireframe.rotation]; } // g i.e. actual_current_active_geom var g = null; if(SHOW_SOLID){ g = globals.mesh_solid.geometry; } if(SHOW_WIREFRAME){ g = globals.mesh_wireframe.geometry; } my_assert(g, "SHOW_SOLID and SHOW_WIREFRAME cannot be both false."); if(!EVEN_REUSE_MESH_OBJECT){ if(SHOW_SOLID){ scene.remove(globals.mesh_solid); } if(SHOW_WIREFRAME){ scene.remove(globals.mesh_wireframe); } } var reused_last_geom = g; //Not sure about the condision if(!UPDATE_SAME_GEOM_OBJECT){ if(SHOW_SOLID){ g.dispose(); g = null; // reused_last_geom is not null and will remain. It is not recommended to use reused_last_geom. } //globals.mesh_wireframe.geometry.dispose(); // Don't do it twice! } // var reused_last_geom = g; if(!EVEN_REUSE_MESH_OBJECT){ globals.mesh_solid = null; globals.mesh_wireframe = null; } var geometry = null; if(UPDATE_SAME_GEOM_OBJECT) { geometry = g; //update_reused_geometry(implisolid_, global_time, geometry); // shape_json: from update, //OLD// update_reused_geometry(implisolid_, shape_json, polygonization_json, geometry); var ignoreNormals = false; IMPLICIT.update_geometry_from_json(geometry, shape_json, polygonization_json, ignoreNormals) } else { /* if(CALL_VERSION==1){ //geometry = make_geometry_oldold(shape_json, polygonization_json); } else */ { //reused_last_geom = null; //OLD// geometry = make_geometry_new2(implisolid_, shape_json, polygonization_json, false, geom_callback__1); //FALSE?? } var ignoreNormals = false; geometry = IMPLICIT.getLiveGeometry(shape_json, polygonization_json, ignoreNormals) }; /* ""; for(var i=0;i<10*3;i++){ //geometry.attributes.position.setXYZ( i, x, y, z ); geometry.attributes.position.array[i] += 0.0002 * (i% 2); //geometry.index.array[ i ] += (i % 2)*40 ; var nverts = geometry.attributes.position.count/3; geometry.index.array[ i ] = (geometry.index.array[ i ] % (nverts)); } //geometry.attributes.position.needsUpdate = true; //geometry.index.needsUpdate = true; ""; */ /* // SLOW. But using -o3 compilation it can make a nice live smooth QEM demo. if (globals.normals) { scene.remove(globals.normals); globals.normals = null } var alpha = 60.0; var norms_ = PS_UTILS.visualise_normals(globals.global_mp5, "post_p_centroids", 0, alpha, 0x009900); // 0x00ff00 // 0x88ff00 scene.add(norms_); globals.normals = norms_; */ /* var ignore_root_matrix = false; update_arrows(globals.arrows, implisolid_, globals.global_mp5, ARROWS_COUNT, ignore_root_matrix); */ if(!EVEN_REUSE_MESH_OBJECT){ if(SHOW_WIREFRAME){ globals.mesh_wireframe = new THREE.Mesh( geometry, material_wireframe ); globals.mesh_wireframe.scale.set( MESH_SCALE, MESH_SCALE, MESH_SCALE ); //copy so that we dont lose the rotation, position of the meshes. globals.mesh_wireframe.position.copy(p2[0]); globals.mesh_wireframe.rotation.copy(p2[1]); scene.add( globals.mesh_wireframe ); } /*var material1 = new THREE.MeshPhongMaterial( { color: 0xaaaaaa, specular: 0xffffff, shininess: 250, side: THREE.DoubleSide, vertexColors: THREE.VertexColors } ); globals.mesh_solid = new THREE.Mesh( geometry, material1 ); */ if(SHOW_SOLID){ globals.mesh_solid = new THREE.Mesh( geometry, globals.chosen_matrial ); // //globals.mesh_solid.position.set( 0, 0, 0 ); globals.mesh_solid.scale.set( MESH_SCALE, MESH_SCALE, MESH_SCALE ); globals.mesh_solid.position.copy(p1[0]); globals.mesh_solid.rotation.copy(p1[1]); scene.add( globals.mesh_solid ); } } } function animate() { requestAnimationFrame( animate ); //Updating the meshes var SPEED = 0 * 3. / 100; if(globals.mesh_wireframe){ globals.mesh_wireframe.rotation.x += 0.01*SPEED; globals.mesh_wireframe.rotation.y += 0.02*SPEED; } if(globals.mesh_solid){ globals.mesh_solid.rotation.x += 0.01*SPEED; globals.mesh_solid.rotation.y += 0.02*SPEED; } mesh2_tiny_box_wireframe .rotation.z += 0.01*SPEED; mesh2_tiny_box_wireframe .rotation.y += 0.02*SPEED; //Updating the matrials //material update callback //materials_list[ materials_list.length - 2 ].emissive.setHSL( 0.54, 1, 0.35 * ( 0.5 + 0.5 * Math.sin( 35 * global_time / 20. ) ) ); //materials_list[ materials_list.length - 3 ].emissive.setHSL( 0.04, 1, 0.35 * ( 0.5 + 0.5 * Math.cos( 35 * global_time / 20.) ) ); renderer.render( scene, camera ); } var scene, camera, renderer; //var geometry; </script> <!--script type="text/javascript" src="wwexample1.js"></script--> <script type="text/javascript"> if(0){ //worker example if (window.Worker) { var myWorker = new Worker("wwexample1.js"); myWorker.postMessage({a:3, b:6}); myWorker.postMessage({a:8, b:9}); myWorker.onmessage = function(e) { console.log('I received this from worker'); //console.log(e); console.log(e.data); /* bubbles : false cancelBubble : false cancelable : false currentTarget : Worker data : Object defaultPrevented : false eventPhase : 0 isTrusted : true isTrusted : true lastEventId : "" origin : "" path : Array[0] ports : Array[0] returnValue : true source : null srcElement : Worker target : Worker timeStamp : 1555.6200000000001 type : "message" */ } } else{ console.warning("Your browser does not support WebWorkers. See http://stackoverflow.com/questions/4739916/what-browsers-currently-support-web-workers "); } } </script> <script> 'use strict'; // global var IMPLICIT; var PS_UTILS; // The code that runs immediately after finishing loading of the Emscripten-generated js. function set_off() { console.log("ready."); assert = my_assert; IMPLICIT = _on_cpp_loaded(); // from implisolid_main.js PS_UTILS = new PS_UTILS_CLASS(IMPLICIT); //if(delta_t === undefined) var delta_t = 0.2; // Subjective time! global_time += delta_t; var d = provide_input(global_time, 0, globals); var shape_json = d.shape_json; var polygonization_json = JSON.stringify(d.polygonization_json); init_scene(IMPLICIT, shape_json, polygonization_json); animate(); }; </script> <!-- Memory profiler code by "jj" from https://groups.google.com/forum/#!topic/emscripten-discuss/HtAzVposlX4 --> <!-- Uncomment the following for foreround (non-webworker) demo--> < ! - - <script type="text/javascript" src="../js_iteration_2/js/lib/memoryprofiler.js"></script> <script> //function letmeknow(){console.log("Loading memory profiler");} var Module; if (!Module) Module = { preRun:[ letmeknow=function (){console.log("Loading memory profiler");}, // memoryprofiler_add_hooks ], onRuntimeInitialized: set_off, memoryInitializerPrefixURL: "../build/", }; </script> <script type="text/javascript" src="../build/mcc2.compiled.js"></script> - - > <!--script> var g1; var g2; var worker = new Worker('../build/mcc2.compiled.js'); var worker2 = new Worker('worker_test.js'); /* Usage: * worker.postMessage({funcName: "worker_api__started"}); * Also see: ~/install/emsdk_portable/emscripten/master/src/library_browser.js at emscripten_call_worker() :1323 emscripten_call_worker() * What is Runtime.getFuncWrapper(func, 'vi')(arg); ? */ /* var transferObject = { 'funcName': funcName, 'callbackId': callbackId, 'data': data ? new Uint8Array({{{ makeHEAPView('U8', 'data', 'data + size') }}}) : 0 }; See: https://kripken.github.io/emscripten-site/docs/api_reference/emscripten.h.html#c.emscripten_call_worker https://kripken.github.io/emscripten-site/docs/api_reference/emscripten.h.html#c.emscripten_worker_respond Q: Why do we need emscripten_get_worker_queue_size() ? See: ~/install/emsdk_portable/emscripten/master/src$ grep -rnw '.' -i -e "worker" */ function send1() { const callbackId = -1; var dataArray = new Uint8Array([3,2,1]); // Cracking the protocol used by Emscripten var temp_copy=null; worker.postMessage( temp_copy={ funcName: "worker_api__started", callbackId: callbackId, data: dataArray? dataArray : 0, // 'finalResponse': false, }, dataArray?[dataArray.buffer]:[] ); worker2.postMessage(temp_copy); } /* //var REAL_V = 1; // enum // var cb_revkeys = {[REAL_V]: "REAL_V", REAL_V: 1}; var cb_keys = {REAL_V: 1, build_geometry: 2}; // enum //var cb_revkeys = // {[cb_keys.REAL_V]: "REAL_V", [cb_keys.build_geometry]: "build_geometry"}; var cb_funcNames = {[cb_keys.REAL_V]: "worker_api__verts", [cb_keys.build_geometry]: "build_geometry"}; // in fact it's better to use emscripten's! // console.log(cb_revkeys); */ // cb_info (for : callback_info) // Keeps the info necessary to communicate to the Web-Worker's API var api_info = { REAL_V: { funcName: "worker_api__verts", callbackId: 1, }, /* build_geometry: { funcName: "build_geometry", callbackId: 2, }, */ test: { funcName: "workerapi_make_geometry_part1", callbackId: 3, }, }; // Maps the callback int id into the key name in api_info dict. For fast lookup. var api_revlookup = { [api_info.REAL_V]: "REAL_V", // [api_info.build_geometry]: "build_geometry", [api_info.test]: "test", }; function send_worker_simple_request(fname) { // no data const callbackId = -1; // Cracking the protocol used by Emscripten var temp_copy = null; worker.postMessage( temp_copy = { funcName: fname, callbackId: callbackId, data: 0, // 'finalResponse': false, } ); worker2.postMessage(temp_copy); } // function send_worker_request_va(fname, callbackId) { function send_worker_request_va() { // no data // // // const callbackId = REAL_V; //const callbackId = cb_keys.REAL_V; // // Cracking the protocol used by Emscripten //var fname = cb_funcNames[callbackId]; //"worker_api__verts"; const callbackId = api_info.REAL_V.callbackId; var fname = api_info.REAL_V.funcName; worker.postMessage( { funcName: fname, callbackId: callbackId, data: 0, // 'finalResponse': false, } ); } function build_geometry_w() { worker.postMessage( { funcName: api_info.build_geometry.funcName, callbackId: api_info.build_geometry.callbackId, data: 0, // 'finalResponse': false, } ); } function test_data_worker(data) { console.log("test_data_worker"); var temp_copy; worker.postMessage( temp_copy={ funcName: api_info.test.funcName, callbackId: api_info.test.callbackId, data: data, //[12345678, 3], // turns this into a two bytes! // 'finalResponse': false, } // [data] ); console.info(temp_copy, api_info.test.funcName); console.info("data", data); worker2.postMessage(temp_copy); if (false) { var a1 = new Float32Array([1,2,3.1415926536123456789012345678901234567890,4]); worker2.postMessage(a1); /* *[12345678,2] */ } } function request() { // send_worker_simple_request("worker_api__verts"); // send_worker_request_va(); var x0=0, y0=0, z0=0; var mp5_json = SIMPLE_CONE; const BB_SIZE = 12.0/10.0; var mc_params = { resolution: Math.floor(14 ), 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}, subdiv: {enabled: 1}, overall_repeats: 1, debug: { enabled_pointsets: 0, post_subdiv_noise: 0.0, }, }; var mcsettings = JSON.stringify(mc_params); // build_geometry_w(mp5_json, mcsettings); //test_data_worker([12345678, 3,5,1,3]); //var b1 = new Uint8Array([5,6,1000,10]); var b1 = new Uint16Array([5,6,1000,10]); if (false) test_data_worker(b1); // new idea! var r = new Float32Array([3.141592651234567890123456780,1,2,3,4,5,6,7,8,9,0.5,1.5,2.5]) var b=new Uint8Array(r.buffer); if (false) test_data_worker(b); console.log("---------------------"); test_data_worker(b); //test_data_worker([b, 60, b]); //test_data_worker({b1:b, d:60, b2:b}); /* * [1,2] -> 1 02 // * [12345678,2] -> 4e 02 // turns this into a two bytes! * [12345677, 3] -> 4d 03 * ["hi.abc", 3] -> 00 03 */ } worker.addEventListener('message', function(event) { // event.data == {callbackId: -1, finalResponse: true, data: 0} //console.log('Worker said: ', event.data); console.log("Message received from worker:", event.data); // event // Reinterpret data g = event.data; g2 = new Float32Array(g.data.buffer); console.log(g2); // problem! Identify the result ID. Callback IS needed. switch (event.data.callbackId) { case cb_keys.REAL_V: console.log("REAL_V REAL_V REAL_V "); g = event.data; g2 = new Float32Array(g.data.buffer); console.log(g2); } }, false); /* worker.onmessage = function(event) { console.log("Message received from worker:", event); console.log(event.data); } */ </script--> <script> 'use strict'; var merge_dicts_nonrecursive = merge_dicts_nonrecursive?merge_dicts_nonrecursive:function() { var merged_dict = {}; var nargs = arguments.length; for (var arg_i = 0; arg_i < nargs; arg_i++) { var newarg = arguments[arg_i]; for (var key in newarg) { if (newarg.hasOwnProperty(key)) { merged_dict[key] = newarg[key]; } } } return merged_dict; }; /* function make_demo_dict() { console.error("Use provide_input() instead."); //var mp5_json = SIMPLE_CONE; const BB_SIZE = 12.0/10.0; // 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 * 10.0; var shape_dict = JSON.parse(mp5_json).root.children[0]; var x0=0, y0=0, z0=0; return { shape_dict: shape_dict, bbox: { min: { x: x0-BB_SIZE, y: y0-BB_SIZE, z: z0-BB_SIZE }, max: { x: x0+BB_SIZE, y: y0+BB_SIZE, z: z0+BB_SIZE } }, }; } */ function demo1() { // request() console.log("demo1"); var dct = provide_input(global_time, 0, globals); var shape_json = dct.shape_json; // aleady stringified // var polygonization_settings_json = JSON.stringify(dct.polygonization_json); var points = new Float32Array([3.141592651234567890123456780,1,2,3,4,5,6,7,8,9,0.5,1.5,2.5, -1,-1]) // var b = new Uint8Array(r.buffer); IMPLICIT_WORKER.wapi_query_implicit_values(23451, shape_json, points, function c3(returned_result, call_identification, shape_id) { console.info("Returned: ALL-POINTS-OUTSIDE-OR-ON = ", returned_result, "shape_id", shape_id); if (call_identification) console.info("Unique Call Identification Id:", call_identification); console.info("demo1() done"); }); // wreq.mp5_str = JSON.stringify(shape_dict); // '{}'; // wreq.points = points; // //worker.postMessage([b,r]); // worker.postMessage(wreq); } </script > <script type="text/javascript" src="../js_iteration_2/js/implisolid_worker.js"></script> <script> function demo2() { //var rrq = make_demo_dict(); // var bbox = {min: {x:-10, y:-10, z:-10}, max:{x:10, y:10, z:10}}; var dct = provide_input(global_time, 0, globals); var shape_json = dct.shape_json; // aleady stringified var polygonization_settings_json = JSON.stringify(dct.polygonization_json); console.info("demo2", dct); //avoid calling IMPLICIT.make_polygonization_settings(); IMPLICIT_WORKER.getLiveGeometry_from_json(22345, shape_json, polygonization_settings_json, function (geom, shape_id){ console.info(geom, "shape_id", shape_id); if (globals.mesh_solid) {scene.remove(globals.mesh_solid); globals.mesh_solid = null;} if (globals.mesh_wireframe) {scene.remove(globals.mesh_wireframe); globals.mesh_wireframe = null;} globals.mesh_solid = new THREE.Mesh( geom, globals.chosen_matrial ); globals.mesh_solid.position.set( 5*0, 5*0, 2*0 ); globals.mesh_solid.scale.set( MESH_SCALE, MESH_SCALE, MESH_SCALE ); scene.add( globals.mesh_solid ); console.info("demo2() done"); }); } function demo3(ver) { console.info("demo3 ver"+ver); // global_time += 2; global_time = 4; var dct = provide_input(global_time, 1, globals); var shape_json = dct.shape_json; // aleady stringified var polygonization_settings_json = JSON.stringify(dct.polygonization_json); var stt = new Date(); var shape_id = 45454; if (ver == 1) { IMPLICIT_WORKER.update_geometry_from_json_ver1(globals.mesh_solid.geometry, shape_id, shape_json, polygonization_settings_json, function(shape_id, result){ console.info("demo3() done", "called on shape:", shape_id); console.info("TIME: ", new Date() - stt); }); } else if (ver == 2) { IMPLICIT_WORKER.update_geometry_from_json_ver2(globals.mesh_solid.geometry, shape_id, shape_json, polygonization_settings_json, function(shape_id, result){ console.info("demo3() done ", "called on shape:", shape_id); console.info("TIME: ", new Date() - stt); }); } else { console.error("Sorry. use (1) or (2)"); } } function demo4() { console.info("demo4: Query implicit values for collision detection. Tests query_implicit_values_old()"); var demoshape = provide_input(global_time += 0.5, 1, globals); var shapejson = JSON.stringify(demoshape.shape_json); console.log(shapejson); var points = new Float32Array([3.141592651234567890123456780,1,2,3,4,5,6,7,8,9,0.5,1.5,2.5, -1,-1]) for (var i=0;i<points.length;++i) points[i] *= 0.0001; console.log(points); var reduce_type = "any-inside"; //{return_callback_id:_callback_id, returned_data: result_values, call_id: _call_id, shape_index: shape_index} IMPLICIT_WORKER.query_implicit_values_old(345123, shapejson, points, reduce_type, 0.0001, function c3(returned_result, call_identification, shape_id) { //returned_result.shape_index // this should be better on the console.info("Returned: "+reduce_type+" = ", returned_result, "called on shape:", shape_id); if (call_identification) console.info("Unique Call Identification Id:", call_identification); console.info("demo4() done"); }); } function demo5() { console.info("demo5: Query a normal. Tests query_a_normal()"); var demoshape = provide_input(global_time, 1, globals); var shapejson = JSON.stringify(demoshape.shape_json); var points = new Float32Array([3.141592651234567890123456780,1,2]) console.log(points); IMPLICIT_WORKER.wapi_query_a_normal (123123, shapejson, points, function c3(returned_result, call_identification, shape