/**
 * SurfaceNets in JavaScript
 *
 * Written by Mikola Lysenko (C) 2012
 *
 * MIT License
 *
 * Based on: S.F. Gibson, "Constrained Elastic Surface Nets". (1998) MERL Tech Report.
 */ import { BufferAttribute , BufferGeometry } from "three" ; var SurfaceNets = ( function ( ) { "use strict" ; var cube_edges = new Int32Array ( 24 ) , edge_table = new Int32Array ( 256 ) ; ( function ( ) { var k = 0 ; for ( var i = 0 ; i < 8 ; ++ i ) { for ( var j = 1 ; j <= 4 ; j <<= 1 ) { var p = i ^ j ; if ( i <= p ) { cube_edges [ k ++ ] = i ; cube_edges [ k ++ ] = p ; } } } for ( var i = 0 ; i < 256 ; ++ i ) { var em = 0 ; for ( var j = 0 ; j < 24 ; j += 2 ) { var a = ! ! ( i & ( 1 << cube_edges [ j ] ) ) , b = ! ! ( i & ( 1 << cube_edges [ j + 1 ] ) ) ; em |= a !== b ? 1 << ( j >> 1 ) : 0 ; } edge_table [ i ] = em ; } } ) ( ) ; var buffer = new Int32Array ( 4096 ) ; return function ( data , dims , isovalue ) { var vertices = [ ] , faces = [ ] , n = 0 , x = new Int32Array ( 3 ) , R = new Int32Array ( [ 1 , dims [ 0 ] + 1 , ( dims [ 0 ] + 1 ) * ( dims [ 1 ] + 1 ) ] ) , grid = new Float32Array ( 8 ) , buf_no = 1 ; if ( R [ 2 ] * 2 > buffer . length ) { buffer = new Int32Array ( R [ 2 ] * 2 ) ; } for ( x [ 2 ] = 0 ; x [ 2 ] < dims [ 2 ] - 1 ; ++ x [ 2 ] , n += dims [ 0 ] , buf_no ^= 1 , R [ 2 ] = - R [ 2 ] ) { var m = 1 + ( dims [ 0 ] + 1 ) * ( 1 + buf_no * ( dims [ 1 ] + 1 ) ) ; for ( x [ 1 ] = 0 ; x [ 1 ] < dims [ 1 ] - 1 ; ++ x [ 1 ] , ++ n , m += 2 ) for ( x [ 0 ] = 0 ; x [ 0 ] < dims [ 0 ] - 1 ; ++ x [ 0 ] , ++ n , ++ m ) { var mask = 0 , g = 0 , idx = n ; for ( var k = 0 ; k < 2 ; ++ k , idx += dims [ 0 ] * ( dims [ 1 ] - 2 ) ) for ( var j = 0 ; j < 2 ; ++ j , idx += dims [ 0 ] - 2 ) for ( var i = 0 ; i < 2 ; ++ i , ++ g , ++ idx ) { var p = data [ idx ] - isovalue ; grid [ g ] = p ; mask |= p < 0 ? 1 << g : 0 ; } if ( mask === 0 || mask === 0xff ) { continue ; } var edge_mask = edge_table [ mask ] , v = [ 0.0 , 0.0 , 0.0 ] , e_count = 0 ; for ( var i = 0 ; i < 12 ; ++ i ) { if ( ! ( edge_mask & ( 1 << i ) ) ) { continue ; } ++ e_count ; var e0 = cube_edges [ i << 1 ] , e1 = cube_edges [ ( i << 1 ) + 1 ] , g0 = grid [ e0 ] , g1 = grid [ e1 ] , t = g0 - g1 ; if ( Math . abs ( t ) > 1e-6 ) { t = g0 / t ; } else { continue ; } for ( var j = 0 , k = 1 ; j < 3 ; ++ j , k <<= 1 ) { var a = e0 & k , b = e1 & k ; if ( a !== b ) { v [ j ] += a ? 1.0 - t : t ; } else { v [ j ] += a ? 1.0 : 0 ; } } } var s = 1.0 / e_count ; for ( var i = 0 ; i < 3 ; ++ i ) { v [ i ] = x [ i ] + s * v [ i ] ; } buffer [ m ] = vertices . length ; vertices . push ( [ ( 2.0 * v [ 0 ] ) / dims [ 0 ] - 1.0 , ( 2.0 * v [ 1 ] ) / dims [ 1 ] - 1.0 , ( 2.0 * v [ 2 ] ) / dims [ 2 ] - 1.0 ] ) ; for ( var i = 0 ; i < 3 ; ++ i ) { if ( ! ( edge_mask & ( 1 << i ) ) ) { continue ; } var iu = ( i + 1 ) % 3 , iv = ( i + 2 ) % 3 ; if ( x [ iu ] === 0 || x [ iv ] === 0 ) { continue ; } var du = R [ iu ] , dv = R [ iv ] ; if ( mask & 1 ) { faces . push ( [ buffer [ m ] , buffer [ m - du ] , buffer [ m - du - dv ] , buffer [ m - dv ] ] ) ; } else { faces . push ( [ buffer [ m ] , buffer [ m - dv ] , buffer [ m - du - dv ] , buffer [ m - du ] ] ) ; } } } } return { vertices : vertices , faces : faces } ; } ; } ) ( ) ; function ConstructTHREEGeometry ( surfaceNetResult ) { var result = surfaceNetResult ; var varray = new Float32Array ( result . vertices . length * 3 ) ; for ( var i = 0 ; i < result . vertices . length ; ++ i ) { var v = result . vertices [ i ] ; varray [ i * 3 + 0 ] = v [ 0 ] ; varray [ i * 3 + 1 ] = v [ 1 ] ; varray [ i * 3 + 2 ] = v [ 2 ] ; } let n_triangles = 0 ; for ( var i = 0 ; i < result . faces . length ; ++ i ) { var f = result . faces [ i ] ; if ( f . length === 3 ) { n_triangles += 1 ; } else if ( f . length === 4 ) { n_triangles += 2 ; } else { console . log ( "unhandled poly with " + f . length + " vertices" ) ; } } var inds = new Uint32Array ( n_triangles * 3 ) ; let j = 0 ; for ( var i = 0 ; i < result . faces . length ; ++ i ) { var f = result . faces [ i ] ; if ( f . length === 3 ) { inds [ j ++ ] = f [ 2 ] ; inds [ j ++ ] = f [ 1 ] ; inds [ j ++ ] = f [ 0 ] ; } else if ( f . length === 4 ) { inds [ j ++ ] = f [ 2 ] ; inds [ j ++ ] = f [ 1 ] ; inds [ j ++ ] = f [ 0 ] ; inds [ j ++ ] = f [ 3 ] ; inds [ j ++ ] = f [ 2 ] ; inds [ j ++ ] = f [ 0 ] ; } } var geo = new BufferGeometry ( ) ; geo . setAttribute ( "position" , new BufferAttribute ( varray , 3 , false ) ) ; geo . setIndex ( new BufferAttribute ( inds , 1 ) ) ; geo . computeVertexNormals ( ) ; return [ geo ] ; } export default { surfaceNets : SurfaceNets , constructTHREEGeometry : ConstructTHREEGeometry , } ;