OGRE 材质脚本解析的分析

来源:互联网 发布:怎么写好记叙文知乎 编辑:程序博客网 时间:2024/04/30 18:07
material 08-Default{technique{pass{ambient 0.588235 0.588235 0.588235 1diffuse 0.588235 0.588235 0.588235 1specular 0 0 0 1 10texture_unit{texture liuxing1.bmp}}}}

上述材质脚本,OGRE 解析是在如下函数中

bool ScriptCompiler::compile(const String &str, const String &source, const String &group){ScriptLexer lexer;ScriptParser parser;ConcreteNodeListPtr nodes = parser.parse(lexer.tokenize(str, source));return compile(nodes, group);}

输入的 str 就是最上边的材质脚本,已经处理为一个字符串。整个解析分3步。

1、lexer.tokenize(str, source))。进行词法分析,输出为一个词数组。结构为:

/** This struct represents a token, which is an ID'd lexeme from theparsing input stream.*/struct ScriptToken{/// This is the lexeme for this tokenString lexeme, file;/// This is the id associated with the lexeme, which comes from a lexeme-token id mappinguint32 type;/// This holds the line number of the input stream where the token was found.uint32 line;};typedef SharedPtr<ScriptToken> ScriptTokenPtr;typedef vector<ScriptTokenPtr>::type ScriptTokenList;typedef SharedPtr<ScriptTokenList> ScriptTokenListPtr;


处理的字符数组剔除了空格,保留了换行符(10)。处理的字符数组剔除了空格,保留了换行符(10)。处理的字符数组剔除了空格,保留了换行符(10)。

2、parser.parse()。进行类似CST(Concrete Syntax Tree) 分析,输出为一个语法节点,结构如下:

/** The ConcreteNode is the struct that holds an un-conditioned sub-tree of parsed input */struct ConcreteNode;typedef SharedPtr<ConcreteNode> ConcreteNodePtr;typedef list<ConcreteNodePtr>::type ConcreteNodeList;typedef SharedPtr<ConcreteNodeList> ConcreteNodeListPtr;struct ConcreteNode : public ScriptCompilerAlloc{String token, file;unsigned int line;ConcreteNodeType type;ConcreteNodeList children;ConcreteNode *parent;};

该语法树已经剔除了换行符,输出节点实例如下:

 

material --- 08-Default ---{   父节点A ---}      父节点A     technique     --- {  父节点B     --- }           父节点B           pass           --- {  父节点C           --- }                  父节点C                  --- ambient                       --- 0.588235                       --- 0.588235                       --- 0.588235                       --- 1                 --- diffuse                      --- 0.588235                      --- 0.588235                       --- 0.588235                      --- 1                 --- specular                      ---  0                      ---  0                      ---  0                      ---  1                      --- 10                  --- texture_unit                       --- { 父节点D                       --- }                              父节点D                               texture                               --- liuxing1.bmp


 3、return compile(nodes, group)。实际包含两步:进行类似AST(Abstract  Syntax Tree) 分析; 之后把AST信息转化为Material。

 3.1 AST。所用的结构为:

class _OgreExport AbstractNode : public AbstractNodeAlloc{public:String file;unsigned int line;AbstractNodeType type;AbstractNode *parent;Any context; // A holder for translation context datapublic:AbstractNode(AbstractNode *ptr);virtual ~AbstractNode(){}/// Returns a new AbstractNode which is a replica of this one.virtual AbstractNode *clone() const = 0;/// Returns a string value depending on the type of the AbstractNode.virtual String getValue() const = 0;};

context 为 Any 类型, 在3.2步根据具体的类型进行相应的转换。
它有众多子类,列举几个: 

/** This specific abstract node represents a script object */class _OgreExport ObjectAbstractNode : public AbstractNode{private:map<String,String>::type mEnv;public:String name, cls;std::vector<String> bases;uint32 id;bool abstract;AbstractNodeList children;AbstractNodeList values;AbstractNodeList overrides; // For use when processing object inheritance and overridingpublic:ObjectAbstractNode(AbstractNode *ptr);AbstractNode *clone() const;String getValue() const;void addVariable(const String &name);void setVariable(const String &name, const String &value);std::pair<bool,String> getVariable(const String &name) const;const map<String,String>::type &getVariables() const;};

其中 name = "08-Default", cls  即类名 material, id 为该类的标志ID。

/** This abstract node represents a script property */class _OgreExport PropertyAbstractNode : public AbstractNode{public:String name;uint32 id;AbstractNodeList values;public:PropertyAbstractNode(AbstractNode *ptr);AbstractNode *clone() const;String getValue() const;};

以及

/** This is an abstract node which cannot be broken down further */class _OgreExport AtomAbstractNode : public AbstractNode{public:String value;uint32 id;public:AtomAbstractNode(AbstractNode *ptr);AbstractNode *clone() const;String getValue() const;private:void parseNumber() const;};


  

经过   AbstractNodeListPtr ast = convertToAST(nodes); 处理后,材质脚本实例为

  1>  ObjectAbstractNode .

          name = "08-Default",  cls="material", id = 3. child 指向下一级, 有1个子节点。

  2> ObjectAbstractNode .

          name = "",  cls="technique", id = 7. child 指向下一级, 有1个子节点。

  3>  ObjectAbstractNode .

          name = "",  cls="pass", id = 8. child 指向下一级, 有4个子节点。

  4>  PropertyAbstractNode. 有3个,分别为 ambient, diffuse, specular

          name = "ambient",   id = 37. values 有4个值,指向下一级。

ObjectAbstractNode . 有一个,即纹理

name = "", cls="texture_unit", id = 9. child 指向下一级, 有1个子节点, 为PropertyAbstractNode,不再列举了。

5> AtomAbstractNode

value = "0.588235", id = 0.

3.2 做了2件事。

A 获得AbstractNode对应的ScriptTranslator:

ScriptTranslator *translator = ScriptCompilerManager::getSingleton().getTranslator(*i);

B 根据ScriptTranslator 生成 material。注意:生成的material各相关量保存在AbstractNode的Any类型的变量context中。

 

CSDN 真垃圾,编辑器现在又乱了,代码和普通文字已经区分不开。

 

 


 

	
				
		
原创粉丝点击