UNPKG

@sohale/implisolid

Version:

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

444 lines (335 loc) 16.2 kB
'use strict'; function init(service) { 'use strict'; //main = Module.cwrap('main', 'number', []); //var service={}; //= newProducer //is an interface service.build_geometry = Module.cwrap('build_geometry', null, [ 'string', 'string']); service.get_v_size = Module.cwrap('get_v_size', 'number', []); service.get_f_size = Module.cwrap('get_f_size', 'number', []); service.get_v = Module.cwrap('get_v', null, ['number']); service.get_f = Module.cwrap('get_f', null, ['number']); service.get_v_ptr = Module.cwrap('get_v_ptr', 'number', []); service.get_f_ptr = Module.cwrap('get_f_ptr', 'number', []); service.finish_geometry = Module.cwrap('finish_geometry', null, []); service.set_object = Module.cwrap('set_object', 'number', ['string', 'number']); service.unset_object = Module.cwrap('unset_object', 'number', ['number']); service.set_x = Module.cwrap('set_x', 'number', ['number', 'number']); // sends the x points for evaluation of implicit or gradient service.unset_x = Module.cwrap('unset_x', null, []); service.calculate_implicit_values = Module.cwrap('calculate_implicit_values', null, []); service.get_values_ptr = Module.cwrap('get_values_ptr', 'number', []); service.get_values_size = Module.cwrap('get_values_size', 'number', []); service.calculate_implicit_gradients = Module.cwrap('calculate_implicit_gradients', null, ['number']); // boolean argument to normalize and reverse the vevtors, suitable for rendering. service.get_gradients_ptr = Module.cwrap('get_gradients_ptr', 'number', []); service.get_gradients_size = Module.cwrap('get_gradients_size', 'number', []); service.get_pointset_ptr = Module.cwrap('get_pointset_ptr', 'number', ['string']); service.get_pointset_size = Module.cwrap('get_pointset_size', 'number', ['string']); if (Module["_about"]) { service.about = Module.cwrap('about', null, []); } else { service.about = "C++ method problem: no about()"; console.error("C++ method problem: a correct version not found"); } /* try { service.about = Module.cwrap('about', null, []); } catch(err) { service.about = "C++ method problem"; console.log("C++ method problem: not found"); } */ service.init = function(){ service.needs_deallocation = false; this.use_II = true; this.use_II_qem = true; } service.finish_with = function (){ //after the last round. if(!this.needs_deallocation){ console.error("cannot `finish_geometry()`. Geometry not produced."); } service.finish_geometry(); service.needs_deallocation = false; } service.set_vect = function (float32Array) { // Accesses module const _FLOAT_SIZE = Float32Array.BYTES_PER_ELEMENT; if (float32Array.length % 3 != 0) {console.error("bad input array");}; var nverts = float32Array.length / 3; 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("result: "+result); if (!result) { console.error("Something went wrong: ", result); } Module._free( verts_space ); }; 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); }; //was: geom. update_normals (service ..) service.make_normals_into_geometry = function(geom, mp5_str, x, ignore_root_matrix) { geom.removeAttribute('normal'); geom.computeVertexNormals(); geom.__set_needsUpdate_flag(false); return; const _FLOAT_SIZE = Float32Array.BYTES_PER_ELEMENT; // console.error(x); /* for( var i = 0 ; i < x.length; i++) { x[i] += Math.random() * 0.9; } */ service.set_object(mp5_str, ignore_root_matrix); service.set_vect(x); // overhead service.calculate_implicit_gradients(true); // Why TRUE doe snot have any effect? var ptr = service.get_gradients_ptr(); var ptr_len = 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; //} geom.update_normals_from_array(gradients); service.unset_x(); service.unset_object(); }; service.init(); return service; } var ImplicitService = function(){ init(this); this.make_geometry = function (shape_params, mc_params) { var startTime = new Date(); const _FLOAT_SIZE = Float32Array.BYTES_PER_ELEMENT; const _INT_SIZE = Uint32Array.BYTES_PER_ELEMENT if(this.needs_deallocation) { this.finish_geometry(); this.needs_deallocation = false; } //console.log("mc_params.resolution " + mc_params.resolution); //mc_params.resolution = 40; var mp5_str = JSON.stringify(shape_params); this.build_geometry(mp5_str, JSON.stringify(mc_params)); this.needs_deallocation = true; var nverts = this.get_v_size(); var nfaces = this.get_f_size(); var verts_address = this.get_v_ptr(); var faces_address = this.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 + 3*nfaces); var allocate_buffers = true; var geom = new LiveBufferGeometry79(verts, faces, allocate_buffers); // Set the normals var ignore_root_matrix = mc_params.ignore_root_matrix; // Does not need other (MC-related) arguments. //geom.update_normals(this, verts, mp5_str, ignore_root_matrix); // Evaluates the implicit function and sets the goemetry's normals based on it. this.make_normals_into_geometry(geom, mp5_str, verts, ignore_root_matrix); // Evaluates the implicit function and sets the goemetry's normals based on it. //this.aaaaaaaaaA(verts); var endTime = new Date(); var timeDiff = endTime - startTime; //report_time(timeDiff, function(){hist();}); return geom; }; /* this.aaaaaaaaaA(x, mp5_str, ignore_root_matrix) { // var x = new Float32Array(nverts); this.set_object(mp5_str, ignore_root_matrix); this.set_vect(x); // overhead this.calculate_implicit_gradients(); var ptr = this.get_gradients_ptr(); var ptr_len = this.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 geom.update_normals(gradients); this.unset_x(); this.unset_object(); } */ //This method is called by the designer to obtain the geometry from the ImplicitService this.getLiveGeometry = function(dict, bbox, ignore_root_matrix) { //var mc_properties = {resolution: 28, box: {xmin: -1, xmax: 1, ymin: -1, ymax: 1, zmin: -1, zmax: 1}}; //var shape_properties = {type:"sphere",displayColor:{x:0.38015037447759337,y:0.6015094592616681,z:0.9774198226067741},matrix:[10,0,0,92.9405888205127,0,10,0,101.93969389296757,0,0,10,8.59828143220919,0,0,0,1],index:7935813} //var shape_properties = {type:"sphere",displayColor:{x:0.38015037447759337,y:0.6015094592616681,z:0.9774198226067741},matrix:[10,0,0,92.9405888205127,0,10,0,101.93969389296757,0,0,10,8.59828143220919,0,0,0,1],index:7935813} /*{subjective_time: 0.0, implicit_obj_name: "sphere"*/ //var shape_properties = {type:"meta_balls",time: 0.0}; var shape_properties = dict; //var radius = 3.0; //var mc_properties = {resolution: 28, box: {xmin: -radius+1, xmax: radius, ymin: -radius, ymax: radius, zmin: -radius, zmax: radius}}; //var shape_properties = {type:"simple_sphere", radius: radius}; // var shape_properties = {type:"egg",displayColor:{x:0.38015037447759337,y:0.6015094592616681,z:0.9774198226067741},matrix:[10,0,0,92.9405888205127,0,10,0,101.93969389296757,0,0,10,8.59828143220919,0,0,0,1],index:7935813} // var s = 10; // var mc_properties = {resolution: 28, box: {xmin: 100-s, xmax: 100+s, ymin: 100-s, ymax: 100+s, zmin: 5-s, zmax: 5+s}}; //var shape_properties = {type:"egg",displayColor:{x:0.38015037447759337,y:0.6015094592616681,z:0.9774198226067741},matrix:[1,0,0,92.9405888205127-100,0,1,0,101.93969389296757-100,0,0,1,8.59828143220919-5,0,0,0,1],index:7935813} var s = 1; //var mc_properties = {resolution: 28, box: {xmin: -s, xmax: s, ymin: -s, ymax: s, zmin: -s, zmax: s}}; //var mc_properties = {resolution: 28, box: {xmin: 92.9405888205127-100-s, xmax: 92.9405888205127-100+s, ymin: 101.93969389296757-100-s, ymax: 101.93969389296757-100+s, zmin: 8.59828143220919-5-s, zmax: 8.59828143220919-5+s}}; //implicit_double_mushroom center will be zero. /* //shape_properties.type = "egg"; var m = shape_properties.matrix; var bb ={}; var dd = 0.0; var wx = Math.sqrt(m[0]*m[0] + m[1]*m[1] + m[2]*m[2]); var wy = Math.sqrt(m[4]*m[4] + m[5]*m[5] + m[6]*m[6]); var wz = Math.sqrt(m[8]*m[8] + m[9]*m[9] + m[10]*m[10]); bb["xmin"] = m[3] - wx/2 +dd; bb["xmax"] = m[3] + wx/2-dd; bb["ymin"] = m[7] - wy/2 +dd; bb["ymax"] = m[7] + wy/2-dd; bb["zmin"] = m[11] - wz/2 +dd; bb["zmax"] = m[11] + wz/2-dd; */ assert(bbox, "yOU need to specify the bounding box"); var bb ={}; var sc = 1.0; var test = 0.; bb["xmin"] = bbox.min.x * sc + test; bb["xmax"] = bbox.max.x * sc - test; bb["ymin"] = bbox.min.y * sc + test; bb["ymax"] = bbox.max.y * sc - test; bb["zmin"] = bbox.min.z * sc + test; bb["zmax"] = bbox.max.z * sc - test; _expect(bb["xmin"], "boundingbox is null"); _expect(bb["xmax"], "boundingbox is null"); _expect(bb["ymin"], "boundingbox is null"); _expect(bb["ymax"], "boundingbox is null"); _expect(bb["zmin"], "boundingbox is null"); _expect(bb["zmax"], "boundingbox is null"); var mc_res = CONFIG.implisolid.default_mc_resolution; /* var mc_properties = { resolution: getResolution(bb), box: bb, ignore_root_matrix: ignore_root_matrix, vresampl: {iters: this.use_II? 1:0, c: 1.0}, projection: {enabled: this.use_II? 1:0}, qem: {enabled: (this.use_II && this.use_II_qem)?1:0}, subdiv: {enabled: 1}, overall_repeats: 1, debug: { post_subdiv_noise: 0.01, } }; */ var mc_properties = { resolution: getResolution(bb), box: bb, ignore_root_matrix: ignore_root_matrix, vresampl: {iters: 1, c: 0.4}, projection: {enabled: 1}, qem: {enabled: 1}, //subdiv: {enabled: 1}, subdiv: {enabled: 0}, overall_repeats: 2, debug: { enabled_pointsets: 0, post_subdiv_noise: 0.01, }, }; console.log("*********************"); console.log (" mc properties : " + JSON.stringify(mc_properties)); var geom = this.make_geometry(shape_properties, mc_properties); return geom; } }; var IMPLICIT = null; function _on_cpp_loaded() { console.log("C++ ready."); //IMPLISOLID. IMPLICIT = new ImplicitService(); assert = _assert_000; }; function getResolution(bb){ return CONFIG.implisolid.default_mc_resolution; const max_value = 40; const min_value = 14; const factor = CONFIG.implisolid.default_mc_resolution; var max_length = Math.max(bb["xmax"] - bb["xmin"], bb["ymax"] - bb["ymin"], bb["zmax"] - bb["zmin"]); var tmp = Math.min(max_value,max_length*factor); return Math.floor(Math.max(tmp,min_value)); // 1 -> 28 // 2 -> 48 } /* Put the following in the HTML <script> Module={preRun:[], onRuntimeInitialized: _on_cpp_loaded, }; </script> <script type="text/javascript" src="mcc2.cpp.js"></script> */ //function test_update1(t, mesh){ function test_update1(t, mesh, dict){ var g = mesh.geometry; IMPLICIT.finish_geometry(); IMPLICIT.needs_deallocation = false; var s = Math.sin(t)*3+3; console.log("s="+s); var mc_properties = {resolution: 28, box: {xmin: (-1-s)*0, xmax: 1+s, ymin: (-1-s)*0 , ymax: 1+s, zmin: (-1-s)*0, zmax: 1+s}}; // Aliasing test: //var res = Math.floor(28*(s+1)/3)-4; var sz = (res) * 0.14/2; //var mc_properties = {resolution: res, box: {xmin: 0, xmax: sz, ymin: 0 , ymax: sz, zmin: 0, zmax: sz}}; //var mc_properties = {resolution: 28, box: {xmin: -1, xmax: 1, ymin: -1, ymax: 1, zmin: -1, zmax: 1}}; //var new_geometry = IMPLICIT.build_geometry(28, mc_properties, "sphere", 0); //var shape_properties = {type: "sphere",matrix:[10,0,0,92.9405888205127,0,10,0,101.93969389296757,0,0,10,8.59828143220919,0,0,0,1]}; //var shape_properties = mesh.parentShape.getDict1(); console.log() if(!dict){ //var shape_properties = {type:"meta_balls",time: t }; var shape_properties = {type:"simple_sphere", radius: 3.0}; } else { var shape_properties = dict; } var new_geometry = IMPLICIT.build_geometry( JSON.stringify(shape_properties) , JSON.stringify(mc_properties)); IMPLICIT.needs_deallocation = true; if(new_geometry){ mesh.geometry = new_geometry; g = new_geometry; } // g.update_geometry(IMPLICIT, true); IMPLICIT.update_geometry(g, true); //??????? g.update_normals(IMPLICIT); var x = "?"; IMPLICIT.make_normals_into_geometry(g, JSON.stringify(shape_properties), x, false); } function test_update2(t){ var g = currentMeshes[0].geometry; // var new_geometry = g.update_geometry(IMPLICIT, false); var new_geometry = IMPLICIT.update_geometry(g, false); // g.update_normals(IMPLICIT); var x = "?"; var mp5_string = "?"; IMPLICIT.make_normals_into_geometry(g, mp5_String, x, false); if(new_geometry){ currentMeshes[0].geometry = new_geometry; } } /* var t=0;m=currentMeshes[0];test_update1(t, m);var iid=setInterval(function(){test_update1(t+=0.02, m);},6+9); var t=0;m=currentMeshes[0]; d=m.parentShape.getDict1();test_update1(t, m);var iid=setInterval(function(){test_update1(t+=0.02, m,d);}, 66); */