]> git.tdb.fi Git - libs/gl.git/commitdiff
Allow copying of Uniforms and ProgramData
authorMikko Rasa <tdb@tdb.fi>
Fri, 12 Feb 2010 15:50:13 +0000 (15:50 +0000)
committerMikko Rasa <tdb@tdb.fi>
Fri, 12 Feb 2010 15:50:13 +0000 (15:50 +0000)
Use typedefs in Scene for shorter code and to avoid collisions with GL::set
Major rework of Object and Technique

14 files changed:
source/object.cpp
source/object.h
source/objectpass.cpp [deleted file]
source/objectpass.h [deleted file]
source/programdata.cpp
source/programdata.h
source/renderpass.cpp [new file with mode: 0644]
source/renderpass.h [new file with mode: 0644]
source/scene.cpp
source/scene.h
source/technique.cpp
source/technique.h
source/uniform.cpp
source/uniform.h

index f2d1f8bf74a9781c64d829e2f7950513296dbae1..edfe39e56008e580e85b292c7508395260de9e71 100644 (file)
@@ -25,94 +25,43 @@ namespace Msp {
 namespace GL {
 
 Object::Object():
-       meshes(1, static_cast<Mesh *>(0)),
-       technique(0),
-       main_texture(0),
-       material(0)
+       meshes(1),
+       own_technique(false),
+       technique(0)
 { }
 
 Object::~Object()
 {
+       if(own_technique)
+               delete technique;
 }
 
 void Object::render(const Tag &tag) const
 {
-       if(!can_render(tag))
+       const RenderPass *pass=get_pass(tag);
+       if(!pass)
                return;
 
-       const ObjectPass *pass=get_pass(tag);
-       setup_render(pass);
+       Bind bind(*pass);
        meshes[0]->draw();
-       finish_render(pass);
 }
 
 void Object::render(const ObjectInstance &inst, const Tag &tag) const
 {
-       if(!can_render(tag))
+       const RenderPass *pass=get_pass(tag);
+       if(!pass)
                return;
 
-       const ObjectPass *pass=get_pass(tag);
-       setup_render(pass);
+       Bind bind(*pass);
        render_instance(inst, tag);
        meshes[0]->draw();
-       finish_render(pass);
 }
 
-bool Object::can_render(const Tag &tag) const
+const RenderPass *Object::get_pass(const Tag &tag) const
 {
-       if(technique)
-               return technique->has_pass(tag);
-       else
-               return tag.id==0;
-}
-
-const ObjectPass *Object::get_pass(const Tag &tag) const
-{
-       if(technique)
-               return &technique->get_pass(tag);
-       else if(tag.id==0)
+       if(!technique->has_pass(tag))
                return 0;
-       throw KeyError("Unknown pass");
-}
-
-void Object::setup_render(const ObjectPass *pass) const
-{
-       if(!meshes[0])
-               throw InvalidState("Trying to render Object without mesh");
-
-       if(pass && pass->shprog)
-       {
-               pass->shprog->bind();
-               pass->shdata->apply();
-               for(unsigned i=0; i<textures.size(); ++i)
-               {
-                       TexUnit::activate(i);
-                       textures[i]->bind();
-               }
-       }
-       else if(main_texture && (!pass || pass->use_textures))
-               main_texture->bind();
-
-       if(material)
-               material->bind();
-}
-
-void Object::finish_render(const ObjectPass *pass) const
-{
-       if(pass && pass->shprog)
-       {
-               Program::unbind();
-               for(unsigned i=textures.size(); i--;)
-               {
-                       TexUnit::activate(i);
-                       Texture::unbind();
-               }
-       }
-       else if(main_texture)
-               Texture::unbind();
-
-       if(material)
-               Material::unbind();
+       return &technique->get_pass(tag);
 }
 
 void Object::render_instance(const ObjectInstance &inst, const Tag &tag) const
@@ -128,76 +77,28 @@ Object::Loader::Loader(Object &o, Collection &c):
        DataFile::CollectionObjectLoader<Object>(o, &c)
 {
        add("lod_mesh", &Loader::lod_mesh);
-       add("material", &Object::material);
-       add("material_inline", &Loader::material_inline);
        add("mesh",     &Loader::mesh);
-       add("shader_texture", &Loader::shader_texture);
        add("technique", &Loader::technique);
-       add("texture",  &Loader::texture);
-}
-
-void Object::Loader::finish()
-{
-       if(obj.technique && !obj.main_texture)
-               obj.main_texture=obj.technique->get_main_texture();
-       for(unsigned i=0; i<obj.textures.size(); ++i)
-       {
-               if(!obj.textures[i])
-               {
-                       obj.textures[i]=obj.technique->get_texture(i);
-                       if(!obj.textures[i])
-                               throw Exception("Object does not specify all textures required by Technique");
-               }
-       }
+       add("technique", &Object::technique);
 }
 
 void Object::Loader::lod_mesh(unsigned l, const string &n)
 {
        obj.meshes.resize(l+1, 0);
-       obj.meshes[l]=coll->get<Mesh>(n);
-}
-
-void Object::Loader::material_inline()
-{
-       RefPtr<Material> mat=new Material;
-       load_sub(*mat);
-       coll->add(format("_%p", mat.get()), mat.get());
-       obj.material=mat.release();
+       obj.meshes[l]=get_collection().get<Mesh>(n);
 }
 
 void Object::Loader::mesh(const string &n)
 {
-       obj.meshes[0]=coll->get<Mesh>(n);
-}
-
-void Object::Loader::shader_texture(const string &n)
-{
-       if(!obj.technique)
-               throw InvalidState("Can't specify shader textures without a Technique");
-
-       string::size_type eqsign=n.find('=');
-       if(eqsign==string::npos)
-               throw InvalidParameterValue("Must specify texture slot name");
-
-       obj.textures[obj.technique->get_texture_index(n.substr(0, eqsign))]=coll->get<Texture>(n.substr(eqsign+1));
-}
-
-void Object::Loader::technique(const string &n)
-{
-       obj.technique=coll->get<Technique>(n);
-       obj.textures.resize(obj.technique->get_n_textures());
-       obj.material=obj.technique->get_material();
+       obj.meshes[0]=get_collection().get<Mesh>(n);
 }
 
-void Object::Loader::texture(const string &n)
+void Object::Loader::technique()
 {
-       if(obj.main_texture)
-               throw Exception("Only one main texture may be specified");
-
-       Texture *tex=coll->get<Texture>(n);
-       if(obj.technique)
-               obj.textures[obj.technique->get_texture_index("texture")]=tex;
-       obj.main_texture=tex;
+       RefPtr<Technique> tch=new Technique;
+       load_sub(*tch, get_collection());
+       obj.technique=tch.release();
+       obj.own_technique=true;
 }
 
 } // namespace GL
index bf4a05249436f5453ec678a274431958597a61fb..d81c4ade6fa0453aadbd5fd27cb5a212204df36d 100644 (file)
@@ -9,6 +9,7 @@ Distributed under the LGPL
 #define MSP_GL_OBJECT_H_
 
 #include <vector>
+#include "misc.h"
 #include "objectpass.h"
 #include "renderable.h"
 
@@ -22,10 +23,7 @@ class Technique;
 class Texture;
 
 /**
-Stores data for a complete 3D object.  An Object must always have a Mesh, and
-may also have a Technique to determine its appearance.  Textures and material
-specified by the Technique may be overridden.  Simple textured objects are also
-possible without a Technique.
+Stores a Mesh together with a Technique to determine its appearance.
 
 It is possible to use a single Object for rendering multiple identical or
 similar objects.  See class ObjectInstance.
@@ -34,10 +32,8 @@ class Object: public Renderable
 {
 private:
        std::vector<const Mesh *> meshes;
+       bool own_technique;
        const Technique *technique;
-       std::vector<const Texture *> textures;
-       const Texture *main_texture;
-       const Material *material;
 
 public:
        class Loader: public DataFile::CollectionObjectLoader<Object>
@@ -46,13 +42,9 @@ public:
                Loader(Object &, Collection &);
 
        private:
-               virtual void finish();
                void lod_mesh(unsigned, const std::string &);
-               void material_inline();
                void mesh(const std::string &);
-               void shader_texture(const std::string &);
-               void technique(const std::string &);
-               void texture(const std::string &);
+               void technique();
        };
 
        Object();
@@ -81,20 +73,16 @@ public:
        template<typename Iter>
        void render(Iter begin, Iter end, const Tag &tag=Tag()) const
        {
-               if(!can_render(tag))
+               const RenderPass *pass=get_pass(tag);
+               if(!pass)
                        return;
 
-               const ObjectPass *pass=get_pass(tag);
-               setup_render(pass);
+               Bind bind(*pass);
                for(Iter i=begin; i!=end; ++i)
                        render_instance(**i, tag);
-               finish_render(pass);
        }
 private:
-       bool can_render(const Tag &) const;
-       const ObjectPass *get_pass(const Tag &) const;
-       void setup_render(const ObjectPass *) const;
-       void finish_render(const ObjectPass *) const;
+       const RenderPass *get_pass(const Tag &) const;
        void render_instance(const ObjectInstance &, const Tag &) const;
 };
 
diff --git a/source/objectpass.cpp b/source/objectpass.cpp
deleted file mode 100644 (file)
index 01a6c2e..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/* $Id$
-
-This file is part of libmspgl
-Copyright © 2007  Mikko Rasa, Mikkosoft Productions
-Distributed under the LGPL
-*/
-
-#include <msp/datafile/collection.h>
-#include "objectpass.h"
-#include "program.h"
-#include "programdata.h"
-
-using namespace std;
-
-namespace Msp {
-namespace GL {
-
-ObjectPass::ObjectPass():
-       shprog(0),
-       shdata(0),
-       use_textures(true)
-{ }
-
-ObjectPass::~ObjectPass()
-{
-}
-
-
-ObjectPass::Loader::Loader(ObjectPass &p, Collection &c):
-       DataFile::CollectionObjectLoader<ObjectPass>(p, &c)
-{
-       add("shader", &Loader::shader);
-       add("use_textures", &ObjectPass::use_textures);
-}
-
-void ObjectPass::Loader::shader(const string &n)
-{
-       Program *shprog=coll->get<Program>(n);
-       if(shprog)  // Allow for unsupported shaders
-       {
-               RefPtr<ProgramData> shdata=new ProgramData;
-               load_sub(*shdata, *shprog);
-
-               obj.shprog=shprog;
-               if(obj.shdata)
-                       delete obj.shdata;
-               obj.shdata=shdata.release();
-       }
-}
-
-} // namespace GL
-} // namespace Msp
diff --git a/source/objectpass.h b/source/objectpass.h
deleted file mode 100644 (file)
index e3cac70..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/* $Id$
-
-This file is part of libmspgl
-Copyright © 2007  Mikko Rasa, Mikkosoft Productions
-Distributed under the LGPL
-*/
-
-#ifndef MSP_GL_OBJECTPASS_H_
-#define MSP_GL_OBJECTPASS_H_
-
-#include <msp/datafile/objectloader.h>
-
-namespace Msp {
-namespace GL {
-
-class Program;
-class ProgramData;
-
-struct ObjectPass
-{
-       class Loader: public DataFile::CollectionObjectLoader<ObjectPass>
-       {
-       public:
-               Loader(ObjectPass &, Collection &);
-       private:
-               void shader(const std::string &);
-       };
-
-       Program *shprog;
-       ProgramData *shdata;
-       bool use_textures;
-
-       ObjectPass();
-       ~ObjectPass();
-};
-
-} // namespace GL
-} // namespace Msp
-
-#endif
index 9acb93bc4d8701361458e4c20956d88b3e36bb21..cc75f28d16cab4bbb0ad8fed7d4819d073908adf 100644 (file)
@@ -20,6 +20,13 @@ ProgramData::ProgramData()
        static RequireExtension _ext("GL_ARB_shader_objects");
 }
 
