Fix #33405: preview render getting stuck in a particular .blend file, ObjectKey
[blender.git] / intern / cycles / render / mesh.cpp
1 /*
2  * Copyright 2011, Blender Foundation.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18
19 #include "bvh.h"
20 #include "bvh_build.h"
21
22 #include "camera.h"
23 #include "device.h"
24 #include "shader.h"
25 #include "light.h"
26 #include "mesh.h"
27 #include "object.h"
28 #include "scene.h"
29
30 #include "osl_globals.h"
31
32 #include "util_cache.h"
33 #include "util_foreach.h"
34 #include "util_progress.h"
35 #include "util_set.h"
36
37 CCL_NAMESPACE_BEGIN
38
39 /* Mesh */
40
41 Mesh::Mesh()
42 {
43         need_update = true;
44         transform_applied = false;
45         transform_negative_scaled = false;
46         displacement_method = DISPLACE_BUMP;
47         bounds = BoundBox::empty;
48
49         bvh = NULL;
50
51         tri_offset = 0;
52         vert_offset = 0;
53
54         attributes.mesh = this;
55 }
56
57 Mesh::~Mesh()
58 {
59         delete bvh;
60 }
61
62 void Mesh::reserve(int numverts, int numtris)
63 {
64         /* reserve space to add verts and triangles later */
65         verts.resize(numverts);
66         triangles.resize(numtris);
67         shader.resize(numtris);
68         smooth.resize(numtris);
69         attributes.reserve(numverts, numtris);
70 }
71
72 void Mesh::clear()
73 {
74         /* clear all verts and triangles */
75         verts.clear();
76         triangles.clear();
77         shader.clear();
78         smooth.clear();
79
80         attributes.clear();
81         used_shaders.clear();
82
83         transform_applied = false;
84         transform_negative_scaled = false;
85 }
86
87 void Mesh::add_triangle(int v0, int v1, int v2, int shader_, bool smooth_)
88 {
89         Triangle t;
90         t.v[0] = v0;
91         t.v[1] = v1;
92         t.v[2] = v2;
93
94         triangles.push_back(t);
95         shader.push_back(shader_);
96         smooth.push_back(smooth_);
97 }
98
99 void Mesh::compute_bounds()
100 {
101         BoundBox bnds = BoundBox::empty;
102         size_t verts_size = verts.size();
103
104         for(size_t i = 0; i < verts_size; i++)
105                 bnds.grow(verts[i]);
106
107         /* happens mostly on empty meshes */
108         if(!bnds.valid())
109                 bnds.grow(make_float3(0.0f, 0.0f, 0.0f));
110
111         bounds = bnds;
112 }
113
114 void Mesh::add_face_normals()
115 {
116         /* don't compute if already there */
117         if(attributes.find(ATTR_STD_FACE_NORMAL))
118                 return;
119
120         /* get attributes */
121         Attribute *attr_fN = attributes.add(ATTR_STD_FACE_NORMAL);
122         float3 *fN = attr_fN->data_float3();
123
124         /* compute face normals */
125         size_t triangles_size = triangles.size();
126         bool flip = transform_negative_scaled;
127
128         if(triangles_size) {
129                 float3 *verts_ptr = &verts[0];
130                 Triangle *triangles_ptr = &triangles[0];
131
132                 for(size_t i = 0; i < triangles_size; i++) {
133                         Triangle t = triangles_ptr[i];
134                         float3 v0 = verts_ptr[t.v[0]];
135                         float3 v1 = verts_ptr[t.v[1]];
136                         float3 v2 = verts_ptr[t.v[2]];
137
138                         fN[i] = normalize(cross(v1 - v0, v2 - v0));
139
140                         if(flip)
141                                 fN[i] = -fN[i];
142                 }
143         }
144 }
145
146 void Mesh::add_vertex_normals()
147 {
148         /* don't compute if already there */
149         if(attributes.find(ATTR_STD_VERTEX_NORMAL))
150                 return;
151
152         /* get attributes */
153         Attribute *attr_fN = attributes.find(ATTR_STD_FACE_NORMAL);
154         Attribute *attr_vN = attributes.add(ATTR_STD_VERTEX_NORMAL);
155
156         float3 *fN = attr_fN->data_float3();
157         float3 *vN = attr_vN->data_float3();
158
159         /* compute vertex normals */
160         memset(vN, 0, verts.size()*sizeof(float3));
161
162         size_t verts_size = verts.size();
163         size_t triangles_size = triangles.size();
164         bool flip = transform_negative_scaled;
165
166         if(triangles_size) {
167                 Triangle *triangles_ptr = &triangles[0];
168
169                 for(size_t i = 0; i < triangles_size; i++)
170                         for(size_t j = 0; j < 3; j++)
171                                 vN[triangles_ptr[i].v[j]] += fN[i];
172         }
173
174         for(size_t i = 0; i < verts_size; i++) {
175                 vN[i] = normalize(vN[i]);
176                 if(flip)
177                         vN[i] = -vN[i];
178         }
179 }
180
181 void Mesh::pack_normals(Scene *scene, float4 *normal, float4 *vnormal)
182 {
183         Attribute *attr_fN = attributes.find(ATTR_STD_FACE_NORMAL);
184         Attribute *attr_vN = attributes.find(ATTR_STD_VERTEX_NORMAL);
185
186         float3 *fN = attr_fN->data_float3();
187         float3 *vN = attr_vN->data_float3();
188         int shader_id = 0;
189         uint last_shader = -1;
190         bool last_smooth = false;
191
192         size_t triangles_size = triangles.size();
193         uint *shader_ptr = (shader.size())? &shader[0]: NULL;
194
195         for(size_t i = 0; i < triangles_size; i++) {
196                 normal[i].x = fN[i].x;
197                 normal[i].y = fN[i].y;
198                 normal[i].z = fN[i].z;
199
200                 /* stuff shader id in here too */
201                 if(shader_ptr[i] != last_shader || last_smooth != smooth[i]) {
202                         last_shader = shader_ptr[i];
203                         last_smooth = smooth[i];
204                         shader_id = scene->shader_manager->get_shader_id(last_shader, this, last_smooth);
205                 }
206
207                 normal[i].w = __int_as_float(shader_id);
208         }
209
210         size_t verts_size = verts.size();
211
212         for(size_t i = 0; i < verts_size; i++)
213                 vnormal[i] = make_float4(vN[i].x, vN[i].y, vN[i].z, 0.0f);
214 }
215
216 void Mesh::pack_verts(float4 *tri_verts, float4 *tri_vindex, size_t vert_offset)
217 {
218         size_t verts_size = verts.size();
219
220         if(verts_size) {
221                 float3 *verts_ptr = &verts[0];
222
223                 for(size_t i = 0; i < verts_size; i++) {
224                         float3 p = verts_ptr[i];
225                         tri_verts[i] = make_float4(p.x, p.y, p.z, 0.0f);
226                 }
227         }
228
229         size_t triangles_size = triangles.size();
230
231         if(triangles_size) {
232                 Triangle *triangles_ptr = &triangles[0];
233
234                 for(size_t i = 0; i < triangles_size; i++) {
235                         Triangle t = triangles_ptr[i];
236
237                         tri_vindex[i] = make_float4(
238                                 __int_as_float(t.v[0] + vert_offset),
239                                 __int_as_float(t.v[1] + vert_offset),
240                                 __int_as_float(t.v[2] + vert_offset),
241                                 0);
242                 }
243         }
244 }
245
246 void Mesh::compute_bvh(SceneParams *params, Progress *progress, int n, int total)
247 {
248         if(progress->get_cancel())
249                 return;
250
251         compute_bounds();
252
253         if(!transform_applied) {
254                 string msg = "Updating Mesh BVH ";
255                 if(name == "")
256                         msg += string_printf("%u/%u", (uint)(n+1), (uint)total);
257                 else
258                         msg += string_printf("%s %u/%u", name.c_str(), (uint)(n+1), (uint)total);
259
260                 Object object;
261                 object.mesh = this;
262
263                 vector<Object*> objects;
264                 objects.push_back(&object);
265
266                 if(bvh && !need_update_rebuild) {
267                         progress->set_status(msg, "Refitting BVH");
268                         bvh->objects = objects;
269                         bvh->refit(*progress);
270                 }
271                 else {
272                         progress->set_status(msg, "Building BVH");
273
274                         BVHParams bparams;
275                         bparams.use_cache = params->use_bvh_cache;
276                         bparams.use_spatial_split = params->use_bvh_spatial_split;
277                         bparams.use_qbvh = params->use_qbvh;
278
279                         delete bvh;
280                         bvh = BVH::create(bparams, objects);
281                         bvh->build(*progress);
282                 }
283         }
284
285         need_update = false;
286         need_update_rebuild = false;
287 }
288
289 void Mesh::tag_update(Scene *scene, bool rebuild)
290 {
291         need_update = true;
292
293         if(rebuild) {
294                 need_update_rebuild = true;
295                 scene->light_manager->need_update = true;
296         }
297         else {
298                 foreach(uint sindex, used_shaders)
299                         if(scene->shaders[sindex]->has_surface_emission)
300                                 scene->light_manager->need_update = true;
301         }
302
303         scene->mesh_manager->need_update = true;
304         scene->object_manager->need_update = true;
305 }
306
307 /* Mesh Manager */
308
309 MeshManager::MeshManager()
310 {
311         bvh = NULL;
312         need_update = true;
313 }
314
315 MeshManager::~MeshManager()
316 {
317         delete bvh;
318 }
319
320 void MeshManager::update_osl_attributes(Device *device, Scene *scene, vector<AttributeRequestSet>& mesh_attributes)
321 {
322 #ifdef WITH_OSL
323         /* for OSL, a hash map is used to lookup the attribute by name. */
324         OSLGlobals *og = (OSLGlobals*)device->osl_memory();
325
326         og->object_name_map.clear();
327         og->attribute_map.clear();
328         og->object_names.clear();
329
330         og->attribute_map.resize(scene->objects.size());
331
332         for(size_t i = 0; i < scene->objects.size(); i++) {
333                 /* set object name to object index map */
334                 Object *object = scene->objects[i];
335                 og->object_name_map[object->name] = i;
336                 og->object_names.push_back(object->name);
337
338                 /* set object attributes */
339                 foreach(ParamValue& attr, object->attributes) {
340                         OSLGlobals::Attribute osl_attr;
341
342                         osl_attr.type = attr.type();
343                         osl_attr.elem = ATTR_ELEMENT_VALUE;
344                         osl_attr.value = attr;
345
346                         og->attribute_map[i][attr.name()] = osl_attr;
347                 }
348
349                 /* find mesh attributes */
350                 size_t j;
351
352                 for(j = 0; j < scene->meshes.size(); j++)
353                         if(scene->meshes[j] == object->mesh)
354                                 break;
355
356                 AttributeRequestSet& attributes = mesh_attributes[j];
357
358                 /* set object attributes */
359                 foreach(AttributeRequest& req, attributes.requests) {
360                         if(req.element == ATTR_ELEMENT_NONE)
361                                 continue;
362
363                         OSLGlobals::Attribute osl_attr;
364
365                         osl_attr.elem = req.element;
366                         osl_attr.offset = req.offset;
367
368                         if(req.type == TypeDesc::TypeFloat)
369                                 osl_attr.type = TypeDesc::TypeFloat;
370                         else
371                                 osl_attr.type = TypeDesc::TypeColor;
372
373                         if(req.std != ATTR_STD_NONE) {
374                                 /* if standard attribute, add lookup by geom: name convention */
375                                 ustring stdname(string("geom:") + string(attribute_standard_name(req.std)));
376                                 og->attribute_map[i][stdname] = osl_attr;
377                         }
378                         else if(req.name != ustring()) {
379                                 /* add lookup by mesh attribute name */
380                                 og->attribute_map[i][req.name] = osl_attr;
381                         }
382                 }
383         }
384 #endif
385 }
386
387 void MeshManager::update_svm_attributes(Device *device, DeviceScene *dscene, Scene *scene, vector<AttributeRequestSet>& mesh_attributes)
388 {
389         /* for SVM, the attributes_map table is used to lookup the offset of an
390          * attribute, based on a unique shader attribute id. */
391
392         /* compute array stride */
393         int attr_map_stride = 0;
394
395         for(size_t i = 0; i < scene->meshes.size(); i++)
396                 attr_map_stride = max(attr_map_stride, mesh_attributes[i].size()+1);
397
398         if(attr_map_stride == 0)
399                 return;
400         
401         /* create attribute map */
402         uint4 *attr_map = dscene->attributes_map.resize(attr_map_stride*scene->objects.size());
403         memset(attr_map, 0, dscene->attributes_map.size()*sizeof(uint));
404
405         for(size_t i = 0; i < scene->objects.size(); i++) {
406                 Object *object = scene->objects[i];
407
408                 /* find mesh attributes */
409                 size_t j;
410
411                 for(j = 0; j < scene->meshes.size(); j++)
412                         if(scene->meshes[j] == object->mesh)
413                                 break;
414
415                 AttributeRequestSet& attributes = mesh_attributes[j];
416
417                 /* set object attributes */
418                 int index = i*attr_map_stride;
419
420                 foreach(AttributeRequest& req, attributes.requests) {
421                         uint id;
422
423                         if(req.std == ATTR_STD_NONE)
424                                 id = scene->shader_manager->get_attribute_id(req.name);
425                         else
426                                 id = scene->shader_manager->get_attribute_id(req.std);
427
428                         attr_map[index].x = id;
429                         attr_map[index].y = req.element;
430                         attr_map[index].z = as_uint(req.offset);
431
432                         if(req.type == TypeDesc::TypeFloat)
433                                 attr_map[index].w = NODE_ATTR_FLOAT;
434                         else
435                                 attr_map[index].w = NODE_ATTR_FLOAT3;
436
437                         index++;
438                 }
439
440                 /* terminator */
441                 attr_map[index].x = ATTR_STD_NONE;
442                 attr_map[index].y = 0;
443                 attr_map[index].z = 0;
444                 attr_map[index].w = 0;
445         }
446
447         /* copy to device */
448         dscene->data.bvh.attributes_map_stride = attr_map_stride;
449         device->tex_alloc("__attributes_map", dscene->attributes_map);
450 }
451
452 void MeshManager::device_update_attributes(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
453 {
454         progress.set_status("Updating Mesh", "Computing attributes");
455
456         /* gather per mesh requested attributes. as meshes may have multiple
457          * shaders assigned, this merges the requested attributes that have
458          * been set per shader by the shader manager */
459         vector<AttributeRequestSet> mesh_attributes(scene->meshes.size());
460
461         for(size_t i = 0; i < scene->meshes.size(); i++) {
462                 Mesh *mesh = scene->meshes[i];
463
464                 scene->need_global_attributes(mesh_attributes[i]);
465
466                 foreach(uint sindex, mesh->used_shaders) {
467                         Shader *shader = scene->shaders[sindex];
468                         mesh_attributes[i].add(shader->attributes);
469                 }
470         }
471
472         /* mesh attribute are stored in a single array per data type. here we fill
473          * those arrays, and set the offset and element type to create attribute
474          * maps next */
475         vector<float> attr_float;
476         vector<float4> attr_float3;
477
478         for(size_t i = 0; i < scene->meshes.size(); i++) {
479                 Mesh *mesh = scene->meshes[i];
480                 AttributeRequestSet& attributes = mesh_attributes[i];
481
482                 /* todo: we now store std and name attributes from requests even if
483                  * they actually refer to the same mesh attributes, optimize */
484                 foreach(AttributeRequest& req, attributes.requests) {
485                         Attribute *mattr = mesh->attributes.find(req);
486
487                         /* todo: get rid of this exception */
488                         if(!mattr && req.std == ATTR_STD_GENERATED) {
489                                 mattr = mesh->attributes.add(ATTR_STD_GENERATED);
490                                 if(mesh->verts.size())
491                                         memcpy(mattr->data_float3(), &mesh->verts[0], sizeof(float3)*mesh->verts.size());
492                         }
493
494                         /* attribute not found */
495                         if(!mattr) {
496                                 req.element = ATTR_ELEMENT_NONE;
497                                 req.offset = 0;
498                                 continue;
499                         }
500
501                         /* we abuse AttributeRequest to pass on info like element and
502                          * offset, it doesn't really make sense but is convenient */
503
504                         /* store element and type */
505                         if(mattr->element == Attribute::VERTEX)
506                                 req.element = ATTR_ELEMENT_VERTEX;
507                         else if(mattr->element == Attribute::FACE)
508                                 req.element = ATTR_ELEMENT_FACE;
509                         else if(mattr->element == Attribute::CORNER)
510                                 req.element = ATTR_ELEMENT_CORNER;
511
512                         req.type = mattr->type;
513
514                         /* store attribute data in arrays */
515                         size_t size = mattr->element_size(mesh->verts.size(), mesh->triangles.size());
516
517                         if(mattr->type == TypeDesc::TypeFloat) {
518                                 float *data = mattr->data_float();
519                                 req.offset = attr_float.size();
520
521                                 attr_float.resize(attr_float.size() + size);
522
523                                 for(size_t k = 0; k < size; k++)
524                                         attr_float[req.offset+k] = data[k];
525                         }
526                         else {
527                                 float3 *data = mattr->data_float3();
528                                 req.offset = attr_float3.size();
529
530                                 attr_float3.resize(attr_float3.size() + size);
531
532                                 for(size_t k = 0; k < size; k++)
533                                         attr_float3[req.offset+k] = float3_to_float4(data[k]);
534                         }
535
536                         /* mesh vertex/triangle index is global, not per object, so we sneak
537                          * a correction for that in here */
538                         if(req.element == ATTR_ELEMENT_VERTEX)
539                                 req.offset -= mesh->vert_offset;
540                         else if(mattr->element == Attribute::FACE)
541                                 req.offset -= mesh->tri_offset;
542                         else if(mattr->element == Attribute::CORNER)
543                                 req.offset -= 3*mesh->tri_offset;
544
545                         if(progress.get_cancel()) return;
546                 }
547         }
548
549         /* create attribute lookup maps */
550         if(scene->shader_manager->use_osl())
551                 update_osl_attributes(device, scene, mesh_attributes);
552         else
553                 update_svm_attributes(device, dscene, scene, mesh_attributes);
554
555         if(progress.get_cancel()) return;
556
557         /* copy to device */
558         progress.set_status("Updating Mesh", "Copying Attributes to device");
559
560         if(attr_float.size()) {
561                 dscene->attributes_float.copy(&attr_float[0], attr_float.size());
562                 device->tex_alloc("__attributes_float", dscene->attributes_float);
563         }
564         if(attr_float3.size()) {
565                 dscene->attributes_float3.copy(&attr_float3[0], attr_float3.size());
566                 device->tex_alloc("__attributes_float3", dscene->attributes_float3);
567         }
568 }
569
570 void MeshManager::device_update_mesh(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
571 {
572         /* count and update offsets */
573         size_t vert_size = 0;
574         size_t tri_size = 0;
575
576         foreach(Mesh *mesh, scene->meshes) {
577                 mesh->vert_offset = vert_size;
578                 mesh->tri_offset = tri_size;
579
580                 vert_size += mesh->verts.size();
581                 tri_size += mesh->triangles.size();
582         }
583
584         if(tri_size == 0)
585                 return;
586
587         /* normals */
588         progress.set_status("Updating Mesh", "Computing normals");
589
590         float4 *normal = dscene->tri_normal.resize(tri_size);
591         float4 *vnormal = dscene->tri_vnormal.resize(vert_size);
592         float4 *tri_verts = dscene->tri_verts.resize(vert_size);
593         float4 *tri_vindex = dscene->tri_vindex.resize(tri_size);
594
595         foreach(Mesh *mesh, scene->meshes) {
596                 mesh->pack_normals(scene, &normal[mesh->tri_offset], &vnormal[mesh->vert_offset]);
597                 mesh->pack_verts(&tri_verts[mesh->vert_offset], &tri_vindex[mesh->tri_offset], mesh->vert_offset);
598
599                 if(progress.get_cancel()) return;
600         }
601
602         /* vertex coordinates */
603         progress.set_status("Updating Mesh", "Copying Mesh to device");
604
605         device->tex_alloc("__tri_normal", dscene->tri_normal);
606         device->tex_alloc("__tri_vnormal", dscene->tri_vnormal);
607         device->tex_alloc("__tri_verts", dscene->tri_verts);
608         device->tex_alloc("__tri_vindex", dscene->tri_vindex);
609 }
610
611 void MeshManager::device_update_bvh(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
612 {
613         /* bvh build */
614         progress.set_status("Updating Scene BVH", "Building");
615
616         BVHParams bparams;
617         bparams.top_level = true;
618         bparams.use_qbvh = scene->params.use_qbvh;
619         bparams.use_spatial_split = scene->params.use_bvh_spatial_split;
620         bparams.use_cache = scene->params.use_bvh_cache;
621
622         delete bvh;
623         bvh = BVH::create(bparams, scene->objects);
624         bvh->build(progress);
625
626         if(progress.get_cancel()) return;
627
628         /* copy to device */
629         progress.set_status("Updating Scene BVH", "Copying BVH to device");
630
631         PackedBVH& pack = bvh->pack;
632
633         if(pack.nodes.size()) {
634                 dscene->bvh_nodes.reference((float4*)&pack.nodes[0], pack.nodes.size());
635                 device->tex_alloc("__bvh_nodes", dscene->bvh_nodes);
636         }
637         if(pack.object_node.size()) {
638                 dscene->object_node.reference((uint*)&pack.object_node[0], pack.object_node.size());
639                 device->tex_alloc("__object_node", dscene->object_node);
640         }
641         if(pack.tri_woop.size()) {
642                 dscene->tri_woop.reference(&pack.tri_woop[0], pack.tri_woop.size());
643                 device->tex_alloc("__tri_woop", dscene->tri_woop);
644         }
645         if(pack.prim_visibility.size()) {
646                 dscene->prim_visibility.reference((uint*)&pack.prim_visibility[0], pack.prim_visibility.size());
647                 device->tex_alloc("__prim_visibility", dscene->prim_visibility);
648         }
649         if(pack.prim_index.size()) {
650                 dscene->prim_index.reference((uint*)&pack.prim_index[0], pack.prim_index.size());
651                 device->tex_alloc("__prim_index", dscene->prim_index);
652         }
653         if(pack.prim_object.size()) {
654                 dscene->prim_object.reference((uint*)&pack.prim_object[0], pack.prim_object.size());
655                 device->tex_alloc("__prim_object", dscene->prim_object);
656         }
657
658         dscene->data.bvh.root = pack.root_index;
659 }
660
661 void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
662 {
663         if(!need_update)
664                 return;
665
666         /* update normals */
667         foreach(Mesh *mesh, scene->meshes) {
668                 foreach(uint shader, mesh->used_shaders)
669                         if(scene->shaders[shader]->need_update_attributes)
670                                 mesh->need_update = true;
671
672                 if(mesh->need_update) {
673                         mesh->add_face_normals();
674                         mesh->add_vertex_normals();
675
676                         if(progress.get_cancel()) return;
677                 }
678         }
679
680         /* device update */
681         device_free(device, dscene);
682
683         device_update_mesh(device, dscene, scene, progress);
684         if(progress.get_cancel()) return;
685
686         device_update_attributes(device, dscene, scene, progress);
687         if(progress.get_cancel()) return;
688
689         /* update displacement */
690         bool displacement_done = false;
691
692         foreach(Mesh *mesh, scene->meshes)
693                 if(mesh->need_update && displace(device, scene, mesh, progress))
694                         displacement_done = true;
695
696         /* todo: properly handle cancel halfway displacement */
697         if(progress.get_cancel()) return;
698
699         /* device re-update after displacement */
700         if(displacement_done) {
701                 device_free(device, dscene);
702
703                 device_update_mesh(device, dscene, scene, progress);
704                 if(progress.get_cancel()) return;
705
706                 device_update_attributes(device, dscene, scene, progress);
707                 if(progress.get_cancel()) return;
708         }
709
710         /* update bvh */
711         size_t i = 0, num_bvh = 0;
712
713         foreach(Mesh *mesh, scene->meshes)
714                 if(mesh->need_update && !mesh->transform_applied)
715                         num_bvh++;
716
717         TaskPool pool;
718
719         foreach(Mesh *mesh, scene->meshes) {
720                 if(mesh->need_update) {
721                         pool.push(function_bind(&Mesh::compute_bvh, mesh, &scene->params, &progress, i, num_bvh));
722                         i++;
723                 }
724         }
725
726         pool.wait_work();
727         
728         foreach(Shader *shader, scene->shaders)
729                 shader->need_update_attributes = false;
730
731         float shuttertime = scene->camera->shuttertime;
732 #ifdef __OBJECT_MOTION__
733         Scene::MotionType need_motion = scene->need_motion(device->info.advanced_shading);
734         bool motion_blur = need_motion == Scene::MOTION_BLUR;
735 #else
736         bool motion_blur = false;
737 #endif
738
739         foreach(Object *object, scene->objects)
740                 object->compute_bounds(motion_blur, shuttertime);
741
742         if(progress.get_cancel()) return;
743
744         device_update_bvh(device, dscene, scene, progress);
745
746         need_update = false;
747 }
748
749 void MeshManager::device_free(Device *device, DeviceScene *dscene)
750 {
751         device->tex_free(dscene->bvh_nodes);
752         device->tex_free(dscene->object_node);
753         device->tex_free(dscene->tri_woop);
754         device->tex_free(dscene->prim_visibility);
755         device->tex_free(dscene->prim_index);
756         device->tex_free(dscene->prim_object);
757         device->tex_free(dscene->tri_normal);
758         device->tex_free(dscene->tri_vnormal);
759         device->tex_free(dscene->tri_vindex);
760         device->tex_free(dscene->tri_verts);
761         device->tex_free(dscene->attributes_map);
762         device->tex_free(dscene->attributes_float);
763         device->tex_free(dscene->attributes_float3);
764
765         dscene->bvh_nodes.clear();
766         dscene->object_node.clear();
767         dscene->tri_woop.clear();
768         dscene->prim_visibility.clear();
769         dscene->prim_index.clear();
770         dscene->prim_object.clear();
771         dscene->tri_normal.clear();
772         dscene->tri_vnormal.clear();
773         dscene->tri_vindex.clear();
774         dscene->tri_verts.clear();
775         dscene->attributes_map.clear();
776         dscene->attributes_float.clear();
777         dscene->attributes_float3.clear();
778 }
779
780 void MeshManager::tag_update(Scene *scene)
781 {
782         need_update = true;
783         scene->object_manager->need_update = true;
784 }
785
786 bool Mesh::need_attribute(Scene *scene, AttributeStandard std)
787 {
788         if(std == ATTR_STD_NONE)
789                 return false;
790         
791         if(scene->need_global_attribute(std))
792                 return true;
793
794         foreach(uint shader, used_shaders)
795                 if(scene->shaders[shader]->attributes.find(std))
796                         return true;
797         
798         return false;
799 }
800
801 bool Mesh::need_attribute(Scene *scene, ustring name)
802 {
803         if(name == ustring())
804                 return false;
805
806         foreach(uint shader, used_shaders)
807                 if(scene->shaders[shader]->attributes.find(name))
808                         return true;
809         
810         return false;
811 }
812
813 CCL_NAMESPACE_END
814