Large Mesh Simplification using Processing Sequences Martin Isenburg UNC Chapel Hill Peter Lindstrom LLNL Livermore Stefan Gumhold GRIS Tubingen Jack Snoeyink UNC Chapel Hill
Overview Motivation Background Processing Sequences Adapted Simplification Schemes – OOCS – Wu & Kobbelt Conclusion
Motivation
Large Meshes 3D scansisosurfaces
Large Meshes 3D scansisosurfaces
PPM isosurface 235 million vertices 469 million triangles 235 million rtices million triangles over 8 Gigabyte ! hampers: distributing / loading rendering processing
in-core algorithms of choice: – Qslim – Rsimp Mesh Simplification alternative: processing sequence [ Garland & Heckbert ’97 ] [ Brodsky & Watson ’00 ] require ~ 200 bytes per vertex current out-of-core approaches: 1. piece by piece 2. external memory 3. polygon soup [ Lindstrom ’00 ] [ Hoppe ’98 ] [ Cignoni et al. ’03 ]
Background
Related Work Large Mesh Processing – Simplification – Compression – Visualization Systems Main Techniques 1. Mesh Cutting 2. Online Processing 3. Batch Processing
cut mesh into small pieces process each separately special treatment for cuts stitch result back together 1. Mesh Cutting figure courtesy of Hugues Hoppe
2. Online Processing external memory data structures “random” mesh access figure courtesy of Paolo Cignoni
3. Batch Processing ( 1 ) polygon soup single scan over stream of de-referenced triangles no explicit connectivity [ Lindstrom ’00 ]
3. Batch Processing ( 2 ) polygon soup single scan over stream of de-referenced triangles no explicit connectivity ( coherent ) reconstruct figure courtesy of Jianhua Wu and Leif Kobbelt [ Wu & Kobbelt ’03 ]
Sequenced Processing coherent triangle ordering interleaved with vertices small footprint streaming finalization of vertices [ Isenburg & Gumhold ’03 ]
Quadric Error Matrices accumulate error vertex placement sum of squared distances of point to set of planes quadric error: figure courtesy of Michael Garland [ Garland & Heckbert ’97 ] Q = q 00 q 01 q 02 q 03 q 10 q 11 q 12 q 13 q 20 q 21 q 22 q 23 q 30 q 31 q 32 q 33 v T Qv
Processing Sequences
A little history … Compressor – region growing
A little history … Compressor – region growing Out - of - Core Mesh – transparent – caching clusters
A little history … Compressor – region growing Out - of - Core Mesh – transparent – caching clusters Compact Format – small footprint – streaming
A little history … Compressor – region growing Out - of - Core Mesh – transparent – caching clusters Compact Format – small footprint – streaming
A little history … Compressor – region growing Out - of - Core Mesh – transparent – caching clusters Compact Format – small footprint – streaming
interleaved ordering of triangles and vertices that “grows regions” processing boundary Processing Sequences border edges Q7Q7 Q1Q1 Q4Q4 available information: – first & last use of edges & vertices – surface border maintain data along boundary
unprocessed region Abstractions boundary-based – one boundary – process immediately processed region waiting area processing boundary
processed region unprocessed region Abstractions boundary-based – one boundary – process immediately buffer-based – two boundaries – process in buffer – read to fill – write to empty in-core buffer output boundary input boundary processed region unprocessed region processing boundary waiting area
OOCS
stream in polygon soup – triangle after triangle vertex clustering – one quadric per grid cell output sensitive – store all quadrics no border info – tangential term added
OOCS Q Q input output
OOCS Q Q Q Q input output
OOCS Q Q Q Q input output
OOCS Q Q QQ Q Q Q input output
OOCS QQ Q Q Q Q QQ Q Q Q Q QQ Q input output Q
OOCS QQ Q Q Q Q QQ QQ Q Q Q Q Q Q Q Q QQ Q Q Q Q Q Q Q Q Q Q Q input output
OOCS QQ Q Q Q Q Q Q Q QQ Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q input output
OOCS QQ Q Q Q Q Q Q Q QQ Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q QQ Q Q Q Q input output
OOCS QQ Q Q Q Q Q Q Q QQ Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q QQ Q Q Q Q input output
OOCS using PS
fewer artifacts – do not collapse multiple layers into single vertex – improved surface boundaries streaming output OOCS using PS memory insensitive – maintain much fewer quadrics
processed region unprocessed region Q7 7 Q OOCS using PS ( detail ) Q3 3 Q4 4 4
processed region unprocessed region Q5 5 Q4 Q Q3 5 3 OOCS using PS ( detail )
processed region unprocessed region Q5 5 Q4 Q Q3 turns into vertex quadric OOCS using PS ( detail )
processed region unprocessed region Q5 5 Q4 Q Q8 8 OOCS using PS ( detail )
processed region unprocessed region Q5 5 Q4 Q Q8 8 OOCS using PS ( detail )
processed region unprocessed region Q5 5 Q4 Q7 7 5 Q8 8 quadric turns into vertex 8 OOCS using PS ( detail )
processed region unprocessed region Q5 5 Q7 7 5 Q8 8 8 Q9 9 OOCS using PS ( detail )
processed region unprocessed region Q5 5 Q7 7 Q8 8 8 Q9 9 quadric merge OOCS using PS ( detail )
OOCS using PS input output Q Q
OOCS using PS Q Q Q Q output input
OOCS using PS Q Q Q Q Q Q output input Q Q
OOCS using PS Q Q Q Q Q Q Q Q Q Q Q Q Q output input Q Q Q Q
OOCS using PS Q Q Q Q Q Q Q Q Q Q Q output input Q Q Q Q Q Q Q Q Q Q Q Q Q Q
OOCS using PS Q Q Q Q Q Q output input Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q
OOCS using PS Q QQ Q Q output input Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q
OOCS using PS Q QQ Q Q Q output input Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q
OOCS using PS Q Q Q Q Q output input Q QQ Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q
OOCS using PS output input Q QQ Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q
Improved Mesh Quality OOCS-PS OOCS vertices: 33,053 non-manifold vertices:3,366 vertices: 35,134 non-manifold vertices:897
Lower Memory Requirements 373 million vertices OOCS memory: 3,282 MB time: 67 min OOCS-PS memory: 121 MB time: 83 min 23 million vertices
Wu & Kobbelt
stream coherent soup into buffer reconstruct connectivity – hash on vertex data – finalize complete stars input boundary aa a a a a a a a accumulating cc collapsible randomized edge collapse – one quadric per vertex – accumulating collapsible randomized streaming output
Wu & Kobbelt c a a a a a a a input output
Wu & Kobbelt c c c c c c c c c a a a a a a a a a a a a a a a a a a a a a a a a a a a input output
Wu & Kobbelt c c c c c a a a a c a a a a a a c c c a a a a a a a a a a a a c c c a a a a a a a a a a a a a a a a a c c c output input
Wu & Kobbelt c c c c c a a a a a a a a a a c c c a a a a a a a a a a a a c c c a a a a a a a a a a a a a a a a a c c a a a a a c c c c c c c c c a a a a c c c c a a output input
Wu & Kobbelt c c c c c a a a a a a a a a a c c a a a a a a a a a a a a c c a a a a a a a a a a a a a a c c a a a a a c c c c c a a a a c c c c a a a a a a a a c c c c c c c c c c c c c c c c c c c output input
Wu & Kobbelt c a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a c a a a a a c a a a a a a a a a a c c c c c c c c a a a a a a a a a a a a a a a a a a a a a a c c c c c c c c c c c c c output input
Wu & Kobbelt a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a c c a a a a a a a a a a a a a a a a a aa a a a c c c a a a a a a a a a a a a a a a c c cc c c c c c c c output input
Wu & Kobbelt a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a c aa a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a c c a a a a c c c c c c c c c a c a output input
Wu & Kobbelt a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a c c c c c a a a a c output input
border Wu & Kobbelt a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a c c c c c output input
Wu & Kobbelt c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c output input
Wu & Kobbelt c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c output input
Wu & Kobbelt c c c c c c c c c c c c c c c c c c c c c c c c output input
Wu & Kobbelt output input
Wu & Kobbelt using PS
less fragmentation of buffer – processing sequence input / output – more collapsible edges immediate boundary simplification – mesh borders known early – truly “streaming” output faster connectivity reconstruction – indexed input / API support
Wu & Kobbelt using PS ( detail ) unprocessed region processed region input boundary output boundary in-core triangle buffer a a a a a a a accumulating c c c c c c c collapsible
Wu & Kobbelt using PS ( detail ) unprocessed region processed region input boundary output boundary in-core triangle buffer c c c c c c c collapsible a a a a a a a accumulating c
Wu & Kobbelt using PS ( detail ) unprocessed region processed region input boundary output boundary in-core triangle buffer c c c c c c c collapsible a a a a a a a a accumulating c c
Wu & Kobbelt using PS ( detail ) unprocessed region processed region input boundary output boundary in-core triangle buffer c c c c c collapsible a a a a a a a a accumulating c c c
Wu & Kobbelt using PS ( detail ) unprocessed region processed region input boundary output boundary in-core triangle buffer c c c c c collapsible a a a a a a a a accumulating c c c
Wu & Kobbelt using PS ( detail ) unprocessed region processed region input boundary output boundary in-core triangle buffer c c c c c collapsible a a a a a a a a accumulating c c
Wu & Kobbelt using PS input output
Wu & Kobbelt using PS a c a a a a a a a a a a c c c output input
Wu & Kobbelt using PS a a aa a a a a a a a a a a a a a a c c c c c c c c c c c c c output input
Wu & Kobbelt using PS a a a a a a a a a a a a a a a aa a a a a a a a a a a c cc c c c c c c c c c c c c c c c c c c c c c c c output input
Wu & Kobbelt using PS a a a a a a a a a a aa a a a a a a a a a a a a c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c output input
Wu & Kobbelt using PS a a a a a a a a a a a a a a c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c input output
Wu & Kobbelt using PS a a a a a a a a a a a a c c c c c c c c c c c c c c c c c c c c c c c c c c c c c input output
Wu & Kobbelt using PS a a a a a a a a a a a a c c c c c c c c c c c a c c c c c c c c c c c c c c c c input output
Wu & Kobbelt using PS a a a a a a a a a c a c c c c c c c c c c c c c a c c c c c c c c c c c c c c c c c input output
Wu & Kobbelt using PS c c c c c c c c c c c c c c c c c input output
Wu & Kobbelt using PS input output
Conclusion & Current Work
Summary processing sequences – efficient large mesh access – streaming input and output – abstractions: boundary-based buffer-based adapted simplification algorithms: – OOCS – Wu & Kobbelt
length of processing boundary – possible – traversal is optimized for lowest bit-rate change heuristic Issues O( n )O( n ) [ Bar-Yehuda & Gotsman ‘96 ] external memory mesh to create processing sequences …? – expensive to build & use – defeats purpose …
Generating PS on-the-fly input: “streaming mesh” v v v f done 2 v f done 1 ⋮ ⋮ ⋮ ⋮ vertices finalized ( not used by subsequent triangles )
extend to volume meshes promote – provide API create / improve – lower processing boundary length Current Work compress – encode on-the-fly
Thank You.
v0v0 v1v1 v2v2 fill Growing Operations v0v0 v1v1 v2v2 end v0v0 v1v1 v2v2 start v0v0 v1v1 v2v2 joinadd v0v0 v1v1 v2v2 processing boundary
read next triangle info about current triangle optional maintaining of user data Prototype of PS API intopen(const char* file_name); intread_triangle(); voidclose(); intt_idx[3]; float* t_pos_f[3]; intt_vflag[3]; intt_eflag[3]; voidset_edata( void* data, int i ); voidset_vdata( void* data, int i ); void*get_edata( int i ); void*get_vdata( int i );
Example ( 1 ) v0v0 v1v1 v2v2 eflag[0] = PS_FIRST eflag[1] = PS_FIRST eflag[2] = PS_FIRST vflag[0] = PS_FIRST vflag[1] = PS_FIRST vflag[2] = PS_FIRST v0v0 v1v1 v2v2 eflag[0] = PS_FIRST eflag[1] = PS_FIRST | PS_LAST eflag[2] = PS_FIRST | PS_LAST vflag[0] = PS_FIRST vflag[1] = PS_FIRST | PS_LAST vflag[2] = PS_FIRST border edge entering edge border edge e0e0 e1e1 e2e2 start
entering edge leaving edges border edge entering edge leaving edge v0v0 v1v1 v2v2 add Example ( 2 ) eflag[0] = PS_LAST eflag[1] = PS_FIRST | PS_LAST eflag[2] = PS_FIRST vflag[0] = 0 vflag[1] = 0 vflag[2] = PS_FIRST eflag[0] = PS_LAST eflag[1] = PS_FIRST eflag[2] = PS_LAST vflag[0] = PS_LAST vflag[1] = 0 vflag[2] = 0 fill v0v0 v1v1 v2v2
Example ( 3 ) eflag[0] = PS_LAST eflag[1] = PS_LAST eflag[2] = PS_LAST vflag[0] = PS_LAST vflag[1] = PS_LAST vflag[2] = PS_LAST eflag[0] = PS_LAST eflag[1] = PS_LAST eflag[2] = PS_LAST vflag[0] = PS_LAST vflag[1] = 0 vflag[2] = PS_LAST leaving edges v0v0 v1v1 v2v2 v0v0 v1v1 v2v2 end
Computing Smooth Normals ps.open ( “bunny.sma” ) ; while ( ps.read_triangle() ) tmp = compute ( ps.t_pos[ 0 ], ps.t_pos[ 1 ], ps.t_pos[ 2 ] ); for ( i = 0; i < 3; i++ ) if ( ps.vflag[i] & PS_FIRST ) n = new Normal (); ps.set_vdata ( n, i ); else n = ps.get_vdata ( i ); add ( n, tmp ); if ( ps.vflag[i] & PS_LAST ) normalize ( n ); do something delete n; ps.close ();