--- /dev/null
+#include <stdexcept>
+#include "misc.h"
+#include "texgen.h"
+#include "texunit.h"
+
+using namespace std;
+
+namespace Msp {
+namespace GL {
+
+TexGen::TexGen():
+ mode(EYE_LINEAR)
+{ }
+
+void TexGen::set_mode(TexGenMode m)
+{
+ mode = m;
+}
+
+void TexGen::set_plane(const Vector4 &p)
+{
+ plane = p;
+}
+
+void TexGen::bind_to(TexCoordComponent c) const
+{
+ if(TexUnit::current().set_texgen(coord_index(c), this))
+ {
+ glTexGeni(c, GL_TEXTURE_GEN_MODE, mode);
+ if(mode==EYE_LINEAR)
+ glTexGenfv(c, GL_EYE_PLANE, &plane.x);
+ else if(mode==OBJECT_LINEAR)
+ glTexGenfv(c, GL_OBJECT_PLANE, &plane.x);
+ enable(GL_TEXTURE_GEN_S+coord_index(c));
+ }
+}
+
+const TexGen *TexGen::current(TexCoordComponent c)
+{
+ return TexUnit::current().get_texgen(coord_index(c));
+}
+
+void TexGen::unbind_from(TexCoordComponent c)
+{
+ if(TexUnit::current().set_texgen(coord_index(c), 0))
+ disable(GL_TEXTURE_GEN_S+coord_index(c));
+}
+
+unsigned TexGen::coord_index(TexCoordComponent c)
+{
+ switch(c)
+ {
+ case SCOORD: return 0;
+ case TCOORD: return 1;
+ case RCOORD: return 2;
+ case QCOORD: return 3;
+ default: throw invalid_argument("TexGen::coord_index");
+ }
+}
+
+} // namespace GL
+} // namespace Msp
--- /dev/null
+#ifndef MSP_GL_TEXGEN_H_
+#define MSP_GL_TEXGEN_H_
+
+#include "gl.h"
+#include "vector.h"
+
+namespace Msp {
+namespace GL {
+
+enum TexCoordComponent
+{
+ SCOORD = GL_S,
+ TCOORD = GL_T,
+ RCOORD = GL_R,
+ QCOORD = GL_Q
+};
+
+enum TexGenMode
+{
+ EYE_LINEAR = GL_EYE_LINEAR,
+ OBJECT_LINEAR = GL_OBJECT_LINEAR,
+ REFLECTION_MAP = GL_REFLECTION_MAP,
+ NORMAL_MAP = GL_NORMAL_MAP
+};
+
+class TexGen
+{
+private:
+ TexGenMode mode;
+ Vector4 plane;
+
+public:
+ TexGen();
+
+ void set_mode(TexGenMode);
+ void set_plane(const Vector4 &);
+
+ void bind_to(TexCoordComponent) const;
+
+ static const TexGen *current(TexCoordComponent);
+ static void unbind_from(TexCoordComponent);
+private:
+ static unsigned coord_index(TexCoordComponent);
+};
+
+} // namespace GL
+} // namespace Msp
+
+#endif
TexUnit::TexUnit():
texture(0),
texenv(0)
-{ }
+{
+ fill(texgen, texgen+4, static_cast<const TexGen *>(0));
+}
bool TexUnit::set_texture(const Texture *tex)
{
return result;
}
+bool TexUnit::set_texgen(unsigned i, const TexGen *gen)
+{
+ if(i>=4)
+ throw invalid_argument("TexUnit::set_texgen");
+ bool result = (texgen[i]!=gen);
+ texgen[i] = gen;
+ return result;
+}
+
+const TexGen *TexUnit::get_texgen(unsigned i)
+{
+ if(i>=4)
+ throw invalid_argument("TexUnit::get_texgen");
+ return texgen[i];
+}
+
unsigned TexUnit::get_n_units()
{
static int count = -1;
namespace GL {
class TexEnv;
+class TexGen;
class Texture;
class TexUnit
private:
const Texture *texture;
const TexEnv *texenv;
+ const TexGen *texgen[4];
static std::vector<TexUnit> units;
static TexUnit *cur_unit;
const Texture *get_texture() const { return texture; }
bool set_texenv(const TexEnv *);
const TexEnv *get_texenv() const { return texenv; }
+ bool set_texgen(unsigned, const TexGen *);
+ const TexGen *get_texgen(unsigned);
static unsigned get_n_units();
static TexUnit &activate(unsigned);