@sohale/implisolid
Version:
A Solid Modelling Kernel in Javascript based on Implicit Surfaces, for MP5 file format
625 lines (463 loc) • 17.4 kB
HTML
<html>
<head>
<meta charset="utf-8"/>
</head>
<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="./geometry77.js"></script>
<script type="text/javascript" src="./controls/OrbitControls.js"></script>
<!--<body>-->
Based on MCC1
<br>
<script>;
var main;
function init_polygonizer()
{
main = Module.cwrap('main', 'number', []);
var newProducer={};
newProducer.build_geometry = Module.cwrap('build_geometry', null, ['number', 'number', 'string', 'number']);
newProducer.get_v_size = Module.cwrap('get_v_size', 'number', []);
newProducer.get_f_size = Module.cwrap('get_f_size', 'number', []);
newProducer.get_v = Module.cwrap('get_v', null, ['number']);
newProducer.get_f = Module.cwrap('get_f', null, ['number']);
newProducer.get_v_ptr = Module.cwrap('get_v_ptr', 'number', []);
newProducer.get_f_ptr = Module.cwrap('get_f_ptr', 'number', []);
newProducer.finish_geometry = Module.cwrap('finish_geometry', null, []);
// newProducer.about = Module.cwrap('about', null, []);
// this is used for version purposes in the current html file
newProducer.init = function(){ newProducer.needs_deallocation = false; }
newProducer.finish_with = function (){
if(!newPolygonizer.needs_deallocation)
console.error("cannot `finish_geometry()`. Geometry not produced.");
newPolygonizer.finish_geometry();
newPolygonizer.needs_deallocation = false;
}
newProducer.init();
return newProducer;
}
</script>
<script>;
const VERBOSE = false;
var WIREFRAME = false;
const _FLOAT_SIZE = 4;
const _INT_SIZE = 4;
var global_time = 0;
;
var call_multiple_times = function() {
var last_active = 0;
var intervals_counter = 0;
function _call_multiple_times(newPolygonizer, update_mc) {
var BURST_COUNT = 50;
var INTERVAL_MSEC = 8-1;
var already_busy_doing_it=0;
var burst_counter = 0;
intervals_counter++;
if(intervals_counter>1)
{
intervals_counter--;
return;
}
last_active = setInterval (
function()
{
if(!last_active)
console.error("!last_active");
burst_counter++;
if(burst_counter<BURST_COUNT)
{
if(already_busy_doing_it<1)
{
already_busy_doing_it++;
update_mc(newPolygonizer, 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
{
if(!last_active)
console.error("!last_active");
clearInterval(last_active);
intervals_counter--;
burst_counter = 0;
last_active = 0;
}
},
INTERVAL_MSEC
);
}
return _call_multiple_times;
}();
function make_geometry_new2(newPolygonizer, subjective_time, reusable_geometry, re_allocate_buffers)
{
var startTime = new Date();
if(newPolygonizer.needs_deallocation) {
newPolygonizer.finish_geometry();
newPolygonizer.needs_deallocation = false;
}
else{
}
newPolygonizer.build_geometry( 28, 1.0, subjective_time);
newPolygonizer.needs_deallocation = true;
var nverts = newPolygonizer.get_v_size();
var nfaces = newPolygonizer.get_f_size();
if(VERBOSE){
console.log(nverts);
}
var verts_address = newPolygonizer.get_v_ptr();
var faces_address = newPolygonizer.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 geom = new MyBufferGeometry77(verts, faces, re_allocate_buffers);
if(VERBOSE){
console.log("nverts : "+ nverts);
console.log("nfaces : "+ nfaces);
}
var endTime = new Date();
var timeDiff = endTime - startTime;
report_time(timeDiff, function(){hist();});
return geom;
}
function my_assert(cond, text){if(!cond){console.error("ASSERT FAILED: "); if(text) console.log(text);}}
function update_reused_geometry(newPolygonizer, subjective_time, geometry) {
var startTime = new Date();
if(newPolygonizer.needs_deallocation) {
newPolygonizer.finish_geometry();
newPolygonizer.needs_deallocation = false;
}
if(newPolygonizer.needs_deallocation)
console.error("not deallocated.");
try{
newPolygonizer.build_geometry( 28, 1.0, subjective_time);
newPolygonizer.needs_deallocation = true;
}catch(err){
console.error("An error occured dugin MCC C++")
console.info(err);
}finally {
}
// geometry. update_geometry (newPolygonizer);
newPolygonizer. update_geometry (geometry);
var endTime = new Date();
var timeDiff = endTime - startTime;
report_time(timeDiff);
}
;
var mesh_solid;
var mesh2_tiny_box_wireframe;
var materials_list;
var material_wireframe;
var mesh_wireframe = null;
const CHOSEN_MATERIAL_INDEX = 2; //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
var chosen_matrial;
const SHOW_WIREFRAME = true;
const SHOW_SOLID = true;
function init_scene(newPolygonizer) {
scene = new THREE.Scene();
var WIDTH = window.innerWidth, HEIGHT = window.innerHeight - 200; //for memory profiler
camera = new THREE.PerspectiveCamera( 75, WIDTH / HEIGHT, 1, 10000 );
camera.position.z = 1000;
materials_list = look_nice(scene);
chosen_matrial = materials_list[CHOSEN_MATERIAL_INDEX];
material_wireframe = new THREE.MeshBasicMaterial( {
color: 0xff0000, wireframe: true, opacity:0.3, transparent: true,} );
var delta_t = 0.2;
global_time += delta_t;
var geometry = null;
geometry = make_geometry_new2(newPolygonizer, global_time, null, true);
if(SHOW_WIREFRAME){
mesh_wireframe = new THREE.Mesh( geometry, material_wireframe );
mesh_wireframe.position.set( 0, 0, 0 );
mesh_wireframe.scale.set( 300, 300, 300 );
scene.add( mesh_wireframe );
}
if(SHOW_SOLID){
mesh_solid = new THREE.Mesh( geometry, chosen_matrial );
mesh_solid.position.set( 0, 0, 0 );
mesh_solid.scale.set( 300, 300, 300 );
scene.add( mesh_solid );
}
var geo2 = new THREE.BoxGeometry( 20, 20, 20 );
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 );
var dirLight = new THREE.DirectionalLight(0xffffff, 1);
dirLight.position.set(100, 100, 50);
scene.add(dirLight);
if(VERBOSE){
console.log("RENDERER");
}
var render_canvas = document.getElementById( 'my_canvas' );
console.log(render_canvas);
renderer = new THREE.WebGLRenderer( { antialias: true, canvas: render_canvas } );
renderer.setSize( WIDTH, HEIGHT );
document.body.appendChild( renderer.domElement );
function doKeyDownListener(event) {
if ( event.keyCode == 17 ) {
call_multiple_times(newPolygonizer, update_mc);
}
else
console.log(event.keyCode);
}
window.addEventListener( "keydown", doKeyDownListener, false );
var cameraControls = new THREE.OrbitControls( camera, renderer.domElement );
cameraControls.target.set( 0, 0, 0 );
cameraControls.addEventListener( 'change', function () {;} );
}
function update_mc(newPolygonizer, delta_t){
var UPDATE_SAME_GEOM_OBJECT = true;
var EVEN_REUSE_MESH_OBJECT = true;
if( EVEN_REUSE_MESH_OBJECT && ! UPDATE_SAME_GEOM_OBJECT)
console.error("Wrong condition.");
if(SHOW_SOLID){
var p1 = [mesh_solid.position, mesh_solid.rotation];
}
if(SHOW_WIREFRAME){
var p2 = [mesh_wireframe.position, mesh_wireframe.rotation];
}
var g = null;
if(SHOW_SOLID){
g = mesh_solid.geometry;
}
if(SHOW_WIREFRAME){
g = 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(mesh_solid);
}
if(SHOW_WIREFRAME){
scene.remove(mesh_wireframe);
}
}
var reused_last_geom = g;
if(!UPDATE_SAME_GEOM_OBJECT){
if(SHOW_SOLID){
g.dispose();
g = null;
}
}
if(!EVEN_REUSE_MESH_OBJECT){
mesh_solid = null;
mesh_wireframe = null;
}
if(delta_t === undefined)
delta_t = 0.2;
global_time += delta_t;
var geometry = null;
if(UPDATE_SAME_GEOM_OBJECT) {
geometry = g;
update_reused_geometry(newPolygonizer, global_time, geometry);
}
else {
geometry = make_geometry_new2(newPolygonizer, global_time, null, false);
};
if(!EVEN_REUSE_MESH_OBJECT){
if(SHOW_WIREFRAME){
mesh_wireframe = new THREE.Mesh( geometry, material_wireframe );
mesh_wireframe.scale.set( 300, 300, 300 );
//copy so that we dont lose the rotation, position of the meshes.
mesh_wireframe.position.copy(p2[0]);
mesh_wireframe.rotation.copy(p2[1]);
scene.add( mesh_wireframe );
}
if(SHOW_SOLID){
mesh_solid = new THREE.Mesh( geometry, chosen_matrial );
mesh_solid.scale.set( 300, 300, 300 );
mesh_solid.position.copy(p1[0]);
mesh_solid.rotation.copy(p1[1]);
scene.add( mesh_solid );
}
}
}
function generateTexture() {
var canvas = document.createElement( 'canvas' );
canvas.width = 256;
canvas.height = 256;
var context = canvas.getContext( '2d' );
var image = context.getImageData( 0, 0, 256, 256 );
var x = 0, y = 0;
for ( var i = 0, j = 0, l = image.data.length; i < l; i += 4, j ++ ) {
x = j % 256;
y = x == 0 ? y + 1 : y;
image.data[ i ] = 255;
image.data[ i + 1 ] = 255;
image.data[ i + 2 ] = 255;
image.data[ i + 3 ] = Math.floor( x ^ y );
}
context.putImageData( image, 0, 0 );
return canvas;
}
function look_nice(scene){
var materials = [];
// Grid
var line_material = new THREE.LineBasicMaterial( { color: 0x303030 } );
var _geometry = new THREE.Geometry();
var floor = -75, step = 25;
for ( var i = 0; i <= 40; i ++ ) {
_geometry.vertices.push( new THREE.Vector3( - 500, floor, i * step - 500 ) );
_geometry.vertices.push( new THREE.Vector3( 500, floor, i * step - 500 ) );
_geometry.vertices.push( new THREE.Vector3( i * step - 500, floor, -500 ) );
_geometry.vertices.push( new THREE.Vector3( i * step - 500, floor, 500 ) );
}
var grid_lines = new THREE.LineSegments( _geometry, line_material );
scene.add( grid_lines );
// Materials
var texture = new THREE.Texture( generateTexture() );
texture.needsUpdate = true;
materials.push( new THREE.MeshLambertMaterial( { map: texture, transparent: true } ) );
materials.push( new THREE.MeshLambertMaterial( { color: 0xdddddd, shading: THREE.FlatShading } ) );
materials.push( new THREE.MeshPhongMaterial( { color: 0xdddddd, specular: 0x009900, shininess: 30, shading: THREE.FlatShading } ) );
materials.push( new THREE.MeshNormalMaterial( ) );
materials.push( new THREE.MeshBasicMaterial( { color: 0xffaa00, transparent: true, blending: THREE.AdditiveBlending } ) );
materials.push( new THREE.MeshLambertMaterial( { color: 0xdddddd, shading: THREE.SmoothShading } ) );
materials.push( new THREE.MeshPhongMaterial( { color: 0xdddddd, specular: 0x009900, shininess: 30, shading: THREE.SmoothShading, map: texture, transparent: true } ) );
materials.push( new THREE.MeshNormalMaterial( { shading: THREE.SmoothShading,
} ));
materials.push( new THREE.MeshBasicMaterial( { color: 0xffaa00, wireframe: true } ) );
materials.push( new THREE.MeshDepthMaterial() );
materials.push( new THREE.MeshLambertMaterial( { color: 0x666666, emissive: 0xff0000, shading: THREE.SmoothShading } ) );
materials.push( new THREE.MeshPhongMaterial( { color: 0x000000, specular: 0x666666, emissive: 0xff0000, shininess: 10, shading: THREE.SmoothShading, opacity: 0.9, transparent: true } ) );
materials.push( new THREE.MeshBasicMaterial( { map: texture, transparent: true } ) );
return materials;
}
var time_queue = [];
var time_queue__last_timeout = 0;
function report_time(time_msec, callback){
time_queue.push(time_msec);
if(time_queue__last_timeout){
clearTimeout(time_queue__last_timeout);
time_queue__last_timeout = 0;
}
time_queue__last_timeout = setTimeout(function(){
console.log("Time: (msec)");
console.log(time_queue);
if(callback)
callback();
time_queue = [];
time_queue__last_timeout =0;
}, 1000);
}
function animate() {
requestAnimationFrame( animate );
//Updating the meshes
var SPEED = 3. / 100;
if(mesh_wireframe){
mesh_wireframe.rotation.x += 0.01*SPEED;
mesh_wireframe.rotation.y += 0.02*SPEED;
}
if(mesh_solid){
mesh_solid.rotation.x += 0.01*SPEED;
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;
renderer.render( scene, camera );
}
var scene, camera, renderer;
window.setTimeout(
3000);
</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.data);
}
}
else{
console.warning("Your browser does not support WebWorkers. See http://stackoverflow.com/questions/4739916/what-browsers-currently-support-web-workers ");
}
}
</script>
<!-- Graph -->
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script>
var ggraph = 0;
function show_hist(data_array){
if(ggraph==0){
add_graph_div();
google.charts.load("current", {packages:["corechart"]});
}
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable(data_array);
var options = {
title: 'Time ( Milliseconds )',
legend: { position: 'none' },
colors: ['#e7711c'],
histogram: {
bucketSize: 1,
},
hAxis: {
ticks: (Array.from(Array(30*1.).keys())).map(function(x){return x/1.;}, Number),
},
};
var div_element = document.getElementById('chart_div');
console.log(div_element);
var chart = new google.visualization.Histogram(div_element);
chart.draw(data, options);
}
ggraph++;
}
var global_histogram_accumulator = [];
function hist_delayed() {
var a = time_queue;
if(global_histogram_accumulator.length==0){
global_histogram_accumulator.push(["Time"]);
}
var UPPER_BOUND = 12;
for(var i=0;i<a.length;i++){
if(a[i]<=UPPER_BOUND)
global_histogram_accumulator.push([a[i]*1.]);
}
show_hist(global_histogram_accumulator);
}
function hist(){
}
function add_graph_div(){
}
</script>
<script>
// The code that runs immediately after finishing loading of the Emscripten-generated js.
function set_off() {
console.log("ready.");
var newPolygonizer = init_polygonizer();
init_scene(newPolygonizer);
animate();
};
</script>
<!-- Memory profiler code by "jj" from https://groups.google.com/forum/#!topic/emscripten-discuss/HtAzVposlX4 -->
<script type="text/javascript" src="./lib/memoryprofiler.js"></script>
<script>
Module={preRun:[
letmeknow=function (){console.log("Loading memory profiler");},
// memoryprofiler_add_hooks
],
onRuntimeInitialized: set_off,
};
</script>
<script type="text/javascript" src="mcc2_MS.cpp.js"></script>