1 /*
2 * Copyright 2011-2020 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 "render/hair.h"
18 #include "render/curves.h"
19 #include "render/scene.h"
20
21 CCL_NAMESPACE_BEGIN
22
23 /* Hair Curve */
24
bounds_grow(const int k,const float3 * curve_keys,const float * curve_radius,BoundBox & bounds) const25 void Hair::Curve::bounds_grow(const int k,
26 const float3 *curve_keys,
27 const float *curve_radius,
28 BoundBox &bounds) const
29 {
30 float3 P[4];
31
32 P[0] = curve_keys[max(first_key + k - 1, first_key)];
33 P[1] = curve_keys[first_key + k];
34 P[2] = curve_keys[first_key + k + 1];
35 P[3] = curve_keys[min(first_key + k + 2, first_key + num_keys - 1)];
36
37 float3 lower;
38 float3 upper;
39
40 curvebounds(&lower.x, &upper.x, P, 0);
41 curvebounds(&lower.y, &upper.y, P, 1);
42 curvebounds(&lower.z, &upper.z, P, 2);
43
44 float mr = max(curve_radius[first_key + k], curve_radius[first_key + k + 1]);
45
46 bounds.grow(lower, mr);
47 bounds.grow(upper, mr);
48 }
49
bounds_grow(const int k,const float3 * curve_keys,const float * curve_radius,const Transform & aligned_space,BoundBox & bounds) const50 void Hair::Curve::bounds_grow(const int k,
51 const float3 *curve_keys,
52 const float *curve_radius,
53 const Transform &aligned_space,
54 BoundBox &bounds) const
55 {
56 float3 P[4];
57
58 P[0] = curve_keys[max(first_key + k - 1, first_key)];
59 P[1] = curve_keys[first_key + k];
60 P[2] = curve_keys[first_key + k + 1];
61 P[3] = curve_keys[min(first_key + k + 2, first_key + num_keys - 1)];
62
63 P[0] = transform_point(&aligned_space, P[0]);
64 P[1] = transform_point(&aligned_space, P[1]);
65 P[2] = transform_point(&aligned_space, P[2]);
66 P[3] = transform_point(&aligned_space, P[3]);
67
68 float3 lower;
69 float3 upper;
70
71 curvebounds(&lower.x, &upper.x, P, 0);
72 curvebounds(&lower.y, &upper.y, P, 1);
73 curvebounds(&lower.z, &upper.z, P, 2);
74
75 float mr = max(curve_radius[first_key + k], curve_radius[first_key + k + 1]);
76
77 bounds.grow(lower, mr);
78 bounds.grow(upper, mr);
79 }
80
bounds_grow(float4 keys[4],BoundBox & bounds) const81 void Hair::Curve::bounds_grow(float4 keys[4], BoundBox &bounds) const
82 {
83 float3 P[4] = {
84 float4_to_float3(keys[0]),
85 float4_to_float3(keys[1]),
86 float4_to_float3(keys[2]),
87 float4_to_float3(keys[3]),
88 };
89
90 float3 lower;
91 float3 upper;
92
93 curvebounds(&lower.x, &upper.x, P, 0);
94 curvebounds(&lower.y, &upper.y, P, 1);
95 curvebounds(&lower.z, &upper.z, P, 2);
96
97 float mr = max(keys[1].w, keys[2].w);
98
99 bounds.grow(lower, mr);
100 bounds.grow(upper, mr);
101 }
102
motion_keys(const float3 * curve_keys,const float * curve_radius,const float3 * key_steps,size_t num_curve_keys,size_t num_steps,float time,size_t k0,size_t k1,float4 r_keys[2]) const103 void Hair::Curve::motion_keys(const float3 *curve_keys,
104 const float *curve_radius,
105 const float3 *key_steps,
106 size_t num_curve_keys,
107 size_t num_steps,
108 float time,
109 size_t k0,
110 size_t k1,
111 float4 r_keys[2]) const
112 {
113 /* Figure out which steps we need to fetch and their interpolation factor. */
114 const size_t max_step = num_steps - 1;
115 const size_t step = min((int)(time * max_step), max_step - 1);
116 const float t = time * max_step - step;
117 /* Fetch vertex coordinates. */
118 float4 curr_keys[2];
119 float4 next_keys[2];
120 keys_for_step(
121 curve_keys, curve_radius, key_steps, num_curve_keys, num_steps, step, k0, k1, curr_keys);
122 keys_for_step(
123 curve_keys, curve_radius, key_steps, num_curve_keys, num_steps, step + 1, k0, k1, next_keys);
124 /* Interpolate between steps. */
125 r_keys[0] = (1.0f - t) * curr_keys[0] + t * next_keys[0];
126 r_keys[1] = (1.0f - t) * curr_keys[1] + t * next_keys[1];
127 }
128
cardinal_motion_keys(const float3 * curve_keys,const float * curve_radius,const float3 * key_steps,size_t num_curve_keys,size_t num_steps,float time,size_t k0,size_t k1,size_t k2,size_t k3,float4 r_keys[4]) const129 void Hair::Curve::cardinal_motion_keys(const float3 *curve_keys,
130 const float *curve_radius,
131 const float3 *key_steps,
132 size_t num_curve_keys,
133 size_t num_steps,
134 float time,
135 size_t k0,
136 size_t k1,
137 size_t k2,
138 size_t k3,
139 float4 r_keys[4]) const
140 {
141 /* Figure out which steps we need to fetch and their interpolation factor. */
142 const size_t max_step = num_steps - 1;
143 const size_t step = min((int)(time * max_step), max_step - 1);
144 const float t = time * max_step - step;
145 /* Fetch vertex coordinates. */
146 float4 curr_keys[4];
147 float4 next_keys[4];
148 cardinal_keys_for_step(curve_keys,
149 curve_radius,
150 key_steps,
151 num_curve_keys,
152 num_steps,
153 step,
154 k0,
155 k1,
156 k2,
157 k3,
158 curr_keys);
159 cardinal_keys_for_step(curve_keys,
160 curve_radius,
161 key_steps,
162 num_curve_keys,
163 num_steps,
164 step + 1,
165 k0,
166 k1,
167 k2,
168 k3,
169 next_keys);
170 /* Interpolate between steps. */
171 r_keys[0] = (1.0f - t) * curr_keys[0] + t * next_keys[0];
172 r_keys[1] = (1.0f - t) * curr_keys[1] + t * next_keys[1];
173 r_keys[2] = (1.0f - t) * curr_keys[2] + t * next_keys[2];
174 r_keys[3] = (1.0f - t) * curr_keys[3] + t * next_keys[3];
175 }
176
keys_for_step(const float3 * curve_keys,const float * curve_radius,const float3 * key_steps,size_t num_curve_keys,size_t num_steps,size_t step,size_t k0,size_t k1,float4 r_keys[2]) const177 void Hair::Curve::keys_for_step(const float3 *curve_keys,
178 const float *curve_radius,
179 const float3 *key_steps,
180 size_t num_curve_keys,
181 size_t num_steps,
182 size_t step,
183 size_t k0,
184 size_t k1,
185 float4 r_keys[2]) const
186 {
187 k0 = max(k0, 0);
188 k1 = min(k1, num_keys - 1);
189 const size_t center_step = ((num_steps - 1) / 2);
190 if (step == center_step) {
191 /* Center step: regular key location. */
192 /* TODO(sergey): Consider adding make_float4(float3, float)
193 * function.
194 */
195 r_keys[0] = make_float4(curve_keys[first_key + k0].x,
196 curve_keys[first_key + k0].y,
197 curve_keys[first_key + k0].z,
198 curve_radius[first_key + k0]);
199 r_keys[1] = make_float4(curve_keys[first_key + k1].x,
200 curve_keys[first_key + k1].y,
201 curve_keys[first_key + k1].z,
202 curve_radius[first_key + k1]);
203 }
204 else {
205 /* Center step is not stored in this array. */
206 if (step > center_step) {
207 step--;
208 }
209 const size_t offset = first_key + step * num_curve_keys;
210 r_keys[0] = make_float4(key_steps[offset + k0].x,
211 key_steps[offset + k0].y,
212 key_steps[offset + k0].z,
213 curve_radius[first_key + k0]);
214 r_keys[1] = make_float4(key_steps[offset + k1].x,
215 key_steps[offset + k1].y,
216 key_steps[offset + k1].z,
217 curve_radius[first_key + k1]);
218 }
219 }
220
cardinal_keys_for_step(const float3 * curve_keys,const float * curve_radius,const float3 * key_steps,size_t num_curve_keys,size_t num_steps,size_t step,size_t k0,size_t k1,size_t k2,size_t k3,float4 r_keys[4]) const221 void Hair::Curve::cardinal_keys_for_step(const float3 *curve_keys,
222 const float *curve_radius,
223 const float3 *key_steps,
224 size_t num_curve_keys,
225 size_t num_steps,
226 size_t step,
227 size_t k0,
228 size_t k1,
229 size_t k2,
230 size_t k3,
231 float4 r_keys[4]) const
232 {
233 k0 = max(k0, 0);
234 k3 = min(k3, num_keys - 1);
235 const size_t center_step = ((num_steps - 1) / 2);
236 if (step == center_step) {
237 /* Center step: regular key location. */
238 r_keys[0] = make_float4(curve_keys[first_key + k0].x,
239 curve_keys[first_key + k0].y,
240 curve_keys[first_key + k0].z,
241 curve_radius[first_key + k0]);
242 r_keys[1] = make_float4(curve_keys[first_key + k1].x,
243 curve_keys[first_key + k1].y,
244 curve_keys[first_key + k1].z,
245 curve_radius[first_key + k1]);
246 r_keys[2] = make_float4(curve_keys[first_key + k2].x,
247 curve_keys[first_key + k2].y,
248 curve_keys[first_key + k2].z,
249 curve_radius[first_key + k2]);
250 r_keys[3] = make_float4(curve_keys[first_key + k3].x,
251 curve_keys[first_key + k3].y,
252 curve_keys[first_key + k3].z,
253 curve_radius[first_key + k3]);
254 }
255 else {
256 /* Center step is not stored in this array. */
257 if (step > center_step) {
258 step--;
259 }
260 const size_t offset = first_key + step * num_curve_keys;
261 r_keys[0] = make_float4(key_steps[offset + k0].x,
262 key_steps[offset + k0].y,
263 key_steps[offset + k0].z,
264 curve_radius[first_key + k0]);
265 r_keys[1] = make_float4(key_steps[offset + k1].x,
266 key_steps[offset + k1].y,
267 key_steps[offset + k1].z,
268 curve_radius[first_key + k1]);
269 r_keys[2] = make_float4(key_steps[offset + k2].x,
270 key_steps[offset + k2].y,
271 key_steps[offset + k2].z,
272 curve_radius[first_key + k2]);
273 r_keys[3] = make_float4(key_steps[offset + k3].x,
274 key_steps[offset + k3].y,
275 key_steps[offset + k3].z,
276 curve_radius[first_key + k3]);
277 }
278 }
279
280 /* Hair */
281
NODE_DEFINE(Hair)282 NODE_DEFINE(Hair)
283 {
284 NodeType *type = NodeType::add("hair", create, NodeType::NONE, Geometry::node_base_type);
285
286 SOCKET_POINT_ARRAY(curve_keys, "Curve Keys", array<float3>());
287 SOCKET_FLOAT_ARRAY(curve_radius, "Curve Radius", array<float>());
288 SOCKET_INT_ARRAY(curve_first_key, "Curve First Key", array<int>());
289 SOCKET_INT_ARRAY(curve_shader, "Curve Shader", array<int>());
290
291 return type;
292 }
293
Hair()294 Hair::Hair() : Geometry(node_type, Geometry::HAIR)
295 {
296 curvekey_offset = 0;
297 curve_shape = CURVE_RIBBON;
298 }
299
~Hair()300 Hair::~Hair()
301 {
302 }
303
resize_curves(int numcurves,int numkeys)304 void Hair::resize_curves(int numcurves, int numkeys)
305 {
306 curve_keys.resize(numkeys);
307 curve_radius.resize(numkeys);
308 curve_first_key.resize(numcurves);
309 curve_shader.resize(numcurves);
310
311 attributes.resize();
312 }
313
reserve_curves(int numcurves,int numkeys)314 void Hair::reserve_curves(int numcurves, int numkeys)
315 {
316 curve_keys.reserve(numkeys);
317 curve_radius.reserve(numkeys);
318 curve_first_key.reserve(numcurves);
319 curve_shader.reserve(numcurves);
320
321 attributes.resize(true);
322 }
323
clear()324 void Hair::clear()
325 {
326 Geometry::clear();
327
328 curve_keys.clear();
329 curve_radius.clear();
330 curve_first_key.clear();
331 curve_shader.clear();
332
333 attributes.clear();
334 }
335
add_curve_key(float3 co,float radius)336 void Hair::add_curve_key(float3 co, float radius)
337 {
338 curve_keys.push_back_reserved(co);
339 curve_radius.push_back_reserved(radius);
340 }
341
add_curve(int first_key,int shader)342 void Hair::add_curve(int first_key, int shader)
343 {
344 curve_first_key.push_back_reserved(first_key);
345 curve_shader.push_back_reserved(shader);
346 }
347
copy_center_to_motion_step(const int motion_step)348 void Hair::copy_center_to_motion_step(const int motion_step)
349 {
350 Attribute *attr_mP = attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
351 if (attr_mP) {
352 float3 *keys = &curve_keys[0];
353 size_t numkeys = curve_keys.size();
354 memcpy(attr_mP->data_float3() + motion_step * numkeys, keys, sizeof(float3) * numkeys);
355 }
356 }
357
get_uv_tiles(ustring map,unordered_set<int> & tiles)358 void Hair::get_uv_tiles(ustring map, unordered_set<int> &tiles)
359 {
360 Attribute *attr;
361
362 if (map.empty()) {
363 attr = attributes.find(ATTR_STD_UV);
364 }
365 else {
366 attr = attributes.find(map);
367 }
368
369 if (attr) {
370 attr->get_uv_tiles(this, ATTR_PRIM_GEOMETRY, tiles);
371 }
372 }
373
compute_bounds()374 void Hair::compute_bounds()
375 {
376 BoundBox bnds = BoundBox::empty;
377 size_t curve_keys_size = curve_keys.size();
378
379 if (curve_keys_size > 0) {
380 for (size_t i = 0; i < curve_keys_size; i++)
381 bnds.grow(curve_keys[i], curve_radius[i]);
382
383 Attribute *curve_attr = attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
384 if (use_motion_blur && curve_attr) {
385 size_t steps_size = curve_keys.size() * (motion_steps - 1);
386 float3 *key_steps = curve_attr->data_float3();
387
388 for (size_t i = 0; i < steps_size; i++)
389 bnds.grow(key_steps[i]);
390 }
391
392 if (!bnds.valid()) {
393 bnds = BoundBox::empty;
394
395 /* skip nan or inf coordinates */
396 for (size_t i = 0; i < curve_keys_size; i++)
397 bnds.grow_safe(curve_keys[i], curve_radius[i]);
398
399 if (use_motion_blur && curve_attr) {
400 size_t steps_size = curve_keys.size() * (motion_steps - 1);
401 float3 *key_steps = curve_attr->data_float3();
402
403 for (size_t i = 0; i < steps_size; i++)
404 bnds.grow_safe(key_steps[i]);
405 }
406 }
407 }
408
409 if (!bnds.valid()) {
410 /* empty mesh */
411 bnds.grow(make_float3(0.0f, 0.0f, 0.0f));
412 }
413
414 bounds = bnds;
415 }
416
apply_transform(const Transform & tfm,const bool apply_to_motion)417 void Hair::apply_transform(const Transform &tfm, const bool apply_to_motion)
418 {
419 /* compute uniform scale */
420 float3 c0 = transform_get_column(&tfm, 0);
421 float3 c1 = transform_get_column(&tfm, 1);
422 float3 c2 = transform_get_column(&tfm, 2);
423 float scalar = powf(fabsf(dot(cross(c0, c1), c2)), 1.0f / 3.0f);
424
425 /* apply transform to curve keys */
426 for (size_t i = 0; i < curve_keys.size(); i++) {
427 float3 co = transform_point(&tfm, curve_keys[i]);
428 float radius = curve_radius[i] * scalar;
429
430 /* scale for curve radius is only correct for uniform scale */
431 curve_keys[i] = co;
432 curve_radius[i] = radius;
433 }
434
435 if (apply_to_motion) {
436 Attribute *curve_attr = attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
437
438 if (curve_attr) {
439 /* apply transform to motion curve keys */
440 size_t steps_size = curve_keys.size() * (motion_steps - 1);
441 float4 *key_steps = curve_attr->data_float4();
442
443 for (size_t i = 0; i < steps_size; i++) {
444 float3 co = transform_point(&tfm, float4_to_float3(key_steps[i]));
445 float radius = key_steps[i].w * scalar;
446
447 /* scale for curve radius is only correct for uniform scale */
448 key_steps[i] = float3_to_float4(co);
449 key_steps[i].w = radius;
450 }
451 }
452 }
453 }
454
pack_curves(Scene * scene,float4 * curve_key_co,float4 * curve_data,size_t curvekey_offset)455 void Hair::pack_curves(Scene *scene,
456 float4 *curve_key_co,
457 float4 *curve_data,
458 size_t curvekey_offset)
459 {
460 size_t curve_keys_size = curve_keys.size();
461
462 /* pack curve keys */
463 if (curve_keys_size) {
464 float3 *keys_ptr = curve_keys.data();
465 float *radius_ptr = curve_radius.data();
466
467 for (size_t i = 0; i < curve_keys_size; i++)
468 curve_key_co[i] = make_float4(keys_ptr[i].x, keys_ptr[i].y, keys_ptr[i].z, radius_ptr[i]);
469 }
470
471 /* pack curve segments */
472 size_t curve_num = num_curves();
473
474 for (size_t i = 0; i < curve_num; i++) {
475 Curve curve = get_curve(i);
476 int shader_id = curve_shader[i];
477 Shader *shader = (shader_id < used_shaders.size()) ? used_shaders[shader_id] :
478 scene->default_surface;
479 shader_id = scene->shader_manager->get_shader_id(shader, false);
480
481 curve_data[i] = make_float4(__int_as_float(curve.first_key + curvekey_offset),
482 __int_as_float(curve.num_keys),
483 __int_as_float(shader_id),
484 0.0f);
485 }
486 }
487
488 CCL_NAMESPACE_END
489