+ProgramData::ProgramData(const ProgramData &other):
+       data(other.data)
+{
+       for(map<int, Uniform *>::iterator i=data.begin(); i!=data.end(); ++i)
+               i->second=i->second->clone();
+}
+
 ProgramData::~ProgramData()
 {
        for(map<int, Uniform *>::iterator i=data.begin(); i!=data.end(); ++i)
index 591ffee347f7dfe6bf97a3e1ef9b9772f87c101a..51ecc579a2582fcfedbcc72e86cb04961e909194 100644 (file)
@@ -41,10 +41,10 @@ public:
 private:
        std::map<int, Uniform *> data;
 
-       ProgramData(const ProgramData &);
        ProgramData &operator=(const ProgramData &);
 public:
        ProgramData();
+       ProgramData(const ProgramData &);
        ~ProgramData();
 
        void uniform(int, Uniform *);
diff --git a/source/renderpass.cpp b/source/renderpass.cpp
new file mode 100644 (file)
index 0000000..d2fe668
--- /dev/null
@@ -0,0 +1,192 @@
+/* $Id$
+
+This file is part of libmspgl
+Copyright © 2007  Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#include <msp/core/refptr.h>
+#include <msp/datafile/collection.h>
+#include <msp/strings/formatter.h>
+#include "material.h"
+#include "renderpass.h"
+#include "program.h"
+#include "programdata.h"
+#include "texture.h"
+
+using namespace std;
+
+namespace Msp {
+namespace GL {
+
+const RenderPass *RenderPass::current=0;
+
+RenderPass::RenderPass():
+       shprog(0),
+       shdata(0),
+       own_material(false),
+       material(0)
+{ }
+
+RenderPass::RenderPass(const RenderPass &other):
+       shprog(other.shprog),
+       shdata(other.shdata ? new ProgramData(*other.shdata) : 0),
+       own_material(other.own_material),
+       material(own_material ? new Material(*other.material) : other.material),
+       textures(other.textures)
+{ }
+
+/*RenderPass &RenderPass::operator=(const RenderPass &other)
+{
+       shprog=other.shprog;
+       delete shdata;
+       shdata=(other.shdata ? new ProgramData(*other.shdata) : 0);
+       material=other.material;
+       use_material=other.use_material;
+       textures=other.textures;
+       use_textures=other.use_textures;
+
+       return *this;
+}*/
+
+RenderPass::~RenderPass()
+{
+       delete shdata;
+       if(own_material)
+               delete material;
+}
+
+void RenderPass::set_material(const Material *mat)
+{
+       material=mat;
+}
+
+unsigned RenderPass::get_texture_index(const string &slot) const
+{
+       for(unsigned i=0; i<textures.size(); ++i)
+               if(textures[i].name==slot)
+                       return i;
+
+       throw KeyError("Unknown texture slot", slot);
+}
+
+void RenderPass::set_texture(const string &slot, const Texture *tex)
+{
+       textures[get_texture_index(slot)]=tex;
+}
+
+void RenderPass::bind() const
+{
+       if(this==current)
+               return;
+
+       const RenderPass *old=current;
+       current=this;
+
+       if(shprog)
+       {
+               shprog->bind();
+               shdata->apply();
+       }
+       else if(old && !old->shprog)
+               GL::Program::unbind();
+
+       if(material)
+               material->bind();
+       else if(old && !old->material)
+               GL::Material::unbind();
+
+       for(unsigned i=0; i<textures.size(); ++i)
+               if(textures[i].texture)
+                       textures[i].texture->bind_to(i);
+       if(old)
+       {
+               for(unsigned i=textures.size(); i<old->textures.size(); ++i)
+                       GL::Texture::unbind_from(i);
+       }
+}
+
+void RenderPass::unbind()
+{
+       if(current)
+       {
+               if(current->shprog)
+                       GL::Program::unbind();
+
+               if(current->material)
+                       GL::Material::unbind();
+
+               for(unsigned i=current->textures.size(); i--; )
+                       GL::Texture::unbind_from(i);
+
+               current=0;
+       }
+}
+
+
+RenderPass::Loader::Loader(RenderPass &p, Collection &c):
+       DataFile::CollectionObjectLoader<RenderPass>(p, &c)
+{
+       add("shader",   &RenderPass::shprog);
+       add("material", &Loader::material);
+       add("material", &RenderPass::material);
+       add("texture",  &Loader::texture);
+       add("uniforms", &Loader::uniforms);
+}
+
+void RenderPass::Loader::finish()
+{
+       if(obj.shprog)
+       {
+               if(!obj.shdata)
+                       obj.shdata=new ProgramData;
+
+               for(unsigned i=0; i<obj.textures.size(); ++i)
+               {
+                       unsigned loc=obj.shprog->get_uniform_location(obj.textures[i].name);
+                       obj.shdata->uniform(loc, static_cast<int>(i));
+               }
+       }
+}
+
+void RenderPass::Loader::material()
+{
+       // XXX Potential memory management trouble with multiple material statements
+       RefPtr<Material> mat=new Material;
+       load_sub(*mat);
+       obj.material=mat.release();
+       obj.own_material=true;
+}
+
+void RenderPass::Loader::texture(const string &n)
+{
+       const Texture *tex=(n.empty() ? 0 : get_collection().get<Texture>(n));
+       TextureSlot slot(tex);
+       slot.name=(obj.textures.empty() ? "texture" : format("texture%d", obj.textures.size()));
+       load_sub(slot);
+       obj.textures.push_back(slot);
+}
+
+void RenderPass::Loader::uniforms()
+{
+       if(!obj.shprog)
+               throw InvalidState("Can't load uniforms without a shader program");
+       if(!obj.shdata)
+               obj.shdata=new ProgramData;
+       load_sub(*obj.shdata, *obj.shprog);
+}
+
+
+RenderPass::TextureSlot::TextureSlot(const Texture *t):
+       texture(t)
+{ }
+
+
+RenderPass::TextureSlot::Loader::Loader(TextureSlot &s):
+       DataFile::ObjectLoader<TextureSlot>(s)
+{
+       add("name", &TextureSlot::name);
+}
+
+} // namespace GL
+} // namespace Msp
diff --git a/source/renderpass.h b/source/renderpass.h
new file mode 100644 (file)
index 0000000..223f57d
--- /dev/null
@@ -0,0 +1,82 @@
+/* $Id$
+
+This file is part of libmspgl
+Copyright © 2007-2008, 2010  Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#ifndef MSP_GL_RENDERPASS_H_
+#define MSP_GL_RENDERPASS_H_
+
+#include <msp/datafile/objectloader.h>
+
+namespace Msp {
+namespace GL {
+
+class Material;
+class Program;
+class ProgramData;
+class Texture;
+
+/**
+Encapsulates the data that determines the appearance of a rendered surface.
+This includes shader and data for it, material and textures.
+*/
+class RenderPass
+{
+public:
+       class Loader: public DataFile::CollectionObjectLoader<RenderPass>
+       {
+       public:
+               Loader(RenderPass &, Collection &);
+
+       private:
+               virtual void finish();
+               void material();
+               void shader(const std::string &);
+               void texture(const std::string &);
+               void uniforms();
+       };
+
+private:
+       struct TextureSlot
+       {
+               class Loader: public DataFile::ObjectLoader<TextureSlot>
+               {
+               public:
+                       Loader(TextureSlot &);
+               };
+
+               const Texture *texture;
+               std::string name;
+
+               TextureSlot(const Texture *);
+       };
+
+       Program *shprog;
+       ProgramData *shdata;
+       bool own_material;
+       const Material *material;
+       std::vector<TextureSlot> textures;
+
+       static const RenderPass *current;
+
+       RenderPass &operator=(const RenderPass &);
+public:
+       RenderPass();
+       RenderPass(const RenderPass &);
+       ~RenderPass();
+
+       void set_material(const Material *);
+       unsigned get_texture_index(const std::string &) const;
+       void set_texture(const std::string &, const Texture *);
+
+       void bind() const;
+
+       static void unbind();
+};
+
+} // namespace GL
+} // namespace Msp
+
+#endif
index c28192d407fe529ae2e258700d32243cee654e32..28b794b035c5b3da61bf4cd9e92363607a5b771a 100644 (file)
@@ -9,8 +9,6 @@ Distributed under the LGPL
 #include "objectinstance.h"
 #include "scene.h"
 
