Cycles: Fix crash in empty scenes
[blender.git] / intern / cycles / render / object.cpp
1 /*
2  * Copyright 2011-2013 Blender Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "camera.h"
18 #include "device.h"
19 #include "light.h"
20 #include "mesh.h"
21 #include "curves.h"
22 #include "object.h"
23 #include "particles.h"
24 #include "scene.h"
25
26 #include "util_foreach.h"
27 #include "util_logging.h"
28 #include "util_map.h"
29 #include "util_progress.h"
30 #include "util_vector.h"
31
32 #include "subd_patch_table.h"
33
34 CCL_NAMESPACE_BEGIN
35
36 /* Object */
37
38 NODE_DEFINE(Object)
39 {
40         NodeType* type = NodeType::add("object", create);
41
42         SOCKET_NODE(mesh, "Mesh", &Mesh::node_type);
43         SOCKET_TRANSFORM(tfm, "Transform", transform_identity());
44         SOCKET_UINT(visibility, "Visibility", ~0);
45         SOCKET_UINT(random_id, "Random ID", 0);
46         SOCKET_INT(pass_id, "Pass ID", 0);
47         SOCKET_BOOLEAN(use_holdout, "Use Holdout", false);
48         SOCKET_POINT(dupli_generated, "Dupli Generated", make_float3(0.0f, 0.0f, 0.0f));
49         SOCKET_POINT2(dupli_uv, "Dupli UV", make_float2(0.0f, 0.0f));
50
51         return type;
52 }
53
54 Object::Object()
55 : Node(node_type)
56 {
57         particle_system = NULL;
58         particle_index = 0;
59         bounds = BoundBox::empty;
60         motion.pre = transform_empty();
61         motion.mid = transform_empty();
62         motion.post = transform_empty();
63         use_motion = false;
64 }
65
66 Object::~Object()
67 {
68 }
69
70 void Object::compute_bounds(bool motion_blur)
71 {
72         BoundBox mbounds = mesh->bounds;
73
74         if(motion_blur && use_motion) {
75                 if(motion.pre == transform_empty() ||
76                    motion.post == transform_empty()) {
77                         /* Hide objects that have no valid previous or next transform, for
78                          * example particle that stop existing. TODO: add support for this
79                          * case in the kernel so we don't get render artifacts. */
80                         bounds = BoundBox::empty;
81                 }
82                 else {
83                         DecompMotionTransform decomp;
84                         transform_motion_decompose(&decomp, &motion, &tfm);
85
86                         bounds = BoundBox::empty;
87
88                         /* todo: this is really terrible. according to pbrt there is a better
89                          * way to find this iteratively, but did not find implementation yet
90                          * or try to implement myself */
91                         for(float t = 0.0f; t < 1.0f; t += (1.0f/128.0f)) {
92                                 Transform ttfm;
93
94                                 transform_motion_interpolate(&ttfm, &decomp, t);
95                                 bounds.grow(mbounds.transformed(&ttfm));
96                         }
97                 }
98         }
99         else {
100                 if(mesh->transform_applied) {
101                         bounds = mbounds;
102                 }
103                 else {
104                         bounds = mbounds.transformed(&tfm);
105                 }
106         }
107 }
108
109 void Object::apply_transform(bool apply_to_motion)
110 {
111         if(!mesh || tfm == transform_identity())
112                 return;
113         
114         /* triangles */
115         if(mesh->verts.size()) {
116                 /* store matrix to transform later. when accessing these as attributes we
117                  * do not want the transform to be applied for consistency between static
118                  * and dynamic BVH, so we do it on packing. */
119                 mesh->transform_normal = transform_transpose(transform_inverse(tfm));
120
121                 /* apply to mesh vertices */
122                 for(size_t i = 0; i < mesh->verts.size(); i++)
123                         mesh->verts[i] = transform_point(&tfm, mesh->verts[i]);
124                 
125                 if(apply_to_motion) {
126                         Attribute *attr = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
127
128                         if(attr) {
129                                 size_t steps_size = mesh->verts.size() * (mesh->motion_steps - 1);
130                                 float3 *vert_steps = attr->data_float3();
131
132                                 for(size_t i = 0; i < steps_size; i++)
133                                         vert_steps[i] = transform_point(&tfm, vert_steps[i]);
134                         }
135
136                         Attribute *attr_N = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_NORMAL);
137
138                         if(attr_N) {
139                                 Transform ntfm = mesh->transform_normal;
140                                 size_t steps_size = mesh->verts.size() * (mesh->motion_steps - 1);
141                                 float3 *normal_steps = attr_N->data_float3();
142
143                                 for(size_t i = 0; i < steps_size; i++)
144                                         normal_steps[i] = normalize(transform_direction(&ntfm, normal_steps[i]));
145                         }
146                 }
147         }
148
149         /* curves */
150         if(mesh->curve_keys.size()) {
151                 /* compute uniform scale */
152                 float3 c0 = transform_get_column(&tfm, 0);
153                 float3 c1 = transform_get_column(&tfm, 1);
154                 float3 c2 = transform_get_column(&tfm, 2);
155                 float scalar = pow(fabsf(dot(cross(c0, c1), c2)), 1.0f/3.0f);
156
157                 /* apply transform to curve keys */
158                 for(size_t i = 0; i < mesh->curve_keys.size(); i++) {
159                         float3 co = transform_point(&tfm, mesh->curve_keys[i]);
160                         float radius = mesh->curve_radius[i] * scalar;
161
162                         /* scale for curve radius is only correct for uniform scale */
163                         mesh->curve_keys[i] = co;
164                         mesh->curve_radius[i] = radius;
165                 }
166
167                 if(apply_to_motion) {
168                         Attribute *curve_attr = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
169
170                         if(curve_attr) {
171                                 /* apply transform to motion curve keys */
172                                 size_t steps_size = mesh->curve_keys.size() * (mesh->motion_steps - 1);
173                                 float4 *key_steps = curve_attr->data_float4();
174
175                                 for(size_t i = 0; i < steps_size; i++) {
176                                         float3 co = transform_point(&tfm, float4_to_float3(key_steps[i]));
177                                         float radius = key_steps[i].w * scalar;
178
179                                         /* scale for curve radius is only correct for uniform scale */
180                                         key_steps[i] = float3_to_float4(co);
181                                         key_steps[i].w = radius;
182                                 }
183                         }
184                 }
185         }
186
187         /* we keep normals pointing in same direction on negative scale, notify
188          * mesh about this in it (re)calculates normals */
189         if(transform_negative_scale(tfm))
190                 mesh->transform_negative_scaled = true;
191
192         if(bounds.valid()) {
193                 mesh->compute_bounds();
194                 compute_bounds(false);
195         }
196
197         /* tfm is not reset to identity, all code that uses it needs to check the
198          * transform_applied boolean */
199 }
200
201 void Object::tag_update(Scene *scene)
202 {
203         if(mesh) {
204                 if(mesh->transform_applied)
205                         mesh->need_update = true;
206
207                 foreach(Shader *shader, mesh->used_shaders) {
208                         if(shader->use_mis && shader->has_surface_emission)
209                                 scene->light_manager->need_update = true;
210                 }
211         }
212
213         scene->camera->need_flags_update = true;
214         scene->curve_system_manager->need_update = true;
215         scene->mesh_manager->need_update = true;
216         scene->object_manager->need_update = true;
217 }
218
219 vector<float> Object::motion_times()
220 {
221         /* compute times at which we sample motion for this object */
222         vector<float> times;
223
224         if(!mesh || mesh->motion_steps == 1)
225                 return times;
226
227         int motion_steps = mesh->motion_steps;
228
229         for(int step = 0; step < motion_steps; step++) {
230                 if(step != motion_steps / 2) {
231                         float time = 2.0f * step / (motion_steps - 1) - 1.0f;
232                         times.push_back(time);
233                 }
234         }
235
236         return times;
237 }
238
239 bool Object::is_traceable()
240 {
241         /* Mesh itself can be empty,can skip all such objects. */
242         if (!bounds.valid() || bounds.size() == make_float3(0.0f, 0.0f, 0.0f)) {
243                 return false;
244         }
245         /* TODO(sergey): Check for mesh vertices/curves. visibility flags. */
246         return true;
247 }
248
249 /* Object Manager */
250
251 ObjectManager::ObjectManager()
252 {
253         need_update = true;
254         need_flags_update = true;
255 }
256
257 ObjectManager::~ObjectManager()
258 {
259 }
260
261 void ObjectManager::device_update_object_transform(UpdateObejctTransformState *state,
262                                                    Object *ob,
263                                                    int object_index)
264 {
265         float4 *objects = state->objects;
266         float4 *objects_vector = state->objects_vector;
267
268         Mesh *mesh = ob->mesh;
269         uint flag = 0;
270
271         /* Compute transformations. */
272         Transform tfm = ob->tfm;
273         Transform itfm = transform_inverse(tfm);
274
275         /* Compute surface area. for uniform scale we can do avoid the many
276          * transform calls and share computation for instances.
277          *
278          * TODO(brecht): Correct for displacement, and move to a better place.
279          */
280         float uniform_scale;
281         float surface_area = 0.0f;
282         float pass_id = ob->pass_id;
283         float random_number = (float)ob->random_id * (1.0f/(float)0xFFFFFFFF);
284         int particle_index = (ob->particle_system)
285                 ? ob->particle_index + state->particle_offset[ob->particle_system]
286                 : 0;
287
288         if(transform_uniform_scale(tfm, uniform_scale)) {
289                 map<Mesh*, float>::iterator it;
290
291                 /* NOTE: This isn't fully optimal and could in theory lead to multiple
292                  * threads calculating area of the same mesh in parallel. However, this
293                  * also prevents suspending all the threads when some mesh's area is
294                  * not yet known.
295                  */
296                 state->surface_area_lock.lock();
297                 it = state->surface_area_map.find(mesh);
298                 state->surface_area_lock.unlock();
299
300                 if(it == state->surface_area_map.end()) {
301                         size_t num_triangles = mesh->num_triangles();
302                         for(size_t j = 0; j < num_triangles; j++) {
303                                 Mesh::Triangle t = mesh->get_triangle(j);
304                                 float3 p1 = mesh->verts[t.v[0]];
305                                 float3 p2 = mesh->verts[t.v[1]];
306                                 float3 p3 = mesh->verts[t.v[2]];
307
308                                 surface_area += triangle_area(p1, p2, p3);
309                         }
310
311                         state->surface_area_lock.lock();
312                         state->surface_area_map[mesh] = surface_area;
313                         state->surface_area_lock.unlock();
314                 }
315                 else {
316                         surface_area = it->second;
317                 }
318
319                 surface_area *= uniform_scale;
320         }
321         else {
322                 size_t num_triangles = mesh->num_triangles();
323                 for(size_t j = 0; j < num_triangles; j++) {
324                         Mesh::Triangle t = mesh->get_triangle(j);
325                         float3 p1 = transform_point(&tfm, mesh->verts[t.v[0]]);
326                         float3 p2 = transform_point(&tfm, mesh->verts[t.v[1]]);
327                         float3 p3 = transform_point(&tfm, mesh->verts[t.v[2]]);
328
329                         surface_area += triangle_area(p1, p2, p3);
330                 }
331         }
332
333         /* Pack in texture. */
334         int offset = object_index*OBJECT_SIZE;
335
336         /* OBJECT_TRANSFORM */
337         memcpy(&objects[offset], &tfm, sizeof(float4)*3);
338         /* OBJECT_INVERSE_TRANSFORM */
339         memcpy(&objects[offset+4], &itfm, sizeof(float4)*3);
340         /* OBJECT_PROPERTIES */
341         objects[offset+8] = make_float4(surface_area, pass_id, random_number, __int_as_float(particle_index));
342
343         if(state->need_motion == Scene::MOTION_PASS) {
344                 /* Motion transformations, is world/object space depending if mesh
345                  * comes with deformed position in object space, or if we transform
346                  * the shading point in world space.
347                  */
348                 Transform mtfm_pre = ob->motion.pre;
349                 Transform mtfm_post = ob->motion.post;
350
351                 /* In case of missing motion information for previous/next frame,
352                  * assume there is no motion. */
353                 if(!ob->use_motion || mtfm_pre == transform_empty()) {
354                         mtfm_pre = ob->tfm;
355                 }
356                 if(!ob->use_motion || mtfm_post == transform_empty()) {
357                         mtfm_post = ob->tfm;
358                 }
359
360                 if(!mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION)) {
361                         mtfm_pre = mtfm_pre * itfm;
362                         mtfm_post = mtfm_post * itfm;
363                 }
364                 else {
365                         flag |= SD_OBJECT_HAS_VERTEX_MOTION;
366                 }
367
368                 memcpy(&objects_vector[object_index*OBJECT_VECTOR_SIZE+0], &mtfm_pre, sizeof(float4)*3);
369                 memcpy(&objects_vector[object_index*OBJECT_VECTOR_SIZE+3], &mtfm_post, sizeof(float4)*3);
370         }
371 #ifdef __OBJECT_MOTION__
372         else if(state->need_motion == Scene::MOTION_BLUR) {
373                 if(ob->use_motion) {
374                         /* decompose transformations for interpolation. */
375                         DecompMotionTransform decomp;
376
377                         transform_motion_decompose(&decomp, &ob->motion, &ob->tfm);
378                         memcpy(&objects[offset], &decomp, sizeof(float4)*8);
379                         flag |= SD_OBJECT_MOTION;
380                         state->have_motion = true;
381                 }
382         }
383 #endif
384
385         if(mesh->use_motion_blur) {
386                 state->have_motion = true;
387         }
388
389         /* Dupli object coords and motion info. */
390         int totalsteps = mesh->motion_steps;
391         int numsteps = (totalsteps - 1)/2;
392         int numverts = mesh->verts.size();
393         int numkeys = mesh->curve_keys.size();
394
395         objects[offset+9] = make_float4(ob->dupli_generated[0], ob->dupli_generated[1], ob->dupli_generated[2], __int_as_float(numkeys));
396         objects[offset+10] = make_float4(ob->dupli_uv[0], ob->dupli_uv[1], __int_as_float(numsteps), __int_as_float(numverts));
397
398         /* Object flag. */
399         if(ob->use_holdout) {
400                 flag |= SD_HOLDOUT_MASK;
401         }
402         state->object_flag[object_index] = flag;
403
404         /* Have curves. */
405         if(mesh->num_curves()) {
406                 state->have_curves = true;
407         }
408 }
409
410 bool ObjectManager::device_update_object_transform_pop_work(
411         UpdateObejctTransformState *state,
412         int *start_index,
413         int *num_objects)
414 {
415         /* Tweakable parameter, number of objects per chunk.
416          * Too small value will cause some extra overhead due to spin lock,
417          * too big value might not use all threads nicely.
418          */
419         static const int OBJECTS_PER_TASK = 32;
420         bool have_work = false;
421         state->queue_lock.lock();
422         int num_scene_objects = state->scene->objects.size();
423         if(state->queue_start_object < num_scene_objects) {
424                 int count = min(OBJECTS_PER_TASK,
425                                 num_scene_objects - state->queue_start_object);
426                 *start_index = state->queue_start_object;
427                 *num_objects = count;
428                 state->queue_start_object += count;
429                 have_work = true;
430         }
431         state->queue_lock.unlock();
432         return have_work;
433 }
434
435 void ObjectManager::device_update_object_transform_task(
436         UpdateObejctTransformState *state)
437 {
438         int start_index, num_objects;
439         while(device_update_object_transform_pop_work(state,
440                                                       &start_index,
441                                                       &num_objects))
442         {
443                 for(int i = 0; i < num_objects; ++i) {
444                         const int object_index = start_index + i;
445                         Object *ob = state->scene->objects[object_index];
446                         device_update_object_transform(state, ob, object_index);
447                 }
448         }
449 }
450
451 void ObjectManager::device_update_transforms(Device *device,
452                                              DeviceScene *dscene,
453                                              Scene *scene,
454                                              uint *object_flag,
455                                              Progress& progress)
456 {
457         UpdateObejctTransformState state;
458         state.need_motion = scene->need_motion(device->info.advanced_shading);
459         state.have_motion = false;
460         state.have_curves = false;
461         state.scene = scene;
462         state.queue_start_object = 0;
463
464         state.object_flag = object_flag;
465         state.objects = dscene->objects.resize(OBJECT_SIZE*scene->objects.size());
466         if(state.need_motion == Scene::MOTION_PASS) {
467                 state.objects_vector = dscene->objects_vector.resize(OBJECT_VECTOR_SIZE*scene->objects.size());
468         }
469         else {
470                 state.objects_vector = NULL;
471         }
472
473         /* Particle system device offsets
474          * 0 is dummy particle, index starts at 1.
475          */
476         int numparticles = 1;
477         foreach(ParticleSystem *psys, scene->particle_systems) {
478                 state.particle_offset[psys] = numparticles;
479                 numparticles += psys->particles.size();
480         }
481
482         /* NOTE: If it's just a handful of objects we deal with them in a single
483          * thread to avoid threading overhead. However, this threshold is might
484          * need some tweaks to make mid-complex scenes optimal.
485          */
486         if(scene->objects.size() < 64) {
487                 int object_index = 0;
488                 foreach(Object *ob, scene->objects) {
489                         device_update_object_transform(&state, ob, object_index);
490                         object_index++;
491                         if(progress.get_cancel()) {
492                                 return;
493                         }
494                 }
495         }
496         else {
497                 const int num_threads = TaskScheduler::num_threads();
498                 TaskPool pool;
499                 for(int i = 0; i < num_threads; ++i) {
500                         pool.push(function_bind(
501                                 &ObjectManager::device_update_object_transform_task,
502                                 this,
503                                 &state));
504                 }
505                 pool.wait_work();
506                 if(progress.get_cancel()) {
507                         return;
508                 }
509         }
510
511         device->tex_alloc("__objects", dscene->objects);
512         if(state.need_motion == Scene::MOTION_PASS) {
513                 device->tex_alloc("__objects_vector", dscene->objects_vector);
514         }
515
516         dscene->data.bvh.have_motion = state.have_motion;
517         dscene->data.bvh.have_curves = state.have_curves;
518         dscene->data.bvh.have_instancing = true;
519 }
520
521 void ObjectManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
522 {
523         if(!need_update)
524                 return;
525
526         VLOG(1) << "Total " << scene->objects.size() << " objects.";
527
528         device_free(device, dscene);
529
530         if(scene->objects.size() == 0)
531                 return;
532
533         /* object info flag */
534         uint *object_flag = dscene->object_flag.resize(scene->objects.size());
535
536         /* set object transform matrices, before applying static transforms */
537         progress.set_status("Updating Objects", "Copying Transformations to device");
538         device_update_transforms(device, dscene, scene, object_flag, progress);
539
540         if(progress.get_cancel()) return;
541
542         /* prepare for static BVH building */
543         /* todo: do before to support getting object level coords? */
544         if(scene->params.bvh_type == SceneParams::BVH_STATIC) {
545                 progress.set_status("Updating Objects", "Applying Static Transformations");
546                 apply_static_transforms(dscene, scene, object_flag, progress);
547         }
548 }
549
550 void ObjectManager::device_update_flags(Device *device,
551                                         DeviceScene *dscene,
552                                         Scene *scene,
553                                         Progress& /*progress*/,
554                                         bool bounds_valid)
555 {
556         if(!need_update && !need_flags_update)
557                 return;
558
559         need_update = false;
560         need_flags_update = false;
561
562         if(scene->objects.size() == 0)
563                 return;
564
565         /* object info flag */
566         uint *object_flag = dscene->object_flag.get_data();
567
568         vector<Object *> volume_objects;
569         bool has_volume_objects = false;
570         foreach(Object *object, scene->objects) {
571                 if(object->mesh->has_volume) {
572                         if(bounds_valid) {
573                                 volume_objects.push_back(object);
574                         }
575                         has_volume_objects = true;
576                 }
577         }
578
579         int object_index = 0;
580         foreach(Object *object, scene->objects) {
581                 if(object->mesh->has_volume) {
582                         object_flag[object_index] |= SD_OBJECT_HAS_VOLUME;
583                 }
584                 else {
585                         object_flag[object_index] &= ~SD_OBJECT_HAS_VOLUME;
586                 }
587
588                 if(bounds_valid) {
589                         foreach(Object *volume_object, volume_objects) {
590                                 if(object == volume_object) {
591                                         continue;
592                                 }
593                                 if(object->bounds.intersects(volume_object->bounds)) {
594                                         object_flag[object_index] |= SD_OBJECT_INTERSECTS_VOLUME;
595                                         break;
596                                 }
597                         }
598                 }
599                 else if(has_volume_objects) {
600                         /* Not really valid, but can't make more reliable in the case
601                          * of bounds not being up to date.
602                          */
603                         object_flag[object_index] |= SD_OBJECT_INTERSECTS_VOLUME;
604                 }
605                 ++object_index;
606         }
607
608         /* allocate object flag */
609         device->tex_alloc("__object_flag", dscene->object_flag);
610 }
611
612 void ObjectManager::device_update_patch_map_offsets(Device *device, DeviceScene *dscene, Scene *scene)
613 {
614         if (scene->objects.size() == 0)
615                 return;
616
617         uint4* objects = (uint4*)dscene->objects.get_data();
618
619         bool update = false;
620
621         int object_index = 0;
622         foreach(Object *object, scene->objects) {
623                 int offset = object_index*OBJECT_SIZE + 11;
624
625                 Mesh* mesh = object->mesh;
626
627                 if(mesh->patch_table) {
628                         uint patch_map_offset = 2*(mesh->patch_table_offset + mesh->patch_table->total_size() -
629                                                    mesh->patch_table->num_nodes * PATCH_NODE_SIZE) - mesh->patch_offset;
630
631                         if(objects[offset].x != patch_map_offset) {
632                                 objects[offset].x = patch_map_offset;
633                                 update = true;
634                         }
635                 }
636
637                 object_index++;
638         }
639
640         if(update) {
641                 device->tex_free(dscene->objects);
642                 device->tex_alloc("__objects", dscene->objects);
643         }
644 }
645
646 void ObjectManager::device_free(Device *device, DeviceScene *dscene)
647 {
648         device->tex_free(dscene->objects);
649         dscene->objects.clear();
650
651         device->tex_free(dscene->objects_vector);
652         dscene->objects_vector.clear();
653
654         device->tex_free(dscene->object_flag);
655         dscene->object_flag.clear();
656 }
657
658 void ObjectManager::apply_static_transforms(DeviceScene *dscene, Scene *scene, uint *object_flag, Progress& progress)
659 {
660         /* todo: normals and displacement should be done before applying transform! */
661         /* todo: create objects/meshes in right order! */
662
663         /* counter mesh users */
664         map<Mesh*, int> mesh_users;
665 #ifdef __OBJECT_MOTION__
666         Scene::MotionType need_motion = scene->need_motion();
667         bool motion_blur = need_motion == Scene::MOTION_BLUR;
668         bool apply_to_motion = need_motion != Scene::MOTION_PASS;
669 #else
670         bool motion_blur = false;
671         bool apply_to_motion = false;
672 #endif
673         int i = 0;
674         bool have_instancing = false;
675
676         foreach(Object *object, scene->objects) {
677                 map<Mesh*, int>::iterator it = mesh_users.find(object->mesh);
678
679                 if(it == mesh_users.end())
680                         mesh_users[object->mesh] = 1;
681                 else
682                         it->second++;
683         }
684
685         if(progress.get_cancel()) return;
686
687         /* apply transforms for objects with single user meshes */
688         foreach(Object *object, scene->objects) {
689                 /* Annoying feedback loop here: we can't use is_instanced() because
690                  * it'll use uninitialized transform_applied flag.
691                  *
692                  * Could be solved by moving reference counter to Mesh.
693                  */
694                 if((mesh_users[object->mesh] == 1 && !object->mesh->has_surface_bssrdf) &&
695                    !object->mesh->has_true_displacement())
696                 {
697                         if(!(motion_blur && object->use_motion)) {
698                                 if(!object->mesh->transform_applied) {
699                                         object->apply_transform(apply_to_motion);
700                                         object->mesh->transform_applied = true;
701
702                                         if(progress.get_cancel()) return;
703                                 }
704
705                                 object_flag[i] |= SD_TRANSFORM_APPLIED;
706                                 if(object->mesh->transform_negative_scaled)
707                                         object_flag[i] |= SD_NEGATIVE_SCALE_APPLIED;
708                         }
709                         else
710                                 have_instancing = true;
711                 }
712                 else
713                         have_instancing = true;
714
715                 i++;
716         }
717
718         dscene->data.bvh.have_instancing = have_instancing;
719 }
720
721 void ObjectManager::tag_update(Scene *scene)
722 {
723         need_update = true;
724         scene->curve_system_manager->need_update = true;
725         scene->mesh_manager->need_update = true;
726         scene->light_manager->need_update = true;
727 }
728
729 CCL_NAMESPACE_END
730