37
39
tfm = transform_identity();
44
bounds = BoundBox::empty;
45
motion.pre = transform_identity();
46
motion.post = transform_identity();
46
void Object::compute_bounds()
56
void Object::compute_bounds(bool motion_blur, float shuttertime)
48
bounds = mesh->bounds.transformed(&tfm);
58
BoundBox mbounds = mesh->bounds;
60
if(motion_blur && use_motion) {
61
DecompMotionTransform decomp;
62
transform_motion_decompose(&decomp, &motion, &tfm);
64
bounds = BoundBox::empty;
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;
72
for(float t = start_t; t < end_t; t += (1.0f/128.0f)*shuttertime) {
75
transform_motion_interpolate(&ttfm, &decomp, t);
76
bounds.grow(mbounds.transformed(&ttfm));
80
bounds = mbounds.transformed(&tfm);
51
83
void Object::apply_transform()
53
85
if(!mesh || tfm == transform_identity())
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);
56
93
for(size_t i = 0; i < mesh->verts.size(); i++)
57
94
mesh->verts[i] = transform_point(&tfm, mesh->verts[i]);
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;
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));
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;
70
float3 *fN = attr_fN->data_float3();
72
for(size_t i = 0; i < mesh->triangles.size(); i++)
73
fN[i] = transform_direction(&ntfm, fN[i]);
77
float3 *vN = attr_vN->data_float3();
79
for(size_t i = 0; i < mesh->verts.size(); i++)
80
vN[i] = transform_direction(&ntfm, vN[i]);
83
112
if(bounds.valid()) {
84
113
mesh->compute_bounds();
114
compute_bounds(false, 0.0f);
88
tfm = transform_identity();
117
/* tfm is not reset to identity, all code that uses it needs to check the
118
transform_applied boolean */
91
121
void Object::tag_update(Scene *scene)
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)
122
float4 *objects = dscene->objects.resize(OBJECT_SIZE*scene->objects.size());
154
float4 *objects_vector = NULL;
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;
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());
126
164
foreach(Object *ob, scene->objects) {
127
165
Mesh *mesh = ob->mesh;
129
168
/* compute transformations */
130
169
Transform tfm = ob->tfm;
131
170
Transform itfm = transform_inverse(tfm);
132
Transform ntfm = transform_transpose(itfm);
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);
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);
192
foreach(Mesh::Curve& curve, mesh->curves) {
193
int first_key = curve.first_key;
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;
201
/* currently ignores segment overlaps*/
202
surface_area += M_PI_F *(r1 + r2) * len(p1 - p2);
153
206
surface_area_map[mesh] = surface_area;
166
219
surface_area += triangle_area(p1, p2, p3);
222
foreach(Mesh::Curve& curve, mesh->curves) {
223
int first_key = curve.first_key;
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;
231
p1 = transform_point(&tfm, p1);
232
p2 = transform_point(&tfm, p2);
234
/* currently ignores segment overlaps*/
235
surface_area += M_PI_F *(r1 + r2) * len(p1 - p2);
170
240
/* pack in texture */
171
241
int offset = i*OBJECT_SIZE;
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));
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;
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;
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);
262
#ifdef __OBJECT_MOTION__
263
else if(need_motion == Scene::MOTION_BLUR) {
265
/* decompose transformations for interpolation */
266
DecompMotionTransform decomp;
268
transform_motion_decompose(&decomp, &ob->motion, &ob->tfm);
269
memcpy(&objects[offset], &decomp, sizeof(float4)*8);
270
flag |= SD_OBJECT_MOTION;
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);
282
flag |= SD_HOLDOUT_MASK;
283
object_flag[i] = flag;
191
302
device_free(device, dscene);
193
306
if(scene->objects.size() == 0)
309
/* object info flag */
310
uint *object_flag = dscene->object_flag.resize(scene->objects.size());
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);
200
316
if(progress.get_cancel()) return;
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);
209
if(progress.get_cancel()) return;
325
/* allocate object flag */
326
device->tex_alloc("__object_flag", dscene->object_flag);
214
329
void ObjectManager::device_free(Device *device, DeviceScene *dscene)
216
331
device->tex_free(dscene->objects);
217
332
dscene->objects.clear();
334
device->tex_free(dscene->objects_vector);
335
dscene->objects_vector.clear();
337
device->tex_free(dscene->object_flag);
338
dscene->object_flag.clear();
220
void ObjectManager::apply_static_transforms(Scene *scene, Progress& progress)
341
void ObjectManager::apply_static_transforms(Scene *scene, uint *object_flag, Progress& progress)
222
343
/* todo: normals and displacement should be done before applying transform! */
223
344
/* todo: create objects/meshes in right order! */
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;
352
bool motion_blur = false;
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;
375
if(progress.get_cancel()) return;
378
object_flag[i] |= SD_TRANSFORM_APPLIED;
247
if(progress.get_cancel()) return;
252
386
void ObjectManager::tag_update(Scene *scene)
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;