Skip to content

Instantly share code, notes, and snippets.

@BlockoS
Created November 11, 2010 22:36
Show Gist options
  • Save BlockoS/673341 to your computer and use it in GitHub Desktop.
Save BlockoS/673341 to your computer and use it in GitHub Desktop.
#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