+ RefPtr<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;
+ }
+
+ update_bounding_sphere();
+}
+
+void Object::update_bounding_sphere()
+{
+ vector<Vector3> points;
+ for(vector<LevelOfDetail>::const_iterator i=lods.begin(); i!=lods.end(); ++i)
+ {
+ if(!i->mesh || !i->mesh->is_loaded())
+ continue;
+
+ const VertexArray &vertices = i->mesh->get_vertices();
+
+ int offset = vertices.get_format().offset(VERTEX3);
+ bool three = true;
+ if(offset<0)
+ {
+ offset = vertices.get_format().offset(VERTEX2);
+ three = false;
+ if(offset<0)
+ continue;
+ }
+
+ unsigned n_vertices = vertices.size();
+ 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)));
+ }
+ }
+
+ /* Don't touch the bounding sphere if we had no vertices to avoid
+ overwriting a possible hint. */
+ if(points.empty())
+ return;
+
+ bounding_sphere = Geometry::BoundingSphere<float, 3>::from_point_cloud(points.begin(), points.end());
+}
+
+const Mesh *Object::get_mesh(unsigned i) const
+{
+ if(i>=lods.size())
+ return 0;
+
+ return lods[i].mesh.get();
+}
+
+void Object::set_technique(unsigned i, const Technique *t)
+{
+ RefPtr<const Technique> &ptr = get_lod(i, "Object::set_technique").technique;
+ ptr = t;
+ ptr.keep();
+}
+
+const Technique *Object::get_technique(unsigned i) const
+{
+ if(i>=lods.size())
+ return 0;
+
+ return lods[i].technique.get();
+}
+
+void Object::render(Renderer &renderer, const Tag &tag) const
+{
+ const RenderPass *pass = get_pass(tag, 0);