~ubuntu-branches/ubuntu/trusty/blender/trusty

« back to all changes in this revision

Viewing changes to intern/cycles/render/object.cpp

  • Committer: Package Import Robot
  • Author(s): Jeremy Bicha
  • Date: 2013-03-06 12:08:47 UTC
  • mfrom: (1.5.1) (14.1.8 experimental)
  • Revision ID: package-import@ubuntu.com-20130306120847-frjfaryb2zrotwcg
Tags: 2.66a-1ubuntu1
* Resynchronize with Debian (LP: #1076930, #1089256, #1052743, #999024,
  #1122888, #1147084)
* debian/control:
  - Lower build-depends on libavcodec-dev since we're not
    doing the libav9 transition in Ubuntu yet

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
#include "device.h"
20
20
#include "light.h"
21
21
#include "mesh.h"
 
22
#include "curves.h"
22
23
#include "object.h"
23
24
#include "scene.h"
24
25
 
25
26
#include "util_foreach.h"
26
27
#include "util_map.h"
27
28
#include "util_progress.h"
 
29
#include "util_vector.h"
28
30
 
29
31
CCL_NAMESPACE_BEGIN
30
32
 
36
38
        mesh = NULL;
37
39
        tfm = transform_identity();
38
40
        visibility = ~0;
 
41
        random_id = 0;
39
42
        pass_id = 0;
 
43
        particle_id = 0;
 
44
        bounds = BoundBox::empty;
 
45
        motion.pre = transform_identity();
 
46
        motion.post = transform_identity();
 
47
        use_motion = false;
 
48
        use_holdout = false;
 
49
        curverender = false;
40
50
}
41
51
 
42
52
Object::~Object()
43
53
{
44
54
}
45
55
 
46
 
void Object::compute_bounds()
 
56
void Object::compute_bounds(bool motion_blur, float shuttertime)
47
57
{
48
 
        bounds = mesh->bounds.transformed(&tfm);
 
58
        BoundBox mbounds = mesh->bounds;
 
59
 
 
60
        if(motion_blur && use_motion) {
 
61
                DecompMotionTransform decomp;
 
62
                transform_motion_decompose(&decomp, &motion, &tfm);
 
63
 
 
64
                bounds = BoundBox::empty;
 
65
 
 
66
                /* todo: this is really terrible. according to pbrt there is a better
 
67
                 * way to find this iteratively, but did not find implementation yet
 
68
                 * or try to implement myself */
 
69
                float start_t = 0.5f - shuttertime*0.25f;
 
70
                float end_t = 0.5f + shuttertime*0.25f;
 
71
 
 
72
                for(float t = start_t; t < end_t; t += (1.0f/128.0f)*shuttertime) {
 
73
                        Transform ttfm;
 
74
 
 
75
                        transform_motion_interpolate(&ttfm, &decomp, t);
 
76
                        bounds.grow(mbounds.transformed(&ttfm));
 
77
                }
 
78
        }
 
79
        else
 
80
                bounds = mbounds.transformed(&tfm);
49
81
}
50
82
 
