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