OGRE 材质脚本解析的分析
2012-03-16 09:25
218 查看
material 08-Default { technique { pass { ambient 0.588235 0.588235 0.588235 1 diffuse 0.588235 0.588235 0.588235 1 specular 0 0 0 1 10 texture_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 the parsing input stream. */ struct ScriptToken { /// This is the lexeme for this token String lexeme, file; /// This is the id associated with the lexeme, which comes from a lexeme-token id mapping uint32 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 data public: 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 overriding public: 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 真垃圾,编辑器现在又乱了,代码和普通文字已经区分不开。
相关文章推荐
- Ogre材质解析代码初步分析(一)
- Ogre材质解析代码初步分析(六)
- Ogre材质解析代码初步分析(二)
- Ogre2.1 分析笔记(七) 材质脚本分析
- OGRE脚本解析流程分析--扫描阶段
- Ogre材质解析代码初步分析(三)
- Ogre材质解析代码初步分析(五)
- Ogre材质解析代码初步分析(四)
- 使用boost spirit库解析ogre材质脚本
- ogre中的材质脚本 (一)
- OGRE的材质脚本 (二)
- 每天花30分钟看OGRE--(13)Ogre的渲染流程,在渲染时材质是如何起作用的,材质加载和解析
- OGRE的材质脚本 (三)
- 利用Notepad++高亮Ogre 材质脚本 Ogre material script highlight in Notepad++
- Ogre材质脚本关健字说明
- OGRE的材质脚本 (三)
- Android系统Recovery工作原理之使用update.zip升级过程分析(八)---解析并执行升级脚本updater-script
- OGRE的材质脚本 (四)
- 包管理系统分析 包管理脚本 /system/bin/pm 解析:
- OGRE中的材质脚本