X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fobject.cpp;h=2026e3d58f3d0b658ed4b3bdba7fe9d211d6ffd1;hb=e77c027ce8efb5dafd93bdd0f77504218a955665;hp=78f445577caa54209044e3db4dc40dd1e33b5cec;hpb=b8b06a0ff96763ba7e188d9fcacbd8c0e3dcd515;p=libs%2Fgl.git diff --git a/source/object.cpp b/source/object.cpp index 78f44557..2026e3d5 100644 --- a/source/object.cpp +++ b/source/object.cpp @@ -14,6 +14,7 @@ Distributed under the LGPL #include "objectpass.h" #include "program.h" #include "programdata.h" +#include "technique.h" #include "texture.h" #include "texunit.h" @@ -24,66 +25,74 @@ namespace GL { Object::Object(): meshes(1, static_cast(0)), + technique(0), main_texture(0), material(0) -{ - normal_pass=&passes[0]; -} +{ } Object::~Object() { - for(map::iterator i=passes.begin(); i!=passes.end(); ++i) - delete i->second.shdata; } bool Object::has_pass(const Tag &tag) const { - return passes.count(tag.id); + if(technique) + return technique->has_pass(tag); + else + return tag.id==0; } -const ObjectPass &Object::get_pass(const Tag &tag) const +void Object::render(const Tag &tag) const { - map::const_iterator i=passes.find(tag.id); - if(i==passes.end()) - throw KeyError("Unknown pass"); - return i->second; + const ObjectPass *pass=get_pass(tag); + setup_render(pass); + meshes[0]->draw(); + finish_render(pass); } -void Object::render(const Tag &tag) const +void Object::render(const ObjectInstance &inst, const Tag &tag) const { - render(get_pass(tag), 0); + const ObjectPass *pass=get_pass(tag); + setup_render(pass); + render_instance(inst, tag); + meshes[0]->draw(); + finish_render(pass); } -void Object::render(const ObjectInstance &inst, const Tag &tag) const +const ObjectPass *Object::get_pass(const Tag &tag) const { - render(get_pass(tag), &inst); + if(technique) + return &technique->get_pass(tag); + else if(tag.id==0) + return 0; + throw KeyError("Unknown pass"); } -void Object::setup_render(const ObjectPass &pass) const +void Object::setup_render(const ObjectPass *pass) const { if(!meshes[0]) throw InvalidState("Trying to render Object without mesh"); - if(pass.shprog) + if(pass && pass->shprog) { - pass.shprog->bind(); - pass.shdata->apply(); + pass->shprog->bind(); + pass->shdata->apply(); for(unsigned i=0; ibind(); } } - else if(main_texture && pass.use_textures) + else if(main_texture && (!pass || pass->use_textures)) main_texture->bind(); if(material) - material->apply(); + material->bind(); } -void Object::finish_render(const ObjectPass &pass) const +void Object::finish_render(const ObjectPass *pass) const { - if(pass.shprog) + if(pass && pass->shprog) { Program::unbind(); for(unsigned i=textures.size(); i--;) @@ -94,26 +103,17 @@ void Object::finish_render(const ObjectPass &pass) const } else if(main_texture) Texture::unbind(); -} - -void Object::render(const ObjectPass &pass, const ObjectInstance *inst) const -{ - setup_render(pass); - - if(inst) - render_instance(pass, *inst); - else - meshes[0]->draw(); - finish_render(pass); + if(material) + Material::unbind(); } -void Object::render_instance(const ObjectPass &pass, const ObjectInstance &inst) const +void Object::render_instance(const ObjectInstance &inst, const Tag &tag) const { - inst.setup_render(pass); + inst.setup_render(tag); unsigned lod=min(inst.get_level_of_detail(), meshes.size()-1); meshes[lod]->draw(); - inst.finish_render(pass); + inst.finish_render(tag); } @@ -125,20 +125,24 @@ Object::Loader::Loader(Object &o, Collection &c): add("material", &Object::material); add("material_inline", &Loader::material_inline); add("mesh", &Loader::mesh); - add("pass", &Loader::pass); - add("shader", &Loader::shader); add("shader_texture", &Loader::shader_texture); + add("technique", &Loader::technique); add("texture", &Loader::texture); } void Object::Loader::finish() { - for(map::iterator i=obj.passes.begin(); i!=obj.passes.end(); ++i) - if(i->second.shdata) + if(obj.technique && !obj.main_texture) + obj.main_texture=obj.technique->get_main_texture(); + for(unsigned i=0; isecond.shdata->uniform(i->second.shprog->get_uniform_location(textures[j]), static_cast(j)); + obj.textures[i]=obj.technique->get_texture(i); + if(!obj.textures[i]) + throw Exception("Object does not specify all textures required by Technique"); } + } } void Object::Loader::lod_mesh(unsigned l, const string &n) @@ -151,7 +155,7 @@ void Object::Loader::material_inline() { RefPtr mat=new Material; load_sub(*mat); - coll.add(format("%p%p", &obj, mat.get()), mat.get()); + coll.add(format("_%p", mat.get()), mat.get()); obj.material=mat.release(); } @@ -160,44 +164,23 @@ void Object::Loader::mesh(const string &n) obj.meshes[0]=coll.get(n); } -void Object::Loader::pass(const string &n) +void Object::Loader::shader_texture(const string &n) { - unsigned id=Tag(n).id; - if(obj.passes.count(id)) - throw KeyError("Duplicate pass name"); - ObjectPass p; - load_sub(p, coll); - obj.passes[id]=p; -} + if(!obj.technique) + throw InvalidState("Can't specify shader textures without a Technique"); -void Object::Loader::shader(const string &n) -{ - Program *shprog=coll.get(n); - if(shprog) // Allow for unsupported shaders - { - RefPtr shdata=new ProgramData; - load_sub(*shdata, *shprog); + unsigned eqsign=n.find('='); + if(eqsign==string::npos) + throw InvalidParameterValue("Must specify texture slot name"); - obj.normal_pass->shprog=shprog; - if(obj.normal_pass->shdata) - delete obj.normal_pass->shdata; - obj.normal_pass->shdata=shdata.release(); - } + obj.textures[obj.technique->get_texture_index(n.substr(0, eqsign))]=coll.get(n.substr(eqsign+1)); } -void Object::Loader::shader_texture(const string &n) +void Object::Loader::technique(const string &n) { - unsigned eqsign=n.find('='); - if(eqsign!=string::npos) - { - obj.textures.push_back(coll.get(n.substr(eqsign+1))); - textures.push_back(n.substr(0, eqsign)); - } - else - { - obj.textures.push_back(coll.get(n)); - textures.push_back(n); - } + obj.technique=coll.get(n); + obj.textures.resize(obj.technique->get_n_textures()); + obj.material=obj.technique->get_material(); } void Object::Loader::texture(const string &n) @@ -205,9 +188,10 @@ void Object::Loader::texture(const string &n) if(obj.main_texture) throw Exception("Only one main texture may be specified"); - obj.main_texture=coll.get(n); - obj.textures.push_back(obj.main_texture); - textures.push_back("texture"); + Texture *tex=coll.get(n); + if(obj.technique) + obj.textures[obj.technique->get_texture_index("texture")]=tex; + obj.main_texture=tex; } } // namespace GL