51
83
void Object::apply_transform()
52
84
{
53
85
        if(!mesh || tfm == transform_identity())
54
86
                return;
55
 
        
 
87
 
 
88
        float3 c0 = transform_get_column(&tfm, 0);
 
89
        float3 c1 = transform_get_column(&tfm, 1);
 
90
        float3 c2 = transform_get_column(&tfm, 2);
 
91
        float scalar = pow(fabsf(dot(cross(c0, c1), c2)), 1.0f/3.0f);
 
92
 
56
93
        for(size_t i = 0; i < mesh->verts.size(); i++)
57
94
                mesh->verts[i] = transform_point(&tfm, mesh->verts[i]);
58
95
 
59
 
        Attribute *attr_fN = mesh->attributes.find(Attribute::STD_FACE_NORMAL);
60
 
        Attribute *attr_vN = mesh->attributes.find(Attribute::STD_VERTEX_NORMAL);
 
96
        for(size_t i = 0; i < mesh->curve_keys.size(); i++) {
 
97
                mesh->curve_keys[i].co = transform_point(&tfm, mesh->curve_keys[i].co);
 
98
                /* scale for strand radius - only correct for uniform transforms*/
 
99
                mesh->curve_keys[i].radius *= scalar;
 
100
        }
61
101
 
62
 
        Transform ntfm = transform_transpose(transform_inverse(tfm));
 
102
        /* store matrix to transform later. when accessing these as attributes we
 
103
         * do not want the transform to be applied for consistency between static
 
104
         * and dynamic BVH, so we do it on packing. */
 
105
        mesh->transform_normal = transform_transpose(transform_inverse(tfm));
63
106
 
64
107
        /* we keep normals pointing in same direction on negative scale, notify
65
 
           mesh about this in it (re)calculates normals */
 
108
         * mesh about this in it (re)calculates normals */
66
109
        if(transform_negative_scale(tfm))
67
110
                mesh->transform_negative_scaled = true;
68
111
 
69
 
        if(attr_fN) {
70
 
                float3 *fN = attr_fN->data_float3();
71
 
 
72
 
                for(size_t i = 0; i < mesh->triangles.size(); i++)
73
 
                        fN[i] = transform_direction(&ntfm, fN[i]);
74
 
        }
75
 
 
76
 
        if(attr_vN) {
77
 
                float3 *vN = attr_vN->data_float3();
78
 
 
79
 
                for(size_t i = 0; i < mesh->verts.size(); i++)
80
 
                        vN[i] = transform_direction(&ntfm, vN[i]);
81
 
        }
82
 
 
83
112
        if(bounds.valid()) {
84
113
                mesh->compute_bounds();
85
 
                compute_bounds();
 
114
                compute_bounds(false, 0.0f);
86
115
        }
87
 
        
88
 
        tfm = transform_identity();
 
116
 
 
117
        /* tfm is not reset to identity, all code that uses it needs to check the
 
118
           transform_applied boolean */
89
119
}
90
120
 
91
121
void Object::tag_update(Scene *scene)
102
132
                }
103
133
        }
104
134
 
 
135
        scene->curve_system_manager->need_update = true;
105
136
        scene->mesh_manager->need_update = true;
106
137
        scene->object_manager->need_update = true;
107
138
}
117
148
{
118
149
}
119
150
 
120
 
void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
 
151
void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene, Scene *scene, uint *object_flag, Progress& progress)
121
152
{
122
 
        float4 *objects = dscene->objects.resize(OBJECT_SIZE*scene->objects.size());
 
153
        float4 *objects;
 
154
        float4 *objects_vector = NULL;
123
155
        int i = 0;
124
156
        map<Mesh*, float> surface_area_map;
 
157
        Scene::MotionType need_motion = scene->need_motion(device->info.advanced_shading);
 
158
        bool have_motion = false;
 
159
 
 
160
        objects = dscene->objects.resize(OBJECT_SIZE*scene->objects.size());
 
161
        if(need_motion == Scene::MOTION_PASS)
 
162
                objects_vector = dscene->objects_vector.resize(OBJECT_VECTOR_SIZE*scene->objects.size());
125
163
 
126
164
        foreach(Object *ob, scene->objects) {
127
165
                Mesh *mesh = ob->mesh;
 
166
                uint flag = 0;
128
167
 
129
168
                /* compute transformations */
130
169
                Transform tfm = ob->tfm;
131
170
                Transform itfm = transform_inverse(tfm);
132
 
                Transform ntfm = transform_transpose(itfm);
133
171
 
134
172
                /* compute surface area. for uniform scale we can do avoid the many
135
 
                   transform calls and share computation for instances */
 
173
                 * transform calls and share computation for instances */
136
174
                /* todo: correct for displacement, and move to a better place */
137
175
                float uniform_scale;
138
176
                float surface_area = 0.0f;
139
177
                float pass_id = ob->pass_id;
 
178
                float random_number = (float)ob->random_id * (1.0f/(float)0xFFFFFFFF);
140
179
                
141
180
                if(transform_uniform_scale(tfm, uniform_scale)) {
142
181
                        map<Mesh*, float>::iterator it = surface_area_map.find(mesh);
150
189
                                        surface_area += triangle_area(p1, p2, p3);
151
190
                                }
152
191
 
 
192
                                foreach(Mesh::Curve& curve, mesh->curves) {
 
193
                                        int first_key = curve.first_key;
 
194
 
 
195
                                        for(int i = 0; i < curve.num_segments(); i++) {
 
196
                                                float3 p1 = mesh->curve_keys[first_key + i].co;
 
197
                                                float r1 = mesh->curve_keys[first_key + i].radius;
 
198
                                                float3 p2 = mesh->curve_keys[first_key + i + 1].co;
 
199
                                                float r2 = mesh->curve_keys[first_key + i + 1].radius;
 
200
 
 
201
                                                /* currently ignores segment overlaps*/
 
202
                                                surface_area += M_PI_F *(r1 + r2) * len(p1 - p2);
 
203
                                        }
 
204
                                }
 
205
 
153
206
                                surface_area_map[mesh] = surface_area;
154
207
                        }
155
208
                        else
165
218
 
166
219
                                surface_area += triangle_area(p1, p2, p3);
167
220
                        }
 
