您的位置:首页 > 其它

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 真垃圾,编辑器现在又乱了,代码和普通文字已经区分不开。





                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: