33 #ifndef __INCLUDE_MIST_MQO__
34 #define __INCLUDE_MIST_MQO__
37 #ifndef __INCLUDE_MIST_H__
42 #ifndef __INCLUDE_MIST_FACET__
57 namespace __mqo_controller__
62 typedef facet_list< T > facet_list_type;
63 typedef typename facet_list_type::facet_type facet_type;
64 typedef typename facet_type::vector_type vector_type;
65 typedef typename facet_type::size_type size_type;
66 typedef vector3< size_type > ivector_type;
68 static const unsigned char *get_line(
const unsigned char *s,
const unsigned char *e, std::string &line )
75 if( s + 1 != e && s[ 1 ] ==
'\n' )
85 else if( s[ 0 ] ==
'\n' )
93 return( s > e ? e : s );
96 static const unsigned char *get_value(
const unsigned char *s,
const unsigned char *e, std::string &line,
bool &flag )
102 if( flag && s[ 0 ] ==
'#' )
109 if( s + 1 != e && s[ 1 ] ==
'\n' )
119 else if( s[ 0 ] ==
'\n' )
127 else if( s[ 0 ] ==
'\r' )
129 if( s + 1 != e && s[ 1 ] ==
'\n' )
139 else if( s[ 0 ] ==
'\n' )
144 else if( s[ 0 ] ==
' ' || s[ 0 ] ==
'\t' )
160 if( s + 1 != e && s[ 1 ] ==
'\n' )
171 else if( s[ 0 ] ==
'\n' )
177 else if( s[ 0 ] ==
' ' || s[ 0 ] ==
'\t' )
185 return( s > e ? e : s );
188 static size_type split_string(
const std::string &line,
const char ch, std::vector< std::string > &elements )
190 std::string str =
"";
193 while( i < line.size( ) )
195 for( ; i < line.size( ) && line[ i ] == ch ; i++ );
198 for( ; i < line.size( ) && line[ i ] != ch ; i++ )
205 elements.push_back( str );
208 return( elements.size( ) );
211 static std::string to_lower( std::string line )
213 for(
size_t i = 0 ; i < line.size( ) ; i++ )
215 if(
'A' <= line[ i ] && line[ i ] <=
'Z' )
217 line[ i ] +=
'a' -
'A';
223 static const unsigned char *skip_chunk(
const unsigned char *p,
const unsigned char *e,
const std::string &ch )
225 std::string line =
"";
230 p = get_line( p, e, line );
232 if( line.find_last_of( ch ) != std::string::npos )
241 static const unsigned char *skip_chunk(
const unsigned char *p,
const unsigned char *e,
const char ch )
243 std::string line =
"";
248 p = get_line( p, e, line );
250 for( size_type i = 0 ; i < line.size( ) ; )
253 unsigned char v1 = line[ i ];
254 unsigned char v2 = i + 1 < line.size( ) ? line[ i + 1 ] : 0x00;
256 if( ( ( 0x81 <= v1 && v1 <= 0x9f ) || ( 0xe0 <= v1 && v1 <= 0xef ) ) && ( 0x40 <= v2 && v2 <= 0xfc && v2 != 0x7f ) )
274 static const unsigned char *process_vertex_chunk( std::vector< vector_type > &vertices,
const unsigned char *p,
const unsigned char *e )
276 std::string line =
"";
277 std::vector< std::string > elements;
282 p = get_value( p, e, line, eol );
286 std::cerr <<
"EOL was found before vertex count appeared!!" << std::endl;
290 size_type num_vertices = atoi( line.c_str( ) );
293 p = skip_chunk( p, e,
"{" );
297 std::cerr <<
"'{' was not found before EOL appeared!!" << std::endl;
302 vertices.reserve( num_vertices );
308 p = get_line( p, e, line );
310 if( line.find_last_of(
'}' ) != std::string::npos )
316 if( split_string( line,
' ', elements ) != 3 )
318 std::cerr <<
"Vertex must have three components." << std::endl;
322 vertices.push_back( vector_type( atof( elements[ 0 ].c_str( ) ), atof( elements[ 1 ].c_str( ) ), atof( elements[ 2 ].c_str( ) ) ) );
325 return( vertices.size( ) == num_vertices ? p : NULL );
328 static const unsigned char *process_face_chunk( std::vector< ivector_type > &faces,
const unsigned char *p,
const unsigned char *e )
330 std::string line =
"";
331 std::vector< std::string > elements;
336 p = get_value( p, e, line, eol );
340 std::cerr <<
"EOL was found before face count appeared!!" << std::endl;
344 size_type num_faces = atoi( line.c_str( ) );
347 p = skip_chunk( p, e,
"{" );
351 std::cerr <<
"'{' was not found before EOL appeared!!" << std::endl;
356 faces.reserve( num_faces );
362 p = get_line( p, e, line );
364 if( line.find_last_of(
'}' ) != std::string::npos )
371 sscanf( line.c_str( ),
"%d", &num );
373 size_type si = line.find(
"V(" );
374 if( si == std::string::npos )
376 std::cerr <<
"Incorrect face chunk is found." << std::endl;
384 size_type ei = line.find(
')', si + 1 );
385 if( ei == std::string::npos )
387 std::cerr <<
"Incorrect face chunk is found." << std::endl;
395 line = line.substr( si, ei - si + 1 );
397 if( split_string( line,
' ', elements ) != num )
399 std::cerr <<
"Incorrect face chunk is found." << std::endl;
405 std::cerr <<
"Face should have more than three vertices." << std::endl;
411 std::cerr <<
"Face should have less than five vertices." << std::endl;
418 faces.push_back( ivector_type( atoi( elements[ 0 ].c_str( ) ), atoi( elements[ 2 ].c_str( ) ), atoi( elements[ 1 ].c_str( ) ) ) );
423 faces.push_back( ivector_type( atoi( elements[ 0 ].c_str( ) ), atoi( elements[ 3 ].c_str( ) ), atoi( elements[ 2 ].c_str( ) ) ) );
424 faces.push_back( ivector_type( atoi( elements[ 0 ].c_str( ) ), atoi( elements[ 2 ].c_str( ) ), atoi( elements[ 1 ].c_str( ) ) ) );
429 return( faces.size( ) == num_faces ? p : NULL );
432 static const unsigned char *process_object_chunk( facet_list_type &facets,
const unsigned char *p,
const unsigned char *e )
434 std::string line =
"";
439 p = get_value( p, e, line, eol );
443 std::cerr <<
"EOL was found before object name appeared!!" << std::endl;
447 if( line.size( ) > 0 && line[ 0 ] ==
'\"' && line[ line.size( ) - 1 ] ==
'\"' )
449 facets.name = line.substr( 1, line.size( ) - 2 );
457 p = skip_chunk( p, e,
"{" );
461 std::cerr <<
"'{' was not found before EOL appeared!!" << std::endl;
465 std::vector< vector_type > vertices;
466 std::vector< ivector_type > faces;
469 while( p != NULL && p < e )
472 p = get_value( p, e, line, eol );
473 line = to_lower( line );
480 else if( line ==
"depth" )
483 else if( line ==
"folding" )
486 else if( line ==
"scale" )
489 else if( line ==
"rotation" )
492 else if( line ==
"translation" )
495 else if( line ==
"patch" )
498 else if( line ==
"segment" )
501 else if( line ==
"visible" )
504 else if( line ==
"locking" )
507 else if( line ==
"shading" )
510 else if( line ==
"facet" )
513 else if( line ==
"color" )
516 else if( line ==
"color_type" )
519 else if( line ==
"mirror" )
522 else if( line ==
"mirror_axis" )
525 else if( line ==
"mirror_dis" )
528 else if( line ==
"lathe" )
531 else if( line ==
"lathe_axis" )
534 else if( line ==
"lathe_seg" )
537 else if( line ==
"vertexattr" )
540 std::cerr <<
"vertexattr chunk is currently not supported." << std::endl;
543 else if( line ==
"bvertex" )
546 std::cerr <<
"BVertex chunk is currently not supported." << std::endl;
549 else if( line ==
"vertex" )
551 p = process_vertex_chunk( vertices, p, e );
554 else if( line ==
"face" )
556 p = process_face_chunk( faces, p, e );
562 std::cerr <<
"Unknown chunk is found!!" << std::endl;
568 p = get_line( p, e, line );
578 facets.reserve( faces.size( ) );
580 for( size_type i = 0 ; i < faces.size( ) ; i++ )
582 const ivector_type &v = faces[ i ];
585 if( 0 <= v.x && v.x < vertices.size( ) )
587 f.p1 = vertices[ v.x ];
591 std::cerr <<
"Incorrect face found: (" << v <<
")" << std::endl;
594 if( 0 <= v.y && v.y < vertices.size( ) )
596 f.p2 = vertices[ v.y ];
600 std::cerr <<
"Incorrect face found: (" << v <<
")" << std::endl;
603 if( 0 <= v.z && v.z < vertices.size( ) )
605 f.p3 = vertices[ v.z ];
609 std::cerr <<
"Incorrect face found: (" << v <<
")" << std::endl;
612 f.normal = ( ( f.p2 - f.p1 ).outer( f.p3 - f.p1 ) ).unit( );
614 facets.push_back( f );
620 static const unsigned char * __process_object_chunk__( std::vector< facet_list_type > &facet_lists,
const unsigned char *p,
const unsigned char *e )
622 facet_lists.push_back( facet_list_type( ) );
623 facet_list_type &facets = facet_lists.back( );
624 p = process_object_chunk( facets, p, e );
627 facet_lists.pop_back( );
633 static const unsigned char * __process_object_chunk__( facet_list_type &facets,
const unsigned char *p,
const unsigned char *e )
636 p = process_object_chunk( fff, p, e );
639 facets.insert( facets.end( ), fff.begin( ), fff.end( ) );
645 template <
class FACETLIST >
646 static bool convert_from_data( FACETLIST &facet_lists,
const unsigned char *buff, size_type len )
648 const unsigned char *p = buff;
649 const unsigned char *e = buff + len;
650 std::string line =
"";
651 std::vector< std::string > elements;
657 p = get_line( p, e, line );
658 if( line !=
"Metasequoia Document" )
660 std::cerr <<
"This is not a Metasequoia Document." << std::endl;
666 p = get_line( p, e, line );
667 if( sscanf( line.c_str( ),
"Format %s Ver %.1f", buff, ver ) <= 0 )
669 std::cerr <<
"This is not a Metasequoia Document." << std::endl;
675 while( p != NULL && p < e )
677 p = get_value( p, e, line, eol );
679 line = to_lower( line );
685 else if( line ==
"eof" )
689 else if( line ==
"trialnoise" )
691 p = skip_chunk( p, e,
'}' );
693 else if( line ==
"includexml" )
695 p = skip_chunk( p, e,
'}' );
697 else if( line ==
"scene" )
699 p = skip_chunk( p, e,
'}' );
701 else if( line ==
"backimage" )
703 p = skip_chunk( p, e,
'}' );
705 else if( line ==
"material" )
707 p = skip_chunk( p, e,
'}' );
709 else if( line ==
"blob" )
711 p = skip_chunk( p, e,
'}' );
713 else if( line ==
"object" )
715 p = __process_object_chunk__( facet_lists, p, e );
719 std::cerr <<
"Unknown chunk found!!" << std::endl;
727 template <
class FACETLIST >
728 static bool read( FACETLIST &facet_lists,
const std::string &filename )
731 facet_lists.clear( );
735 if( ( fp = fopen( filename.c_str( ),
"rb" ) ) == NULL )
return(
false );
737 fseek( fp, 0, SEEK_END );
738 filesize = ftell( fp );
739 fseek( fp, 0, SEEK_SET );
742 unsigned char *buff =
new unsigned char[ filesize + 1 ];
743 unsigned char *pointer = buff;
744 size_type read_size = 0;
745 while( feof( fp ) == 0 )
747 read_size = fread( pointer,
sizeof(
unsigned char ), 1024, fp );
748 if( read_size < 1024 )
752 pointer += read_size;
756 bool ret = convert_from_data( facet_lists, buff, filesize );
763 static bool write(
const std::vector< facet_list_type > &facet_lists,
const std::string &filename )
765 if( facet_lists.empty( ) )
767 std::cerr <<
"There is no object!" << std::endl;
772 if( ( fp = fopen( filename.c_str( ),
"wb" ) ) == NULL )
777 fprintf( fp,
"Metasequoia Document\r\n" );
778 fprintf( fp,
"Format Text Ver 1.0\r\n\r\n" );
781 fprintf( fp,
"Scene {\r\n" );
782 fprintf( fp,
"\tpos 0.0000 0.0000 1000.0\r\n" );
783 fprintf( fp,
"\tlookat 0.0000 0.0000 0.0000\r\n" );
784 fprintf( fp,
"\thead 0.0000\r\n" );
785 fprintf( fp,
"\tpich 0.0000\r\n" );
786 fprintf( fp,
"\tortho 0\r\n" );
787 fprintf( fp,
"\tzoom2 5.0\r\n" );
788 fprintf( fp,
"\tamb 0.250 0.250 0.250\r\n" );
789 fprintf( fp,
"}\r\n" );
792 fprintf( fp,
"Material 1 {\r\n" );
793 fprintf( fp,
"\t\"default\" shader(3) col(1.000 1.000 1.000 1.000) dif(0.800) amb(0.600) emi(0.000) spc(0.000) power(5.00)\r\n" );
794 fprintf( fp,
"}\r\n" );
797 for( size_type l = 0 ; l < facet_lists.size( ) ; l++ )
799 const facet_list_type &facets = facet_lists[ l ];
801 std::vector< vector_type > vertices;
802 std::vector< ivector_type > faces;
805 fprintf( fp,
"Object \"%s\" {\r\n", facets.name.c_str( ) );
806 fprintf( fp,
"\tvisible 15\r\n" );
807 fprintf( fp,
"\tlocking 0\r\n" );
808 fprintf( fp,
"\tshading 1\r\n" );
809 fprintf( fp,
"\tcolor 1.000 1.000 1.000\r\n" );
810 fprintf( fp,
"\tcolor_type 0\r\n" );
813 fprintf( fp,
"\tvertex %d {\r\n", static_cast< int >( vertices.size( ) ) );
814 for( size_type i = 0 ; i < vertices.size( ) ; i++ )
816 const vector_type &f = vertices[ i ];
817 double fx = ( f.x * 1e4 + 0.5 ) * 1e-4;
818 double fy = ( f.y * 1e4 + 0.5 ) * 1e-4;
819 double fz = ( f.z * 1e4 + 0.5 ) * 1e-4;
820 fprintf( fp,
"\t\t%.4f %.4f %.4f\r\n", f.x, f.y, f.z );
822 fprintf( fp,
"\t}\r\n" );
826 fprintf( fp,
"\tface %d {\r\n", static_cast< int >( faces.size( ) ) );
827 for( size_type i = 0 ; i < faces.size( ) ; i++ )
829 const ivector_type &f = faces[ i ];
832 fprintf( fp,
"\t\t%d V(%d %d %d) M(0)\r\n", 3, f.x, f.z, f.y );
834 fprintf( fp,
"\t}\r\n" );
837 fprintf( fp,
"}\r\n" );
841 fprintf( fp,
"Eof" );
878 return( __mqo_controller__::mqo_controller< T >::read( facet_lists, filename ) );
908 return( __mqo_controller__::mqo_controller< T >::read( facets, filename ) );
938 return( __mqo_controller__::mqo_controller< T >::write( facet_lists, filename ) );
966 std::vector< facet_list< T > > tmp;
967 tmp.push_back( facets );
968 return( __mqo_controller__::mqo_controller< T >::write( tmp, filename ) );
999 #endif // __INCLUDE_MIST_MQO__