3 This file is part of libmspgl
4 Copyright © 2007 Mikko Rasa, Mikkosoft Productions
5 Distributed under the LGPL
8 #include <msp/datafile/collection.h>
9 #include <msp/strings/formatter.h>
14 #include "objectinstance.h"
15 #include "objectpass.h"
17 #include "programdata.h"
18 #include "technique.h"
28 meshes(1, static_cast<Mesh *>(0)),
38 void Object::render(const Tag &tag) const
43 const ObjectPass *pass=get_pass(tag);
49 void Object::render(const ObjectInstance &inst, const Tag &tag) const
54 const ObjectPass *pass=get_pass(tag);
56 render_instance(inst, tag);
61 bool Object::can_render(const Tag &tag) const
64 return technique->has_pass(tag);
69 const ObjectPass *Object::get_pass(const Tag &tag) const
72 return &technique->get_pass(tag);
75 throw KeyError("Unknown pass");
78 void Object::setup_render(const ObjectPass *pass) const
81 throw InvalidState("Trying to render Object without mesh");
83 if(pass && pass->shprog)
86 pass->shdata->apply();
87 for(unsigned i=0; i<textures.size(); ++i)
93 else if(main_texture && (!pass || pass->use_textures))
100 void Object::finish_render(const ObjectPass *pass) const
102 if(pass && pass->shprog)
105 for(unsigned i=textures.size(); i--;)
107 TexUnit::activate(i);
111 else if(main_texture)
118 void Object::render_instance(const ObjectInstance &inst, const Tag &tag) const
120 inst.setup_render(tag);
121 unsigned lod=min<unsigned>(inst.get_level_of_detail(), meshes.size()-1);
123 inst.finish_render(tag);
127 Object::Loader::Loader(Object &o, Collection &c):
128 DataFile::CollectionObjectLoader<Object>(o, &c)
130 add("lod_mesh", &Loader::lod_mesh);
131 add("material", &Object::material);
132 add("material_inline", &Loader::material_inline);
133 add("mesh", &Loader::mesh);
134 add("shader_texture", &Loader::shader_texture);
135 add("technique", &Loader::technique);
136 add("texture", &Loader::texture);
139 void Object::Loader::finish()
141 if(obj.technique && !obj.main_texture)
142 obj.main_texture=obj.technique->get_main_texture();
143 for(unsigned i=0; i<obj.textures.size(); ++i)
147 obj.textures[i]=obj.technique->get_texture(i);
149 throw Exception("Object does not specify all textures required by Technique");
154 void Object::Loader::lod_mesh(unsigned l, const string &n)
156 obj.meshes.resize(l+1, 0);
157 obj.meshes[l]=coll->get<Mesh>(n);
160 void Object::Loader::material_inline()
162 RefPtr<Material> mat=new Material;
164 coll->add(format("_%p", mat.get()), mat.get());
165 obj.material=mat.release();
168 void Object::Loader::mesh(const string &n)
170 obj.meshes[0]=coll->get<Mesh>(n);
173 void Object::Loader::shader_texture(const string &n)
176 throw InvalidState("Can't specify shader textures without a Technique");
178 string::size_type eqsign=n.find('=');
179 if(eqsign==string::npos)
180 throw InvalidParameterValue("Must specify texture slot name");
182 obj.textures[obj.technique->get_texture_index(n.substr(0, eqsign))]=coll->get<Texture>(n.substr(eqsign+1));
185 void Object::Loader::technique(const string &n)
187 obj.technique=coll->get<Technique>(n);
188 obj.textures.resize(obj.technique->get_n_textures());
189 obj.material=obj.technique->get_material();
192 void Object::Loader::texture(const string &n)
195 throw Exception("Only one main texture may be specified");
197 Texture *tex=coll->get<Texture>(n);
199 obj.textures[obj.technique->get_texture_index("texture")]=tex;
200 obj.main_texture=tex;