https://github.com/hhoppe/Mesh-processing-library
C++ libraries and programs demonstrating mesh processing research published in ACM SIGGRAPH (1992-2003)
https://github.com/hhoppe/Mesh-processing-library
mesh-processing triangle-mesh
Last synced: 13 days ago
JSON representation
C++ libraries and programs demonstrating mesh processing research published in ACM SIGGRAPH (1992-2003)
- Host: GitHub
- URL: https://github.com/hhoppe/Mesh-processing-library
- Owner: hhoppe
- License: mit
- Created: 2017-01-03T05:48:29.000Z (over 8 years ago)
- Default Branch: main
- Last Pushed: 2025-04-13T06:00:40.000Z (17 days ago)
- Last Synced: 2025-04-14T13:08:37.228Z (15 days ago)
- Topics: mesh-processing, triangle-mesh
- Language: C++
- Homepage:
- Size: 73.9 MB
- Stars: 847
- Watchers: 34
- Forks: 137
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Mesh Processing Library
## Overview
This package contains C++ libraries and programs demonstrating mesh processing research
published in ACM SIGGRAPH (1992–2003):- surface reconstruction (from unorganized, unoriented points)
- mesh optimization
- subdivision surface fitting
- mesh simplification
- progressive meshes (level-of-detail representation)
- geomorphs (smooth transitions across LOD meshes)
- view-dependent mesh refinement
- smooth terrain LOD
- progressive simplicial complexes
- optimized mesh traversal (for transparent vertex caching)
- spherical parameterizationThe source code has been updated to modern C++ style and for cross-platform use.
## Requirements / dependencies
The code can be compiled with Microsoft Visual Studio using the solution (`*.sln`)
and project (`*.vcxproj`) files.On Unix (Linux, Mac OS, and Cygwin),
the code compiles using the `clang` and `gcc` compilers and GNU `make`.Reading/writing of images and videos is enabled using several options.
If available, image I/O can use `libpng`/`libjpeg` or Windows Imaging Component (WIC).
Video I/O can use Windows Media Foundation (WMF).
Across all platforms, if the command `ffmpeg`
is present in the `PATH`,
it is spawned in a piped subprocess for both image and video I/O.On Mac OS X, it is necessary to install
`XQuartz` for `X11` support and
`ffmpeg` for image/video I/O.## Code compilation
### Build using Microsoft Visual Studio
Open the `mesh_processing.sln` file and build the solution
(typically as a `"ReleaseMD - x64"` build).
Executables are placed in `bin`, `bin/debug`, `bin/Win32`, or `bin/Win32/debug`,
depending on the build configuration.### Build using GNU `make`
The `CONFIG` environment variable determines
which `make/Makefile_config_*` definition file is loaded.
On Windows, `CONFIG` can be chosen among `{win, w32, cygwin, mingw, mingw32, clang}`,
defaulting to `win` if undefined.
On Unix platforms (Linux and Mac OS), `CONFIG=unix` is the unique and default setting.For example, to build using the Microsoft `cl` compiler (Debug, placing `*.exe` into directory `bin/win`):
`make -j8`To build all programs (into either `bin/unix` or `bin/win`) and run all unit tests:
`make -j test`To build on Unix, forcing the use of the `gcc` compiler (default is `clang`):
`make CC=gcc -j`To build just the main library using the `mingw gcc` compiler on Windows:
`make CONFIG=mingw -j libHh`To build the `Filtermesh` program (into `bin/clang`) using the `clang` compiler on Windows:
`make CONFIG=clang -j Filtermesh`To build all programs (into `bin/cygwin`) and run all demos using the `gcc` compiler under Cygwin:
`make CONFIG=cygwin -j demos`To clean up all files in all configurations:
`make CONFIG=all -j deepclean`Note that additional options such as debug/release, 32-bit/64-bit, and
compiler tool paths/parameters are set in the various `make/Makefile_*` files.
These need to be adjusted depending on the versions and installation paths of the tools.
For instance, the line
`"rel ?= 0"` in `make/Makefile_config_win` specifies a debug (non-release) build, and
`"$(call prepend_PATH,...)"` in `make/Makefile_base_vc` sets the compiler directory.## Publications and associated programs/demos
![]()
ACM SIGGRAPH 1992 Proceedings. (2023 Seminal Paper.)
Signed-distance field estimated from a set of unoriented noisy points.
Demos:create_recon_*.{sh,bat}
,view_recon_*.{sh,bat}
![]()
ACM SIGGRAPH 1993 Proceedings.
Traversing the space of triangle meshes to optimize model fidelity and conciseness.
Demos:create_recon_*
,view_recon_*
,create_simplified_using_meshopt
,view_simplified_using_meshopt
![]()
ACM SIGGRAPH 1994 Proceedings.
Subdivision surfaces with sharp features, and their automatic creation by data fitting.
Demos:create_recon_cactus
,view_recon_cactus
![]()
ACM SIGGRAPH 1996 Proceedings. (2023 Seminal Paper.)
Efficient, lossless, continuous-resolution representation of surface triangulations.
Demos:create_geomorphs
,view_geomorphs
![]()
Computers & Graphics, 22(1), 1998.
Progressive mesh data structures compatible with GPU vertex buffers.
Demos:create_pm_club
,view_pm_club
,determine_approximation_error
![]()
ACM SIGGRAPH 1997 Proceedings.
Lossless multiresolution structure for incremental local refinement/coarsening.
Demos:create_sr_office
,view_sr_office
![]()
IEEE Visualization 1998 Conference. (2023 Test of Time Award.)
Visually smooth adaptation of mesh refinement using cascaded temporal geomorphs.
Demos:create_terrain_hierarchy
,view_terrain_hierarchy
,create_sr_terrain
,view_sr_terrain
,view_gcanyon_*
![]()
ACM SIGGRAPH 1997 Proceedings.
Progressive encoding of both topology and geometry.
Demos:view_psc_drumset
![]()
ACM SIGGRAPH 1999 Proceedings.
Face reordering for efficient GPU vertex cache, advocating a FIFO policy.
Demos:create_vertexcache_bunny
,view_vertexcache_bunny
![]()
ACM SIGGRAPH 2003 Proceedings.
Robust mapping of a surface onto a sphere, allowing 2D-grid resampling.
Demos:create_spherical_param_bunny
,view_spherical_param_bunny
## Demos
After the code is compiled, the demos can be run as follows.
In Windows, create, view, and clean up all the results using the `batch` scripts:
```shell
demos/all_demos_create_results.bat
demos/all_demos_view_results.bat
all_demos_clean.bat
```On Unix-based systems (e.g. Linux, Mac OS, Cygwin), either run the `bash` scripts:
```shell
demos/all_demos_create_results.sh
demos/all_demos_view_results.sh
demos/all_demos_clean.sh
```or alternatively (and faster), invoke `make` to create all results in parallel and then view them sequentially:
make [CONFIG=config] -j demosNote that pressing the Esc key closes any open program window.
## Filter programs
All programs recognize the argument `--help` (or `-?`) to show their many options.
The programs `Filterimage`, `Filtermesh`, `Filtervideo`,
`FilterPM`, and `Filterframe` are all designed to:
- read media from `stdin` (or from files or procedures specified as initial arguments),
- perform operations specified by arguments, and
- write media to `stdout` (unless `-nooutput` is specified).For example, the **`Filterimage`** command
```shell
Filterimage demos/data/gaudipark.png -rotate 20 -cropleft 100 -cropright 100 \
-filter lanczos6 -scaletox 100 -color 0 0 255 255 -boundary border -cropall -20 \
-setalpha 255 -color 0 0 0 0 -drawrectangle 30% 30% -30% -30% -gdfill \
-info -to jpg >gaudipark.new.jpg
```
- reads the specified image,
- rotates it 20 degrees counterclockwise (with the default reflection boundary rule),
- crops its left and right sides by 100 pixels,
- scales it uniformly to a horizontal resolution of 100 pixels using a 6×6 Lanczos filter,
- adds a 20-pixel blue border on all sides,
- adds an alpha channel and creates an undefined (`alpha=0`) rectangular region in the image center,
- fills this region using gradient-domain smoothing,
- outputs some statistics on pixel colors (to `stderr`), and
- writes the result to a file under a different encoding.As another example, the **`FilterPM`** command
```shell
FilterPM demos/data/standingblob.pm -info -nfaces 1000 -outmesh | \
Filtermesh -info -signeddistcontour 60 -genus | \
G3dOGL -key DmDe
```
- reads a progressive mesh stream to construct a mesh with 1000 faces,
- reports statistics on the mesh geometry,
- remeshes the surface as the zero isocontour of its signed-distance function on a 603 grid,
- reports the new mesh genus, and
- shows the result in an interactive viewer using the specified view parameters,
- simulating keypresses Dm to enable flat shading and De to make mesh edges visible.The **`Filtermesh`** command
```shell
FilterPM demos/data/spheretext.pm -nf 2000 -outmesh | \
Filtermesh -angle 35 -silsubdiv -silsubdiv -mark | \
G3dOGL -key DmDeDbJ---- -st demos/data/spheretext.s3d
```
- reads a 2000-face mesh, marks all edges with dihedral angle greater than 35 degrees as sharp,
- applies two steps of adaptive subdivision near these sharp edges, and
- shows the result flat-shaded (Dm), with edges (De),
without backface culling (Db), spinning (J) somewhat slowly (----),
- starting from the view parameters stored in the `spheretext.s3d` file.The **`Filtervideo`** command
```shell
Filtervideo demos/data/palmtrees_small.mp4 -filter keys -scaleu 1.5 >palmtrees_small.scale1.5.mp4
```
- reads the video (entirely into memory),
- uniformly scales the two spatial dimensions by a factor 1.5 using the Keys bicubic filter, and
- saves the new video.The command
```shell
Filtervideo demos/data/palmtrees_small.mp4 -info -trimbeg 4 -boundary clamped -trimend -20% | \
-tscale 1.5 -framerate 150% -croprectangle 50% 50% 400 240 -gamma 1.5 -bitrate 10m | \
VideoViewer demos/data/palmtrees_small.mp4 - -key =an
```
- reads the video (entirely into memory),
- reports statistics on the color channels,
- trims off 4 frames at the beginning,
- adds repeated copies of the last frames (with length 20% of the video),
- temporally scales the content by a factor of 1.5 and adjusts the framerate accordingly,
- spatially crops a centered rectangle with width 400 pixels and height 240 pixels,
- adjusts the color gamma,
- sets the output bitrate to 10 megabits/sec, and
- shows the result (`-` for `stdin`) together with the original video in an interactive viewer,
- with keypress = to scale the window by 2, a to loop all (two) videos,
and n to initially select the next video.## Surface reconstruction
This program reads a list of 3D (x, y, z) points assumed to be sampled near some unknown manifold surface,
and reconstructs an approximating triangle mesh.
For example,
```shell
Recon Dm)
and mesh edges (De).
To show the progression of the Marching Cubes algorithm,
```shell
Recon DC) and without backface culling (Db).To show a similar streaming reconstruction of the surface mesh,
```shell
Recon _) rotation (J)
about the object frame (o).
The same program can also read a list of 2D (y, z) points to reconstruct an approximating curve:
```shell
Recon MeshfitGiven an initial mesh and a list of 3D points, this program optimizes both the mesh connectivity and
geometry to improve the fit, i.e. minimizing the squared distances from the points to the surface.
For example,
```shell
Meshfit -mfile distcap.recon.m -file demos/data/distcap.pts -crep 1e-5 -reconstruct | \
tee distcap.opt.m | G3dOGL -st demos/data/distcap.s3d -key DmDe
```
- reads the previously reconstructed mesh and the original list of points,
- applies an optimized sequence of perturbations to improve both the mesh connectivity and geometry,
- using a specified tradeoff between mesh conciseness and fidelity
(crep=1e-4 yields a coarser mesh),
- saves the result to a file, and displays it interactively.The input points can also be sampled from an existing surface, e.g.:
```shell
Filtermesh demos/data/blob5.orig.m -randpts 10000 -vertexpts | \
Meshfit -mfile demos/data/blob5.orig.m -file - -crep 1e-6 -simplify | \
G3dOGL -st demos/data/blob5.s3d -key DmDe
```To view the real-time fitting optimization,
```shell
Meshfit -mfile distcap.recon.m -file demos/data/distcap.pts \
-crep 1e-5 -outmesh - -record -reconstruct | \
G3dOGL -st demos/data/distcap.s3d -key DmDeDC -async -terse
```
- writes both the initial mesh and the stream of mesh modifications, and
- displays the changing mesh asynchronously with display-list caching disabled (DC).This related program performs a similar optimization of a 1D polyline (either open or closed)
to fit a set of 2D points. For example,
```shell
Polyfit -pfile curve1.a3d -file demos/data/curve1.pts -crep 3e-4 -spring 1 -reconstruct | \
G3dOGL demos/data/curve1.pts -input -st demos/data/curve1.s3d
```
- reads the previously reconstructed polyline and the original list of points,
- optimizes vertex positions and simplifies the number of line segments according to some representation cost, and
- displays the result together with the original points.In a subdivision surface representation, a coarse base mesh tagged with sharp edges
defines a piecewise smooth surface as the limit of a subdivision process.
Such a representation both improves geometric fidelity and leads to a more concise description.
```shell
Filtermesh distcap.opt.m -angle 52 -mark | \
Subdivfit -mfile - -file demos/data/distcap.pts -crep 1e-5 -csharp .2e-5 -reconstruct >distcap.sub0.m
```
- reads the previously optimized mesh and tags all edges with dihedral angle greater than 52 degrees as sharp,
- loads this tagged mesh and the original list of points,
- optimizes the mesh connectivity, geometry, and assignment of sharp edges to fit a
subdivision surface to the points,
- with a representation cost of `1e-5` per vertex and `.2e-5` per sharp edge, and
- saves the resulting optimized base mesh to a file. (The overall process takes a few minutes.)To view the result,
```shell
G3dOGL distcap.sub0.m "Subdivfit -mf distcap.sub0.m -nsub 2 -outn |" \
-st demos/data/distcap.s3d -key NDmDe -hwdelay 5 -hwkey N
```
- reads the base mesh together with a second mesh obtained by applying two iterations of subdivision,
- shows the first mesh (N) with flat-shaded faces and edges (DmDe),
- waits for 5 seconds, and displays the second mesh (N) as a smooth surface without edges.This program computes measures of differences between two meshes.
It samples a dense set of points from a first mesh and computes the
projections of each point onto the closest point on a second mesh.
```shell
MeshDistance -mfile distcap.recon.m -mfile distcap.opt.m -bothdir 1 -maxerror 1 -distance
```
- `MeshDistance` loads the earlier results of mesh reconstruction and mesh optimization,
- computes correspondences from points sampled on each mesh to the other mesh (in both directions), and
- reports differences in geometric distance, color, and surface normals,
using both L2 (rms) and L∞ (max) norms.## Mesh simplification
Given a mesh, `MeshSimplify` applies a sequence of edge collapse operations
to simplify it to a coarse base mesh while trying to best preserve the appearance of the original model.
It supports many different simplification criteria, as well as face properties,
edges tagged as sharp, and vertex and corner attributes
(nx,ny,nz normals,
r,g,b colors, and u,v texture coordinates).For example,
```shell
MeshSimplify demos/data/club.orig.m -prog club.prog -simplify >club.base.m
```
- reads the original mesh and randomly samples points over its surface,
- progressively simplifies it by examining point residual distances, while recording changes to a `*.prog` file, and
- writes the resulting base mesh.The next step is to reverse the sequence of stored edge collapses,
i.e. forming a progressive sequence of vertex splits:
```shell
reverselines club.prog >club.rprog
```We construct a concise progressive mesh by encoding the base mesh together
with the sequence of vertex splits that exactly recover the original mesh:
```shell
Filterprog -fbase club.base.m -fprog club.rprog -pm_encode >club.pm
```The complete process from the original mesh to the progressive mesh is implemented by the script call
```shell
demos/bin/meshtopm.{sh,bat} demos/data/club.orig.m >club.pm
```Given a progressive mesh, we can interactively traverse its continuous levels of detail:
```shell
G3dOGL -pm_mode club.pm -st demos/data/club.s3d -lightambient .4
```
- by dragging the left vertical slider using the left or right mouse button, and
- toggling mesh edges using the De key sequence.
We can also define geomorphs between discrete levels of detail, e.g.
```shell
FilterPM club.pm -nfaces 2000 -geom_nfaces 3300 -geom_nfaces 5000 -geom_nfaces 8000 | \
G3dOGL -st demos/data/club.s3d -key SPDeN -lightambient .5 -thickboundary 1 -video 101 - | \
VideoViewer - -key m
```
- creates a geomorph between 2000 and 3300 faces, another between 3300 and 5000 faces, and one more,
- shows these in a viewer with the level-of-detail slider enabled (S),
- selects all three geomorph meshes (P), enables mesh edges (De),
selects the first mesh (N),
- records a video of 101 frames while moving the LOD slider, and
- shows the resulting video with mirror looping enabled (m).This example displays a progressive mesh after truncating all detail below 300 faces and above 10000 faces:
```shell
FilterPM demos/data/standingblob.pm -nf 300 -truncate_prior -nf 10000 -truncate_beyond | \
G3dOGL -pm_mode - -st demos/data/standingblob.s3d
```As an example of simplifying meshes with appearance attributes,
```shell
Filterimage demos/data/gaudipark.png -scaletox 200 -tomesh | \
MeshSimplify - -nfaces 4000 -simplify | \
G3dOGL -st demos/data/imageup.s3d -key De -lightambient 1 -lightsource 0
```
- forms a planar grid mesh whose 200×200 vertices have colors sampled from a downsampled image,
- simplifies the mesh to 4000 faces while minimizing color differences,
- shows the result with mesh edges (De) and only ambient lighting.## Selective view-dependent mesh refinement
Within `demos/create_sr_office`, the script call
```shell
meshtopm.{sh,bat} demos/data/office.nf80000.orig.m -vsgeom >office.sr.pm
```
creates a progressive mesh in which the simplified vertices are constrained to lie
at their original positions (`-vsgeom`).
This enables selective refinement, demonstrated by
```shell
G3dOGL -eyeob demos/data/unit_frustum.a3d -sr_mode office.sr.pm -st demos/data/office_srfig.s3d \
-key ,DnDeDoDb -lightambient .4 -sr_screen_thresh .002 -frustum_frac 2
```The mesh is adaptively refined within the view frustum, shown as the inset rectangle (key Do)
or in the top view (key Dr). Drag the mouse buttons to rotate, pan, and dolly the object.## Terrain level-of-detail control
Within `demos/create_sr_terrain.{sh,bat}`,
```shell
Filterimage demos/data/gcanyon_elev_crop.bw.png -tobw -elevation -step 6 -scalez 0.000194522 \
-removekinks -tomesh | \
Filtermesh -assign_normals >gcanyon_sq200.orig.m
demos/bin/meshtopm.{sh,bat} gcanyon_sq200.orig.m -vsgeom -terrain >gcanyon_sq200.pm
```
- converts an elevation image to a smoothed terrain grid mesh, and
- simplifies it to create a selectively refinable mesh.Then, within `demos/view_sr_terrain.sh`,
```shell
(common="-eyeob demos/data/unit_frustum.a3d -sr_mode gcanyon_sq200.pm -st demos/data/gcanyon_fly_v98.s3d \
-texturemap demos/data/gcanyon_color.1024.png -key DeDtDG -sr_screen_thresh .02292 -sr_gtime 64 \
-lightambient .5"; \
export G3D_REV_AUTO=1; \
G3dOGL $common -geom 800x820+100+10 -key "&O" -key ,o----J | \
G3dOGL $common -geom 800x820+920+10 -async -killeof -input -key Dg)
```- opens two synchronized side-by-side windows of the same texture mapped terrain,
- in which the first windows shows the temporal pops resulting from instantaneous mesh operations,
- whereas the second window shows the smooth appearance provided by runtime geomorphs (Dg).For large terrain meshes, we form a hierarchical progressive mesh by partitioning the terrain mesh into tiles,
simplifying each tile independently to form a progressive mesh,
stitching the progressive meshes together 2-by-2,
and recursively simplifying and merging at coarser pyramid levels.An example is presented in `demos/create_terrain_hierarchy`. It makes use of
```shell
StitchPM -rootname terrain.level0 -blockx 2 -blocky 2 -blocks 32 -stitch >terrain.level0.stitched.pm
```
to assemble each 2-by-2 set of progressive mesh tiles `terrain.level0.x{0,1}.y{0,1}.pm` at the finest level.The script `demos/view_gcanyon_interactive` launches an interactive flythrough over a Grand Canyon terrain model,
using a progressive mesh precomputed from an original 4096×2048 height field.Alternatively, `demos/view_gcanyon_frames` shows a real-time flythrough using a pre-recorded flight path,
whereby keystroke commands embedded within the input stream automatically change viewing modes.## Topology simplification
The program **`MinCycles`** removes topological noise from a mesh
by iteratively pinching off the smallest nonseparating cycle of edges until a
specified criterion (cycle length, number of cycle edges, number of cycles, or mesh genus) is reached.For example, within `demos/create_topologically_simplified.{sh,bat}`,
```shell
FilterPM demos/data/office.pm -nf 200000 -outmesh | \
MinCycles - -frac_cycle_length 1.2 -max_cycle_length 0.10 | \
G3dOGL -st demos/data/office.s3d -key DeDEJ---- -thickboundary 0 -lightambient .9
```
- extracts a mesh of 200000 faces from a progressive mesh,
- closes 46 topological handles to reduce the mesh genus from 50 to 4,
- where the final remaining handle would require a nonseparating cycle of length greater than `0.10`.
- speeding up the process by identifying approximately shortest nonseparating cycles
within a factor 1.2 of optimal, and
- shows the resulting closed edge cycles (tagged as sharp) in blue.The program **`MeshReorder`** reorders the triangle faces (and optionally vertices) within a mesh
to exploit GPU vertex caching and thereby minimize memory bandwidth and shading cost.For example, within `demos/create_vertexcache_bunny`,
```shell
MeshReorder data/bunny.orig.m -fifo -cache_size 16 -analyze -meshify5 -color_corners 1 -analyze \
>data/bunny.vertexcache.m
```
- simulates traversal using a FIFO cache of 16 vertices and reports cache miss rates,
- optimizes the triangle face ordering,
- reports the updated cache miss rate, and
- writes the mesh with corner colors that identify cache misses.Then, within `demos/view_vertexcache_bunny`,
```shell
G3dOGL data/bunny.vertexcache.m -st data/bunny.s3d -key DmDTDTDC
```
visualizes the resulting sequence of triangle strips and cache misses.The program **`SphereParam`** computes spherical coordinates `sph` at the mesh vertices
so as to minimize parametric stretch from the sphere to the surface mesh.For example, within `demos/create_spherical_param_bunny`,
```shell
meshtopm.{sh,bat} data/bunny.orig.m -minqem -vsgeom -dihallow | \
SphereParam - -rot data/bunny.s3d >data/bunny.sphparam.m
```
- creates a progressive mesh (`*.pm`) stream minimizing a quadric error metric (`qem`),
- runs a coarse-to-fine spherical parameterization optimization,
- aligning the spherical coordinates to the model's default view (`bunny.s3d`), and
- writes the spherically parameterized mesh.Then, within `demos/view_spherical_param_bunny`,
```shell
Filtermesh data/bunny.sphparam.m -renamekey v sph P | \
G3dOGL - -st data/unitsphere_ang.s3d -key DeoJ
```
- transfers each vertex's spherical coordinates `sph` to its position `P`,
- visualizes the resulting triangulated sphere domain,
- showing mesh edges (`De`) and rotating slowly (`J`) about the object axis (`o`).The program **`SphereSample`** computes uniform samplings of a spherically parameterized mesh.
For example, within `demos/create_create_spherical_param_bunny`,
```shell
SphereSample -egrid 128 -domain octaflat -scheme best -param data/bunny.sphparam.m \
-rot data/bunny.s3d -keys imageuv -remesh | \
Filtermesh -renamekey v imageuv uv >data/bunny.spheresample.remesh.m
```
- defines an effective 128×128 regular grid
- using a flat-octahedron domain mapped on the sphere,
- maps these samples onto the bunny mesh using its spherical parameterization,
- generates a remesh where vertices include image-space coordinates (`imageuv`),
- renames those coordinates to `uv` coordinates, and
- writes the final remesh.Also,
```shell
SphereSample -egrid 1024 -omit_faces -domain octaflat -scheme best -param data/bunny.sphparam.m \
-rot data/identity.s3d -signal N -write_texture \
data/bunny.spheresample.octaflat.unrotated.normalmap.png
```
- defines an effective 1024×1024 regular grid
- using a flat-octahedron domain mapped on the sphere,
- maps these samples onto the bunny mesh using its spherical parameterization,
- samples the surface normal (`N`) field, and
- writes these sampled normal vectors as RGB colors in a normap-map `png` image.Then, within `demos/view_vertexcache_bunny`,
```shell
G3dOGL data/bunny.spheresample.remesh.m -st data/bunny.s3d \
-texturemap data/bunny.spheresample.octaflat.unrotated.normalmap.png \
-texturenormal 1 -key DmDe -hwkey '(DtDe)' -hwdelay 1.0
```
- renders the remesh using flat shading (`Dm`) and mesh edges (`De`), and
- after 1 second, enables normal-mapping using the normals stored in the `png` image.The **`G3dOGL`** program shows interactive rasterized renderings of 3D (and 2D) geometry,
represented as- streams of polygons/polylines/points (`*.a3d` format),
- triangle meshes including geomorphs (`*.m`),
- progressive meshes (`*.pm`),
- encoded selectively refinable meshes (`*.srm`),
- progressive simplicial complexes (`*.psc`), or
- simple `*.ply` files.Please see the many examples presented earlier.
The viewer can also read `*.frame` elements to position the viewer and the objects in world space.
Elements of `*.a3d`, `*.m`, and `*.frame` streams can all be interleaved in a single input stream.The viewer can take image snapshots (see `demos/create_rendered_mechpart_image`) and
record videos (see `demos/create_rendered_mechpart_video`).The mouse/keyboard UI controls include:
Mouse movements:
left mouse: rotate
middle mouse: pan
right mouse: dolly
shift-left: pan
shift-middle mouse: roll
shift-right mouse: zoom
(mouse movements are with respect to current object; see '0-9' below)Important key strokes:
? : print complete list of keys
D?: print list of keys prefixed by 'D'
De: toggle edges
Ds: toggle shading of faces
Db: toggle backface culling
Dm: toggle Gouraud/flat shading
DP: save current window as an image file
DS: toggle show some sliders
S : toggle show some other sliders
j : jump to a default viewpoint
J : automatically rotate object
D/: edit viewpoint filename
, : read the viewpoint
. : save the viewpoint
0-9: select object (0=eye_frame, 1=first object, 2=second object...)
u : display/hide current object
N : select next object
P : select previous object
-=: decrease/increase the magnitude of all movements
f : toggle flying (usually with '0' eye selected)To record a 6-second (360-frame) video of a rotating mesh and then view the resulting video:
```shell
G3dOGL demos/data/standingblob.orig.m -st demos/data/standingblob.s3d -key iioJ \
-video 360 output_video.mp4
VideoViewer output_video.mp4
```The related program **`G3dVec`** shows wireframe hidden-line-removed renderings of `*.a3d` streams and `*.m` meshes.
It can write vector-based Postscript figures (see `demos/view_hidden_line_removed`).In both programs, the keys ? and D? show a list of available keyboard commands.
The **`VideoViewer`** program enables interactive viewing and simple editing of both images and videos.
Again, the key ? shows a list of available keyboard commands.
Press pageup/pagedown to quickly browse through the videos and/or images in a directory.
Audio is not currently supported.## File formats
### Mesh (`*.m`)
See the documentation at the end of `libHh/GMesh.h`
A mesh is a set of vertices and faces. These in turn also define edges and corners.
Arbitrary string tuples can be associated with vertices, faces, edges, and corners.
Examples of string tuples:
`{normal=(.1 .2 .3) rgb=(1 1 1) matid=5 material="string"}`.
See the several `demos/data/*.m` files for examples of the mesh format.
Note that the indices of vertices and faces start at 1 instead of 0;
in hindsight that was a poor choice.### Geometry stream (`*.a3d`, `*.pts`)
See the documentation at the end of `libHh/A3dStream.h`
The stream contains polygons, polylines, points, and control codes
(like end-of-frame, end-of-input, change-of-object).
Unlike in a mesh, these primitives do not share vertices. The stream can be either text or binary.### Frame stream (`*.frame`, `*.s3d`)
See the documentation at the end of `libHh/FrameIO.h`
This text or binary format encodes a 4×3 affine transformation
(plus an object id and a scalar field-of-view zoom).
It is used to record default viewing configurations, and sequences of frames for flythroughs.
It usually represents the linear transform from object space (or eye space) to world space.
The stream can be either text or binary.### Progressive mesh (`*.pm`)
This is a binary representation that consists of a coarse base mesh and a sequence of vertex split records.
### Edge collapse / vertex split records (`*.prog`, `*.rprog`)
These are temporary text files containing verbose information for a sequence of edge collapse / vertex split records
used by MeshSimplify / reverselines / Filterprog to create a progressive mesh.## Libraries
The library `libHh`
contains the main reusable classes.
All files include `Hh.h` which sets up a common cross-platform environment.The libraries `libHwWindows`
and `libHwX`
define different implementations of a simple windowing interface (class `Hw`),
under `Win32` and `X Windows`, respectively.
Both implementations support `OpenGL` rendering.## Code details
The include file
libHh/RangeOp.h
defines many functions that act on ranges,
which are containers or views for which `begin()` and `end()` are defined.
For example, the function call `hh::fill(ar, 1.f)` assigns the value `1.f` to all
elements in the array named `ar`,
and the function call `hh::mean(matrix)` computes the average value of all entries in the
named `matrix`.The debugging macro
SHOW(expr)
outputs `expr = ...` on `stderr`
and also returns `expr`.
It also accepts multiple arguments in which case it returns `void`.
For example, `SHOW(min(1, 2), "hello", 3*2)` outputs the line `min(1, 2)=1 hello 3*2=6`.
Note the special treatment of literal string values.Unicode strings are stored using UTF-8 encoding into ordinary `std::string` variables.
The functions `hh::utf16_from_utf8()` and `hh::utf8_from_utf16()` convert to and from the
`std::wstring` UTF-16 encodings used in `Win32` system calls.All files use end-of-line encodings based on Unix `'\n'` LF (rather than DOS `'\r\n'` CR+LF).
All streams are opened in binary mode. This allows text and binary to coexist in the same file.## License
See `LICENSE`.
This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact [email protected] with any additional questions or comments.