221
 
 
222
                        foreach(Mesh::Curve& curve, mesh->curves) {
 
223
                                int first_key = curve.first_key;
 
224
 
 
225
                                for(int i = 0; i < curve.num_segments(); i++) {
 
226
                                        float3 p1 = mesh->curve_keys[first_key + i].co;
 
227
                                        float r1 = mesh->curve_keys[first_key + i].radius;
 
228
                                        float3 p2 = mesh->curve_keys[first_key + i + 1].co;
 
229
                                        float r2 = mesh->curve_keys[first_key + i + 1].radius;
 
230
 
 
231
                                        p1 = transform_point(&tfm, p1);
 
232
                                        p2 = transform_point(&tfm, p2);
 
233
 
 
234
                                        /* currently ignores segment overlaps*/
 
235
                                        surface_area += M_PI_F *(r1 + r2) * len(p1 - p2);
 
236
                                }
 
237
                        }
168
238
                }
169
239
 
170
240
                /* pack in texture */
171
241
                int offset = i*OBJECT_SIZE;
172
242
 
173
 
                memcpy(&objects[offset], &tfm, sizeof(float4)*4);
174
 
                memcpy(&objects[offset+4], &itfm, sizeof(float4)*4);
175
 
                memcpy(&objects[offset+8], &ntfm, sizeof(float4)*4);
176
 
                objects[offset+12] = make_float4(surface_area, pass_id, 0.0f, 0.0f);
 
243
                memcpy(&objects[offset], &tfm, sizeof(float4)*3);
 
244
                memcpy(&objects[offset+4], &itfm, sizeof(float4)*3);
 
245
                objects[offset+8] = make_float4(surface_area, pass_id, random_number, __int_as_float(ob->particle_id));
 
246
 
 
247
                if(need_motion == Scene::MOTION_PASS) {
 
248
                        /* motion transformations, is world/object space depending if mesh
 
249
                         * comes with deformed position in object space, or if we transform
 
250
                         * the shading point in world space */
 
251
                        Transform mtfm_pre = ob->motion.pre;
 
252
                        Transform mtfm_post = ob->motion.post;
 
253
 
 
254
                        if(!mesh->attributes.find(ATTR_STD_MOTION_PRE))
 
255
                                mtfm_pre = mtfm_pre * itfm;
 
256
                        if(!mesh->attributes.find(ATTR_STD_MOTION_POST))
 
257
                                mtfm_post = mtfm_post * itfm;
 
258
 
 
259
                        memcpy(&objects_vector[i*OBJECT_VECTOR_SIZE+0], &mtfm_pre, sizeof(float4)*3);
 
260
                        memcpy(&objects_vector[i*OBJECT_VECTOR_SIZE+3], &mtfm_post, sizeof(float4)*3);
 
261
                }
 
262
#ifdef __OBJECT_MOTION__
 
263
                else if(need_motion == Scene::MOTION_BLUR) {
 
264
                        if(ob->use_motion) {
 
265
                                /* decompose transformations for interpolation */
 
266
                                DecompMotionTransform decomp;
 
267
 
 
268
                                transform_motion_decompose(&decomp, &ob->motion, &ob->tfm);
 
269
                                memcpy(&objects[offset], &decomp, sizeof(float4)*8);
 
270
                                flag |= SD_OBJECT_MOTION;
 
271
                                have_motion = true;
 
272
                        }
 
273
                }
 
274
#endif
 
275
 
 
276
                /* dupli object coords */
 
277
                objects[offset+9] = make_float4(ob->dupli_generated[0], ob->dupli_generated[1], ob->dupli_generated[2], 0.0f);
 
278
                objects[offset+10] = make_float4(ob->dupli_uv[0], ob->dupli_uv[1], 0.0f, 0.0f);
 
279
 
 
280
                /* object flag */
 
281
                if(ob->use_holdout)
 
282
                        flag |= SD_HOLDOUT_MASK;
 
