]> git.tdb.fi Git - libs/gl.git/blobdiff - source/render/object.cpp
Use emplace_back when a new object is being constructed
[libs/gl.git] / source / render / object.cpp
index 702faaf9217eb9b8ba1374c358f228c0952ccf68..65e9a7ef083fc52db1f899906b7febaed96264a5 100644 (file)
@@ -1,38 +1,47 @@
 #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()
 {
@@ -56,33 +65,37 @@ Object::LevelOfDetail &Object::get_lod(unsigned i, const char *caller)
 
 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;
@@ -98,8 +111,8 @@ void Object::update_bounding_sphere()
                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));
                }
        }
 
@@ -116,14 +129,12 @@ const Mesh *Object::get_mesh(unsigned i) const
        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
@@ -131,21 +142,21 @@ 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, 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);
+       method->apply(renderer);
 
        setup_render(renderer, tag);
        mesh->draw(renderer);
@@ -155,16 +166,16 @@ void Object::render(Renderer &renderer, 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);
+       method->apply(renderer);
 
        setup_render(renderer, tag);
        inst.setup_render(renderer, tag);
@@ -173,40 +184,29 @@ void Object::render(Renderer &renderer, const ObjectInstance &inst, Tag tag) con
        finish_render(renderer, tag);
 }
 
-const RenderPass *Object::get_pass(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);
@@ -224,13 +224,13 @@ void Object::Loader::bounding_sphere_hint(float x, float y, float z, float r)
 
 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"))
 {
@@ -249,7 +249,8 @@ void Object::LodLoader::mesh_inline()
 {
        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 string &n)
@@ -260,11 +261,12 @@ void Object::LodLoader::technique(const string &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