Included below are notes on the design and implementation of the
Geometry Conversion Library (LIBGCV).


ARCHITECTURE
============

From an architecture standpoint, here are a few tenets that LIBGCV
should adhere to:

1) Minimal library dependencies.  It needs to drop into external codes
without needing more than BRL-CAD's core libraries (libbu, libbn,
libwdb, librt, libbrep).  Stand-alone distribution is a requirement.

2) Public C or C++ API, not both.  If it's a C++ API, it shouldn't
have free-floating global functions.  If it's a C API, it shouldn't
expose C++ types in the public API without compilation safeguards.

3) API independence.  Each added geometry format should extend LIBGCV
without requiring ANY change to the public API.  That means we should
not have an enum or #defines or public functions that embed a format
(e.g., no public gcv_obj_to_g() functions).

4) Plugin architecture.  Each format should require only one
line/block be added to some GCV initialization function (or
dynamically loaded at runtime) to register itself.  Ideally, each
format lives in a sub-directory self-contained.

5) Simplicity, consistency.  The API design should declare minimal
symbols, types, structs, functions, designs.  It should follow
conventions of our existing libraries in terms of conventions and
patterns.


API DESIGN
==========

T.B.D.

By design, this library is intended to be useful for reading and
writing 3D geometry.  The public API design is intentionally very
simple while supporting a number of file formats and geometry
representation types.

Supported file formats for reading and/or writing currently includes
the following formats: OBJ, STL, VRML, FASTGEN4, and BRL-CAD.

The library includes support for a number of implicit and explicit
geometry representation types including Bags o' Triangles (triangle
mesh geometry), n-Manifold polygonal meshes, volumetric data, NURBS,
and implicit primitives with constructive solid geometry (CSG) Boolean
operations.

Multipass processing.  First check if all geometry records can be
processed, e.g., whether a given geometry subtree or a particular
geometry object will convert given a prescribed request.  This is to
catch errors earlier in the pipeline.  Lossy or context-sensitive
translations, e.g., exporting an infinite halfspace to polygonal
format, are example considerations.

Normalization.  Whether a prescribed output format supports a
hierarchy and/or matrices or is modeled far from floating-point origin
can influence conversion results.  Supporting normalization is not a
priority, but may influence design options.


PLAN OF ATTACK
==============

  1) move just the STL code without making any improvements or refactoring, get it under the API.
  2) that will undoubtedly require API adjusting.  adjust.
  3) get gcv command reading/writing stl files via libgcv.
  4) implement a brl-cad import/export plugin for v4/v5 binary, hook into libgcv.
  5) again, adjust and modify the API as needed here, checkpoint status.
  6) ensure gcv command recognizes stl and .g without requiring knowledge of them.
  7) test that g-to-stl is working and stl-to-g is working.
  8) migrate obj support into gcv (redundancies and all).
  9) implement general testing framework to evaluate all possible input/output combinations.
 10) test g-to-obj, obj-to-g, stl-to-obj, obj-to-stl, and report status.
 11) migrate fast4 import support.
 12) migrate vrml export support.
 13) test fast4-to-g, fast4-to-obj, fast4-to-stl, fast4-to-vrml, g-to-vrml, stl-to-vrml, obj-to-vrml.
 14) evaluate refactoring/consolidation of polygonal mesh logic in all formats.
 15) ensure gcv documentation is accurate and up-to-date (doxygen comments in the header).
  *) eliminate globals
  *) create a libgcv plugin template
  *) fast4 export
  *) vrml import
  *) create a stand-alone basic application runtime toolkit (BAR = libbu+libbn)
  *) update build system so GCV can be separated from the build tree stand-alone with BAR
  *) make gcv convert multithreaded


NEW FORMATS
===========

Adding a few notes on libraries that may be worth investigating to see
if they have parsing logic that would help in developing converters
for various formats.  They may amount to nothing, but are worth
checking.

For a fairly comprehensive list, see Paul Bourke's data formats page:
http://paulbourke.net/dataformats/

