Blender V5.0
hair.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#include <algorithm>
6
7#include "bvh/bvh.h"
8
9#include "scene/curves.h"
10#include "scene/hair.h"
11#include "scene/object.h"
12#include "scene/scene.h"
13
15
16#include "util/progress.h"
17#include "util/tbb.h"
18
20
21/* Hair Curve */
22void Hair::Curve::bounds_grow(const int k, const float4 *keys, BoundBox &bounds) const
23{
24 float3 P[4];
25
26 P[0] = make_float3(keys[max(first_key + k - 1, first_key)]);
27 P[1] = make_float3(keys[first_key + k]);
28 P[2] = make_float3(keys[first_key + k + 1]);
29 P[3] = make_float3(keys[min(first_key + k + 2, first_key + num_keys - 1)]);
30
31 float3 lower;
32 float3 upper;
33
34 curvebounds(&lower.x, &upper.x, P, 0);
35 curvebounds(&lower.y, &upper.y, P, 1);
36 curvebounds(&lower.z, &upper.z, P, 2);
37
38 const float mr = max(keys[1].w, keys[2].w);
39
40 bounds.grow(lower, mr);
41 bounds.grow(upper, mr);
42}
43
44void Hair::Curve::bounds_grow(const int k,
45 const float3 *curve_keys,
46 const float *curve_radius,
47 BoundBox &bounds) const
48{
49 float3 P[4];
50
51 P[0] = curve_keys[max(first_key + k - 1, first_key)];
52 P[1] = curve_keys[first_key + k];
53 P[2] = curve_keys[first_key + k + 1];
54 P[3] = curve_keys[min(first_key + k + 2, first_key + num_keys - 1)];
55
56 float3 lower;
57 float3 upper;
58
59 curvebounds(&lower.x, &upper.x, P, 0);
60 curvebounds(&lower.y, &upper.y, P, 1);
61 curvebounds(&lower.z, &upper.z, P, 2);
62
63 const float mr = max(curve_radius[first_key + k], curve_radius[first_key + k + 1]);
64
65 bounds.grow(lower, mr);
66 bounds.grow(upper, mr);
67}
68
69void Hair::Curve::bounds_grow(const int k,
70 const float3 *curve_keys,
71 const float *curve_radius,
72 const Transform &aligned_space,
73 BoundBox &bounds) const
74{
75 float3 P[4];
76
77 P[0] = curve_keys[max(first_key + k - 1, first_key)];
78 P[1] = curve_keys[first_key + k];
79 P[2] = curve_keys[first_key + k + 1];
80 P[3] = curve_keys[min(first_key + k + 2, first_key + num_keys - 1)];
81
82 P[0] = transform_point(&aligned_space, P[0]);
83 P[1] = transform_point(&aligned_space, P[1]);
84 P[2] = transform_point(&aligned_space, P[2]);
85 P[3] = transform_point(&aligned_space, P[3]);
86
87 float3 lower;
88 float3 upper;
89
90 curvebounds(&lower.x, &upper.x, P, 0);
91 curvebounds(&lower.y, &upper.y, P, 1);
92 curvebounds(&lower.z, &upper.z, P, 2);
93
94 const float mr = max(curve_radius[first_key + k], curve_radius[first_key + k + 1]);
95
96 bounds.grow(lower, mr);
97 bounds.grow(upper, mr);
98}
99
101{
102 float3 P[4] = {
103 make_float3(keys[0]),
104 make_float3(keys[1]),
105 make_float3(keys[2]),
106 make_float3(keys[3]),
107 };
108
109 float3 lower;
110 float3 upper;
111
112 curvebounds(&lower.x, &upper.x, P, 0);
113 curvebounds(&lower.y, &upper.y, P, 1);
114 curvebounds(&lower.z, &upper.z, P, 2);
115
116 const float mr = max(keys[1].w, keys[2].w);
117
118 bounds.grow(lower, mr);
119 bounds.grow(upper, mr);
120}
121
122void Hair::Curve::motion_keys(const float3 *curve_keys,
123 const float *curve_radius,
124 const float4 *key_steps,
125 const size_t num_curve_keys,
126 const size_t num_steps,
127 const float time,
128 size_t k0,
129 size_t k1,
130 float4 r_keys[2]) const
131{
132 /* Figure out which steps we need to fetch and their interpolation factor. */
133 const size_t max_step = num_steps - 1;
134 const size_t step = std::min((size_t)(time * max_step), max_step - 1);
135 const float t = time * max_step - step;
136 /* Fetch vertex coordinates. */
137 float4 curr_keys[2];
138 float4 next_keys[2];
140 curve_keys, curve_radius, key_steps, num_curve_keys, num_steps, step, k0, k1, curr_keys);
142 curve_keys, curve_radius, key_steps, num_curve_keys, num_steps, step + 1, k0, k1, next_keys);
143 /* Interpolate between steps. */
144 r_keys[0] = (1.0f - t) * curr_keys[0] + t * next_keys[0];
145 r_keys[1] = (1.0f - t) * curr_keys[1] + t * next_keys[1];
146}
147
149 const float *curve_radius,
150 const float4 *key_steps,
151 const size_t num_curve_keys,
152 const size_t num_steps,
153 const float time,
154 size_t k0,
155 size_t k1,
156 size_t k2,
157 size_t k3,
158 float4 r_keys[4]) const
159{
160 /* Figure out which steps we need to fetch and their interpolation factor. */
161 const size_t max_step = num_steps - 1;
162 const size_t step = min((size_t)(time * max_step), max_step - 1);
163 const float t = time * max_step - step;
164 /* Fetch vertex coordinates. */
165 float4 curr_keys[4];
166 float4 next_keys[4];
167 cardinal_keys_for_step(curve_keys,
168 curve_radius,
169 key_steps,
170 num_curve_keys,
171 num_steps,
172 step,
173 k0,
174 k1,
175 k2,
176 k3,
177 curr_keys);
178 cardinal_keys_for_step(curve_keys,
179 curve_radius,
180 key_steps,
181 num_curve_keys,
182 num_steps,
183 step + 1,
184 k0,
185 k1,
186 k2,
187 k3,
188 next_keys);
189 /* Interpolate between steps. */
190 r_keys[0] = (1.0f - t) * curr_keys[0] + t * next_keys[0];
191 r_keys[1] = (1.0f - t) * curr_keys[1] + t * next_keys[1];
192 r_keys[2] = (1.0f - t) * curr_keys[2] + t * next_keys[2];
193 r_keys[3] = (1.0f - t) * curr_keys[3] + t * next_keys[3];
194}
195
196void Hair::Curve::keys_for_step(const float3 *curve_keys,
197 const float *curve_radius,
198 const float4 *key_steps,
199 const size_t num_curve_keys,
200 const size_t num_steps,
201 size_t step,
202 size_t k0,
203 size_t k1,
204 float4 r_keys[2]) const
205{
206 k0 = max(k0, (size_t)0);
207 k1 = min(k1, (size_t)(num_keys - 1));
208 const size_t center_step = ((num_steps - 1) / 2);
209 if (step == center_step) {
210 /* Center step: regular key location. */
211 r_keys[0] = make_float4(curve_keys[first_key + k0], curve_radius[first_key + k0]);
212 r_keys[1] = make_float4(curve_keys[first_key + k1], curve_radius[first_key + k1]);
213 }
214 else {
215 /* Center step is not stored in this array. */
216 if (step > center_step) {
217 step--;
218 }
219 const size_t offset = first_key + step * num_curve_keys;
220 r_keys[0] = make_float4(key_steps[offset + k0].x,
221 key_steps[offset + k0].y,
222 key_steps[offset + k0].z,
223 curve_radius[first_key + k0]);
224 r_keys[1] = make_float4(key_steps[offset + k1].x,
225 key_steps[offset + k1].y,
226 key_steps[offset + k1].z,
227 curve_radius[first_key + k1]);
228 }
229}
230
232 const float *curve_radius,
233 const float4 *key_steps,
234 const size_t num_curve_keys,
235 const size_t num_steps,
236 size_t step,
237 size_t k0,
238 size_t k1,
239 size_t k2,
240 size_t k3,
241 float4 r_keys[4]) const
242{
243 k0 = max(k0, (size_t)0);
244 k3 = min(k3, (size_t)(num_keys - 1));
245 const size_t center_step = ((num_steps - 1) / 2);
246 if (step == center_step) {
247 /* Center step: regular key location. */
248 r_keys[0] = make_float4(curve_keys[first_key + k0], curve_radius[first_key + k0]);
249 r_keys[1] = make_float4(curve_keys[first_key + k1], curve_radius[first_key + k1]);
250 r_keys[2] = make_float4(curve_keys[first_key + k2], curve_radius[first_key + k2]);
251 r_keys[3] = make_float4(curve_keys[first_key + k3], curve_radius[first_key + k3]);
252 }
253 else {
254 /* Center step is not stored in this array. */
255 if (step > center_step) {
256 step--;
257 }
258 const size_t offset = first_key + step * num_curve_keys;
259 r_keys[0] = make_float4(key_steps[offset + k0].x,
260 key_steps[offset + k0].y,
261 key_steps[offset + k0].z,
262 curve_radius[first_key + k0]);
263 r_keys[1] = make_float4(key_steps[offset + k1].x,
264 key_steps[offset + k1].y,
265 key_steps[offset + k1].z,
266 curve_radius[first_key + k1]);
267 r_keys[2] = make_float4(key_steps[offset + k2].x,
268 key_steps[offset + k2].y,
269 key_steps[offset + k2].z,
270 curve_radius[first_key + k2]);
271 r_keys[3] = make_float4(key_steps[offset + k3].x,
272 key_steps[offset + k3].y,
273 key_steps[offset + k3].z,
274 curve_radius[first_key + k3]);
275 }
276}
277
278/* Hair */
279
281{
282 NodeType *type = NodeType::add("hair", create, NodeType::NONE, Geometry::get_node_base_type());
283
284 SOCKET_POINT_ARRAY(curve_keys, "Curve Keys", array<float3>());
285 SOCKET_FLOAT_ARRAY(curve_radius, "Curve Radius", array<float>());
286 SOCKET_INT_ARRAY(curve_first_key, "Curve First Key", array<int>());
287 SOCKET_INT_ARRAY(curve_shader, "Curve Shader", array<int>());
288
289 return type;
290}
291
292Hair::Hair() : Geometry(get_node_type(), Geometry::HAIR)
293{
297}
298
299Hair::~Hair() = default;
300
301void Hair::resize_curves(const int numcurves, const int numkeys)
302{
303 curve_keys.resize(numkeys);
304 curve_radius.resize(numkeys);
305 curve_first_key.resize(numcurves);
306 curve_shader.resize(numcurves);
307
308 attributes.resize();
309}
310
311void Hair::reserve_curves(const int numcurves, const int numkeys)
312{
313 curve_keys.reserve(numkeys);
314 curve_radius.reserve(numkeys);
315 curve_first_key.reserve(numcurves);
316 curve_shader.reserve(numcurves);
317
318 attributes.resize(true);
319}
320
321void Hair::clear(bool preserve_shaders)
322{
323 Geometry::clear(preserve_shaders);
324
325 curve_keys.clear();
326 curve_radius.clear();
327 curve_first_key.clear();
328 curve_shader.clear();
329
330 attributes.clear();
331}
332
333void Hair::add_curve_key(const float3 co, const float radius)
334{
335 curve_keys.push_back_reserved(co);
336 curve_radius.push_back_reserved(radius);
337
338 tag_curve_keys_modified();
339 tag_curve_radius_modified();
340}
341
342void Hair::add_curve(const int first_key, const int shader)
343{
344 curve_first_key.push_back_reserved(first_key);
345 curve_shader.push_back_reserved(shader);
346
347 tag_curve_first_key_modified();
348 tag_curve_shader_modified();
349}
350
352{
354 if (attr_mP) {
355 float3 *keys = curve_keys.data();
356 const size_t numkeys = curve_keys.size();
357 std::copy_n(keys, numkeys, attr_mP->data_float3() + motion_step * numkeys);
358 }
359}
360
361void Hair::get_uv_tiles(ustring map, unordered_set<int> &tiles)
362{
363 Attribute *attr;
364
365 if (map.empty()) {
366 attr = attributes.find(ATTR_STD_UV);
367 }
368 else {
369 attr = attributes.find(map);
370 }
371
372 if (attr) {
374 }
375}
376
378{
380 const size_t curve_keys_size = curve_keys.size();
381 const size_t curve_num = num_curves();
382
383 if (curve_keys_size > 0) {
385 blocked_range<size_t>(0, curve_num),
387 [&](const blocked_range<size_t> &range, const BoundBox &partial_bounds) {
388 BoundBox current_bounds = partial_bounds;
389 for (size_t i = range.begin(); i < range.end(); ++i) {
390 const Curve curve = get_curve(i);
391 const int num_segments = curve.num_segments();
392 for (int k = 0; k < num_segments; k++) {
393 curve.bounds_grow(k, curve_keys.data(), curve_radius.data(), current_bounds);
394 }
395 }
396 return current_bounds;
397 },
398 [](const BoundBox &bounds_a, const BoundBox &bounds_b) {
399 BoundBox combined_bounds = bounds_a;
400 combined_bounds.grow(bounds_b);
401 return combined_bounds;
402 }));
403
405 if (use_motion_blur && curve_attr) {
406 const size_t steps_size = curve_keys.size() * (motion_steps - 1);
407 // Attribute data is stored as a float4 and is not
408 // interchangeable with float3
409 float4 *key_steps = curve_attr->data_float4();
410
411 for (size_t i = 0; i < steps_size; i++) {
412 bnds.grow(make_float3(key_steps[i]));
413 }
414 }
415
416 if (!bnds.valid()) {
417 bnds = BoundBox::empty;
418
419 /* skip nan or inf coordinates */
420 for (size_t i = 0; i < curve_keys_size; i++) {
421 bnds.grow_safe(curve_keys[i], curve_radius[i]);
422 }
423
424 if (use_motion_blur && curve_attr) {
425 const size_t steps_size = curve_keys.size() * (motion_steps - 1);
426 // Attribute data is stored as a float4 which is not
427 // interchangeable with float4
428 float4 *key_steps = curve_attr->data_float4();
429
430 for (size_t i = 0; i < steps_size; i++) {
431 bnds.grow_safe(make_float3(key_steps[i]));
432 }
433 }
434 }
435 }
436
437 if (!bnds.valid()) {
438 /* empty mesh */
439 bnds.grow(zero_float3());
440 }
441
442 bounds = bnds;
443}
444
445void Hair::apply_transform(const Transform &tfm, const bool apply_to_motion)
446{
447 /* compute uniform scale */
448 const float3 c0 = transform_get_column(&tfm, 0);
449 const float3 c1 = transform_get_column(&tfm, 1);
450 const float3 c2 = transform_get_column(&tfm, 2);
451 const float scalar = powf(fabsf(dot(cross(c0, c1), c2)), 1.0f / 3.0f);
452
453 /* apply transform to curve keys */
454 for (size_t i = 0; i < curve_keys.size(); i++) {
455 const float3 co = transform_point(&tfm, curve_keys[i]);
456 const float radius = curve_radius[i] * scalar;
457
458 /* scale for curve radius is only correct for uniform scale */
459 curve_keys[i] = co;
460 curve_radius[i] = radius;
461 }
462
463 tag_curve_keys_modified();
464 tag_curve_radius_modified();
465
466 if (apply_to_motion) {
468
469 if (curve_attr) {
470 /* apply transform to motion curve keys */
471 const size_t steps_size = curve_keys.size() * (motion_steps - 1);
472 float4 *key_steps = curve_attr->data_float4();
473
474 for (size_t i = 0; i < steps_size; i++) {
475 const float3 co = transform_point(&tfm, make_float3(key_steps[i]));
476 const float radius = key_steps[i].w * scalar;
477
478 /* scale for curve radius is only correct for uniform scale */
479 key_steps[i] = make_float4(co);
480 key_steps[i].w = radius;
481 }
482 }
483 }
484}
485
487 float4 *curve_key_co,
488 KernelCurve *curves,
489 KernelCurveSegment *curve_segments)
490{
491 const size_t curve_keys_size = curve_keys.size();
492
493 /* pack curve keys */
494 if (curve_keys_size) {
495 float3 *keys_ptr = curve_keys.data();
496 float *radius_ptr = curve_radius.data();
497
498 for (size_t i = 0; i < curve_keys_size; i++) {
499 curve_key_co[i] = make_float4(keys_ptr[i], radius_ptr[i]);
500 }
501 }
502
503 /* pack curve segments */
505
506 const size_t curve_num = num_curves();
507 size_t index = 0;
508
509 for (size_t i = 0; i < curve_num; i++) {
510 const Curve curve = get_curve(i);
511 int shader_id = curve_shader[i];
512 Shader *shader = (shader_id < used_shaders.size()) ?
513 static_cast<Shader *>(used_shaders[shader_id]) :
514 scene->default_surface;
515 shader_id = scene->shader_manager->get_shader_id(shader, false);
516
517 curves[i].shader_id = shader_id;
518 curves[i].first_key = curve_key_offset + curve.first_key;
519 curves[i].num_keys = curve.num_keys;
520 curves[i].type = type;
521
522 for (int k = 0; k < curve.num_segments(); ++k, ++index) {
523 curve_segments[index].prim = prim_offset + i;
524 curve_segments[index].type = PRIMITIVE_PACK_SEGMENT(type, k);
525 }
526 }
527}
528
539
540/* Fill in coordinates for curve transparency shader evaluation on device. */
541static int fill_shader_input(const Hair *hair,
542 const size_t object_index,
544{
545 int d_input_size = 0;
546 KernelShaderEvalInput *d_input_data = d_input.data();
547
548 const int num_curves = hair->num_curves();
549 for (int i = 0; i < num_curves; i++) {
550 const Hair::Curve curve = hair->get_curve(i);
551 const int num_segments = curve.num_segments();
552
553 for (int j = 0; j < num_segments + 1; j++) {
555 in.object = object_index;
556 in.prim = hair->prim_offset + i;
557 in.u = (j < num_segments) ? 0.0f : 1.0f;
558 in.v = (j < num_segments) ? __int_as_float(j) : __int_as_float(j - 1);
559 d_input_data[d_input_size++] = in;
560 }
561 }
562
563 return d_input_size;
564}
565
566/* Read back curve transparency shader output. */
567static void read_shader_output(float *shadow_transparency,
568 bool &is_fully_opaque,
569 const device_vector<float> &d_output)
570{
571 const int num_keys = d_output.size();
572 const float *output_data = d_output.data();
573 bool is_opaque = true;
574
575 for (int i = 0; i < num_keys; i++) {
576 shadow_transparency[i] = output_data[i];
577 if (shadow_transparency[i] > 0.0f) {
578 is_opaque = false;
579 }
580 }
581
582 is_fully_opaque = is_opaque;
583}
584
586{
587 if (!is_traceable()) {
588 return false;
589 }
590
591 for (const Node *node : used_shaders) {
592 const Shader *shader = static_cast<const Shader *>(node);
593 if (shader->has_surface_transparent && shader->get_use_transparent_shadow()) {
594 return true;
595 }
596 }
597
598 return false;
599}
600
602{
604 /* If no shaders with shadow transparency, remove attribute. */
606 if (attr) {
607 attributes.remove(attr);
608 return true;
609 }
610 return false;
611 }
612
613 const string msg = string_printf("Computing Shadow Transparency %s", name.c_str());
614 progress.set_status("Updating Hair", msg);
615
616 /* Create shadow transparency attribute. */
618 const bool attribute_exists = (attr != nullptr);
619 if (!attribute_exists) {
621 }
622
623 float *attr_data = attr->data_float();
624
625 /* Find object index. */
626 size_t object_index = OBJECT_NONE;
627
628 for (size_t i = 0; i < scene->objects.size(); i++) {
629 if (scene->objects[i]->get_geometry() == this) {
630 object_index = i;
631 break;
632 }
633 }
634
635 /* Evaluate shader on device. */
636 ShaderEval shader_eval(device, progress);
637 bool is_fully_opaque = false;
638 shader_eval.eval(
640 num_keys(),
641 1,
642 [this, object_index](device_vector<KernelShaderEvalInput> &d_input) {
643 return fill_shader_input(this, object_index, d_input);
644 },
645 [attr_data, &is_fully_opaque](const device_vector<float> &d_output) {
646 read_shader_output(attr_data, is_fully_opaque, d_output);
647 });
648
649 if (is_fully_opaque) {
650 attributes.remove(attr);
651 return attribute_exists;
652 }
653
654 return true;
655}
656
struct BoundBox BoundBox
SIMD_FORCE_INLINE const btScalar & z() const
Return the z value.
Definition btQuadWord.h:117
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
int motion_step(const float time) const
BoundBox bounds
size_t prim_offset
virtual bool has_motion_blur() const
AttributeSet attributes
Geometry(const NodeType *node_type, const Type type)
virtual void clear(bool preserve_shaders=false)
Definition hair.h:13
bool is_traceable() const
Definition hair.h:136
void add_curve_key(const float3 co, const float radius)
Definition hair.cpp:333
bool need_shadow_transparency()
Definition hair.cpp:585
Curve get_curve(const size_t i) const
Definition hair.h:111
void compute_bounds() override
Definition hair.cpp:377
size_t curve_key_offset
Definition hair.h:89
size_t curve_segment_offset
Definition hair.h:90
void add_curve(const int first_key, const int shader)
Definition hair.cpp:342
size_t num_curves() const
Definition hair.h:126
bool update_shadow_transparency(Device *device, Scene *scene, Progress &progress)
Definition hair.cpp:601
void get_uv_tiles(ustring map, unordered_set< int > &tiles) override
Definition hair.cpp:361
void copy_center_to_motion_step(const int motion_step)
Definition hair.cpp:351
void resize_curves(const int numcurves, const int numkeys)
Definition hair.cpp:301
~Hair() override
void pack_curves(Scene *scene, float4 *curve_key_co, KernelCurve *curve, KernelCurveSegment *curve_segments)
Definition hair.cpp:486
size_t num_segments() const
Definition hair.h:131
CurveShapeType curve_shape
Definition hair.h:91
void clear(bool preserve_shaders=false) override
Definition hair.cpp:321
size_t num_keys() const
Definition hair.h:121
void apply_transform(const Transform &tfm, const bool apply_to_motion) override
Definition hair.cpp:445
PrimitiveType primitive_type() const override
Definition hair.cpp:529
Hair()
Definition hair.cpp:292
void reserve_curves(const int numcurves, const int numkeys)
Definition hair.cpp:311
void set_status(const string &status_, const string &substatus_="")
Definition progress.h:248
bool eval(const ShaderEvalType type, const int max_num_inputs, const int num_channels, const std::function< int(device_vector< KernelShaderEvalInput > &)> &fill_input, const std::function< void(device_vector< float > &)> &read_output)
bool has_surface_transparent
size_t size() const
size_t size() const
dot(value.rgb, luminance_coefficients)") DEFINE_VALUE("REDUCE(lhs
static void fill_shader_input(device_vector< KernelShaderEvalInput > &d_input, const Octree *octree, const Object *object, const Shader *shader, const int resolution)
static void read_shader_output(const device_vector< float > &d_output, const Octree *octree, const int num_channels, const int resolution, vector< Extrema< float > > &sigmas)
#define PRIMITIVE_PACK_SEGMENT(type, segment)
#define OBJECT_NONE
#define powf(x, y)
#define CCL_NAMESPACE_END
ccl_device_forceinline float3 make_float3(const float x, const float y, const float z)
#define __int_as_float(x)
#define in
VecBase< float, D > step(VecOp< float, D >, VecOp< float, D >) RET
VecBase< float, 3 > cross(VecOp< float, 3 >, VecOp< float, 3 >) RET
static void read_shader_output(float *shadow_transparency, bool &is_fully_opaque, const device_vector< float > &d_output)
Definition hair.cpp:567
static int fill_shader_input(const Hair *hair, const size_t object_index, device_vector< KernelShaderEvalInput > &d_input)
Definition hair.cpp:541
ccl_gpu_kernel_postfix ccl_global KernelWorkTile * tiles
PrimitiveType
@ PRIMITIVE_MOTION_CURVE_RIBBON
@ PRIMITIVE_CURVE_THICK_LINEAR
@ PRIMITIVE_CURVE_RIBBON
@ PRIMITIVE_MOTION_CURVE_THICK
@ PRIMITIVE_CURVE_THICK
@ PRIMITIVE_MOTION_CURVE_THICK_LINEAR
@ ATTR_STD_UV
@ ATTR_STD_MOTION_VERTEX_POSITION
@ ATTR_STD_SHADOW_TRANSPARENCY
@ CURVE_RIBBON
@ CURVE_THICK_LINEAR
@ ATTR_PRIM_GEOMETRY
CCL_NAMESPACE_BEGIN ccl_device_inline float3 zero_float3()
Definition math_float3.h:17
#define SOCKET_POINT_ARRAY(name, ui_name, default_value,...)
Definition node_type.h:268
#define SOCKET_FLOAT_ARRAY(name, ui_name, default_value,...)
Definition node_type.h:259
#define SOCKET_INT_ARRAY(name, ui_name, default_value,...)
Definition node_type.h:257
#define NODE_DEFINE(structname)
Definition node_type.h:152
#define fabsf
#define make_float4
CCL_NAMESPACE_BEGIN void curvebounds(float *lower, float *upper, float3 *p, const int dim)
@ SHADER_EVAL_CURVE_SHADOW_TRANSPARENCY
Definition shader_eval.h:21
#define min(a, b)
Definition sort.cc:36
CCL_NAMESPACE_BEGIN string string_printf(const char *format,...)
Definition string.cpp:23
void get_uv_tiles(Geometry *geom, AttributePrimitive prim, unordered_set< int > &tiles) const
float * data_float()
float3 * data_float3()
float4 * data_float4()
__forceinline bool valid() const
Definition boundbox.h:127
__forceinline void grow_safe(const float3 &pt)
Definition boundbox.h:56
__forceinline void grow(const float3 &pt)
Definition boundbox.h:35
void bounds_grow(const int k, const float3 *curve_keys, const float *curve_radius, BoundBox &bounds) const
Definition hair.cpp:44
void cardinal_motion_keys(const float3 *curve_keys, const float *curve_radius, const float4 *key_steps, const size_t num_curve_keys, const size_t num_steps, const float time, size_t k0, size_t k1, size_t k2, size_t k3, float4 r_keys[4]) const
Definition hair.cpp:148
void cardinal_keys_for_step(const float3 *curve_keys, const float *curve_radius, const float4 *key_steps, const size_t num_curve_keys, const size_t num_steps, const size_t step, size_t k0, size_t k1, size_t k2, size_t k3, float4 r_keys[4]) const
Definition hair.cpp:231
int first_key
Definition hair.h:19
void motion_keys(const float3 *curve_keys, const float *curve_radius, const float4 *key_steps, const size_t num_curve_keys, const size_t num_steps, const float time, size_t k0, size_t k1, float4 r_keys[2]) const
Definition hair.cpp:122
void keys_for_step(const float3 *curve_keys, const float *curve_radius, const float4 *key_steps, const size_t num_curve_keys, const size_t num_steps, const size_t step, size_t k0, size_t k1, float4 r_keys[2]) const
Definition hair.cpp:196
int num_segments() const
Definition hair.h:22
int num_keys
Definition hair.h:20
static NodeType * add(const char *name, CreateFunc create, Type type=NONE, const NodeType *base=nullptr)
const NodeType * type
Definition graph/node.h:178
ustring name
Definition graph/node.h:177
Node(const NodeType *type, ustring name=ustring())
Shader * default_surface
Definition scene.h:157
unique_ptr< ShaderManager > shader_manager
Definition scene.h:148
unique_ptr_vector< Object > objects
Definition scene.h:141
float z
Definition sky_math.h:136
float y
Definition sky_math.h:136
float x
Definition sky_math.h:136
float w
Definition sky_math.h:225
i
Definition text_draw.cc:230
max
Definition text_draw.cc:251
static Value parallel_reduce(const int range, const Value &identity, const Function &function, const Reduction &reduction)
Definition tracking.cc:2514
ccl_device_inline float3 transform_get_column(const Transform *t, const int column)
Definition transform.h:354
ccl_device_inline float3 transform_point(const ccl_private Transform *t, const float3 a)
Definition transform.h:56