Created
November 11, 2010 22:36
-
-
Save BlockoS/673341 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <pugixml.hpp> | |
#include <iostream> | |
#include <string.h> | |
#include <vector> | |
#include <unordered_map> | |
typedef int GLenum; | |
#define GL_NONE 0 | |
#define GL_TEXTURE_1D 1 | |
#define GL_TEXTURE_2D 2 | |
#define GL_TEXTURE_3D 3 | |
#define GL_TEXTURE_CUBE_MAP 4 | |
#define GL_TEXTURE_RECTANGLE 5 | |
#define GL_TEXTURE_1D_ARRAY 6 | |
#define GL_TEXTURE_2D_ARRAY 7 | |
#define GL_TEXTURE_BUFFER 8 | |
#define GL_TEXTURE_2D_MULTISAMPLE 9 | |
#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 10 | |
#define GL_CLAMP_TO_EDGE 11 | |
#define GL_CLAMP_TO_BORDER 12 | |
#define GL_MIRRORED_REPEAT 13 | |
#define GL_REPEAT 14 | |
#define GL_NEAREST 15 | |
#define GL_LINEAR 16 | |
#define GL_NEAREST_MIPMAP_NEAREST 17 | |
#define GL_LINEAR_MIPMAP_NEAREST 18 | |
#define GL_NEAREST_MIPMAP_LINEAR 19 | |
#define GL_LINEAR_MIPMAP_LINEAR 20 | |
class Hasherzor | |
{ | |
public: | |
typedef const pugi::char_t* _Kty; | |
size_t operator()(const _Kty& _Keyval) const | |
{ // hash _Keyval to size_t value by pseudorandomizing transform | |
size_t _Val = 2166136261U; | |
_Kty _Begin = _Keyval; | |
_Kty _End = _Keyval + strlen(_Keyval); | |
while (_Begin != _End) | |
_Val = 16777619U * _Val ^ (size_t)*_Begin++; | |
return (_Val); | |
} | |
}; | |
class Comparezor | |
{ | |
public: | |
typedef const pugi::char_t* _Kty; | |
bool operator() (const _Kty& left, const _Kty& right) const | |
{ | |
return !strcmp(left, right); | |
} | |
}; | |
template<typename T> | |
class ValueDictionary | |
{ | |
public: | |
ValueDictionary() {} | |
virtual ~ValueDictionary() | |
{ | |
if(!_dict.empty()) | |
{ | |
_dict.clear(); | |
} | |
} | |
void Set(const std::pair<const pugi::char_t*, T> *valueDict, int n) | |
{ | |
for(int i=0; i<n; i++) | |
{ | |
_dict.insert(valueDict[i]); | |
} | |
} | |
bool Get(const pugi::char_t *name, T& value) | |
{ | |
std::unordered_map<const pugi::char_t*, T>::iterator it = _dict.find(name); | |
if(it != _dict.end()) | |
{ | |
value = it->second; | |
return true; | |
} | |
return false; | |
} | |
bool Get(pugi::xml_attribute& attr, T& value, const T& defaultValue) | |
{ | |
value = defaultValue; | |
if(attr) | |
return Get(attr.value(), value); | |
return true; | |
} | |
protected: | |
std::unordered_map<const pugi::char_t*, T, Hasherzor, Comparezor> _dict; | |
}; | |
struct Filter | |
{ | |
GLenum min; | |
GLenum mag; | |
Filter() {} | |
Filter(const Filter& f) : | |
min(f.min), | |
mag(f.mag) | |
{} | |
Filter& operator=(const Filter& f) | |
{ | |
min = f.min; | |
mag = f.mag; | |
return *this; | |
} | |
}; | |
struct Wrap | |
{ | |
union | |
{ | |
struct | |
{ | |
GLenum s, t, r; | |
}; | |
GLenum param[3]; | |
}; | |
static const char *attrName[]; | |
static const int attrNameCount; | |
Wrap() {} | |
Wrap(const Wrap& w) : | |
s(w.s), | |
t(w.t), | |
r(w.r) | |
{} | |
Wrap& operator=(const Wrap& w) | |
{ | |
s = w.s; | |
t = w.t; | |
r = w.r; | |
return *this; | |
} | |
}; | |
struct Sampler | |
{ | |
GLenum type; | |
int level; | |
Filter filter; | |
Wrap wrap; | |
Sampler() {} | |
Sampler(const Sampler& s) : | |
type(s.type), | |
level(s.level), | |
filter(s.filter), | |
wrap(s.wrap) | |
{} | |
Sampler& operator=(const Sampler& s) | |
{ | |
type = s.type; | |
level = s.level; | |
filter = s.filter; | |
wrap = s.wrap; | |
return *this; | |
} | |
}; | |
class XMLFragmentReader | |
{ | |
public: | |
bool Init() | |
{ | |
std::pair<const pugi::char_t*, GLenum> samplerTypeTuples[] = | |
{ | |
std::pair<const pugi::char_t*, GLenum>("sampler1D", GL_TEXTURE_1D), | |
std::pair<const pugi::char_t*, GLenum>("sampler2D", GL_TEXTURE_2D), | |
std::pair<const pugi::char_t*, GLenum>("sampler3D", GL_TEXTURE_3D), | |
std::pair<const pugi::char_t*, GLenum>("samplerCube", GL_TEXTURE_CUBE_MAP), | |
std::pair<const pugi::char_t*, GLenum>("sampler2DRect", GL_TEXTURE_RECTANGLE), | |
std::pair<const pugi::char_t*, GLenum>("sampler1DArray", GL_TEXTURE_1D_ARRAY), | |
std::pair<const pugi::char_t*, GLenum>("sampler2DArray", GL_TEXTURE_2D_ARRAY), | |
std::pair<const pugi::char_t*, GLenum>("samplerBuffer", GL_TEXTURE_BUFFER), | |
std::pair<const pugi::char_t*, GLenum>("sampler2DMS", GL_TEXTURE_2D_MULTISAMPLE), | |
std::pair<const pugi::char_t*, GLenum>("sampler2DMSArray", GL_TEXTURE_2D_MULTISAMPLE_ARRAY), | |
std::pair<const pugi::char_t*, GLenum>("sampler1DShadow", GL_TEXTURE_1D), | |
std::pair<const pugi::char_t*, GLenum>("sampler2DShadow", GL_TEXTURE_2D), | |
std::pair<const pugi::char_t*, GLenum>("samplerCubeShadow", GL_TEXTURE_CUBE_MAP), | |
std::pair<const pugi::char_t*, GLenum>("sampler2DRectShadow", GL_TEXTURE_RECTANGLE), | |
std::pair<const pugi::char_t*, GLenum>("sampler1DArrayShadow", GL_TEXTURE_1D_ARRAY), | |
std::pair<const pugi::char_t*, GLenum>("sampler2DArrayShadow", GL_TEXTURE_2D_ARRAY) | |
}; | |
std::pair<const pugi::char_t*, GLenum> filterValueTuples[] = | |
{ | |
std::pair<const pugi::char_t*, GLenum>("NEAREST", GL_NEAREST), | |
std::pair<const pugi::char_t*, GLenum>("LINEAR", GL_LINEAR), | |
std::pair<const pugi::char_t*, GLenum>("NEAREST_MIPMAP_NEAREST", GL_NEAREST_MIPMAP_NEAREST), | |
std::pair<const pugi::char_t*, GLenum>("LINEAR_MIPMAP_NEAREST", GL_LINEAR_MIPMAP_NEAREST), | |
std::pair<const pugi::char_t*, GLenum>("NEAREST_MIPMAP_LINEAR", GL_NEAREST_MIPMAP_LINEAR), | |
std::pair<const pugi::char_t*, GLenum>("LINEAR_MIPMAP_LINEAR", GL_LINEAR_MIPMAP_LINEAR) | |
}; | |
std::pair<const pugi::char_t*, GLenum> wrapValueTuples[] = | |
{ | |
std::pair<const pugi::char_t*, GLenum>("CLAMP_TO_EDGE", GL_CLAMP_TO_EDGE), | |
std::pair<const pugi::char_t*, GLenum>("CLAMP_TO_BORDER", GL_CLAMP_TO_BORDER), | |
std::pair<const pugi::char_t*, GLenum>("REPEAT", GL_REPEAT), | |
std::pair<const pugi::char_t*, GLenum>("MIRRORED_REPEAT", GL_MIRRORED_REPEAT) | |
}; | |
m_samplerTypeDict.Set(samplerTypeTuples, sizeof(samplerTypeTuples)/sizeof(samplerTypeTuples[0])); | |
m_filterValueDict.Set(filterValueTuples, sizeof(filterValueTuples)/sizeof(filterValueTuples[0])); | |
m_wrapValueDict.Set(wrapValueTuples, sizeof(wrapValueTuples)/sizeof(wrapValueTuples[0])); | |
return true; | |
} | |
bool ParseSampler(pugi::xml_node& node) | |
{ | |
Sampler sampler; | |
if(!m_samplerTypeDict.Get(node.name(), sampler.type)) | |
{ | |
// TODO: Log_Error("Undefined sampler type: %s", node.name()); | |
return false; | |
} | |
pugi::xml_attribute attr = node.attribute("level"); | |
sampler.level = (attr ? attr.as_int() : 0); | |
attr = node.attribute("minFilter"); | |
if(!m_filterValueDict.Get(attr, sampler.filter.min, GL_NEAREST)) | |
{ | |
return false; | |
} | |
attr = node.attribute("magFilter"); | |
if(!m_filterValueDict.Get(attr, sampler.filter.mag, GL_NEAREST)) | |
{ | |
return false; | |
} | |
attr = node.attribute("wrapS"); | |
if(m_wrapValueDict.Get(attr, sampler.wrap.s, GL_CLAMP_TO_BORDER)) | |
{ | |
return false; | |
} | |
attr = node.attribute("wrapT"); | |
if(!m_wrapValueDict.Get(attr, sampler.wrap.t, GL_CLAMP_TO_BORDER)) | |
{ | |
return false; | |
} | |
attr = node.attribute("wrapR"); | |
if(!m_wrapValueDict.Get(attr, sampler.wrap.r, GL_CLAMP_TO_BORDER)) | |
{ | |
return false; | |
} | |
return true; | |
} | |
bool ParseSamplerList(pugi::xml_node& node) | |
{ | |
for(pugi::xml_node_iterator it=node.begin(); it!=node.end(); it++) | |
{ | |
if(!ParseSampler(*it)) | |
{} | |
} | |
return true; | |
} | |
protected: | |
ValueDictionary<GLenum> m_samplerTypeDict; | |
ValueDictionary<GLenum> m_filterValueDict; | |
ValueDictionary<GLenum> m_wrapValueDict; | |
}; | |
int main() | |
{ | |
pugi::xml_document doc; | |
pugi::xml_parse_result result = doc.load_file("frag.xml"); | |
std::cout << "Load result: " << result.description() << std::endl; | |
XMLFragmentReader fragmentReader; | |
fragmentReader.Init(); | |
pugi::xml_node samplerList = doc.child("samplerList"); | |
fragmentReader.ParseSamplerList(samplerList); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment