c06cf86ea9cca709b110a179ac656e0f992a23de
[blender-staging.git] / intern / cycles / render / mesh_displace.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 "device/device.h"
18
19 #include "render/mesh.h"
20 #include "render/object.h"
21 #include "render/scene.h"
22 #include "render/shader.h"
23
24 #include "util/util_foreach.h"
25 #include "util/util_progress.h"
26
27 CCL_NAMESPACE_BEGIN
28
29 static float3 compute_face_normal(const Mesh::Triangle& t, float3 *verts)
30 {
31         float3 v0 = verts[t.v[0]];
32         float3 v1 = verts[t.v[1]];
33         float3 v2 = verts[t.v[2]];
34
35         float3 norm = cross(v1 - v0, v2 - v0);
36         float normlen = len(norm);
37
38         if(normlen == 0.0f)
39                 return make_float3(1.0f, 0.0f, 0.0f);
40
41         return norm / normlen;
42 }
43
44 bool MeshManager::displace(Device *device, DeviceScene *dscene, Scene *scene, Mesh *mesh, Progress& progress)
45 {
46         /* verify if we have a displacement shader */
47         if(!mesh->has_true_displacement()) {
48                 return false;
49         }
50
51         string msg = string_printf("Computing Displacement %s", mesh->name.c_str());
52         progress.set_status("Updating Mesh", msg);
53
54         /* find object index. todo: is arbitrary */
55         size_t object_index = OBJECT_NONE;
56
57         for(size_t i = 0; i < scene->objects.size(); i++) {
58                 if(scene->objects[i]->mesh == mesh) {
59                         object_index = i;
60                         break;
61                 }
62         }
63
64         /* setup input for device task */
65         const size_t num_verts = mesh->verts.size();
66         vector<bool> done(num_verts, false);
67         device_vector<uint4> d_input(device, "displace_input", MEM_READ_ONLY);
68         uint4 *d_input_data = d_input.resize(num_verts);
69         size_t d_input_size = 0;
70
71         size_t num_triangles = mesh->num_triangles();
72         for(size_t i = 0; i < num_triangles; i++) {
73                 Mesh::Triangle t = mesh->get_triangle(i);
74                 int shader_index = mesh->shader[i];
75                 Shader *shader = (shader_index < mesh->used_shaders.size()) ?
76                         mesh->used_shaders[shader_index] : scene->default_surface;
77
78                 if(!shader->has_displacement || shader->displacement_method == DISPLACE_BUMP) {
79                         continue;
80                 }
81
82                 for(int j = 0; j < 3; j++) {
83                         if(done[t.v[j]])
84                                 continue;
85
86                         done[t.v[j]] = true;
87
88                         /* set up object, primitive and barycentric coordinates */
89                         int object = object_index;
90                         int prim = mesh->tri_offset + i;
91                         float u, v;
92                         
93                         switch(j) {
94                                 case 0:
95                                         u = 1.0f;
96                                         v = 0.0f;
97                                         break;
98                                 case 1:
99                                         u = 0.0f;
100                                         v = 1.0f;
101                                         break;
102                                 default:
103                                         u = 0.0f;
104                                         v = 0.0f;
105                                         break;
106                         }
107
108                         /* back */
109                         uint4 in = make_uint4(object, prim, __float_as_int(u), __float_as_int(v));
110                         d_input_data[d_input_size++] = in;
111                 }
112         }
113
114         if(d_input_size == 0)
115                 return false;
116         
117         /* run device task */
118         device_vector<float4> d_output(device, "displace_output", MEM_WRITE_ONLY);
119         d_output.resize(d_input_size);
120
121         /* needs to be up to data for attribute access */
122         device->const_copy_to("__data", &dscene->data, sizeof(dscene->data));
123
124         device->mem_alloc(d_input);
125         device->mem_copy_to(d_input);
126         device->mem_alloc(d_output);
127         device->mem_zero(d_output);
128
129         DeviceTask task(DeviceTask::SHADER);
130         task.shader_input = d_input.device_pointer;
131         task.shader_output = d_output.device_pointer;
132         task.shader_eval_type = SHADER_EVAL_DISPLACE;
133         task.shader_x = 0;
134         task.shader_w = d_output.size();
135         task.num_samples = 1;
136         task.get_cancel = function_bind(&Progress::get_cancel, &progress);
137
138         device->task_add(task);
139         device->task_wait();
140
141         if(progress.get_cancel()) {
142                 device->mem_free(d_input);
143                 device->mem_free(d_output);
144                 return false;
145         }
146
147         device->mem_copy_from(d_output, 0, 1, d_output.size(), sizeof(float4));
148         device->mem_free(d_input);
149         device->mem_free(d_output);
150
151         /* read result */
152         done.clear();
153         done.resize(num_verts, false);
154         int k = 0;
155
156         float4 *offset = (float4*)d_output.data_pointer;
157
158         Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
159         for(size_t i = 0; i < num_triangles; i++) {
160                 Mesh::Triangle t = mesh->get_triangle(i);
161                 int shader_index = mesh->shader[i];
162                 Shader *shader = (shader_index < mesh->used_shaders.size()) ?
163                         mesh->used_shaders[shader_index] : scene->default_surface;
164
165                 if(!shader->has_displacement || shader->displacement_method == DISPLACE_BUMP) {
166                         continue;
167                 }
168
169                 for(int j = 0; j < 3; j++) {
170                         if(!done[t.v[j]]) {
171                                 done[t.v[j]] = true;
172                                 float3 off = float4_to_float3(offset[k++]);
173                                 /* Avoid illegal vertex coordinates. */
174                                 off = ensure_finite3(off);
175                                 mesh->verts[t.v[j]] += off;
176                                 if(attr_mP != NULL) {
177                                         for(int step = 0; step < mesh->motion_steps - 1; step++) {
178                                                 float3 *mP = attr_mP->data_float3() + step*num_verts;
179                                                 mP[t.v[j]] += off;
180                                         }
181                                 }
182                         }
183                 }
184         }
185
186         /* for displacement method both, we only need to recompute the face
187          * normals, as bump mapping in the shader will already alter the
188          * vertex normal, so we start from the non-displaced vertex normals
189          * to avoid applying the perturbation twice. */
190         mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
191         mesh->add_face_normals();
192
193         bool need_recompute_vertex_normals = false;
194
195         foreach(Shader *shader, mesh->used_shaders) {
196                 if(shader->has_displacement && shader->displacement_method == DISPLACE_TRUE) {
197                         need_recompute_vertex_normals = true;
198                         break;
199                 }
200         }
201
202         if(need_recompute_vertex_normals) {
203                 bool flip = mesh->transform_negative_scaled;
204                 vector<bool> tri_has_true_disp(num_triangles, false);
205
206                 for(size_t i = 0; i < num_triangles; i++) {
207                         int shader_index = mesh->shader[i];
208                         Shader *shader = (shader_index < mesh->used_shaders.size()) ?
209                                 mesh->used_shaders[shader_index] : scene->default_surface;
210
211                         tri_has_true_disp[i] = shader->has_displacement && shader->displacement_method == DISPLACE_TRUE;
212                 }
213
214                 /* static vertex normals */
215
216                 /* get attributes */
217                 Attribute *attr_fN = mesh->attributes.find(ATTR_STD_FACE_NORMAL);
218                 Attribute *attr_vN = mesh->attributes.find(ATTR_STD_VERTEX_NORMAL);
219
220                 float3 *fN = attr_fN->data_float3();
221                 float3 *vN = attr_vN->data_float3();
222
223                 /* compute vertex normals */
224
225                 /* zero vertex normals on triangles with true displacement */
226                 for(size_t i = 0; i < num_triangles; i++) {
227                         if(tri_has_true_disp[i]) {
228                                 for(size_t j = 0; j < 3; j++) {
229                                         vN[mesh->get_triangle(i).v[j]] = make_float3(0.0f, 0.0f, 0.0f);
230                                 }
231                         }
232                 }
233
234                 /* add face normals to vertex normals */
235                 for(size_t i = 0; i < num_triangles; i++) {
236                         if(tri_has_true_disp[i]) {
237                                 for(size_t j = 0; j < 3; j++) {
238                                         vN[mesh->get_triangle(i).v[j]] += fN[i];
239                                 }
240                         }
241                 }
242
243                 /* normalize vertex normals */
244                 done.clear();
245                 done.resize(num_verts, false);
246
247                 for(size_t i = 0; i < num_triangles; i++) {
248                         if(tri_has_true_disp[i]) {
249                                 for(size_t j = 0; j < 3; j++) {
250                                         int vert = mesh->get_triangle(i).v[j];
251
252                                         if(done[vert]) {
253                                                 continue;
254                                         }
255
256                                         vN[vert] = normalize(vN[vert]);
257                                         if(flip)
258                                                 vN[vert] = -vN[vert];
259
260                                         done[vert] = true;
261                                 }
262                         }
263                 }
264
265                 /* motion vertex normals */
266                 Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
267                 Attribute *attr_mN = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_NORMAL);
268
269                 if(mesh->has_motion_blur() && attr_mP && attr_mN) {
270                         for(int step = 0; step < mesh->motion_steps - 1; step++) {
271                                 float3 *mP = attr_mP->data_float3() + step*mesh->verts.size();
272                                 float3 *mN = attr_mN->data_float3() + step*mesh->verts.size();
273
274                                 /* compute */
275
276                                 /* zero vertex normals on triangles with true displacement */
277                                 for(size_t i = 0; i < num_triangles; i++) {
278                                         if(tri_has_true_disp[i]) {
279                                                 for(size_t j = 0; j < 3; j++) {
280                                                         mN[mesh->get_triangle(i).v[j]] = make_float3(0.0f, 0.0f, 0.0f);
281                                                 }
282                                         }
283                                 }
284
285                                 /* add face normals to vertex normals */
286                                 for(size_t i = 0; i < num_triangles; i++) {
287                                         if(tri_has_true_disp[i]) {
288                                                 for(size_t j = 0; j < 3; j++) {
289                                                         float3 fN = compute_face_normal(mesh->get_triangle(i), mP);
290                                                         mN[mesh->get_triangle(i).v[j]] += fN;
291                                                 }
292                                         }
293                                 }
294
295                                 /* normalize vertex normals */
296                                 done.clear();
297                                 done.resize(num_verts, false);
298
299                                 for(size_t i = 0; i < num_triangles; i++) {
300                                         if(tri_has_true_disp[i]) {
301                                                 for(size_t j = 0; j < 3; j++) {
302                                                         int vert = mesh->get_triangle(i).v[j];
303
304                                                         if(done[vert]) {
305                                                                 continue;
306                                                         }
307
308                                                         mN[vert] = normalize(mN[vert]);
309                                                         if(flip)
310                                                                 mN[vert] = -mN[vert];
311
312                                                         done[vert] = true;
313                                                 }
314                                         }
315                                 }
316                         }
317                 }
318         }
319
320         return true;
321 }
322
323 CCL_NAMESPACE_END
324