📄 rubyscenegraph.cpp
字号:
/*********************************************************************************** In the name of Almighty ** ** RubySceneGraph.cpp : Robocup Soccer Simulator Developement Team: Zigorat ** ** Date: 07/08/2007 ** Author: Mahdi Hamdarsi ** Research Coordinator: Amin Mohammadi ** Comments: Ruby scene Loader and initializer ** ***********************************************************************************//*! \file RubySceneGraph.cpp<pre><b>File:</b> RubySceneGraph.cpp<b>Project:</b> Robocup Soccer Simulator Developement Team: Zigorat<b>Authors:</b> Mahdi Hamdarsi, Amin Mohammadi<b>Created:</b> 12/02/2001<b>Last Revision:</b> $ID$<b>Contents:</b> Ruby scene Loader and initializer<hr size=2><h2><b>Changes</b></h2><b>Date</b> <b>Author</b> <b>Comment</b>07/08/2007 Mahdi Hamdarsi Initial version created</pre>*/#include <GL/glut.h>#include <fstream>#include "RubySceneGraph.h"#include "Parse.h"/*! This is the Multi-Filed OpenGL Engine instance */extern TOpenGLEngine * OpenGLEngine;/*********************************************************************************************//*********************************** Class TRubySceneGraph *********************************//*********************************************************************************************//** * This is the constructor of class TRubySceneGraph which intializes the internals of the * class with default values and, if supplied, tries to load the robot information from * the specified file given * @param strFileName filename to load the robot information from */TRubySceneGraph::TRubySceneGraph( const char * strFileName ){ m_Loaded = false; if( *strFileName ) ParseMain( strFileName );}/** * This is the destructor of the TRubySceneGraph class */TRubySceneGraph::~ TRubySceneGraph(){ clearScene();}/** * This method returns a data parsed previously * @param param_name Name of the parameter * @return Parameter instance */PGenericData TRubySceneGraph::getParam( string param_name ) const{ for( unsigned i = 0; i < m_Data.size(); i++ ) if( m_Data[i]->getName() == param_name ) return m_Data[i]; return NULL;}/** * This method reads a evaluation token and converts it to a data * @param str String containing the evaluation data * @param index current position in the string * @return Data that is parsed */TGenericData TRubySceneGraph::readEvaluationData( string & str, unsigned & index ){ TGenericData error, data; string param; error.setValue( "NaN" ); if( !Parse::gotoFirstParsableModule( str, index ) ) { cerr << "TRubySceneGraph::readEvaluationData: Nothing to parse" << endl; return error; } if( str[index] == '$' ) /// 1: If the eval was a definition { if( !Parse::getToken( str, index, param ) ) { cerr << "TRubySceneGraph::readEvaluationData: Evaluation terminated due to broken message in parsing previous define" << endl; return error; } PGenericData p = getParam( param ); if( p == NULL || p->getAsString() == "NaN" ) { cerr << "TRubySceneGraph::readEvaluationData: Evaluation wanted a previuos var which is not found: '" << param << "'" << endl; return error; } data.setValue( p->getAsString() ); } else if( str.compare( index, 5, "(eval" ) == 0 ) /// 2: If the eval was another evaluation data = evaluate( str, index ); else /// 3: If it was a simple arithmetic { string temp; if( !Parse::getToken( str, index, temp ) ) { cerr << "TRubySceneGraph::evaluate: Evaluation terminated due to broken message in parsing a number" << endl; Parse::eatMessage( str, index, 1 ); return error; } data.setValue( temp ); } return data;}/** * This method evaluates a value in the context * @param str String to evaluate upon * @param index current index of string * @return TData instance containing the value */TGenericData TRubySceneGraph::evaluate( string & str, unsigned & index ){ TGenericData result, data, error; char sign = '+'; error.setValue( "NaN" ); if( !Parse::gotoFirstParsableModule( str, index ) ) { cerr << "TRubySceneGraph::evaluate: Evaluation terminated due to broken message in '(eval'" << endl; Parse::eatMessage( str, index, 0 ); return error; } /// -------------- The first part should exists index += 5; do { data = readEvaluationData( str, index ); if( data.getAsString() == "NaN" ) { Parse::eatMessage( str, index, 1 ); return error; } /// ---> setting the result of evaluation till here if( sign == '+' ) result.setValue( result.getAsDouble() + data.getAsDouble() ); else if( sign == '-' ) result.setValue( result.getAsDouble() - data.getAsDouble() ); else if( sign == '*' ) result.setValue( result.getAsDouble() * data.getAsDouble() ); else if( sign == '/' ) result.setValue( result.getAsDouble() / data.getAsDouble() ); else { cerr << "TRubySceneGraph::evaluate: Unknown sign: huh?" << endl; Parse::eatMessage( str, index, 1 ); return error; } Parse::gotoFirstParsableModule( str, index ); if( index == str.size() ) { cerr << "TRubySceneGraph::evaluate: Evaluation terminated due to broken message in the end of evaluation" << endl; Parse::eatMessage( str, index, 1 ); return error; } if( str[index] == ')' ) break; /// ---> break to outside of loop to return the data /// ---> This is the part that parsing has finished sign = str[index]; if( sign != '-' && sign != '+' && sign != '*' && sign != '/' ) { cerr << "TRubySceneGraph::evaluate: Evaluation terminated due to unknonw operator parsed" << endl; Parse::eatMessage( str, index, 1 ); return error; } index++; } while( index < str.size() ); if( str[index] != ')' ) { cerr << "TRubySceneGraph::evaluate: Evaluation terminated due to broken message in the end of it" << endl; Parse::eatMessage( str, index, 1 ); return error; } index++; return result;}/** * This method parses the string given for a defintion, I mean ($define name value) * @param str String to be parsed for data * @return Indicating a parse was done correctly */bool TRubySceneGraph::parseDefinition( string str ){ if( str[0] != '(' ) return false; unsigned index = 4; string definition_name, value; if( !Parse::getToken( str, index, definition_name ) ) return false; if( !Parse::gotoFirstParsableModule( str, index ) ) { cerr << "TRubySceneGraph::parseDefinition: definition terminated" << endl; return false; } if( str.compare( index, 5, "(eval" ) == 0 ) { TGenericData data = evaluate( str, index ); value = data.getAsString(); if( value == "NaN" ) { cerr << "TRubySceneGraph::parseDefinition: found undetermined value" << endl; return false; } } else if( str[index] == '$' ) { string base_def; if( !Parse::getToken(str, index, base_def) ) { cerr << "TRubySceneGraph::parseDefinition: definition terminated for base define" << endl; return false; } value = getParam(base_def)->getAsString(); } else if( !Parse::getToken( str, index, value ) ) return false; Parse::gotoFirstParsableModule( str, index ); if( str[index] != ')' ) cerr << "TRubySceneGraph::parseDefinition: definition continues, perhaps a new structure" << endl; PGenericData data = new TGenericData; data->setName( definition_name ); data->setValue( value ); m_Data.push_back( data ); return true;}/** * This method clears the data definions in RubySceneGrapg so that more * memory remains for use */void TRubySceneGraph::clearDatas(){ for( unsigned i = 0; i < m_Data.size(); i++ ) delete m_Data[i]; m_Data.clear();}/** * This method loads scene information, namely version from the file * @param str String to be parsed for basic information * @return Indicats wheather basic information was parsed successfully */bool TRubySceneGraph::loadSceneBasicInfo( string & str, unsigned & index ){ if( !Parse::gotoFirstParsableModule( str, index ) || str[index] != '(' ) { cerr << "TRubySceneGraph::loadSceneBasicInfo: Couldn't get into basic info" << endl; return false; } index++; string token1, token2, token3; if( !Parse::getToken( str, index, token1 ) || token1 == ")" ) { cerr << "TRubySceneGraph::loadSceneBasicInfo: Couldn't get first parameter" << endl; return false; } if( !Parse::getToken( str, index, token2 ) || token2 == ")" ) { cerr << "TRubySceneGraph::loadSceneBasicInfo: Couldn't get second parameter" << endl; return false; } if( !Parse::getToken( str, index, token3 ) || token3 == ")" ) { cerr << "TRubySceneGraph::loadSceneBasicInfo: Couldn't get third parameter" << endl; return false; } Parse::gotoFirstParsableModule( str, index ); if( str[index] != ')' ) { cerr << "TRubySceneGraph::loadSceneBasicInfo: basic info continues ???" << endl; return false; } if( token1 != "RSG" || TGenericData::getNumberFromString( token2 ) != 0 || TGenericData::getNumberFromString( token3 ) != 1 ) { cerr << "TRubySceneGraph::loadSceneBasicInfo: Version is not supported" << endl; return false; } index++; return true;}/** * This method is the intial part of parsing module of TRubySceneGraph class. It loads the * file into memory, takes out the definitions and evaluations, replaces the variables and * starts parsing and updating of the nodes. * @param strFileName File name to load and parse * @return Indicates wheather parse was successfull */bool TRubySceneGraph::ParseMain( const char * strFileName ){ ifstream file(strFileName, ios::in ); if(!file) return false; string str = "", strDefine, strEval, strVar; char buff[65536]; bool bComment = false; int cnt, iLine = 0, pran; unsigned index, i; do { file.read( buff, 65536 ); cnt = file.gcount(); for(int i = 0; i < cnt; i++) { if( buff[i] == '\n' ) /// ---------> New line { bComment = false; iLine++; } else if( buff[i] == ';' ) /// --------> Comment bComment = true; else if( !bComment ) { /// -------------------------------------------1: take out define statements ------------------------------------ if( (cnt - i) > 6 && strncmp(buff + i, "(def", 4) == 0 ) { strDefine = "("; pran = 1; while( i < cnt && pran > 0 ) { i++; if( buff[i] == ')' ) pran--; else if( buff[i] == '(' ) pran++; strDefine += buff[i]; } if( i >= cnt || buff[i] != ')' )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -