Blender V4.3
scene/attribute.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 "scene/attribute.h"
6#include "scene/hair.h"
7#include "scene/image.h"
8#include "scene/mesh.h"
9#include "scene/pointcloud.h"
10
11#include "util/foreach.h"
12#include "util/log.h"
13#include "util/transform.h"
14
16
17/* Attribute */
18
20 ustring name, TypeDesc type, AttributeElement element, Geometry *geom, AttributePrimitive prim)
21 : name(name), std(ATTR_STD_NONE), type(type), element(element), flags(0), modified(true)
22{
23 /* string and matrix not supported! */
24 assert(type == TypeDesc::TypeFloat || type == TypeDesc::TypeColor ||
25 type == TypeDesc::TypePoint || type == TypeDesc::TypeVector ||
26 type == TypeDesc::TypeNormal || type == TypeDesc::TypeMatrix || type == TypeFloat2 ||
27 type == TypeFloat4 || type == TypeRGBA);
28
29 if (element == ATTR_ELEMENT_VOXEL) {
30 buffer.resize(sizeof(ImageHandle));
31 new (buffer.data()) ImageHandle();
32 }
33 else {
34 resize(geom, prim, false);
35 }
36}
37
39{
40 /* For voxel data, we need to free the image handle. */
41 if (element == ATTR_ELEMENT_VOXEL && buffer.size()) {
42 ImageHandle &handle = data_voxel();
43 handle.~ImageHandle();
44 }
45}
46
47void Attribute::resize(Geometry *geom, AttributePrimitive prim, bool reserve_only)
48{
49 if (element != ATTR_ELEMENT_VOXEL) {
50 if (reserve_only) {
51 buffer.reserve(buffer_size(geom, prim));
52 }
53 else {
54 buffer.resize(buffer_size(geom, prim), 0);
55 }
56 }
57}
58
59void Attribute::resize(size_t num_elements)
60{
61 if (element != ATTR_ELEMENT_VOXEL) {
62 buffer.resize(num_elements * data_sizeof(), 0);
63 }
64}
65
66void Attribute::add(const float &f)
67{
68 assert(data_sizeof() == sizeof(float));
69
70 char *data = (char *)&f;
71 size_t size = sizeof(f);
72
73 for (size_t i = 0; i < size; i++) {
74 buffer.push_back(data[i]);
75 }
76
77 modified = true;
78}
79
80void Attribute::add(const uchar4 &f)
81{
82 assert(data_sizeof() == sizeof(uchar4));
83
84 char *data = (char *)&f;
85 size_t size = sizeof(f);
86
87 for (size_t i = 0; i < size; i++) {
88 buffer.push_back(data[i]);
89 }
90
91 modified = true;
92}
93
94void Attribute::add(const float2 &f)
95{
96 assert(data_sizeof() == sizeof(float2));
97
98 char *data = (char *)&f;
99 size_t size = sizeof(f);
100
101 for (size_t i = 0; i < size; i++) {
102 buffer.push_back(data[i]);
103 }
104
105 modified = true;
106}
107
108void Attribute::add(const float3 &f)
109{
110 assert(data_sizeof() == sizeof(float3));
111
112 char *data = (char *)&f;
113 size_t size = sizeof(f);
114
115 for (size_t i = 0; i < size; i++) {
116 buffer.push_back(data[i]);
117 }
118
119 modified = true;
120}
121
123{
124 assert(data_sizeof() == sizeof(Transform));
125
126 char *data = (char *)&f;
127 size_t size = sizeof(f);
128
129 for (size_t i = 0; i < size; i++) {
130 buffer.push_back(data[i]);
131 }
132
133 modified = true;
134}
135
136void Attribute::add(const char *data)
137{
138 size_t size = data_sizeof();
139
140 for (size_t i = 0; i < size; i++) {
141 buffer.push_back(data[i]);
142 }
143
144 modified = true;
145}
146
148{
149 assert(other.std == std);
150 assert(other.type == type);
151 assert(other.element == element);
152
153 this->flags = other.flags;
154
155 if (this->buffer.size() != other.buffer.size()) {
156 this->buffer = std::move(other.buffer);
157 modified = true;
158 }
159 else if (memcmp(this->data(), other.data(), other.buffer.size()) != 0) {
160 this->buffer = std::move(other.buffer);
161 modified = true;
162 }
163}
164
166{
167 if (element == ATTR_ELEMENT_VOXEL) {
168 return sizeof(ImageHandle);
169 }
170 else if (element == ATTR_ELEMENT_CORNER_BYTE) {
171 return sizeof(uchar4);
172 }
173 else if (type == TypeDesc::TypeFloat) {
174 return sizeof(float);
175 }
176 else if (type == TypeFloat2) {
177 return sizeof(float2);
178 }
179 else if (type == TypeDesc::TypeMatrix) {
180 return sizeof(Transform);
181 // The float3 type is not interchangeable with float4
182 // as it is now a packed type.
183 }
184 else if (type == TypeDesc::TypeFloat4) {
185 return sizeof(float4);
186 }
187 else if (type == TypeRGBA) {
188 return sizeof(float4);
189 }
190 else {
191 return sizeof(float3);
192 }
193}
194
196{
197 if (flags & ATTR_FINAL_SIZE) {
198 return buffer.size() / data_sizeof();
199 }
200
201 size_t size = 0;
202
203 switch (element) {
207 size = 1;
208 break;
211 Mesh *mesh = static_cast<Mesh *>(geom);
212 size = mesh->get_verts().size() + mesh->get_num_ngons();
213 if (prim == ATTR_PRIM_SUBD) {
214 size -= mesh->get_num_subd_verts();
215 }
216 }
217 else if (geom->geometry_type == Geometry::POINTCLOUD) {
218 PointCloud *pointcloud = static_cast<PointCloud *>(geom);
219 size = pointcloud->num_points();
220 }
221 break;
223 if (geom->geometry_type == Geometry::MESH) {
224 Mesh *mesh = static_cast<Mesh *>(geom);
225 DCHECK_GT(mesh->get_motion_steps(), 0);
226 size = (mesh->get_verts().size() + mesh->get_num_ngons()) * (mesh->get_motion_steps() - 1);
227 if (prim == ATTR_PRIM_SUBD) {
228 size -= mesh->get_num_subd_verts() * (mesh->get_motion_steps() - 1);
229 }
230 }
231 else if (geom->geometry_type == Geometry::POINTCLOUD) {
232 PointCloud *pointcloud = static_cast<PointCloud *>(geom);
233 size = pointcloud->num_points() * (pointcloud->get_motion_steps() - 1);
234 }
235 break;
238 Mesh *mesh = static_cast<Mesh *>(geom);
239 if (prim == ATTR_PRIM_GEOMETRY) {
240 size = mesh->num_triangles();
241 }
242 else {
243 size = mesh->get_num_subd_faces() + mesh->get_num_ngons();
244 }
245 }
246 break;
249 if (geom->geometry_type == Geometry::MESH) {
250 Mesh *mesh = static_cast<Mesh *>(geom);
251 if (prim == ATTR_PRIM_GEOMETRY) {
252 size = mesh->num_triangles() * 3;
253 }
254 else {
255 size = mesh->get_subd_face_corners().size() + mesh->get_num_ngons();
256 }
257 }
258 break;
260 if (geom->geometry_type == Geometry::HAIR) {
261 Hair *hair = static_cast<Hair *>(geom);
262 size = hair->num_curves();
263 }
264 break;
266 if (geom->geometry_type == Geometry::HAIR) {
267 Hair *hair = static_cast<Hair *>(geom);
268 size = hair->get_curve_keys().size();
269 }
270 break;
272 if (geom->geometry_type == Geometry::HAIR) {
273 Hair *hair = static_cast<Hair *>(geom);
274 DCHECK_GT(hair->get_motion_steps(), 0);
275 size = hair->get_curve_keys().size() * (hair->get_motion_steps() - 1);
276 }
277 break;
278 default:
279 break;
280 }
281
282 return size;
283}
284
286{
287 return element_size(geom, prim) * data_sizeof();
288}
289
291{
292 if (a == b) {
293 return true;
294 }
295
296 if (a == TypeDesc::TypeColor || a == TypeDesc::TypePoint || a == TypeDesc::TypeVector ||
297 a == TypeDesc::TypeNormal)
298 {
299 if (b == TypeDesc::TypeColor || b == TypeDesc::TypePoint || b == TypeDesc::TypeVector ||
300 b == TypeDesc::TypeNormal)
301 {
302 return true;
303 }
304 }
305 return false;
306}
307
308void Attribute::zero_data(void *dst)
309{
310 memset(dst, 0, data_sizeof());
311}
312
313void Attribute::add_with_weight(void *dst, void *src, float weight)
314{
315 if (element == ATTR_ELEMENT_CORNER_BYTE) {
316 for (int i = 0; i < 4; i++) {
317 ((uchar *)dst)[i] += uchar(((uchar *)src)[i] * weight);
318 }
319 }
320 else if (same_storage(type, TypeDesc::TypeFloat)) {
321 *((float *)dst) += *((float *)src) * weight;
322 }
323 else if (same_storage(type, TypeFloat2)) {
324 *((float2 *)dst) += *((float2 *)src) * weight;
325 }
326 else if (same_storage(type, TypeDesc::TypeVector)) {
327 // Points are float3s and not float4s
328 *((float3 *)dst) += *((float3 *)src) * weight;
329 }
330 else {
331 assert(!"not implemented for this type");
332 }
333}
334
336{
337 switch (std) {
339 return "N";
341 return "Ng";
342 case ATTR_STD_UV:
343 return "uv";
345 return "generated";
347 return "generated_transform";
349 return "tangent";
351 return "tangent_sign";
353 return "vertex_color";
355 return "undeformed";
357 return "undisplaced";
359 return "motion_P";
361 return "motion_N";
363 return "particle";
365 return "curve_intercept";
367 return "curve_length";
369 return "curve_random";
371 return "point_random";
373 return "ptex_face_id";
374 case ATTR_STD_PTEX_UV:
375 return "ptex_uv";
377 return "density";
379 return "color";
381 return "flame";
383 return "heat";
385 return "temperature";
387 return "velocity";
389 return "velocity_x";
391 return "velocity_y";
393 return "velocity_z";
395 return "pointiness";
397 return "random_per_island";
399 return "shadow_transparency";
401 case ATTR_STD_NONE:
402 case ATTR_STD_NUM:
403 return "";
404 }
405
406 return "";
407}
408
410{
411 if (name) {
412 for (int std = ATTR_STD_NONE; std < ATTR_STD_NUM; std++) {
413 if (strcmp(name, Attribute::standard_name((AttributeStandard)std)) == 0) {
414 return (AttributeStandard)std;
415 }
416 }
417 }
418
419 return ATTR_STD_NONE;
420}
421
423{
424 if (attr.element == ATTR_ELEMENT_CORNER) {
426 }
427
428 if (attr.type == TypeDesc::TypeFloat) {
430 }
431
432 if (attr.type == TypeFloat2) {
434 }
435
436 if (attr.type == TypeFloat4 || attr.type == TypeRGBA || attr.type == TypeDesc::TypeMatrix) {
438 }
439
441}
442
445 unordered_set<int> &tiles) const
446{
447 if (type != TypeFloat2) {
448 return;
449 }
450
451 const int num = element_size(geom, prim);
452 const float2 *uv = data_float2();
453 for (int i = 0; i < num; i++, uv++) {
454 float u = uv->x, v = uv->y;
455 int x = (int)u, y = (int)v;
456
457 if (x < 0 || y < 0 || x >= 10) {
458 continue;
459 }
460
461 /* Be conservative in corners - precisely touching the right or upper edge of a tile
462 * should not load its right/upper neighbor as well. */
463 if (x > 0 && (u < x + 1e-6f)) {
464 x--;
465 }
466 if (y > 0 && (v < y + 1e-6f)) {
467 y--;
468 }
469
470 tiles.insert(1001 + 10 * y + x);
471 }
472}
473
474/* Attribute Set */
475
477 : modified_flag(~0u), geometry(geometry), prim(prim)
478{
479}
480
482
484{
485 Attribute *attr = find(name);
486
487 if (attr) {
488 /* return if same already exists */
489 if (attr->type == type && attr->element == element) {
490 return attr;
491 }
492
493 /* overwrite attribute with same name but different type/element */
494 remove(name);
495 }
496
497 Attribute new_attr(name, type, element, geometry, prim);
498 attributes.emplace_back(std::move(new_attr));
499 tag_modified(attributes.back());
500 return &attributes.back();
501}
502
503Attribute *AttributeSet::find(ustring name) const
504{
505 foreach (const Attribute &attr, attributes)
506 if (attr.name == name) {
507 return (Attribute *)&attr;
508 }
509
510 return NULL;
511}
512
513void AttributeSet::remove(ustring name)
514{
515 Attribute *attr = find(name);
516
517 if (attr) {
518 list<Attribute>::iterator it;
519
520 for (it = attributes.begin(); it != attributes.end(); it++) {
521 if (&*it == attr) {
522 remove(it);
523 return;
524 }
525 }
526 }
527}
528
530{
531 Attribute *attr = NULL;
532
533 if (name == ustring()) {
534 name = Attribute::standard_name(std);
535 }
536
537 if (geometry->geometry_type == Geometry::MESH) {
538 switch (std) {
540 attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_VERTEX);
541 break;
543 attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_FACE);
544 break;
545 case ATTR_STD_UV:
546 attr = add(name, TypeFloat2, ATTR_ELEMENT_CORNER);
547 break;
549 attr = add(name, TypeDesc::TypeVector, ATTR_ELEMENT_CORNER);
550 break;
552 attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CORNER);
553 break;
556 break;
560 attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
561 break;
563 attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX_MOTION);
564 break;
566 attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_VERTEX_MOTION);
567 break;
569 attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_FACE);
570 break;
571 case ATTR_STD_PTEX_UV:
572 attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
573 break;
575 attr = add(name, TypeDesc::TypeMatrix, ATTR_ELEMENT_MESH);
576 break;
578 attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_VERTEX);
579 break;
581 attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_FACE);
582 break;
583 default:
584 assert(0);
585 break;
586 }
587 }
588 else if (geometry->geometry_type == Geometry::POINTCLOUD) {
589 switch (std) {
590 case ATTR_STD_UV:
591 attr = add(name, TypeFloat2, ATTR_ELEMENT_VERTEX);
592 break;
594 attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
595 break;
597 attr = add(name, TypeDesc::TypeFloat4, ATTR_ELEMENT_VERTEX_MOTION);
598 break;
600 attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_VERTEX);
601 break;
603 attr = add(name, TypeDesc::TypeMatrix, ATTR_ELEMENT_MESH);
604 break;
605 default:
606 assert(0);
607 break;
608 }
609 }
610 else if (geometry->geometry_type == Geometry::VOLUME) {
611 switch (std) {
613 attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_VERTEX);
614 break;
616 attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_FACE);
617 break;
625 attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_VOXEL);
626 break;
628 attr = add(name, TypeDesc::TypeColor, ATTR_ELEMENT_VOXEL);
629 break;
631 attr = add(name, TypeDesc::TypeVector, ATTR_ELEMENT_VOXEL);
632 break;
633 default:
634 assert(0);
635 break;
636 }
637 }
638 else if (geometry->geometry_type == Geometry::HAIR) {
639 switch (std) {
641 attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_CURVE_KEY);
642 break;
643 case ATTR_STD_UV:
644 attr = add(name, TypeFloat2, ATTR_ELEMENT_CURVE);
645 break;
647 attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE);
648 break;
650 attr = add(name, TypeDesc::TypeFloat4, ATTR_ELEMENT_CURVE_KEY_MOTION);
651 break;
653 attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CURVE_KEY);
654 break;
656 attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CURVE);
657 break;
659 attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CURVE);
660 break;
662 attr = add(name, TypeDesc::TypeMatrix, ATTR_ELEMENT_MESH);
663 break;
665 attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_VERTEX);
666 break;
668 attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_FACE);
669 break;
671 attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CURVE_KEY);
672 break;
673 default:
674 assert(0);
675 break;
676 }
677 }
678
679 attr->std = std;
680
681 return attr;
682}
683
685{
686 foreach (const Attribute &attr, attributes)
687 if (attr.std == std) {
688 return (Attribute *)&attr;
689 }
690
691 return NULL;
692}
693
695{
696 for (Attribute &attr : attributes) {
697 if (attr.name != other.name) {
698 continue;
699 }
700 if (attr.std != other.std) {
701 continue;
702 }
703 if (attr.type != other.type) {
704 continue;
705 }
706 if (attr.element != other.element) {
707 continue;
708 }
709 return &attr;
710 }
711 return nullptr;
712}
713
715{
716 Attribute *attr = find(std);
717
718 if (attr) {
719 list<Attribute>::iterator it;
720
721 for (it = attributes.begin(); it != attributes.end(); it++) {
722 if (&*it == attr) {
723 remove(it);
724 return;
725 }
726 }
727 }
728}
729
731{
732 if (req.std == ATTR_STD_NONE) {
733 return find(req.name);
734 }
735 else {
736 return find(req.std);
737 }
738}
739
741{
742 if (attribute->std == ATTR_STD_NONE) {
743 remove(attribute->name);
744 }
745 else {
746 remove(attribute->std);
747 }
748}
749
750void AttributeSet::remove(list<Attribute>::iterator it)
751{
752 tag_modified(*it);
753 attributes.erase(it);
754}
755
756void AttributeSet::resize(bool reserve_only)
757{
758 foreach (Attribute &attr, attributes) {
759 attr.resize(geometry, prim, reserve_only);
760 }
761}
762
763void AttributeSet::clear(bool preserve_voxel_data)
764{
765 if (preserve_voxel_data) {
766 list<Attribute>::iterator it;
767
768 for (it = attributes.begin(); it != attributes.end();) {
769 if (it->element == ATTR_ELEMENT_VOXEL || it->std == ATTR_STD_GENERATED_TRANSFORM) {
770 it++;
771 }
772 else {
773 attributes.erase(it++);
774 }
775 }
776 }
777 else {
778 attributes.clear();
779 }
780}
781
782void AttributeSet::update(AttributeSet &&new_attributes)
783{
784 /* Remove any attributes not on new_attributes. */
785 list<Attribute>::iterator it;
786 for (it = attributes.begin(); it != attributes.end();) {
787 const Attribute &old_attr = *it;
788 if (new_attributes.find_matching(old_attr) == nullptr) {
789 remove(it++);
790 continue;
791 }
792 it++;
793 }
794
795 /* Add or update old_attributes based on the new_attributes. */
796 foreach (Attribute &attr, new_attributes.attributes) {
797 Attribute *nattr = add(attr.name, attr.type, attr.element);
798 nattr->std = attr.std;
799 nattr->set_data_from(std::move(attr));
800 }
801
802 /* If all attributes were replaced, transform is no longer applied. */
803 geometry->transform_applied = false;
804}
805
807{
808 foreach (Attribute &attr, attributes) {
809 attr.modified = false;
810 }
811
812 modified_flag = 0;
813}
814
815void AttributeSet::tag_modified(const Attribute &attr)
816{
817 /* Some attributes are not stored in the various kernel attribute arrays
818 * (DeviceScene::attribute_*), so the modified flags are only set if the associated standard
819 * corresponds to an attribute which will be stored in the kernel's attribute arrays. */
820 const bool modifies_device_array = (attr.std != ATTR_STD_FACE_NORMAL &&
822
823 if (modifies_device_array) {
824 AttrKernelDataType kernel_type = Attribute::kernel_type(attr);
825 modified_flag |= (1u << kernel_type);
826 }
827}
828
830{
831 return (modified_flag & (1u << kernel_type)) != 0;
832}
833
834/* AttributeRequest */
835
837{
838 name = name_;
840
841 type = TypeDesc::TypeFloat;
843 desc.offset = 0;
845
846 subd_type = TypeDesc::TypeFloat;
848 subd_desc.offset = 0;
850}
851
853{
854 name = ustring();
855 std = std_;
856
857 type = TypeDesc::TypeFloat;
859 desc.offset = 0;
861
862 subd_type = TypeDesc::TypeFloat;
864 subd_desc.offset = 0;
866}
867
868/* AttributeRequestSet */
869
871
873
875{
876 if (requests.size() != other.requests.size()) {
877 return true;
878 }
879
880 for (size_t i = 0; i < requests.size(); i++) {
881 bool found = false;
882
883 for (size_t j = 0; j < requests.size() && !found; j++) {
884 if (requests[i].name == other.requests[j].name && requests[i].std == other.requests[j].std) {
885 found = true;
886 }
887 }
888
889 if (!found) {
890 return true;
891 }
892 }
893
894 return false;
895}
896
897void AttributeRequestSet::add(ustring name)
898{
899 foreach (AttributeRequest &req, requests) {
900 if (req.name == name) {
901 return;
902 }
903 }
904
905 requests.push_back(AttributeRequest(name));
906}
907
909{
910 foreach (AttributeRequest &req, requests)
911 if (req.std == std) {
912 return;
913 }
914
915 requests.push_back(AttributeRequest(std));
916}
917
919{
920 foreach (AttributeRequest &req, reqs.requests) {
921 if (req.std == ATTR_STD_NONE) {
922 add(req.name);
923 }
924 else {
925 add(req.std);
926 }
927 }
928}
929
931{
932 if (name.empty()) {
933 return;
934 }
935
937
938 if (std) {
939 add(std);
940 }
941 else {
942 add(name);
943 }
944}
945
947{
948 foreach (AttributeRequest &req, requests)
949 if (req.name == name) {
950 return true;
951 }
952
953 return false;
954}
955
957{
958 foreach (AttributeRequest &req, requests)
959 if (req.std == std) {
960 return true;
961 }
962
963 return false;
964}
965
967{
968 return requests.size();
969}
970
972{
973 requests.clear();
974}
975
unsigned char uchar
ATTR_WARN_UNUSED_RESULT const BMVert * v
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
vector< AttributeRequest > requests
bool find(ustring name)
void add(ustring name)
bool modified(const AttributeRequestSet &other)
void add_standard(ustring name)
AttributeRequest(ustring name_)
AttributeDescriptor subd_desc
AttributeDescriptor desc
AttributeStandard std
Attribute * add(ustring name, TypeDesc type, AttributeElement element)
void update(AttributeSet &&new_attributes)
list< Attribute > attributes
Attribute * find(ustring name) const
Attribute * find_matching(const Attribute &other)
bool modified(AttrKernelDataType kernel_type) const
void remove(ustring name)
AttributeSet(Geometry *geometry, AttributePrimitive prim)
void resize(bool reserve_only=false)
void clear(bool preserve_voxel_data=false)
AttributePrimitive prim
AttributeElement element
static bool same_storage(TypeDesc a, TypeDesc b)
void add_with_weight(void *dst, void *src, float weight)
static AttrKernelDataType kernel_type(const Attribute &attr)
char * data()
static AttributeStandard name_standard(const char *name)
TypeDesc type
void resize(Geometry *geom, AttributePrimitive prim, bool reserve_only)
size_t element_size(Geometry *geom, AttributePrimitive prim) const
void get_uv_tiles(Geometry *geom, AttributePrimitive prim, unordered_set< int > &tiles) const
vector< char > buffer
void set_data_from(Attribute &&other)
void zero_data(void *dst)
Attribute(ustring name, TypeDesc type, AttributeElement element, Geometry *geom, AttributePrimitive prim)
static const char * standard_name(AttributeStandard std)
size_t buffer_size(Geometry *geom, AttributePrimitive prim) const
AttributeStandard std
ImageHandle & data_voxel()
size_t data_sizeof() const
void add(const float &f)
float2 * data_float2()
Type geometry_type
Definition hair.h:14
size_t num_curves() const
Definition hair.h:126
local_group_size(16, 16) .push_constant(Type b
#define CCL_NAMESPACE_END
#define NULL
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
ccl_gpu_kernel_postfix ccl_global KernelWorkTile * tiles
@ NODE_ATTR_FLOAT
AttributeStandard
@ ATTR_STD_CURVE_INTERCEPT
@ ATTR_STD_GENERATED_TRANSFORM
@ ATTR_STD_UV
@ ATTR_STD_MOTION_VERTEX_NORMAL
@ ATTR_STD_VOLUME_VELOCITY_Y
@ ATTR_STD_VOLUME_TEMPERATURE
@ ATTR_STD_VERTEX_NORMAL
@ ATTR_STD_UV_TANGENT
@ ATTR_STD_NOT_FOUND
@ ATTR_STD_NONE
@ ATTR_STD_VOLUME_VELOCITY_Z
@ ATTR_STD_POINT_RANDOM
@ ATTR_STD_VERTEX_COLOR
@ ATTR_STD_VOLUME_DENSITY
@ ATTR_STD_NUM
@ ATTR_STD_POSITION_UNDISPLACED
@ ATTR_STD_VOLUME_FLAME
@ ATTR_STD_PTEX_FACE_ID
@ ATTR_STD_VOLUME_VELOCITY
@ ATTR_STD_POSITION_UNDEFORMED
@ ATTR_STD_VOLUME_COLOR
@ ATTR_STD_MOTION_VERTEX_POSITION
@ ATTR_STD_VOLUME_HEAT
@ ATTR_STD_UV_TANGENT_SIGN
@ ATTR_STD_CURVE_RANDOM
@ ATTR_STD_SHADOW_TRANSPARENCY
@ ATTR_STD_FACE_NORMAL
@ ATTR_STD_PTEX_UV
@ ATTR_STD_POINTINESS
@ ATTR_STD_GENERATED
@ ATTR_STD_CURVE_LENGTH
@ ATTR_STD_VOLUME_VELOCITY_X
@ ATTR_STD_RANDOM_PER_ISLAND
@ ATTR_STD_PARTICLE
@ ATTR_FINAL_SIZE
AttributeElement
@ ATTR_ELEMENT_NONE
@ ATTR_ELEMENT_CORNER_BYTE
@ ATTR_ELEMENT_CURVE_KEY
@ ATTR_ELEMENT_CURVE_KEY_MOTION
@ ATTR_ELEMENT_VOXEL
@ ATTR_ELEMENT_CORNER
@ ATTR_ELEMENT_OBJECT
@ ATTR_ELEMENT_VERTEX_MOTION
@ ATTR_ELEMENT_VERTEX
@ ATTR_ELEMENT_FACE
@ ATTR_ELEMENT_MESH
@ ATTR_ELEMENT_CURVE
AttributePrimitive
@ ATTR_PRIM_SUBD
@ ATTR_PRIM_GEOMETRY
#define DCHECK_GT(a, b)
Definition log.h:60
static constexpr TypeDesc TypeRGBA(TypeDesc::FLOAT, TypeDesc::VEC4, TypeDesc::COLOR)
CCL_NAMESPACE_BEGIN static OIIO_NAMESPACE_USING constexpr TypeDesc TypeFloat2(TypeDesc::FLOAT, TypeDesc::VEC2)
AttrKernelDataType
@ FLOAT4
@ FLOAT2
@ UCHAR4
@ FLOAT3
@ FLOAT
long long TypeDesc
AttributeElement element
NodeAttributeType type
size_t num_triangles() const
Definition scene/mesh.h:80
size_t get_num_subd_verts()
Definition scene/mesh.h:243
size_t num_points() const
float x
float y
CCL_NAMESPACE_BEGIN struct Transform Transform