Blender V4.5
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/log.h"
12#include "util/transform.h"
13
15
16/* Attribute */
17
19 const TypeDesc type,
21 Geometry *geom,
24{
25 /* string and matrix not supported! */
26 assert(type == TypeFloat || type == TypeColor || type == TypePoint || type == TypeVector ||
27 type == TypeNormal || type == TypeMatrix || type == TypeFloat2 || type == TypeFloat4 ||
28 type == TypeRGBA);
29
31 buffer.resize(sizeof(ImageHandle));
32 new (buffer.data()) ImageHandle();
33 }
34 else {
35 resize(geom, prim, false);
36 }
37}
38
40{
41 /* For voxel data, we need to free the image handle. */
42 if (element == ATTR_ELEMENT_VOXEL && !buffer.empty()) {
43 ImageHandle &handle = data_voxel();
44 handle.~ImageHandle();
45 }
46}
47
48void Attribute::resize(Geometry *geom, AttributePrimitive prim, bool reserve_only)
49{
51 if (reserve_only) {
52 buffer.reserve(buffer_size(geom, prim));
53 }
54 else {
55 buffer.resize(buffer_size(geom, prim), 0);
56 }
57 }
58}
59
60void Attribute::resize(const size_t num_elements)
61{
63 buffer.resize(num_elements * data_sizeof(), 0);
64 }
65}
66
67void Attribute::add(const float &f)
68{
69 assert(data_sizeof() == sizeof(float));
70
71 char *data = (char *)&f;
72 const size_t size = sizeof(f);
73
74 for (size_t i = 0; i < size; i++) {
75 buffer.push_back(data[i]);
76 }
77
78 modified = true;
79}
80
81void Attribute::add(const uchar4 &f)
82{
83 assert(data_sizeof() == sizeof(uchar4));
84
85 char *data = (char *)&f;
86 const size_t size = sizeof(f);
87
88 for (size_t i = 0; i < size; i++) {
89 buffer.push_back(data[i]);
90 }
91
92 modified = true;
93}
94
95void Attribute::add(const float2 &f)
96{
97 assert(data_sizeof() == sizeof(float2));
98
99 char *data = (char *)&f;
100 const size_t size = sizeof(f);
101
102 for (size_t i = 0; i < size; i++) {
103 buffer.push_back(data[i]);
104 }
105
106 modified = true;
107}
108
109void Attribute::add(const float3 &f)
110{
111 assert(data_sizeof() == sizeof(float3));
112
113 char *data = (char *)&f;
114 const size_t size = sizeof(f);
115
116 for (size_t i = 0; i < size; i++) {
117 buffer.push_back(data[i]);
118 }
119
120 modified = true;
121}
122
124{
125 assert(data_sizeof() == sizeof(Transform));
126
127 char *data = (char *)&f;
128 const size_t size = sizeof(f);
129
130 for (size_t i = 0; i < size; i++) {
131 buffer.push_back(data[i]);
132 }
133
134 modified = true;
135}
136
137void Attribute::add(const char *data)
138{
139 const size_t size = data_sizeof();
140
141 for (size_t i = 0; i < size; i++) {
142 buffer.push_back(data[i]);
143 }
144
145 modified = true;
146}
147
149{
150 assert(other.std == std);
151 assert(other.type == type);
152 assert(other.element == element);
153
154 this->flags = other.flags;
155
156 if (this->buffer.size() != other.buffer.size()) {
157 this->buffer = std::move(other.buffer);
158 modified = true;
159 }
160 else if (memcmp(this->data(), other.data(), other.buffer.size()) != 0) {
161 this->buffer = std::move(other.buffer);
162 modified = true;
163 }
164}
165
167{
169 return sizeof(ImageHandle);
170 }
172 return sizeof(uchar4);
173 }
174 if (type == TypeFloat) {
175 return sizeof(float);
176 }
177 if (type == TypeFloat2) {
178 return sizeof(float2);
179 }
180 if (type == TypeMatrix) {
181 return sizeof(Transform);
182 // The float3 type is not interchangeable with float4
183 // as it is now a packed type.
184 }
185 if (type == TypeFloat4) {
186 return sizeof(float4);
187 }
188 if (type == TypeRGBA) {
189 return sizeof(float4);
190 }
191 return sizeof(float3);
192}
193
195{
196 size_t size = 0;
197
198 switch (element) {
202 size = 1;
203 break;
205 if (geom->is_mesh() || geom->is_volume()) {
206 Mesh *mesh = static_cast<Mesh *>(geom);
207 if (prim == ATTR_PRIM_SUBD) {
209 }
210 else {
211 size = mesh->get_verts().size();
212 }
213 }
214 else if (geom->is_pointcloud()) {
215 PointCloud *pointcloud = static_cast<PointCloud *>(geom);
216 size = pointcloud->num_points();
217 }
218 break;
220 if (geom->is_mesh()) {
221 Mesh *mesh = static_cast<Mesh *>(geom);
222 DCHECK_GT(mesh->get_motion_steps(), 0);
223 if (prim == ATTR_PRIM_SUBD) {
224 size = mesh->get_num_subd_base_verts() * (mesh->get_motion_steps() - 1);
225 }
226 else {
227 size = mesh->get_verts().size() * (mesh->get_motion_steps() - 1);
228 }
229 }
230 else if (geom->is_pointcloud()) {
231 PointCloud *pointcloud = static_cast<PointCloud *>(geom);
232 size = pointcloud->num_points() * (pointcloud->get_motion_steps() - 1);
233 }
234 break;
236 if (geom->is_mesh() || geom->is_volume()) {
237 Mesh *mesh = static_cast<Mesh *>(geom);
238 if (prim == ATTR_PRIM_SUBD) {
239 size = mesh->get_num_subd_faces();
240 }
241 else {
242 size = mesh->num_triangles();
243 }
244 }
245 break;
248 if (geom->is_mesh()) {
249 Mesh *mesh = static_cast<Mesh *>(geom);
250 if (prim == ATTR_PRIM_SUBD) {
251 size = mesh->get_subd_face_corners().size();
252 }
253 else {
254 size = mesh->num_triangles() * 3;
255 }
256 }
257 break;
259 if (geom->is_hair()) {
260 Hair *hair = static_cast<Hair *>(geom);
261 size = hair->num_curves();
262 }
263 break;
265 if (geom->is_hair()) {
266 Hair *hair = static_cast<Hair *>(geom);
267 size = hair->get_curve_keys().size();
268 }
269 break;
271 if (geom->is_hair()) {
272 Hair *hair = static_cast<Hair *>(geom);
273 DCHECK_GT(hair->get_motion_steps(), 0);
274 size = hair->get_curve_keys().size() * (hair->get_motion_steps() - 1);
275 }
276 break;
277 default:
278 break;
279 }
280
281 return size;
282}
283
285{
286 return element_size(geom, prim) * data_sizeof();
287}
288
290{
291 if (a == b) {
292 return true;
293 }
294
295 if (a == TypeColor || a == TypePoint || a == TypeVector || a == TypeNormal) {
296 if (b == TypeColor || b == TypePoint || b == TypeVector || b == TypeNormal) {
297 return true;
298 }
299 }
300 return false;
301}
302
303void Attribute::zero_data(void *dst)
304{
305 memset(dst, 0, data_sizeof());
306}
307
309{
310 switch (std) {
312 return "N";
313 case ATTR_STD_UV:
314 return "uv";
316 return "generated";
318 return "generated_transform";
320 return "tangent";
322 return "tangent_sign";
324 return "vertex_color";
326 return "undeformed";
328 return "undisplaced";
330 return "undisplaced_N";
332 return "motion_P";
334 return "motion_N";
336 return "particle";
338 return "curve_intercept";
340 return "curve_length";
342 return "curve_random";
344 return "point_random";
346 return "ptex_face_id";
347 case ATTR_STD_PTEX_UV:
348 return "ptex_uv";
350 return "density";
352 return "color";
354 return "flame";
356 return "heat";
358 return "temperature";
360 return "velocity";
362 return "velocity_x";
364 return "velocity_y";
366 return "velocity_z";
368 return "pointiness";
370 return "random_per_island";
372 return "shadow_transparency";
374 case ATTR_STD_NONE:
375 case ATTR_STD_NUM:
376 return "";
377 }
378
379 return "";
380}
381
383{
384 if (name) {
385 for (int std = ATTR_STD_NONE; std < ATTR_STD_NUM; std++) {
387 return (AttributeStandard)std;
388 }
389 }
390 }
391
392 return ATTR_STD_NONE;
393}
394
396{
397 if (attr.element == ATTR_ELEMENT_CORNER) {
399 }
400
401 if (attr.type == TypeFloat) {
403 }
404
405 if (attr.type == TypeFloat2) {
407 }
408
409 if (attr.type == TypeFloat4 || attr.type == TypeRGBA || attr.type == TypeMatrix) {
411 }
412
414}
415
418 unordered_set<int> &tiles) const
419{
420 if (type != TypeFloat2) {
421 return;
422 }
423
424 const int num = element_size(geom, prim);
425 const float2 *uv = data_float2();
426 for (int i = 0; i < num; i++, uv++) {
427 const float u = uv->x;
428 const float v = uv->y;
429 int x = (int)u;
430 int y = (int)v;
431
432 if (x < 0 || y < 0 || x >= 10) {
433 continue;
434 }
435
436 /* Be conservative in corners - precisely touching the right or upper edge of a tile
437 * should not load its right/upper neighbor as well. */
438 if (x > 0 && (u < x + 1e-6f)) {
439 x--;
440 }
441 if (y > 0 && (v < y + 1e-6f)) {
442 y--;
443 }
444
445 tiles.insert(1001 + 10 * y + x);
446 }
447}
448
449/* Attribute Set */
450
455
457
459{
460 Attribute *attr = find(name);
461
462 if (attr) {
463 /* return if same already exists */
464 if (attr->type == type && attr->element == element) {
465 return attr;
466 }
467
468 /* overwrite attribute with same name but different type/element */
469 remove(name);
470 }
471
472 Attribute new_attr(name, type, element, geometry, prim);
473 attributes.emplace_back(std::move(new_attr));
474 tag_modified(attributes.back());
475 return &attributes.back();
476}
477
478Attribute *AttributeSet::find(ustring name) const
479{
480 for (const Attribute &attr : attributes) {
481 if (attr.name == name) {
482 return (Attribute *)&attr;
483 }
484 }
485
486 return nullptr;
487}
488
489void AttributeSet::remove(ustring name)
490{
491 Attribute *attr = find(name);
492
493 if (attr) {
494 list<Attribute>::iterator it;
495
496 for (it = attributes.begin(); it != attributes.end(); it++) {
497 if (&*it == attr) {
498 remove(it);
499 return;
500 }
501 }
502 }
503}
504
506{
507 Attribute *attr = nullptr;
508
509 if (name.empty()) {
510 name = Attribute::standard_name(std);
511 }
512
513 if (geometry->is_mesh()) {
514 switch (std) {
517 attr = add(name, TypeNormal, ATTR_ELEMENT_VERTEX);
518 break;
519 case ATTR_STD_UV:
520 attr = add(name, TypeFloat2, ATTR_ELEMENT_CORNER);
521 break;
523 attr = add(name, TypeVector, ATTR_ELEMENT_CORNER);
524 break;
526 attr = add(name, TypeFloat, ATTR_ELEMENT_CORNER);
527 break;
530 break;
534 attr = add(name, TypePoint, ATTR_ELEMENT_VERTEX);
535 break;
537 attr = add(name, TypePoint, ATTR_ELEMENT_VERTEX_MOTION);
538 break;
540 attr = add(name, TypeNormal, ATTR_ELEMENT_VERTEX_MOTION);
541 break;
543 attr = add(name, TypeFloat, ATTR_ELEMENT_FACE);
544 break;
545 case ATTR_STD_PTEX_UV:
546 attr = add(name, TypeFloat2, ATTR_ELEMENT_CORNER);
547 break;
549 attr = add(name, TypeMatrix, ATTR_ELEMENT_MESH);
550 break;
552 attr = add(name, TypeFloat, ATTR_ELEMENT_VERTEX);
553 break;
555 attr = add(name, TypeFloat, ATTR_ELEMENT_FACE);
556 break;
557 default:
558 assert(0);
559 break;
560 }
561 }
562 else if (geometry->is_pointcloud()) {
563 switch (std) {
564 case ATTR_STD_UV:
565 attr = add(name, TypeFloat2, ATTR_ELEMENT_VERTEX);
566 break;
568 attr = add(name, TypePoint, ATTR_ELEMENT_VERTEX);
569 break;
571 attr = add(name, TypeFloat4, ATTR_ELEMENT_VERTEX_MOTION);
572 break;
574 attr = add(name, TypeFloat, ATTR_ELEMENT_VERTEX);
575 break;
577 attr = add(name, TypeMatrix, ATTR_ELEMENT_MESH);
578 break;
579 default:
580 assert(0);
581 break;
582 }
583 }
584 else if (geometry->is_volume()) {
585 switch (std) {
587 attr = add(name, TypeNormal, ATTR_ELEMENT_VERTEX);
588 break;
596 attr = add(name, TypeFloat, ATTR_ELEMENT_VOXEL);
597 break;
599 attr = add(name, TypeColor, ATTR_ELEMENT_VOXEL);
600 break;
602 attr = add(name, TypeVector, ATTR_ELEMENT_VOXEL);
603 break;
604 default:
605 assert(0);
606 break;
607 }
608 }
609 else if (geometry->is_hair()) {
610 switch (std) {
612 attr = add(name, TypeNormal, ATTR_ELEMENT_CURVE_KEY);
613 break;
614 case ATTR_STD_UV:
615 attr = add(name, TypeFloat2, ATTR_ELEMENT_CURVE);
616 break;
618 attr = add(name, TypePoint, ATTR_ELEMENT_CURVE);
619 break;
621 attr = add(name, TypeFloat4, ATTR_ELEMENT_CURVE_KEY_MOTION);
622 break;
624 attr = add(name, TypeFloat, ATTR_ELEMENT_CURVE_KEY);
625 break;
627 attr = add(name, TypeFloat, ATTR_ELEMENT_CURVE);
628 break;
630 attr = add(name, TypeFloat, ATTR_ELEMENT_CURVE);
631 break;
633 attr = add(name, TypeMatrix, ATTR_ELEMENT_MESH);
634 break;
636 attr = add(name, TypeFloat, ATTR_ELEMENT_VERTEX);
637 break;
639 attr = add(name, TypeFloat, ATTR_ELEMENT_FACE);
640 break;
642 attr = add(name, TypeFloat, ATTR_ELEMENT_CURVE_KEY);
643 break;
644 default:
645 assert(0);
646 break;
647 }
648 }
649
650 attr->std = std;
651
652 return attr;
653}
654
656{
657 Attribute &copy_attr = *add(attr.name, attr.type, attr.element);
658 copy_attr.std = attr.std;
659 return copy_attr;
660}
661
663{
664 for (const Attribute &attr : attributes) {
665 if (attr.std == std) {
666 return (Attribute *)&attr;
667 }
668 }
669
670 return nullptr;
671}
672
674{
675 for (Attribute &attr : attributes) {
676 if (attr.name != other.name) {
677 continue;
678 }
679 if (attr.std != other.std) {
680 continue;
681 }
682 if (attr.type != other.type) {
683 continue;
684 }
685 if (attr.element != other.element) {
686 continue;
687 }
688 return &attr;
689 }
690 return nullptr;
691}
692
694{
695 Attribute *attr = find(std);
696
697 if (attr) {
698 list<Attribute>::iterator it;
699
700 for (it = attributes.begin(); it != attributes.end(); it++) {
701 if (&*it == attr) {
702 remove(it);
703 return;
704 }
705 }
706 }
707}
708
710{
711 if (req.std == ATTR_STD_NONE) {
712 return find(req.name);
713 }
714 return find(req.std);
715}
716
718{
719 if (attribute->std == ATTR_STD_NONE) {
720 remove(attribute->name);
721 }
722 else {
723 remove(attribute->std);
724 }
725}
726
727void AttributeSet::remove(list<Attribute>::iterator it)
728{
729 tag_modified(*it);
730 attributes.erase(it);
731}
732
733void AttributeSet::resize(bool reserve_only)
734{
735 for (Attribute &attr : attributes) {
736 attr.resize(geometry, prim, reserve_only);
737 }
738}
739
740void AttributeSet::clear(bool preserve_voxel_data)
741{
742 if (preserve_voxel_data) {
743 list<Attribute>::iterator it;
744
745 for (it = attributes.begin(); it != attributes.end();) {
746 if (it->element == ATTR_ELEMENT_VOXEL || it->std == ATTR_STD_GENERATED_TRANSFORM) {
747 it++;
748 }
749 else {
750 attributes.erase(it++);
751 }
752 }
753 }
754 else {
755 attributes.clear();
756 }
757}
758
759void AttributeSet::update(AttributeSet &&new_attributes)
760{
761 /* Remove any attributes not on new_attributes. */
762 list<Attribute>::iterator it;
763 for (it = attributes.begin(); it != attributes.end();) {
764 const Attribute &old_attr = *it;
765 if (new_attributes.find_matching(old_attr) == nullptr) {
766 remove(it++);
767 continue;
768 }
769 it++;
770 }
771
772 /* Add or update old_attributes based on the new_attributes. */
773 for (Attribute &attr : new_attributes.attributes) {
774 Attribute *nattr = add(attr.name, attr.type, attr.element);
775 nattr->std = attr.std;
776 nattr->set_data_from(std::move(attr));
777 }
778
779 /* If all attributes were replaced, transform is no longer applied. */
780 geometry->transform_applied = false;
781}
782
784{
785 for (Attribute &attr : attributes) {
786 attr.modified = false;
787 }
788
789 modified_flag = 0;
790}
791
792void AttributeSet::tag_modified(const Attribute &attr)
793{
794 /* Some attributes are not stored in the various kernel attribute arrays
795 * (DeviceScene::attribute_*), so the modified flags are only set if the associated standard
796 * corresponds to an attribute which will be stored in the kernel's attribute arrays. */
797 const bool modifies_device_array = (attr.std != ATTR_STD_VERTEX_NORMAL);
798
799 if (modifies_device_array) {
800 const AttrKernelDataType kernel_type = Attribute::kernel_type(attr);
801 modified_flag |= (1u << kernel_type);
802 }
803}
804
806{
807 return (modified_flag & (1u << kernel_type)) != 0;
808}
809
810/* AttributeRequest */
811
813{
814 name = name_;
816
817 type = TypeFloat;
818 desc.element = ATTR_ELEMENT_NONE;
819 desc.offset = 0;
820 desc.type = NODE_ATTR_FLOAT;
821}
822
824{
825 name = ustring();
826 std = std_;
827
828 type = TypeFloat;
829 desc.element = ATTR_ELEMENT_NONE;
830 desc.offset = 0;
831 desc.type = NODE_ATTR_FLOAT;
832}
833
834/* AttributeRequestSet */
835
837
839
841{
842 if (requests.size() != other.requests.size()) {
843 return true;
844 }
845
846 for (size_t i = 0; i < requests.size(); i++) {
847 bool found = false;
848
849 for (size_t j = 0; j < requests.size() && !found; j++) {
850 if (requests[i].name == other.requests[j].name && requests[i].std == other.requests[j].std) {
851 found = true;
852 }
853 }
854
855 if (!found) {
856 return true;
857 }
858 }
859
860 return false;
861}
862
863void AttributeRequestSet::add(ustring name)
864{
865 for (const AttributeRequest &req : requests) {
866 if (req.name == name) {
867 return;
868 }
869 }
870
871 requests.push_back(AttributeRequest(name));
872}
873
875{
876 for (const AttributeRequest &req : requests) {
877 if (req.std == std) {
878 return;
879 }
880 }
881
882 requests.push_back(AttributeRequest(std));
883}
884
886{
887 for (const AttributeRequest &req : reqs.requests) {
888 if (req.std == ATTR_STD_NONE) {
889 add(req.name);
890 }
891 else {
892 add(req.std);
893 }
894 }
895}
896
898{
899 if (name.empty()) {
900 return;
901 }
902
903 const AttributeStandard std = Attribute::name_standard(name.c_str());
904
905 if (std) {
906 add(std);
907 }
908 else {
909 add(name);
910 }
911}
912
914{
915 for (const AttributeRequest &req : requests) {
916 if (req.name == name) {
917 return true;
918 }
919 }
920
921 return false;
922}
923
925{
926 for (const AttributeRequest &req : requests) {
927 if (req.std == std) {
928 return true;
929 }
930 }
931
932 return false;
933}
934
936{
937 return requests.size();
938}
939
941{
942 requests.clear();
943}
944
ATTR_WARN_UNUSED_RESULT const size_t num
return true
ATTR_WARN_UNUSED_RESULT const void * element
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 desc
AttributeStandard std
Geometry * geometry
void update(AttributeSet &&new_attributes)
Attribute & copy(const Attribute &attr)
list< Attribute > attributes
Attribute * find(ustring name) const
Attribute * find_matching(const Attribute &other)
bool modified(AttrKernelDataType kernel_type) const
Attribute * add(ustring name, const TypeDesc type, AttributeElement element)
void remove(ustring name)
AttributeSet(Geometry *geometry, AttributePrimitive prim)
void resize(bool reserve_only=false)
void clear(bool preserve_voxel_data=false)
AttributePrimitive prim
bool is_volume() const
bool is_pointcloud() const
bool is_hair() const
bool is_mesh() const
Definition hair.h:13
size_t num_curves() const
Definition hair.h:126
#define CCL_NAMESPACE_END
VecBase< float, 4 > float4
#define assert(assertion)
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_NORMAL_UNDISPLACED
@ ATTR_STD_UV_TANGENT_SIGN
@ ATTR_STD_CURVE_RANDOM
@ ATTR_STD_SHADOW_TRANSPARENCY
@ 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
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
#define DCHECK_GT(a, b)
Definition log.h:59
static constexpr TypeDesc TypeRGBA(TypeDesc::FLOAT, TypeDesc::VEC4, TypeDesc::COLOR)
AttrKernelDataType
@ FLOAT4
@ FLOAT2
@ UCHAR4
@ FLOAT3
@ FLOAT
long long TypeDesc
const char * name
AttributeElement element
Attribute(ustring name, const TypeDesc type, AttributeElement element, Geometry *geom, AttributePrimitive prim)
static AttrKernelDataType kernel_type(const Attribute &attr)
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)
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
static bool same_storage(const TypeDesc a, const TypeDesc b)
void add(const float &f)
float2 * data_float2()
size_t get_num_subd_faces() const
Definition scene/mesh.h:229
size_t get_num_subd_base_verts() const
Definition scene/mesh.h:237
size_t num_triangles() const
Definition scene/mesh.h:77
size_t num_points() const
float x
float y
i
Definition text_draw.cc:230