UNPKG

@sohale/implisolid

Version:

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

686 lines (526 loc) 22.4 kB
<html> <head> <meta charset="utf-8"/> </head> <script type="text/javascript" src="mc2_pb.cpp.js"></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r77/three.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 type="text/javascript" src="./controls/OrbitControls.js"></script> <body> Written using C++ and ThreeJS. <br> <script> //'use strict'; var WIREFRAME = false; var make_object; var main; function init1() { make_object = Module.cwrap('make_object', null, ['number', 'number', 'number', 'number']); main = Module.cwrap('main', 'number', []); console.log("ok"); } function do_it(q) { const VEC_SIZE = 3; const ELEM_SIZE = 8; var offset = Module._malloc(ELEM_SIZE*VEC_SIZE) Module.HEAPF64.set(new Float64Array(q), offset/ELEM_SIZE); //Module.HEAPF64 is a Float64Array var r2 = Module.HEAPF64.subarray(offs2/ELEM_SIZE, offs2/ELEM_SIZE + VEC_SIZE); return r2; } function do_vf() { //const DBLFLOAT_SIZE = 8; const FLOAT_SIZE = 4; const INT_SIZE = 4; //4 int //4 float //4 long //var max_verts = 2000 * 3; // *2 //var max_faces = 10000; //*5 var max_verts = 10000; // *2 var max_faces = 5000; //*5 var verts_address = Module._malloc(FLOAT_SIZE*3*max_verts); var nv_address = Module._malloc(INT_SIZE*1); var faces_address = Module._malloc(INT_SIZE*3*max_faces) var nf_address = Module._malloc(INT_SIZE*1); //Module.HEAPF64.set(new Float64Array(q), offset/DBLFLOAT_SIZE); make_object(verts_address, nv_address, faces_address, nf_address); //Module.HEAPF64 is a Float64Array var nverts = Module.HEAPU32[nv_address/INT_SIZE]; console.log("nverts : "+ nverts) var nfaces = Module.HEAPU32[nf_address/INT_SIZE]; console.log("nfaces : "+ nfaces) 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 verts = undefined; return [verts, faces]; } //init1(); //alert('Computing3: ' + JSON.stringify(do_vf() )); var q = [2., 3, 4] //alert('Computing2: ' + callvect(q)); //var r2 = do_it(q) //console.log("Result:"); //console.log( do_it(q) ); //alert('Computing2: ' + JSON.stringify(r2)); //console.log(JSON.stringify( do_vf() )); /* function make_my_geometry() { vf = do_vf(); v = vf[0]; f = vf[1]; for(int vi=0; vi < v.length; vi++) for(int di=0; di < 3; di++) verts[vi*3+di] = verts1[vi][di]; for(int fi=0; fi < f.length; fi++) for(int si=0; si < 3; si++) faces[fi*3+si] = f1[fi][si]; return [v, f]; } */ MyBufferGeometry = function ( verts, faces, width, height, depth, widthSegments, heightSegments, depthSegments ) { THREE.BufferGeometry.call( this ); this.type = 'MyBufferGeometry'; //console.log(verts); width=20; height=20; depth=20; widthSegments=undefined; heightSegments=undefined; depthSegments=undefined; this.parameters = { /*width: width, height: height, depth: depth, widthSegments: widthSegments, heightSegments: heightSegments, depthSegments: depthSegments*/ }; var scope = this; // segments widthSegments = Math.floor( widthSegments ) || 1; heightSegments = Math.floor( heightSegments ) || 1; depthSegments = Math.floor( depthSegments ) || 1; //var vcount = 24; // //calculateVertexCount( widthSegments, heightSegments, depthSegments ); //vcount = verts.length/3; // these are used to calculate buffer length //var vertexCount = 24; //vcount; //var indexCount = 36; //calculateIndexCount( widthSegments, heightSegments, depthSegments ); var vertexCount = 24; //verts.length; var indexCount = 36; //faces.length; var vertexCount = calculateVertexCount( widthSegments, heightSegments, depthSegments ); var indexCount = calculateIndexCount( widthSegments, heightSegments, depthSegments ); var vertexCount = verts.length/3; var indexCount = faces.length; var facecount = indexCount/3; console.log("vertexCount indexCount") console.log(vertexCount+ " , " + indexCount); // buffers var indices = new ( indexCount > 65535 ? Uint32Array : Uint16Array )( indexCount ); var vertices = new Float32Array( vertexCount * 3 ); var normals = new Float32Array( vertexCount * 3 ); var uvs = new Float32Array( vertexCount * 2 ); // offset variables var vertexBufferOffset = 0; var uvBufferOffset = 0; var indexBufferOffset = 0; var numberOfVertices = 0; // group variables var groupStart = 0; // build each side of the box geometry /* buildPlane( 'z', 'y', 'x', - 1, - 1, depth, height, width, depthSegments, heightSegments, 0 ); // px buildPlane( 'z', 'y', 'x', 1, - 1, depth, height, - width, depthSegments, heightSegments, 1 ); // nx buildPlane( 'x', 'z', 'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2 ); // py buildPlane( 'x', 'z', 'y', 1, - 1, width, depth, - height, widthSegments, depthSegments, 3 ); // ny buildPlane( 'x', 'y', 'z', 1, - 1, width, height, depth, widthSegments, heightSegments, 4 ); // pz buildPlane( 'x', 'y', 'z', - 1, - 1, width, height, - depth, widthSegments, heightSegments, 5 ); // nz */ //output: vertices, normals, uvs, indices SCALE = 1. if(1){ //console.log(verts.length); //console.log(faces.length); //console.log(verts); //console.log(faces); //exfdgdg() console.log("Vertexcount: "+vertexCount); console.log("**************************************"); for(var i=0; i < vertexCount; i++) { for(var di=0;di<3;di++) vertices[i*3+di] = verts[i*3+di] * SCALE; x = verts[i*3+0]; y = verts[i*3+1]; z = verts[i*3+2]; d = Math.sqrt(x*x+y*y+z*z); d=d+0.; //if(d==0) d=1.; if(isNaN(d)) { d=1.;x=1.;y=1.;z=1.; console.log("Warning"); } //console.log("x y z"+x+" "+y+" "+z+" / "+ d) /* if(Math.random()>0.5) sgn=-1; else sgn = +1; */ sgn = +1; normals[i*3 + 0] = x/d*sgn; normals[i*3 + 1] = y/d*sgn; normals[i*3 + 2] = z/d*sgn; if(isNaN(x/d)) console.error("WARNING: NaN."); //console.log("verts "+verts[i*3+0]+" "+verts[i*3+1]+" "+verts[i*3+2]) //console.log("d "+d) //if(d<0.00001){ // sdsgf() //} d2 = Math.sqrt(x*x+y*y); uvs[i*2+0] = x/d2; uvs[i*2+1] = y/d2; } for(var i=0; i < facecount; i++) for(var si=0; si<3; si++) indices[i*3+si] = faces[i*3+si]; materialIndex = 0; this.addGroup( 0, facecount*3, materialIndex ); //not sure about *3 . Why?? //console.log(vertices); //console.log(normals); //console.log(uvs); //console.log(indices); } //this.addGroup( groupStart, groupCount, materialIndex ); //groupCount is same as indices' index. //modified, but not output: indexBufferOffset, vertexBufferOffset, uvBufferOffset, numberOfVertices, groupStart // build geometry this.setIndex( new THREE.BufferAttribute( indices, 3 ) ); this.addAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) ); this.addAttribute( 'normal', new THREE.BufferAttribute( normals, 3 ) ); this.addAttribute( 'uv', new THREE.BufferAttribute( uvs, 2 ) ); // helper functions function calculateVertexCount ( w, h, d ) { var vertices = 0; // calculate the amount of vertices for each side (plane) vertices += (w + 1) * (h + 1) * 2; // xy vertices += (w + 1) * (d + 1) * 2; // xz vertices += (d + 1) * (h + 1) * 2; // zy return vertices; } function calculateIndexCount ( w, h, d ) { var index = 0; // calculate the amount of squares for each side index += w * h * 2; // xy index += w * d * 2; // xz index += d * h * 2; // zy return index * 6; // two triangles per square => six vertices per square } function buildPlane ( u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex ) { /* output: vertices, normals, uvs, vertexBufferOffset, uvBufferOffset indices indexBufferOffset numberOfVertices groupStart */ var segmentWidth = width / gridX; var segmentHeight = height / gridY; var widthHalf = width / 2; var heightHalf = height / 2; var depthHalf = depth / 2; var gridX1 = gridX + 1; var gridY1 = gridY + 1; var vertexCounter = 0; var groupCount = 0; var vector = new THREE.Vector3(); // generate vertices, normals and uvs for ( var iy = 0; iy < gridY1; iy ++ ) { var y = iy * segmentHeight - heightHalf; for ( var ix = 0; ix < gridX1; ix ++ ) { var x = ix * segmentWidth - widthHalf; // set values to correct vector component vector[ u ] = x * udir; vector[ v ] = y * vdir; vector[ w ] = depthHalf; // now apply vector to vertex buffer vertices[ vertexBufferOffset ] = vector.x; vertices[ vertexBufferOffset + 1 ] = vector.y; vertices[ vertexBufferOffset + 2 ] = vector.z; // set values to correct vector component vector[ u ] = 0; vector[ v ] = 0; vector[ w ] = depth > 0 ? 1 : - 1; // now apply vector to normal buffer normals[ vertexBufferOffset ] = vector.x; normals[ vertexBufferOffset + 1 ] = vector.y; normals[ vertexBufferOffset + 2 ] = vector.z; // uvs uvs[ uvBufferOffset ] = ix / gridX; uvs[ uvBufferOffset + 1 ] = 1 - ( iy / gridY ); // update offsets and counters vertexBufferOffset += 3; uvBufferOffset += 2; vertexCounter += 1; } } // 1. you need three indices to draw a single face // 2. a single segment consists of two faces // 3. so we need to generate six (2*3) indices per segment for ( iy = 0; iy < gridY; iy ++ ) { for ( ix = 0; ix < gridX; ix ++ ) { // indices var a = numberOfVertices + ix + gridX1 * iy; var b = numberOfVertices + ix + gridX1 * ( iy + 1 ); var c = numberOfVertices + ( ix + 1 ) + gridX1 * ( iy + 1 ); var d = numberOfVertices + ( ix + 1 ) + gridX1 * iy; // face one indices[ indexBufferOffset ] = a; indices[ indexBufferOffset + 1 ] = b; indices[ indexBufferOffset + 2 ] = d; // face two indices[ indexBufferOffset + 3 ] = b; indices[ indexBufferOffset + 4 ] = c; indices[ indexBufferOffset + 5 ] = d; // update offsets and counters indexBufferOffset += 6; groupCount += 6; } } // add a group to the geometry. this will ensure multi material support scope.addGroup( groupStart, groupCount, materialIndex ); // calculate new start value for groups groupStart += groupCount; // update total number of vertices numberOfVertices += vertexCounter; } }; MyBufferGeometry.prototype = Object.create( THREE.BufferGeometry.prototype ); MyBufferGeometry.prototype.constructor = MyBufferGeometry; MyGeometry = function (verts, faces) { //vects, faces THREE.Geometry.call( this ); this.type = 'ImplicitGeometry'; //? this.parameters = { /*width: width, height: height, depth: depth, widthSegments: widthSegments, heightSegments: heightSegments, depthSegments: depthSegments*/ }; //faces = faces.subarray(0, 300); this.fromBufferGeometry( new MyBufferGeometry( verts, faces ) ); //this.mergeVertices(); }; MyGeometry.prototype = Object.create( THREE.Geometry.prototype ); MyGeometry.prototype.constructor = MyGeometry; //var zz=new MyGeometry(); //console.log(zz); function make_geometry() { vf = do_vf(); v = vf[0]; f = vf[1]; //console.log(v); //console.log(f); //scale return new MyGeometry(v, f); } function cut_away(){ //return new THREE.BoxGeometry( 200, 200, 200 ); /* var geometry = new THREE.Geometry(); //console.log(v); console.log(v.length/3.); for(var vi=0; vi < v.length/3; vi++) { geometry.vertices.push( new THREE.Vector3( v[vi*3 + 0], v[vi*3 + 1], v[vi*3 + 2] ) ); } geometry.faces.push( new THREE.Face3( 0, 1, 2 ) ); geometry.faces.push( new THREE.Face3( 0, 1, 3 ) ); geometry.computeFaceNormals(); geometry.computeBoundingSphere(); */ //geometry //return geometry; /* this = geometry; var positions = new THREE.BufferAttribute( new Float32Array( vertexCount * 3 ), 3 ); var normals = new THREE.BufferAttribute( new Float32Array( vertexCount * 3 ), 3 ); var uvs = new THREE.BufferAttribute( new Float32Array( vertexCount * 2 ), 2 ); this.setIndex( new ( positions.count > 65535 ? THREE.Uint32Attribute : THREE.Uint16Attribute )( indices, 1 ) ); this.addAttribute( 'position', positions ); this.addAttribute( 'normal', normals ); this.addAttribute( 'uv', uvs ); this.boundingSphere = new THREE.Sphere( new THREE.Vector3(), radius ); */ if(0) { geometry = new THREE.BufferGeometry(); positions = new THREE.BufferAttribute( v ); //geometry.addAttribute( 'position', positions ); //this.addAttribute( 'normal', normals ); //this.addAttribute( 'uv', uvs ); //indices = f; indices = [] for(var i=0; i < f.length; i++) indices.push( f[i] ); console.log( indices ); geometry.setIndex( new ( positions.count > 65535 ? THREE.Uint32Attribute : THREE.Uint16Attribute )( indices, 1 ) ); geometry.addAttribute( 'position', positions ); /* this.addAttribute( 'normal', normals ); this.addAttribute( 'uv', uvs ); */ geometry.computeFaceNormals(); geometry.computeBoundingSphere(); return geometry; } if(0){ var geom = new THREE.Geometry(); for(var i=0; i < v.length; i++) //geom.vertices.push( new THREE.Vector3(v[i][0], v[i][1], v[i][2] ) ); geom.vertices.push( v[i][0], v[i][1], v[i][2] ); for(var i=0; i < f.length; i++) //geom.faces.push( new THREE.Face3( f[i][0], f[i][1], f[i][2] ) ); geom.faces.push( f[i][0], f[i][1], f[i][2] ); console.log(geom.vertices); console.log(geom.faces); geom.computeFaceNormals(); geom.computeBoundingSphere(); return geom; } } mesh = null; function init2() { scene = new THREE.Scene(); WIDTH = 300; HEIGHT = 300; WIDTH = window.innerWidth; HEIGHT = window.innerHeight; camera = new THREE.PerspectiveCamera( 75, WIDTH / HEIGHT, 1, 10000 ); camera.position.z = 1000; materials_list = look_nice(scene); material = new THREE.MeshBasicMaterial( { color: 0xff0000, wireframe: true, opacity:0.3, transparent: true, } ); if(1){ //geometry = new THREE.BoxGeometry( 200, 200, 200 ); geometry = make_geometry(); //geometry = new MyGeometry(); mesh = new THREE.Mesh( geometry, material ); mesh.position.set( 0, 0, 0 ); //mesh.scale.set( 10*10, 10*10, 10*10 ); mesh.scale.set( 300, 300, 300 ); //mesh.position.z = +0; //mesh.rotation.y = -Math.PI * .5; scene.add( mesh ); //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 } ); //meshf = new THREE.Mesh( geometry, material_f ); //nice ones: 2, 3, (checked until 4) meshf = new THREE.Mesh( geometry, materials_list[3] ); meshf.position.set( 0, 0, 0 ); meshf.scale.set( 300, 300, 300 ); scene.add( meshf ); geo2 = new THREE.BoxGeometry( 20, 20, 20 ); mesh2 = new THREE.Mesh( geo2, material ); mesh2.position.set( 0, 0, 0 ); scene.add( mesh2 ); //mesh2.scale.set( 10, 10, 10 ); var dirLight = new THREE.DirectionalLight(0xffffff, 1); dirLight.position.set(100, 100, 50); scene.add(dirLight); console.log("RENDERER"); renderer = new THREE.WebGLRenderer( { antialias: true } ); //renderer.setSize( window.innerWidth, window.innerHeight ); renderer.setSize( WIDTH, HEIGHT ); document.body.appendChild( renderer.domElement ); // CONTROLS //see https://github.com/mrdoob/three.js/blob/master/examples/webgl_geometry_teapot.html cameraControls = new THREE.OrbitControls( camera, renderer.domElement ); cameraControls.target.set( 0, 0, 0 ); cameraControls.addEventListener( 'change', function () {;} ); } //based on http://threejs.org/examples/#webgl_materials 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 } ), geometry = new THREE.Geometry(), 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 line = new THREE.LineSegments( geometry, line_material ); scene.add( line ); // 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.MeshBasicMaterial( { color: 0xff0000, blending: THREE.SubtractiveBlending } ) ); 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; } function animate() { requestAnimationFrame( animate ); var SPEED = 3. / 100; if(mesh){ mesh.rotation.x += 0.01*SPEED; mesh.rotation.y += 0.02*SPEED; meshf.rotation.x += 0.01*SPEED; meshf.rotation.y += 0.02*SPEED; } mesh2.rotation.z += 0.01*SPEED; mesh2.rotation.y += 0.02*SPEED; //materials_list[ materials.length - 2 ].emissive.setHSL( 0.54, 1, 0.35 * ( 0.5 + 0.5 * Math.sin( 35 * timer ) ) ); //materials_list[ materials.length - 3 ].emissive.setHSL( 0.04, 1, 0.35 * ( 0.5 + 0.5 * Math.cos( 35 * timer ) ) ); renderer.render( scene, camera ); } var scene, camera, renderer; var geometry, material, mesh; window.setTimeout(function() { init1(); init2(); animate(); }, 2000); </script>