diff options
Diffstat (limited to 'tool_src/makeodt/makeodt.cpp')
| -rw-r--r-- | tool_src/makeodt/makeodt.cpp | 633 |
1 files changed, 633 insertions, 0 deletions
diff --git a/tool_src/makeodt/makeodt.cpp b/tool_src/makeodt/makeodt.cpp new file mode 100644 index 0000000..8b9f296 --- /dev/null +++ b/tool_src/makeodt/makeodt.cpp @@ -0,0 +1,633 @@ +/* + * makeodt.cpp + */ + + +// bsplib headers +#include "BRep.h" +#include "InputData3D.h" +#include "OutputData3D.h" +#include "BspObjectList.h" +#include "BoundingBox.h" +#include "ObjectBSPNode.h" +#include "ObjectBinFormat.h" + +#include "getopt.h" + +using BspLib::InputData3D; +using BspLib::BspObjectList; +using BspLib::Vector3; +using BspLib::Vertex3; +using BspLib::ObjectBSPTree; + + +// string constants ----------------------------------------------------------- +// +static const char options_invalid[] = "\nUse \"-h\" for a list of command line options.\n"; + + +// pointer to input data object ----------------------------------------------- +// +class Scene { + +public: + Scene() { m_inputscene = NULL; m_objectlist = NULL; m_objbsptree = NULL; } + ~Scene() { delete m_objbsptree; delete m_objectlist; } + + void AllocObjectList(); + void DestroyObjectList(); + + void BuildObjectBSPTree(); + + void setInput( InputData3D *inp ) { m_inputscene = inp; } + InputData3D* getInput() { return m_inputscene; } + void deleteInput() { if ( m_inputscene != NULL ) { delete m_inputscene; m_inputscene = NULL; } } + + BspObjectList* getObjectList() { return m_objectlist; } + +private: + // pointer to input data object + BspLib::InputData3D* m_inputscene; + + // object bsp tree (convex subspaces contain entire objects) + BspLib::ObjectBSPTree* m_objbsptree; + + // object list + BspLib::BspObjectList* m_objectlist; +}; + + +// allocate new objectlist (an already existing list will be destroyed) ------- +// +void Scene::AllocObjectList() +{ + if ( m_objbsptree != NULL ) { + delete m_objbsptree; + m_objbsptree = NULL; + } + + if ( m_objectlist != NULL ) { + delete m_objectlist; + } + m_objectlist = new BspObjectList; +} + + +// destroy objectlist --------------------------------------------------------- +// +void Scene::DestroyObjectList() +{ + delete m_objbsptree; + m_objbsptree = NULL; + + delete m_objectlist; + m_objectlist = NULL; +} + + +// build a bsp tree of objects from unordered object list --------------------- +// +void Scene::BuildObjectBSPTree() +{ + if ( m_objectlist != NULL ) { + BspLib::BoundingBox *boxlist = m_objectlist->BuildBoundingBoxList(); + m_objbsptree = new BspLib::ObjectBSPTree; + m_objbsptree->InitTree( boxlist ? boxlist->PartitionSpace() : NULL ); + } +} + + +// ---------------------------------------------------------------------------- +// +static Scene* world = NULL; + + +// filename of currently loaded object file ----------------------------------- +// +static char current_object_file[ PATH_MAX + 1 ] = ""; + + +// ---------------------------------------------------------------------------- +// +static char input_file_name[ PATH_MAX + 1 ] = ""; + + +// ---------------------------------------------------------------------------- +// +static int bspgenopt_actions[] = { 0, 0, 0, 0 }; +static int bspgenopt_outpoptions[] = { 0, 0, 0, 0 }; +static int bspgenopt_policy[] = { 0, 0, 0, 0 }; +static int bspgenopt_samplesize = 0; +static int bspgenopt_sampletype = 0; + +static int bspgeoopt_pregeometry[] = { 0, 0, 0, 0 }; +static int bspgeoopt_postgeometry[] = { 0, 0, 0, 0 }; +static int bspgeoopt_enforceeps[] = { 0, 0, 0, 0 }; +static double bspgeoopt_epsilons[] = { 0.0, 0.0, 0.0, 0.0 }; + +static int vrmlopt_gen[] = { 0, 0, 0, 0, 0, 0 }; +static int vrmlopt_lod = 0; +static int vrmlopt_tessellation = 8; + +static int mesgopt_mesg[] = { 0, 0, 0, 0, 0 }; +static int mesgopt_misc[] = { 0, 0, 0, 0 }; +static int mesgopt_stat[] = { 0, 0, 0, 0 }; +static int mesgopt_err[] = { 0, 0, 0, 0 }; + +static int objprocessor_opt[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + + +// submit selected bsp compilation options to bsplib -------------------------- +// +PRIVATE +void SetBspLibOptions() +{ + using namespace BspLib; + + if ( bspgeoopt_enforceeps[ 3 ] ) { + EpsAreas::eps_scalarproduct = bspgeoopt_epsilons[ 3 ]; + EpsAreas::eps_planethickness = bspgeoopt_epsilons[ 3 ]; +// EpsAreas::eps_vanishdenominator = bspgeoopt_epsilons[ 3 ]; +// EpsAreas::eps_vanishcomponent = bspgeoopt_epsilons[ 3 ]; + } + if ( bspgeoopt_enforceeps[ 2 ] ) { + EpsAreas::eps_pointonlineseg = bspgeoopt_epsilons[ 2 ]; + } + if ( bspgeoopt_enforceeps[ 1 ] ) { + EpsAreas::eps_vertexmergearea = bspgeoopt_epsilons[ 1 ]; + } + + static int splittercrit_values[] = { + Polygon::SPLITTERCRIT_FIRST_POLY, + Polygon::SPLITTERCRIT_SAMPLE_FIRST_N, + Polygon::SPLITTERCRIT_SAMPLE_ALL, + Polygon::SPLITTERCRIT_RANDOM_SAMPLE + }; + + InputData3D::EnableRGBConversion( bspgenopt_actions[ 1 ] ); + InputData3D::EnableMaximumExtent( bspgeoopt_pregeometry[ 3 ], bspgeoopt_epsilons[ 0 ] ); + InputData3D::EnableScaleFactors( bspgenopt_actions[ 2 ] ); + InputData3D::EnableAxesChange( bspgenopt_actions[ 3 ] ); + InputData3D::EnableAllowNGons( !bspgenopt_policy[ 1 ] ); + + Polygon::setSplitterSelection( splittercrit_values[ bspgenopt_sampletype ] ); + Polygon::setSampleSize( bspgenopt_samplesize ); + Polygon::setTriangulationFlag( bspgenopt_policy[ 3 ] ); + + BspObject::setEliminateDoubletsOnMergeFlag( bspgenopt_policy[ 2 ] ); + + int msgflags = Polygon::MESSAGEMASK_DISPLAY_ALL & ~Polygon::MESSAGE_CHECKING_POLYGON_PLANES; + if ( !mesgopt_mesg[ 0 ] ) + msgflags &= ~( Polygon::MESSAGE_NEW_SPLITVERTEX | + Polygon::MESSAGE_REUSING_SPLITVERTEX | + Polygon::MESSAGE_TRACEVERTEX_INSERTED ); + if ( !mesgopt_mesg[ 1 ] ) + msgflags &= ~Polygon::MESSAGE_SPLITTING_QUADRILATERAL; + if ( !mesgopt_mesg[ 2 ] ) + msgflags &= ~( Polygon::MESSAGE_STARTVERTEX_IN_SPLITTER_PLANE | Polygon::MESSAGE_VERTEX_IN_SPLITTER_PLANE ); + if ( !mesgopt_mesg[ 3 ] ) + msgflags &= ~Polygon::MESSAGE_INVOCATION; + if ( !mesgopt_mesg[ 4 ] ) + msgflags &= ~Polygon::MESSAGE_SPLITTING_POLYGON; + Polygon::setDisplayMessagesFlag( msgflags ); + + BRep::setTriangulation( vrmlopt_gen[ 2 ] ); + BRep::setMaterialFlag( vrmlopt_gen[ 4 ] ); + BRep::setMirrorTextureVFlag( vrmlopt_gen[ 5 ] ); + BRep::setTessellation( vrmlopt_tessellation ); +} + + +// set global bsplib options to user specified values ------------------------- +// +PRIVATE +void InitBspLibOptions() +{ + bspgeoopt_epsilons[ 3 ] = BspLib::EpsAreas::eps_planethickness; + bspgeoopt_epsilons[ 2 ] = BspLib::EpsAreas::eps_pointonlineseg; + bspgeoopt_epsilons[ 1 ] = BspLib::EpsAreas::eps_vertexmergearea; + + bspgeoopt_epsilons[ 0 ] = 600.0;// maximum extents to force + + bspgeoopt_enforceeps[ 0 ] = 0; // use default epsilon areas + bspgeoopt_enforceeps[ 1 ] = 0; + bspgeoopt_enforceeps[ 2 ] = 0; + bspgeoopt_enforceeps[ 3 ] = 0; + + bspgenopt_actions[ 1 ] = 0; // don't convert color indexes to rgb triplets + bspgenopt_actions[ 2 ] = 0; // don't apply specified object scale factors + bspgenopt_actions[ 3 ] = 0; // don't apply axes mapping + + bspgenopt_policy[ 0 ] = 1; // always normalize normal vectors + bspgenopt_policy[ 1 ] = 1; // allow only triangles and quadrilaterals + bspgenopt_policy[ 2 ] = 1; // eliminate vertex doublets on object merge + bspgenopt_policy[ 3 ] = 0; // don't always triangulate + + vrmlopt_lod = 0; + vrmlopt_tessellation = 4; // set vrml tessellation resolution per PI/2 + vrmlopt_gen[ 1 ] = 1; // tessellate vrml primitives + vrmlopt_gen[ 2 ] = 0; // triangulate vrml objects + vrmlopt_gen[ 3 ] = 1; // build bounding box hierarchy + vrmlopt_gen[ 4 ] = 0; // don't use full material specification + vrmlopt_gen[ 5 ] = 1; // mirror texture v axis + + mesgopt_misc[ 0 ] = 0; // don't create messagelog + mesgopt_misc[ 1 ] = 0; // don't create output window + + bspgenopt_samplesize = 20; // set n=20 (sample size) + bspgenopt_sampletype = 1; // sample first n polygons + + bspgeoopt_pregeometry[ 0 ] = 0; // n/a + bspgeoopt_pregeometry[ 1 ] = 0; // n/a + bspgeoopt_pregeometry[ 2 ] = 1; // check planes of faces + bspgeoopt_pregeometry[ 3 ] = 1; // enforce maximum object extents + + bspgeoopt_postgeometry[ 0 ] = 0; // don't insert trace vertices + bspgeoopt_postgeometry[ 1 ] = 0; // check for multiple vertices + bspgeoopt_postgeometry[ 2 ] = 0; // don't calc node bounding boxes + bspgeoopt_postgeometry[ 3 ] = 0; // don't calc explicit separator planes + + mesgopt_mesg[ 0 ] = 1; // show message on vertex insertion + mesgopt_mesg[ 1 ] = 1; // show message on triangulation of quadrilateral + mesgopt_mesg[ 2 ] = 0; // don't show message on vertex contained in splitter plane + mesgopt_mesg[ 3 ] = 0; // don't show message on every call of PartitionSpace() + mesgopt_mesg[ 4 ] = 1; // show message on splitting of polygon + + mesgopt_stat[ 0 ] = 0; // don't display basic statistics + mesgopt_stat[ 1 ] = 0; // don't display detailed statistics + + bspgenopt_outpoptions[ 0 ] = 1; // write normal vectors + bspgenopt_outpoptions[ 1 ] = 1; // write palette info + bspgenopt_outpoptions[ 2 ] = 0; // don't write compiler info + bspgenopt_outpoptions[ 3 ] = 0; // don't write viewer info + + mesgopt_err[ 0 ] = 1; // display error message on non-convex polygon + + SetBspLibOptions(); // pass options to bsplib +} + + + + + +// check if bsp tree is available for current scene --------------------------- +// +int BspTreeAvailable() +{ + BspLib::BspObjectList *objectlist = world->getObjectList(); + BspLib::BspObject *obj = objectlist ? objectlist->getListHead() : NULL; + return ( obj ? obj->BspTreeAvailable() : 0 ); +} + + +// merge entire object list into single object -------------------------------- +// +void MergeListIntoSingleObject() +{ + if ( world->getObjectList() ) { + + if ( !BspTreeAvailable() ) { + + // configure BspLib + SetBspLibOptions(); + + // do actual merge + world->getObjectList()->CollapseObjectList(); + MSGOUT( "Objectlist merged into single object.\n" ); + + } else { + + MSGOUT( "Objects already bsp-compiled: Merging not possible.\n" ); + } + + } else { + + MSGOUT( "No objects to merge.\n" ); + } +} + + +// ---------------------------------------------------------------------------- +// +enum { + + OUTPUT_FORMAT_SINGLE, + OUTPUT_FORMAT_ODT, + OUTPUT_FORMAT_OD2, +}; + + + +static int output_format = OUTPUT_FORMAT_OD2; +static int bsp_compile_done = FALSE; + + +static int critical_bsplib_error = 0; + + +// handle critical error encountered within bsplib ---------------------------- +// +PRIVATE +int CriticalBspLibError( int flags ) +{ +/* + // close message log if enabled + if ( messagelog_fp != NULL ) { + fclose( messagelog_fp ); + messagelog_fp = NULL; + } +*/ + if ( ( flags & BspLib::SystemIO::CRITERR_ALLOW_RET ) == 0 ) { + return 0; + } else { + critical_bsplib_error = 1; + return 1; + } +} + + +// close an open data file ---------------------------------------------------- +// +PRIVATE +void CloseDataFile() +{ + // reset compile done flag + bsp_compile_done = FALSE; + + // delete old InputData3D object + world->deleteInput(); + + // destroy old object list + world->DestroyObjectList(); + + // no current file name + *current_object_file = 0; +} + + +// read data file, parse it, and establish scene graph in memory -------------- +// +PRIVATE +int ReadDataFile( char *fullfname, char *fname ) +{ + // delete old InputData3D object + world->deleteInput(); + + // allocate new BspObjectList (delete old) + world->AllocObjectList(); + + // configure BspLib + SetBspLibOptions(); + + // create input data + BspObjectList *objectlist = world->getObjectList(); + world->setInput( new BspLib::InputData3D( *objectlist, fullfname ) ); + + // process already parsed input if valid + if ( !world->getInput()->InputDataValid() ) { + CloseDataFile(); + return FALSE; + } + + // calculate plane normals if not already valid (read from input file) + objectlist->ProcessObjects( BspObjectList::CALC_PLANE_NORMALS ); + + // check if bsp tree read from file and update caption accordingly + int anybsp = objectlist->BspTreeAvailable(); +// Global::UpdateCaption( hwnd, fname, anybsp ? +// Global::CAPTION_BSPCOMPILED : Global::CAPTION_NOBSPAVAILABLE ); + + // check if only flat tree available + if ( anybsp && !objectlist->BSPTreeAvailable() ) { + // if only flat bsp tree available build linked tree from it + objectlist->ProcessObjects( BspObjectList::BUILD_FROM_FLAT ); + } + +// if ( !anybsp ) { +// world.setUseBSP( FALSE ); +// CheckRenderingMenuItems( GetMenu( hwndMain ) ); +// } + + // set current object file name + strcpy( current_object_file, fname ); + + return TRUE; +} + + +// ---------------------------------------------------------------------------- +// +PRIVATE +int OpenInput() +{ + // reset compile done flag + bsp_compile_done = FALSE; + + // register callbacks with bsplib + critical_bsplib_error = 0; + BspLib::SystemIO::SetCriticalErrorCallback( CriticalBspLibError ); + + // read in data file + int rc = ReadDataFile( input_file_name, input_file_name ); + + // unregister callbacks + BspLib::SystemIO::SetCriticalErrorCallback( NULL ); + + return rc; +} + + +// ---------------------------------------------------------------------------- +// +PRIVATE +void SaveOutput() +{ + if ( !world->getObjectList() ) { + MSGOUT( "No objects to save.\n" ); + return; + } + + char *outname = new char[ PATH_MAX + 1 ]; + strcpy( outname, current_object_file ); + int n = strlen( outname ); + while ( ( n > 0 ) && ( outname[ n ] != '.' ) ) + --n; + strcpy( &outname[ n ], ".od2" ); + + // configure BspLib + SetBspLibOptions(); + + // check if binary output is desired + if ( ( output_format == OUTPUT_FORMAT_ODT ) || + ( output_format == OUTPUT_FORMAT_OD2 ) ) { + + if ( BspTreeAvailable() ) { + + // do direct binary output of ODT or OD2 file containing BSP tree + BspObjectList *objectlist = world->getObjectList(); + BspLib::ObjectBinFormat outobj( *objectlist->getListHead() ); + + int format = ( output_format == OUTPUT_FORMAT_OD2 ) ? + BspLib::ObjectBinFormat::BINFORMAT_OD2 : BspLib::ObjectBinFormat::BINFORMAT_ODT; + outobj.WriteDataToFile( outname, format ); + + } else { + + if ( output_format == OUTPUT_FORMAT_OD2 ) { + + // do direct binary output of OD2 file without BSP tree + BspObjectList *objectlist = world->getObjectList(); + BspLib::ObjectBinFormat outobj( *objectlist->getListHead() ); + outobj.WriteDataToFile( outname, BspLib::ObjectBinFormat::BINFORMAT_OD2 ); + } + } + + } else { + + // do output in BspLib's singleoutput formats + if ( output_format == OUTPUT_FORMAT_SINGLE ) { + + int format; + if ( BspTreeAvailable() ) { + format = BspLib::IOData3D::BSP_FORMAT_1_1; + } else { + format = BspLib::IOData3D::AOD_FORMAT_1_1; + // merge all objects in list into single object + world->getObjectList()->CollapseObjectList(); + } + + // write output file + if ( world->getInput() != NULL ) { + world->getInput()->setFileName( outname ); + BspLib::OutputData3D outputdata( *world->getInput(), format ); + } + } + } + + delete outname; +} + + + + + +// ---------------------------------------------------------------------------- +// + + + +// ---------------------------------------------------------------------------- +// +PRIVATE +int OptSetInputFile( char **filename ) +{ + char *name = filename[ 0 ]; + + strcpy( input_file_name, name ); + + return TRUE; +} + +// ---------------------------------------------------------------------------- +// +PRIVATE +int OptSetObjectScale( float *scale ) +{ + bspgeoopt_epsilons[ 0 ] = *scale; + + return TRUE; +} + + +// register command line options ---------------------------------------------- +// +PRIVATE +void RegisterOptions() +{ + OPT_RegisterStringOption( "i", "input", OptSetInputFile ); + OPT_RegisterFloatOption( "s", "scale", OptSetObjectScale ); +} + + +// ---------------------------------------------------------------------------- +// +void msg_callback( const char *msg ) +{ + printf( "%s", msg ); +// printf( "\n" ); +} + + +// ---------------------------------------------------------------------------- +// +PRIVATE +int InitMakeODT() +{ + BspLib::SystemIO::SetProgramName( "makeodt" ); + +#if defined ( _WINDOWS ) || defined ( WIN32 ) + BspLib::SystemIO::SetMainWindowHandle( NULL ); +#endif + + BspLib::SystemIO::SetInfoMessageCallback( msg_callback ); + BspLib::SystemIO::SetErrorMessageCallback( msg_callback ); + + InitBspLibOptions(); + + return TRUE; +} + + +// ---------------------------------------------------------------------------- +// +PRIVATE +void ConvertObject() +{ + // create global scene + world = new Scene; + + // open, convert, save + if ( OpenInput() ) { + MergeListIntoSingleObject(); + SaveOutput(); + } + + // delete global scene + delete world; + world = NULL; +} + + +// main ----------------------------------------------------------------------- +// +int main( int argc, char **argv ) +{ + // init application + if ( !InitMakeODT() ) { + return EXIT_FAILURE; + } + + // register command line options + RegisterOptions(); + + // exec all registered command line options + if ( !OPT_ExecRegisteredOptions( argc, argv ) ) { + MSGOUT( options_invalid ); + exit( EXIT_FAILURE ); + } + + // set modified options + SetBspLibOptions(); + + // check for file name + if ( input_file_name[ 0 ] == 0 ) { + MSGOUT( "No file name specified.\n" ); + exit( EXIT_FAILURE ); + } + + // do object conversion + ConvertObject(); + + return EXIT_SUCCESS; +} + |