283
                object_flag[i] = flag;
177
284
 
178
285
                i++;
179
286
 
181
288
        }
182
289
 
183
290
        device->tex_alloc("__objects", dscene->objects);
 
291
        if(need_motion == Scene::MOTION_PASS)
 
292
                device->tex_alloc("__objects_vector", dscene->objects_vector);
 
293
 
 
294
        dscene->data.bvh.have_motion = have_motion;
184
295
}
185
296
 
186
297
void ObjectManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
190
301
        
191
302
        device_free(device, dscene);
192
303
 
 
304
        need_update = false;
 
305
 
193
306
        if(scene->objects.size() == 0)
194
307
                return;
195
308
 
 
309
        /* object info flag */
 
310
        uint *object_flag = dscene->object_flag.resize(scene->objects.size());
 
311
 
196
312
        /* set object transform matrices, before applying static transforms */
197
313
        progress.set_status("Updating Objects", "Copying Transformations to device");
198
 
        device_update_transforms(device, dscene, scene, progress);
 
314
        device_update_transforms(device, dscene, scene, object_flag, progress);
199
315
 
200
316
        if(progress.get_cancel()) return;
201
317
 
203
319
        /* todo: do before to support getting object level coords? */
204
320
        if(scene->params.bvh_type == SceneParams::BVH_STATIC) {
205
321
                progress.set_status("Updating Objects", "Applying Static Transformations");
206
 
                apply_static_transforms(scene, progress);
 
322
                apply_static_transforms(scene, object_flag, progress);
207
323
        }
208
324
 
209
 
        if(progress.get_cancel()) return;
210
 
 
211
 
        need_update = false;
 
325
        /* allocate object flag */
 
326
        device->tex_alloc("__object_flag", dscene->object_flag);
212
327
}
213
328
 
214
329
void ObjectManager::device_free(Device *device, DeviceScene *dscene)
215
330
{
216
331
        device->tex_free(dscene->objects);
217
332
        dscene->objects.clear();
 
333
 
 
334
        device->tex_free(dscene->objects_vector);
 
335
        dscene->objects_vector.clear();
 
336
 
 
337
        device->tex_free(dscene->object_flag);
 
338
        dscene->object_flag.clear();
218
339
}
219
340
 
220
 
void ObjectManager::apply_static_transforms(Scene *scene, Progress& progress)
 
341
void ObjectManager::apply_static_transforms(Scene *scene, uint *object_flag, Progress& progress)
221
342
{
222
343
        /* todo: normals and displacement should be done before applying transform! */
223
344
        /* todo: create objects/meshes in right order! */
224
345
 
225
346
        /* counter mesh users */
226
347
        map<Mesh*, int> mesh_users;
 
348
#ifdef __OBJECT_MOTION__
 
349
        Scene::MotionType need_motion = scene->need_motion();
 
350
        bool motion_blur = need_motion == Scene::MOTION_BLUR;
 
351
#else
 
352
        bool motion_blur = false;
 
353
#endif
 
354
        int i = 0;
227
355
 
228
356
        foreach(Object *object, scene->objects) {
229
357
                map<Mesh*, int>::iterator it = mesh_users.find(object->mesh);
239
367
        /* apply transforms for objects with single user meshes */
240
368
        foreach(Object *object, scene->objects) {
241
369
                if(mesh_users[object->mesh] == 1) {
242
 
                        if(!object->mesh->transform_applied) {
243
 
                                object->apply_transform();
244
 
                                object->mesh->transform_applied = true;
 
370
                        if(!(motion_blur && object->use_motion)) {
 
371
                                if(!object->mesh->transform_applied) {
 
372
                                        object->apply_transform();
 
373
                                        object->mesh->transform_applied = true;
 
374
 
 
375
                                        if(progress.get_cancel()) return;
 
376
                                }
 
377
 
 
378
                                object_flag[i] |= SD_TRANSFORM_APPLIED;
245
379
                        }
246
 
 
247
 
                        if(progress.get_cancel()) return;
248
380
                }
 
381
 
 
382
                i++;
249
383
        }
250
384
}
251
385
 
252
386
void ObjectManager::tag_update(Scene *scene)
253
387
{
254
388
        need_update = true;
 
389
        scene->curve_system_manager->need_update = true;
255
390
        scene->mesh_manager->need_update = true;
256
391
        scene->light_manager->need_update = true;
257
392
}