Collada (MIT licensed libraries)
http://opencollada.org/
http://sourceforge.net/projects/colladamaya/
http://colladamaya.svn.sourceforge.net/viewvc/colladamaya/trunk/FCollada/

Inventor files: (LGPL license)
http://oss.sgi.com/projects/inventor/
http://www.mevislab.de/inventor/ (website changed, see src/libgcv in
				  dmtogl branch of BRL-CAD for patch)
http://fl-inventor.sourceforge.net/
Note that the Coin3D library is now 3-clause BSD as well, a better
source from a licensing standpoint for extracting parsers etc.:
https://bitbucket.org/Coin3D/coin/wiki/Home

AutoCAD dwg - none (opendwg not compatible with BRL-CAD licensing)

Solidworks (.sat, .sldprt, .sldasm)
No external libraries apparent, probably unlikely
src/external/Cubit/g-sat.cpp should be  useful as a starting point.

Parasolid/UGS
No external libraries apparent, probably unlikely

POV-RAY
Haven't found anything with a compatible license...

Blender

Apparently their file format is a bit... weird.  Possibly useful notes
here:
http://www.atmind.nl/blender/mystery_ot_blend.html
http://www.blender.org/development/architecture/
http://www.blender.org/development/architecture/notes-on-sdna/

Since blender is GPL, unlikely their code can be used directly. Since
their storage format seems to be close to their data structures, it
might be worth contacting the project and asking specifically about
the parsing code, if they have the flexibility to sub-license just
that piece as LGPL.

Update: From discussions at SIGGRAPH Blender forum, unlikely they have
flexibility to relicense anything.  Much more interestingly, Gamekit
was announced there which DOES import Blender files and is MIT
licensed:

http://code.google.com/p/gamekit/

Exporting Blender may be impractical (i.e. no well defined format to
target) but as Blender has importers for a wide variety of formats
exporting to Blender directly may not be necessary

Universal 3D (Apache 2.0 license)
http://sourceforge.net/projects/u3d/

PLY
http://www.tecgraf.puc-rio.br/~diego/professional/rply/ (newer,
probably should start here)
http://www.cc.gatech.edu/projects/large_models/ply.html


VRML/X3d  (LGPL license)
http://openvrml.sourceforge.net/
http://sourceforge.net/projects/x3dtoolkit/


===

# inspired by https://xiph.org/flac/api/group__flac__stream__decoder.html

gcv = new() := create context
delete(gcv) := delete context
set_...(gcv, ...) := set context properties
get_...(gcv, ...) := get context properties
init_fd(gcv, callbacks) := connect to a file descriptor
init_FILE(gcv, callbacks) := connect to a file pointer
init_file(gcv, callbacks) := connect to a file
finish(gcv) := complete the conversion process, flush buffers, reset context (pairs with init)
flush(gcv) := ensure all output streams are flushed (ensures writes)
reset(gcv) := resets the context to an initialization state
process_single(gcv) := process single object
process(gcv) := process to end of stream

# per format

read(gcv, object(s), client_data) := read object(s)
write(gcv, const object(s), client_data) := write object(s)
seek(gcv, offset, client_data) := go to object #
tell(gcv, offset, client_data) := current object position #
length(gcv, length, client_data) := object count
metadata(gcv, metadata, client_data) := object metadata (first, last, length/size, type, data)
error(gcv, status, client_data) := called whenever an error occurs during conversion

# modeled after java streams
# inspired by http://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html

stream() := similar to read/write, returns set of objects
filter() := applies filtering expression, returns set of objects
toArray() := returns objects as a null-terminated array
skip() := returns object set after discarding first n objects
limit() := returns object set after discarding last n objects
sorted() := returns object set sorted by specified criteria
of() := returns ordered set of specified values
min() := returns minimum object matching comparator callback
max() : = returns maximum object matching comparator callback
forEach() := perform action on each object
count() := returns size of the object set
distinct() := returns set of distinct objects from stream
concat() := joins two streams together
