#include <msp/datafile/collection.h>
+#include <msp/fs/utils.h>
#include <msp/strings/format.h>
#include "error.h"
-#include "material.h"
#include "mesh.h"
#include "object.h"
#include "objectinstance.h"
-#include "program.h"
-#include "programdata.h"
#include "renderer.h"
#include "resourcemanager.h"
#include "technique.h"
-#include "texturing.h"
using namespace std;
namespace Msp {
namespace GL {
-Matrix Object::identity_matrix;
+const Matrix Object::identity_matrix;
Object::Object():
- lods(1),
- lod0_watched(false)
+ lods(1)
{ }
Object::Object(const Mesh *m, const Technique *t):
- lods(1),
- lod0_watched(false)
+ Object()
{
set_mesh(m);
set_technique(t);
}
-// TODO should have copy-c'tor to set watch on lod0 mesh if necessary
+Object::Object(const Object &other):
+ lods(other.lods),
+ bounding_sphere(other.bounding_sphere)
+{
+ if(other.lod0_watched)
+ watch_lod0();
+}
+
+Object::Object(Object &&other):
+ lods(move(other.lods)),
+ bounding_sphere(move(other.bounding_sphere))
+{
+ if(other.lod0_watched)
+ watch_lod0();
+}
Object::~Object()
{
void Object::set_mesh(unsigned i, const Mesh *m)
{
- RefPtr<const Mesh> &ptr = get_lod(i, "Object::set_mesh").mesh;
+ const Mesh *&ptr = get_lod(i, "Object::set_mesh").mesh;
if(i==0 && ptr && lod0_watched)
if(ResourceManager *rm = ptr->get_manager())
rm->unobserve_resource(*ptr, *this);
ptr = m;
- ptr.keep();
lod0_watched = false;
if(i==0 && m)
- if(ResourceManager *rm = m->get_manager())
- {
- rm->observe_resource(*m, *this);
- lod0_watched = true;
- }
+ watch_lod0();
update_bounding_sphere();
}
+void Object::watch_lod0()
+{
+ if(ResourceManager *rm = lods[0].mesh->get_manager())
+ {
+ rm->observe_resource(*lods[0].mesh, *this);
+ lod0_watched = true;
+ }
+}
+
void Object::update_bounding_sphere()
{
vector<Vector3> points;
- for(vector<LevelOfDetail>::const_iterator i=lods.begin(); i!=lods.end(); ++i)
+ for(const LevelOfDetail &l: lods)
{
- if(!i->mesh || !i->mesh->is_loaded())
+ if(!l.mesh || !l.mesh->is_loaded())
continue;
- const VertexArray &vertices = i->mesh->get_vertices();
+ const VertexArray &vertices = l.mesh->get_vertices();
int offset = vertices.get_format().offset(VERTEX3);
bool three = true;
points.reserve(points.size()+n_vertices);
for(unsigned j=0; j<n_vertices; ++j)
{
- const float *v = vertices[j];
- points.push_back(Vector3(v[offset], v[offset+1], (three ? v[offset+2] : 0.0f)));
+ const float *v = reinterpret_cast<const float *>(vertices[j]+offset);
+ points.emplace_back(v[0], v[1], (three ? v[2] : 0.0f));
}
}
if(i>=lods.size())
return 0;
- return lods[i].mesh.get();
+ return lods[i].mesh;
}
void Object::set_technique(unsigned i, const Technique *t)
{
- RefPtr<const Technique> &ptr = get_lod(i, "Object::set_technique").technique;
- ptr = t;
- ptr.keep();
+ get_lod(i, "Object::set_technique").technique = t;
}
const Technique *Object::get_technique(unsigned i) const
if(i>=lods.size())
return 0;
- return lods[i].technique.get();
+ return lods[i].technique;
}
-void Object::render(Renderer &renderer, const Tag &tag) const
+void Object::render(Renderer &renderer, Tag tag) const
{
- const RenderPass *pass = get_pass(tag, 0);
- if(!pass)
+ const RenderMethod *method = get_method(tag, 0);
+ if(!method)
return;
- const Mesh *mesh = lods.front().mesh.get();
+ const Mesh *mesh = lods.front().mesh;
if (!mesh)
throw logic_error("no mesh");
Renderer::Push push(renderer);
- pass->apply(renderer);
+ renderer.set_pipeline_key(this, tag.id);
+ method->apply(renderer);
setup_render(renderer, tag);
mesh->draw(renderer);
finish_render(renderer, tag);
}
-void Object::render(Renderer &renderer, const ObjectInstance &inst, const Tag &tag) const
+void Object::render(Renderer &renderer, const ObjectInstance &inst, Tag tag) const
{
unsigned lod = min<unsigned>(inst.get_level_of_detail(renderer), lods.size()-1);
- const RenderPass *pass = get_pass(tag, lod);
- if(!pass)
+ const RenderMethod *method = get_method(tag, lod);
+ if(!method)
return;
- const Mesh *mesh = lods[lod].mesh.get();
+ const Mesh *mesh = lods[lod].mesh;
if (!mesh)
throw logic_error("no mesh");
Renderer::Push push(renderer);
- pass->apply(renderer);
+ renderer.set_pipeline_key(this, tag.id);
+ method->apply(renderer);
setup_render(renderer, tag);
inst.setup_render(renderer, tag);
finish_render(renderer, tag);
}
-const RenderPass *Object::get_pass(const Tag &tag, unsigned lod) const
+const RenderMethod *Object::get_method(Tag tag, unsigned lod) const
{
- const Technique *tech = lods[lod].technique.get();
+ const Technique *tech = lods[lod].technique;
if(!tech)
throw logic_error("no technique");
- return tech->find_pass(tag);
+ return tech->find_method(tag);
}
void Object::resource_loaded(Resource &res)
{
- if(&res==lods.front().mesh.get() && bounding_sphere.is_empty())
+ if(&res==lods.front().mesh && bounding_sphere.is_empty())
update_bounding_sphere();
}
void Object::resource_removed(Resource &res)
{
- if(&res==lods.front().mesh.get())
+ if(&res==lods.front().mesh)
lod0_watched = false;
}
-Object::Loader::Loader(Object &o):
- LodLoader(o, 0, 0)
-{
- init();
-}
-
Object::Loader::Loader(Object &o, Collection &c):
- LodLoader(o, 0, &c)
-{
- init();
-}
-
-void Object::Loader::init()
+ LodLoader(o, 0, c)
{
add("bounding_sphere_hint", &Loader::bounding_sphere_hint);
add("level_of_detail", &Loader::level_of_detail);
void Object::Loader::level_of_detail(unsigned i)
{
- LodLoader ldr(obj, i, coll);
+ LodLoader ldr(obj, i, get_collection());
load_sub_with(ldr);
}
-Object::LodLoader::LodLoader(Object &o, unsigned i, Collection *c):
- DataFile::CollectionObjectLoader<Object>(o, c),
+Object::LodLoader::LodLoader(Object &o, unsigned i, Collection &c):
+ DataFile::CollectionObjectLoader<Object>(o, &c),
index(i),
lod(obj.get_lod(index, "Object::LodLoader::LodLoader"))
{
{
RefPtr<Mesh> msh = new Mesh;
load_sub(*msh);
- lod.mesh = msh;
+ get_collection().add(format("%s/lod%d.mesh", FS::basename(get_source()), index), msh.get());
+ lod.mesh = msh.release();
}
-void Object::LodLoader::technique(const std::string &n)
+void Object::LodLoader::technique(const string &n)
{
obj.set_technique(index, &get_collection().get<Technique>(n));
}
void Object::LodLoader::technique_inline()
{
RefPtr<Technique> tech = new Technique;
- if(coll)
- load_sub(*tech, get_collection());
- else
- load_sub(*tech);
- lod.technique = tech;
+ Technique::Loader ldr(*tech, get_collection());
+ string name = format("%s/lod%d.tech", FS::basename(get_source()), index);
+ ldr.set_inline_base_name(name);
+ load_sub(*tech, get_collection());
+ get_collection().add(name, tech.get());
+ lod.technique = tech.release();
}
} // namespace GL