-using namespace std;
-
 namespace Msp {
 namespace GL {
 
@@ -26,7 +24,7 @@ void Scene::remove(const Renderable &r)
 {
        if(const ObjectInstance *oi=dynamic_cast<const ObjectInstance *>(&r))
        {
-               map<const Object *, set<const ObjectInstance *> >::iterator i=objects.find(&oi->get_object());
+               ObjectMap::iterator i=objects.find(&oi->get_object());
                if(i!=objects.end())
                {
                        i->second.erase(oi);
@@ -40,10 +38,10 @@ void Scene::remove(const Renderable &r)
 
 void Scene::render(const Tag &tag) const
 {
-       for(map<const Object *, set<const ObjectInstance *> >::const_iterator i=objects.begin(); i!=objects.end(); ++i)
+       for(ObjectMap::const_iterator i=objects.begin(); i!=objects.end(); ++i)
                i->first->render(i->second.begin(), i->second.end(), tag);
 
-       for(set<const Renderable *>::const_iterator i=renderables.begin(); i!=renderables.end(); ++i)
+       for(RenderableSet::const_iterator i=renderables.begin(); i!=renderables.end(); ++i)
                (*i)->render(tag);
 }
 
index 05c5b6785b3bf53cb2de92c2d45ee180c85bbc0e..6a4be91d9f77a75a06017f572c5e214e13abb0cd 100644 (file)
@@ -21,8 +21,12 @@ class ObjectInstance;
 class Scene: public Renderable
 {
 private:
-       std::map<const Object *, std::set<const ObjectInstance *> > objects;
-       std::set<const Renderable *> renderables;
+       typedef std::set<const ObjectInstance *> InstanceSet;
+       typedef std::map<const Object *, InstanceSet> ObjectMap;
+       typedef std::set<const Renderable *> RenderableSet;
+
+       ObjectMap objects;
+       RenderableSet renderables;
 
 public:
        void add(const Renderable &);
index 26837b61533167e0ddc268715f2722aee008272e..78060e01f9b89e80e28f7171fc40cea23188d327 100644 (file)
@@ -20,24 +20,12 @@ using namespace std;
 namespace Msp {
 namespace GL {
 
-Technique::Technique():
-       main_texture(0),
-       normal_pass(&passes[0]),
-       material(0)
-{ }
-
-Technique::~Technique()
-{
-       for(PassMap::iterator i=passes.begin(); i!=passes.end(); ++i)
-               delete i->second.shdata;
-}
-
 bool Technique::has_pass(const GL::Tag &tag) const
 {
        return passes.count(tag);
 }
 
-const ObjectPass &Technique::get_pass(const GL::Tag &tag) const
+const RenderPass &Technique::get_pass(const GL::Tag &tag) const
 {
        PassMap::const_iterator i=passes.find(tag);
        if(i==passes.end())
@@ -45,55 +33,19 @@ const ObjectPass &Technique::get_pass(const GL::Tag &tag) const
        return i->second;
 }
 
-unsigned Technique::get_texture_index(const std::string &n) const
-{
-       for(unsigned i=0; i<textures.size(); ++i)
-               if(textures[i].name==n)
-                       return i;
-
-       throw KeyError("Unknown texture slot", n);
-}
-
-const Texture *Technique::get_texture(unsigned i) const
-{
-       if(i>=textures.size())
-               throw KeyError("Texture index out of range");
-
-       return textures[i].texture;
-}
-
 
 Technique::Loader::Loader(Technique &t, Collection &c):
        DataFile::CollectionObjectLoader<Technique>(t, &c)
 {
-       add("material",        &Technique::material);
-       add("material_inline", &Loader::material_inline);
-       add("pass",            &Loader::pass);
-       add("shader",          &Loader::shader);
-       add("shader_texture",  &Loader::shader_texture);
-       add("texture",         &Loader::texture);
-       add("texture_slot",    &Loader::texture_slot);
-}
-
-void Technique::Loader::finish()
-{
-       for(PassMap::iterator i=obj.passes.begin(); i!=obj.passes.end(); ++i)
-               if(i->second.shdata)
-               {
-                       for(unsigned j=0; j<obj.textures.size(); ++j)
-                       {
-                               unsigned loc=i->second.shprog->get_uniform_location(obj.textures[j].name);
-                               i->second.shdata->uniform(loc, static_cast<int>(j));
-                       }
-               }
+       add("inherit", &Loader::inherit);
+       add("pass", &Loader::pass);
 }
 
-void Technique::Loader::material_inline()
+void Technique::Loader::inherit(const string &n)
 {
-       RefPtr<Material> mat=new Material;
-       load_sub(*mat);
-       coll->add(format("_%p", mat.get()), mat.get());
-       obj.material=mat.release();
+       obj.passes=get_collection().get<Technique>(n)->get_passes();
+       InheritLoader ldr(obj, get_collection());
+       load_sub_with(ldr);
 }
 
 void Technique::Loader::pass(const string &n)
@@ -101,64 +53,31 @@ void Technique::Loader::pass(const string &n)
        Tag tag(n);
        if(obj.passes.count(tag))
                throw KeyError("Duplicate pass name", n);
-       ObjectPass p;
+
+       RenderPass p;
        load_sub(p, *coll);
-       obj.passes[tag]=p;
+       obj.passes.insert(PassMap::value_type(tag, p));
 }
 
-void Technique::Loader::shader(const string &n)
-{
-       Program *shprog=coll->get<Program>(n);
-       if(shprog)  // Allow for unsupported shaders
-       {
-               RefPtr<ProgramData> shdata=new ProgramData;
-               load_sub(*shdata, *shprog);
 
-               obj.normal_pass->shprog=shprog;
-               if(obj.normal_pass->shdata)
-                       delete obj.normal_pass->shdata;
-               obj.normal_pass->shdata=shdata.release();
-       }
+Technique::InheritLoader::InheritLoader(Technique &t, Collection &c):
+       DataFile::CollectionObjectLoader<Technique>(t, &c)
+{
+       add("texture", &InheritLoader::texture);
 }
 
-void Technique::Loader::shader_texture(const string &n)
+void Technique::InheritLoader::texture(const string &slot, const string &name)
 {
-       string::size_type eqsign=n.find('=');
-       TextureSlot tex;
-       if(eqsign!=string::npos)
-       {
-               tex.name=n.substr(0, eqsign);
-               tex.texture=coll->get<Texture>(n.substr(eqsign+1));
-       }
-       else
+       Texture *tex=get_collection().get<Texture>(name);
+       for(PassMap::iterator i=obj.passes.begin(); i!=obj.passes.end(); ++i)
        {
-               string::size_type dot=n.rfind('.');
-               tex.name=n.substr(0, dot);
-               tex.texture = coll->get<Texture>(n);
+               try
+               {
+                       i->second.set_texture(slot, tex);
+               }
+               catch(const KeyError &)
+               { }
        }
-       for(string::iterator i=tex.name.begin(); i!=tex.name.end(); ++i)
-               if(!isalnum(*i))
-                       *i='_';
-       obj.textures.push_back(tex);
-}
-
-void Technique::Loader::texture(const string &n)
-{
-       if(obj.main_texture)
-               throw Exception("Only one main texture may be specified");
-
-       obj.main_texture=coll->get<Texture>(n);
-       TextureSlot tex;
-       tex.name="texture";
-       tex.texture=obj.main_texture;
-       obj.textures.push_back(tex);
-}
-
-void Technique::Loader::texture_slot(const string &n)
-{
-       TextureSlot tex;
-       tex.name=n;
-       obj.textures.push_back(tex);
 }
 
 } // namespace GL
index 3bb347ea4c98b9bb535cf132ec68dbb429383b4c..cc81b53120d3d9c408964902d8727d5bc0edd012 100644 (file)
@@ -18,9 +18,6 @@ class Tag;
 class Texture;
 
 /**
-Stores a complete multipass rendering technique for an Object.  This includes
-shaders, textures and a material.  A Technique can also specify empty texture
-slots which Objects must override.
 */
 class Technique
 {
@@ -31,43 +28,28 @@ public:
                Loader(Technique &, Collection &);
 
        private:
-               virtual void finish();
-               void material_inline();
+               void inherit(const std::string &);
                void pass(const std::string &);
-               void shader(const std::string &);
-               void shader_texture(const std::string &);
-               void texture(const std::string &);
-               void texture_slot(const std::string &);
        };
 
 private:
-       struct TextureSlot
+       class InheritLoader: public Msp::DataFile::CollectionObjectLoader<Technique>
        {
-               std::string name;
-               const Texture *texture;
-
-               TextureSlot(): texture(0) { }
+       public:
+               InheritLoader(Technique &, Collection &);
+       
+       private:
+               void texture(const std::string &, const std::string &);
        };
 
-       typedef std::map<Tag, ObjectPass> PassMap;
+       typedef std::map<Tag, RenderPass> PassMap;
 
-       std::vector<TextureSlot> textures;
-       const Texture *main_texture;
        PassMap passes;
-       ObjectPass *normal_pass;
-       const Material *material;
 
 public:
-       Technique();
-       ~Technique();
-
        bool has_pass(const GL::Tag &) const;
-       const ObjectPass &get_pass(const GL::Tag &) const;
-       unsigned get_n_textures() const { return textures.size(); }
-       unsigned get_texture_index(const std::string &) const;
-       const Texture *get_texture(unsigned) const;
-       const Texture *get_main_texture() const { return main_texture; }
-       const Material *get_material() const { return material; }
+       const RenderPass &get_pass(const GL::Tag &) const;
+       const PassMap &get_passes() const { return passes; }
 };
 
 } // namespace GL
index 88c42d377067f73fbde380164b7acad458b6cdf7..8ed1336e4d05268ded65f707ddd0f64f3baad3b7 100644 (file)
@@ -20,6 +20,11 @@ void Uniform1i::apply(int index) const
        glUniform1iARB(index, v);
 }
 
+Uniform1i *Uniform1i::clone() const
+{
+       return new Uniform1i(v);
+}
+
 
 Uniform1f::Uniform1f(float v_):
        v(v_)
@@ -30,6 +35,11 @@ void Uniform1f::apply(int index) const
        glUniform1fARB(index, v);
 }
 
+Uniform1f *Uniform1f::clone() const
+{
+       return new Uniform1f(v);
+}
+
 
 Uniform2f::Uniform2f(float v0, float v1)
 {
@@ -42,6 +52,11 @@ void Uniform2f::apply(int index) const
        glUniform2fvARB(index, 1, v);
 }
 
+Uniform2f *Uniform2f::clone() const
+{
+       return new Uniform2f(v[0], v[1]);
+}
+
 
 Uniform3f::Uniform3f(float v0, float v1, float v2)
 {
@@ -55,6 +70,11 @@ void Uniform3f::apply(int index) const
        glUniform3fvARB(index, 1, v);
 }
 
+Uniform3f *Uniform3f::clone() const
+{
+       return new Uniform3f(v[0], v[1], v[2]);
+}
+
 
 Uniform4f::Uniform4f(float v0, float v1, float v2, float v3)
 {
@@ -69,5 +89,10 @@ void Uniform4f::apply(int index) const
        glUniform4fvARB(index, 1, v);
 }
 
+Uniform4f *Uniform4f::clone() const
+{
+       return new Uniform4f(v[0], v[1], v[2], v[3]);
+}
+
 } // namespace GL
 } // namespace Msp
index e6b4ca3a0ffa1dd7c97a2959d44dcd929aa9fa79..ac73e99db01347c6de3edcdabf048d9e3916bc47 100644 (file)
@@ -17,10 +17,14 @@ class Uniform
 {
 protected:
        Uniform() { }
+private:
+       Uniform(const Uniform &);
+       Uniform &operator=(const Uniform &);
 public:
        virtual ~Uniform() { }
 
        virtual void apply(int) const =0;
+       virtual Uniform *clone() const =0;
 };
 
 
@@ -31,7 +35,9 @@ private:
 
 public:
        Uniform1i(int v_);
+
        virtual void apply(int index) const;
+       virtual Uniform1i *clone() const;
 };
 
 
@@ -42,7 +48,9 @@ private:
 
 public:
        Uniform1f(float v_);
+
        virtual void apply(int index) const;
+       virtual Uniform1f *clone() const;
 };
 
 
@@ -53,7 +61,9 @@ private:
 
 public:
        Uniform2f(float v0, float v1);
+
        virtual void apply(int index) const;
+       virtual Uniform2f *clone() const;
 };
 
 
@@ -64,7 +74,9 @@ private:
 
 public:
        Uniform3f(float v0, float v1, float v2);
+
        virtual void apply(int index) const;
+       virtual Uniform3f *clone() const;
 };
 
 
@@ -75,7 +87,9 @@ private:
 
 public:
        Uniform4f(float v0, float v1, float v2, float v3);
+
        virtual void apply(int index) const;
+       virtual Uniform4f *clone() const;
 };
 
 } // namespace GL