⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gribparser.cpp

📁 一个非常有用的开源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
//#pragma warning( disable : 4786 )//#include <fstream.h>#include "GRibParser.h"#include "../GClasses/GRayTrace.h"// I use uint for readability.#ifndef uinttypedef unsigned int uint;#endifusing std::vector;using std::map;using std::string;using std::list;// Hopefully you'll never need this.//#define PARSER_DEBUGRibParser::RibParser(): m_pScene(NULL), image_width(256), image_height(256), fov( 35 ), baseDir( "" ), in_object_definition( false ){	// Add the root state block.	state.push_back( StateBlock() );}RibParser::~RibParser(){	// Delete the memory that the files were read into, since it's no longer needed.	for ( uint i = 0; i < lineBuffs.size(); i++ )		delete[] lineBuffs[ i ];	delete(m_pScene);}/*static*/ GRayTraceScene* RibParser::LoadScene(const char* szFilename){	RibParser parser;	if(!parser.createScene(szFilename))		return NULL;	return parser.DropScene();}// This is just a convenience function, taking a filename instead of a stream.// See the other overloaded method for actual behaviorbool RibParser::createScene(string filename){	FILE *F = fopen(filename.c_str(), "r");	if (!F) return false;	// Set the base name on the parser, so that it knows where to find relative files	// TODO: test for bugs	{		string delims = "\\/";		string blank = "";#ifdef WIN32		char mydelim = '\\';		char otherdelim = '/';#else		char mydelim = '/';		char otherdelim = '\\';#endif		// First, see if there's any directory delimiters		string::size_type last_delim = filename.find_last_of( delims );		if ( last_delim != string::npos ) 		{			baseDir = filename;			baseDir.erase( last_delim + 1 );			for ( string::size_type i = 0; i < baseDir.size(); i++ )				if ( baseDir[i] == otherdelim )					baseDir[i] = mydelim;		}	}	return createScene(F);}// This reads the whole file at once, then handles each commandbool RibParser::createScene(FILE* F){	// If we're recursing, then m_pScene has already been allocated	if(!m_pScene)		m_pScene = new GRayTraceScene();	bool success = true; // Let's be optimistic	vector< int > lines, line_nums;	int total_length;	RibData line;	total_length = readLines( F, lines, line_nums );	//printf("Read %d lines, parsing...\n", lines.size());	char* line_buff = lineBuffs.back();	// build RibData and handle each line.	for ( uint i = 0; i < lines.size(); i++ )	{		buildData( line_buff, lines[ i ], line_nums[ i ], line );		success = handleLine( line ) && success;		line.clear();	}	//printf("Done parsing scene\n");	return success;}int RibParser::readLines( FILE* F, vector< int >& lines, vector< int >& line_nums ){	char *line_buff;	string temp;	int length;	int length_guess; // Oddly enough, length_guess != length.  It filters out '\r' because it's in ascii mode..	int num_file_lines = 0;	int seek_ahead;	int brackets_match = 0;	bool empty_line = true;	fseek(F, 0, SEEK_END);	length_guess = ftell(F);	line_buff = new char[length_guess + 4];	fseek(F, 0, SEEK_SET);	length = fread(line_buff, 1, length_guess, F);	line_buff[length] = '\0';	fclose(F);	if (length == 0) {		printf("RIB Error! Could not load file.\n");		delete[] line_buff;		return 0;	}	// store the location of line_buff on the RibParser object, so that it will be deleted properly later	lineBuffs.push_back( line_buff );	int prev_pos = 0;	for ( int i = 0; i < length; i++ )	{		switch( line_buff[ i ] )		{                case '\r':                        line_buff[i] = '\n'; // Then fall through		case '\n':			{ // End of line				num_file_lines++;				if ( empty_line )				{ // Whitespace only line.					line_buff[ i ] = ' '; // Concat blank lines as trailing whitespace to previous line					prev_pos = i+1;					continue;				}				else 				{ // Line with something useful on it is ending.					// To make sure it's really the end of the line, 					// we need to seek ahead to find the first non-whitespace character.					// If it's " or [, then this isn't the end of a line (because the next line doesn't					// begin with a Rib command - it's a continuation)					// We also have to ignore comments, and blank lines.					// We also need to make sure we're not in the middle of a list.					// This can be kind of a pain.					if ( brackets_match != 0 )					{ // We're in the middle of a list - keep it all as one line.						line_buff[ i ] = ' ';						continue;					}					else					{						bool end_of_line = true;						for ( seek_ahead = i; seek_ahead < length; seek_ahead++ )						{							switch( line_buff[ seek_ahead ] )							{							case ' ':							case '\t':							case '\n':								// Keep going through whitespace - this isn't what we're looking for.								break;							case '#':								// Eat the rest of the comment - this isn't what we're looking for either.								while ( seek_ahead < length )								{									if ( line_buff[ seek_ahead ] == '\n' )										break;									seek_ahead++;								}								break;							case '\"':							case '[':								// Not the end of the line								end_of_line = false;								seek_ahead = length; // This is a way of breaking out of the for loop								break;							default:								end_of_line = true;								seek_ahead = length; // This is a way of breaking out of the for loop								break;							}						}						if ( !end_of_line )						{ // This isn't the end of the line							line_buff[ i ] = ' ';							continue;						}					}					// At this point, we're sure that this was the end of a line.					// Add this line to the vector					line_buff[ i ] = '\0';					lines.push_back( prev_pos );					line_nums.push_back( num_file_lines );					// Reset for next line					prev_pos = i+1;					empty_line = true;				}			}			break;		case ' ':		case '\t':			{ // Whitespace			}			break;		case '#': 			{ // Just blank out the comments until the end of the line.  We don't need to parse comments.				while ( i < length && line_buff[i+1] != '\n' )				{					line_buff[i] = ' ';					i++;				}				line_buff[i] = ' ';			}			break;		case '[':			brackets_match++;			empty_line = false;			break;		case ']':			brackets_match--;			empty_line = false;			break;		default:			empty_line = false;		}	}	// We'll check to see if we had a final line that hasn't been added yet	if ( !empty_line )	{		lines.push_back( prev_pos );		line_nums.push_back( num_file_lines );	}	// Return the total length of the stream read.	return length;}void RibParser::buildData( char* big_str, int begin, int line_num, RibData& line ){	char* str = big_str + begin;	int length = strlen( str );	int prev_pos = 0;	char temp;	//int brackets_balance = 0;	int i;	// Find first non-whitespace	for ( i = 0; i < length; i++ )	{		if ( str[ i ] != ' ' || str[ i ] != '\t' )			break;	}#ifdef PARSER_DEBUG		if ( str[ i ] == '\"' || str[ i ] == '[' )	{		// This shouldn't happen, unless there's a bug in read_lines, or a problem in the file		fprintf(stderr, "First token on line is quote or an open bracket.\nThis is an error in the rib file (or perhaps the parser).\n");	}#endif	// Set position to first non-whitespace	prev_pos = i;	// The main state machine loop.	for ( i = prev_pos; i < length; i++ )	{		switch( str[ i ] )		{		case ' ':		case '\t':			// This is delimiting whitespace.  Make it a string terminator			str[ i ] = '\0';			break; 		case '[':			{				// It's possible to have an open bracket terminate a token.  So, let's make it a string terminator also.				str[i] = '\0';				// Make the parent RibData and add it to the line.				line.append( RibData( RibData::LEAF_ARRAY ) );				// Actually do the extraction.  This is somewhat involved, so I made it a separate function				this->extractArray( str, length, i, line.back() );			}			break;#ifdef PARSER_DEBUG			case ']':			fprintf(stderr, "Mismatched close bracket\n"); break;		case '#':			fprintf(stderr, "All the comments should be removed by now..\n"); break;#endif		case '\"':			// Find the whole quoted string			i++;			prev_pos = i;			while ( i < length && str[ i ] != '\"' )				i++;#ifdef PARSER_DEBUG				if ( !( i < length ) )				fprintf(stderr, "Error: Unterminated string.\n");#endif			str[ i ] = '\0'; // Zero out the final quote			line.append( RibData( &str[ prev_pos ], true ) );			break;		default:			// Find the whole token			prev_pos = i;			while ( i < length )			{				i++;				char c = str[ i ];				if ( c == ' ' || c == '\t' || c == '[' || c == '\"' )					break;			};			// The next character might be significant for the state ( '[' and '"' are significant ).			// So we'll have to save it, so it can be processed by the state machine.			temp = str[ i ];			str[ i ] = '\0';			line.append( RibData( &str[ prev_pos ], false ) );			str[ i ] = temp;			i--; // Back up, so as not to miss a character after the loop increment			break;		}	}}void RibParser::extractArray( char* str, int length, int& i, RibData& parent ){ 	list< char* > temp_vals; // Just store it as a list temporarily.  We'll move it to a vector when we know the size	// Let's chew through the array values.	for ( i++; i < length; i++ )	{		if ( str[i] == ' ' || str[i] == '\t' )		{			str[i] = '\0';			continue;		}		else if ( str[i] == ']' )		{			str[i] = '\0';			// The array is done - build the vector and return.			parent.reserveCapacity( temp_vals.size() );			vector< const char* >& vals = parent.accessVals();			vals.clear();			vals.resize( temp_vals.size(), (const char*)0xdeafbeef );			int ival = 0;			std::list< char* >::iterator lit;			for ( lit = temp_vals.begin(); lit != temp_vals.end(); lit++, ival++ )			{				vals[ ival ] = *lit;			}			return;		}		else if ( str[i] == '\"' )		{			char* start_ptr = str + i; // We start at the quote, so we know it's a quoted string.						               // Although the end quote is overwritten by a null, to make									   // string manipulation a little bit easier.			// Get off the current quote			i++;			// Find matching quote			while ( i < length && str[i] != '\"' )				i++;			// At this point, we're either at the end of string ( which means malformed RIB )			// or, str[i] == '\"'#ifdef PARSER_DEBUG				if ( ! (i < length) )				fprintf(stderr, "Malformed RIB: Unterminated quote, unterminated array\n");#endif			// Add the entry to the parent's vals.			str[i] = '\0'; // Overwrite the quote with nul, to make string manipulation easier			temp_vals.push_back( start_ptr );		}		else		{   // Some normal token: either a string, double, or int.  We'll find out when we are asked for it.			// This is inner loop for large scenes, so I'm going to use pointer arithmetic instead of indices			char* start_ptr = str + i;			char* next_ptr = start_ptr + 1;			char* end_ptr = start_ptr + length;			// Find end of the token.  Can be terminated by whitespace, or close bracket.			while ( next_ptr != end_ptr )			{				if ( *next_ptr == ' ' || *next_ptr == ']' )					break; // Note that a null is written to these positions, to ease string manipulation							// The null is actually written to str in the next round of the outer for loop				next_ptr++;			}			i += next_ptr - start_ptr - 1;			temp_vals.push_back( start_ptr );		}	}	fprintf(stderr, "Error in Rib file: Unterminated array\n");}bool RibParser::handleLine( const RibData& data ){#ifdef PARSER_DEBUG		if ( data.size() == 0 )	{		fprintf(stderr, "The data passed in should always be an array\n");		return false;	}#endif	bool success = true;	string command;	command = data[ 0 ].asString();	// If defining an object, store commands to be instanced later.	if ( in_object_definition && command != "ObjectEnd" )	{		RibData& object_parent = getObjectDefinition( curr_object );		object_parent.append( data );		return true;	}	// Block management	if ( command == "TransformBegin" ) {		pushState( StateBlock::TRANSFORMBLOCK );	} else if ( command == "TransformEnd" ) {		popState( StateBlock::TRANSFORMBLOCK );	} else if ( command == "AttributeBegin" ) {		pushState( StateBlock::ATTRIBUTEBLOCK );	} else if ( command == "AttributeEnd" ) {		popState( StateBlock::ATTRIBUTEBLOCK );	} else if ( command == "WorldBegin" ) {		pushState( StateBlock::WORLDBLOCK );	} else if ( command == "WorldEnd" ) {		popState( StateBlock::WORLDBLOCK );	} else if ( command == "FrameBegin" ) {		pushState( StateBlock::FRAMEBLOCK );	} else if ( command == "FrameEnd" ) {		popState( StateBlock::FRAMEBLOCK );	} 	// These are the handlers for various commands	else if ( command == "Transform" ) {		success = handleTransform( data );	} else if ( command == "ConcatTransform" ) {		success = handleConcatTransform( data );	} else if ( command == "Translate" ) {		success = handleTranslate( data );	} else if ( command == "ReadArchive" ) {		success = handleReadArchive( data );	} else if ( command == "ObjectBegin" ) {		success = handleObjectBegin( data );	} else if ( command == "ObjectEnd" ) {		success = handleObjectEnd( data );	} else if ( command == "ObjectInstance" ) {		success = handleObjectInstance( data );	} else if ( command == "Format" ) {		success = handleFormat( data );	} else if ( command == "PixelSamples" ) {		success = handlePixelSamples( data );	} else if ( command == "Imager" ) {		success = handleImager( data );	} else if ( command == "Projection" ) {		success = handleProjection( data );	} else if ( command == "DepthOfField" ) {		success = handleDepthOfField( data );	} else if ( command == "Attribute" ) {		success = handleAttribute( data );	} else if ( command == "Color" ) {		success = handleColor( data );	} else if ( command == "Surface" ) {		success = handleSurface( data );	} else if ( command == "LightSource" ) {		success = handleLight( data );	} else if ( command == "Sphere" ) {		success = handleSphere( data );	} else if ( command == "NuPatch" ) {		success = handleNuPatch( data );	} else if ( command == "PointsGeneralPolygons" ) {		success = handlePointsGeneralPolygons( data );	} else if ( command == "AreaLightSource" ) {		success = handleAreaLightSource( data );	} else if ( command == "Display" || command == "Clipping" || command == "ReverseOrientation" || command == "Orientation" ) {		// Silently ignore these commands.	} else {		printf("Warning: Unhandled RIB data: %s\n", command.c_str());		//data.debugPrint( cout, 3 );	}		return success;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -