ClangFormat: apply to source, most of intern
[blender.git] / intern / cycles / render / attribute.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 "render/image.h"
18 #include "render/mesh.h"
19 #include "render/attribute.h"
20
21 #include "util/util_foreach.h"
22 #include "util/util_transform.h"
23
24 CCL_NAMESPACE_BEGIN
25
26 /* Attribute */
27
28 Attribute::~Attribute()
29 {
30   /* for voxel data, we need to remove the image from the image manager */
31   if (element == ATTR_ELEMENT_VOXEL) {
32     VoxelAttribute *voxel_data = data_voxel();
33
34     if (voxel_data && voxel_data->slot != -1) {
35       voxel_data->manager->remove_image(voxel_data->slot);
36     }
37   }
38 }
39
40 void Attribute::set(ustring name_, TypeDesc type_, AttributeElement element_)
41 {
42   name = name_;
43   type = type_;
44   element = element_;
45   std = ATTR_STD_NONE;
46   flags = 0;
47
48   /* string and matrix not supported! */
49   assert(type == TypeDesc::TypeFloat || type == TypeDesc::TypeColor ||
50          type == TypeDesc::TypePoint || type == TypeDesc::TypeVector ||
51          type == TypeDesc::TypeNormal || type == TypeDesc::TypeMatrix || type == TypeFloat2);
52 }
53
54 void Attribute::resize(Mesh *mesh, AttributePrimitive prim, bool reserve_only)
55 {
56   if (reserve_only) {
57     buffer.reserve(buffer_size(mesh, prim));
58   }
59   else {
60     buffer.resize(buffer_size(mesh, prim), 0);
61   }
62 }
63
64 void Attribute::resize(size_t num_elements)
65 {
66   buffer.resize(num_elements * data_sizeof(), 0);
67 }
68
69 void Attribute::add(const float &f)
70 {
71   assert(data_sizeof() == sizeof(float));
72
73   char *data = (char *)&f;
74   size_t size = sizeof(f);
75
76   for (size_t i = 0; i < size; i++)
77     buffer.push_back(data[i]);
78 }
79
80 void 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 void Attribute::add(const float2 &f)
92 {
93   assert(data_sizeof() == sizeof(float2));
94
95   char *data = (char *)&f;
96   size_t size = sizeof(f);
97
98   for (size_t i = 0; i < size; i++)
99     buffer.push_back(data[i]);
100 }
101
102 void Attribute::add(const float3 &f)
103 {
104   assert(data_sizeof() == sizeof(float3));
105
106   char *data = (char *)&f;
107   size_t size = sizeof(f);
108
109   for (size_t i = 0; i < size; i++)
110     buffer.push_back(data[i]);
111 }
112
113 void Attribute::add(const Transform &f)
114 {
115   assert(data_sizeof() == sizeof(Transform));
116
117   char *data = (char *)&f;
118   size_t size = sizeof(f);
119
120   for (size_t i = 0; i < size; i++)
121     buffer.push_back(data[i]);
122 }
123
124 void Attribute::add(const VoxelAttribute &f)
125 {
126   assert(data_sizeof() == sizeof(VoxelAttribute));
127
128   char *data = (char *)&f;
129   size_t size = sizeof(f);
130
131   for (size_t i = 0; i < size; i++)
132     buffer.push_back(data[i]);
133 }
134
135 void Attribute::add(const char *data)
136 {
137   size_t size = data_sizeof();
138
139   for (size_t i = 0; i < size; i++)
140     buffer.push_back(data[i]);
141 }
142
143 size_t Attribute::data_sizeof() const
144 {
145   if (element == ATTR_ELEMENT_VOXEL)
146     return sizeof(VoxelAttribute);
147   else if (element == ATTR_ELEMENT_CORNER_BYTE)
148     return sizeof(uchar4);
149   else if (type == TypeDesc::TypeFloat)
150     return sizeof(float);
151   else if (type == TypeFloat2)
152     return sizeof(float2);
153   else if (type == TypeDesc::TypeMatrix)
154     return sizeof(Transform);
155   else
156     return sizeof(float3);
157 }
158
159 size_t Attribute::element_size(Mesh *mesh, AttributePrimitive prim) const
160 {
161   if (flags & ATTR_FINAL_SIZE) {
162     return buffer.size() / data_sizeof();
163   }
164
165   size_t size;
166
167   switch (element) {
168     case ATTR_ELEMENT_OBJECT:
169     case ATTR_ELEMENT_MESH:
170     case ATTR_ELEMENT_VOXEL:
171       size = 1;
172       break;
173     case ATTR_ELEMENT_VERTEX:
174       size = mesh->verts.size() + mesh->num_ngons;
175       if (prim == ATTR_PRIM_SUBD) {
176         size -= mesh->num_subd_verts;
177       }
178       break;
179     case ATTR_ELEMENT_VERTEX_MOTION:
180       size = (mesh->verts.size() + mesh->num_ngons) * (mesh->motion_steps - 1);
181       if (prim == ATTR_PRIM_SUBD) {
182         size -= mesh->num_subd_verts * (mesh->motion_steps - 1);
183       }
184       break;
185     case ATTR_ELEMENT_FACE:
186       if (prim == ATTR_PRIM_TRIANGLE) {
187         size = mesh->num_triangles();
188       }
189       else {
190         size = mesh->subd_faces.size() + mesh->num_ngons;
191       }
192       break;
193     case ATTR_ELEMENT_CORNER:
194     case ATTR_ELEMENT_CORNER_BYTE:
195       if (prim == ATTR_PRIM_TRIANGLE) {
196         size = mesh->num_triangles() * 3;
197       }
198       else {
199         size = mesh->subd_face_corners.size() + mesh->num_ngons;
200       }
201       break;
202     case ATTR_ELEMENT_CURVE:
203       size = mesh->num_curves();
204       break;
205     case ATTR_ELEMENT_CURVE_KEY:
206       size = mesh->curve_keys.size();
207       break;
208     case ATTR_ELEMENT_CURVE_KEY_MOTION:
209       size = mesh->curve_keys.size() * (mesh->motion_steps - 1);
210       break;
211     default:
212       size = 0;
213       break;
214   }
215
216   return size;
217 }
218
219 size_t Attribute::buffer_size(Mesh *mesh, AttributePrimitive prim) const
220 {
221   return element_size(mesh, prim) * data_sizeof();
222 }
223
224 bool Attribute::same_storage(TypeDesc a, TypeDesc b)
225 {
226   if (a == b)
227     return true;
228
229   if (a == TypeDesc::TypeColor || a == TypeDesc::TypePoint || a == TypeDesc::TypeVector ||
230       a == TypeDesc::TypeNormal) {
231     if (b == TypeDesc::TypeColor || b == TypeDesc::TypePoint || b == TypeDesc::TypeVector ||
232         b == TypeDesc::TypeNormal) {
233       return true;
234     }
235   }
236   return false;
237 }
238
239 void Attribute::zero_data(void *dst)
240 {
241   memset(dst, 0, data_sizeof());
242 }
243
244 void Attribute::add_with_weight(void *dst, void *src, float weight)
245 {
246   if (element == ATTR_ELEMENT_CORNER_BYTE) {
247     for (int i = 0; i < 4; i++) {
248       ((uchar *)dst)[i] += uchar(((uchar *)src)[i] * weight);
249     }
250   }
251   else if (same_storage(type, TypeDesc::TypeFloat)) {
252     *((float *)dst) += *((float *)src) * weight;
253   }
254   else if (same_storage(type, TypeDesc::TypeVector)) {
255     *((float4 *)dst) += *((float4 *)src) * weight;
256   }
257   else {
258     assert(!"not implemented for this type");
259   }
260 }
261
262 const char *Attribute::standard_name(AttributeStandard std)
263 {
264   switch (std) {
265     case ATTR_STD_VERTEX_NORMAL:
266       return "N";
267     case ATTR_STD_FACE_NORMAL:
268       return "Ng";
269     case ATTR_STD_UV:
270       return "uv";
271     case ATTR_STD_GENERATED:
272       return "generated";
273     case ATTR_STD_GENERATED_TRANSFORM:
274       return "generated_transform";
275     case ATTR_STD_UV_TANGENT:
276       return "tangent";
277     case ATTR_STD_UV_TANGENT_SIGN:
278       return "tangent_sign";
279     case ATTR_STD_POSITION_UNDEFORMED:
280       return "undeformed";
281     case ATTR_STD_POSITION_UNDISPLACED:
282       return "undisplaced";
283     case ATTR_STD_MOTION_VERTEX_POSITION:
284       return "motion_P";
285     case ATTR_STD_MOTION_VERTEX_NORMAL:
286       return "motion_N";
287     case ATTR_STD_PARTICLE:
288       return "particle";
289     case ATTR_STD_CURVE_INTERCEPT:
290       return "curve_intercept";
291     case ATTR_STD_CURVE_RANDOM:
292       return "curve_random";
293     case ATTR_STD_PTEX_FACE_ID:
294       return "ptex_face_id";
295     case ATTR_STD_PTEX_UV:
296       return "ptex_uv";
297     case ATTR_STD_VOLUME_DENSITY:
298       return "density";
299     case ATTR_STD_VOLUME_COLOR:
300       return "color";
301     case ATTR_STD_VOLUME_FLAME:
302       return "flame";
303     case ATTR_STD_VOLUME_HEAT:
304       return "heat";
305     case ATTR_STD_VOLUME_TEMPERATURE:
306       return "temperature";
307     case ATTR_STD_VOLUME_VELOCITY:
308       return "velocity";
309     case ATTR_STD_POINTINESS:
310       return "pointiness";
311     case ATTR_STD_NOT_FOUND:
312     case ATTR_STD_NONE:
313     case ATTR_STD_NUM:
314       return "";
315   }
316
317   return "";
318 }
319
320 AttributeStandard Attribute::name_standard(const char *name)
321 {
322   if (name) {
323     for (int std = ATTR_STD_NONE; std < ATTR_STD_NUM; std++) {
324       if (strcmp(name, Attribute::standard_name((AttributeStandard)std)) == 0) {
325         return (AttributeStandard)std;
326       }
327     }
328   }
329
330   return ATTR_STD_NONE;
331 }
332
333 /* Attribute Set */
334
335 AttributeSet::AttributeSet()
336 {
337   triangle_mesh = NULL;
338   curve_mesh = NULL;
339   subd_mesh = NULL;
340 }
341
342 AttributeSet::~AttributeSet()
343 {
344 }
345
346 Attribute *AttributeSet::add(ustring name, TypeDesc type, AttributeElement element)
347 {
348   Attribute *attr = find(name);
349
350   if (attr) {
351     /* return if same already exists */
352     if (attr->type == type && attr->element == element)
353       return attr;
354
355     /* overwrite attribute with same name but different type/element */
356     remove(name);
357   }
358
359 #if __cplusplus >= 201103L
360   attributes.emplace_back();
361   attr = &attributes.back();
362   attr->set(name, type, element);
363 #else
364   {
365     Attribute attr_temp;
366     attr_temp.set(name, type, element);
367     attributes.push_back(attr_temp);
368     attr = &attributes.back();
369   }
370 #endif
371
372   /* this is weak .. */
373   if (triangle_mesh)
374     attr->resize(triangle_mesh, ATTR_PRIM_TRIANGLE, false);
375   if (curve_mesh)
376     attr->resize(curve_mesh, ATTR_PRIM_CURVE, false);
377   if (subd_mesh)
378     attr->resize(subd_mesh, ATTR_PRIM_SUBD, false);
379
380   return attr;
381 }
382
383 Attribute *AttributeSet::find(ustring name) const
384 {
385   foreach (const Attribute &attr, attributes)
386     if (attr.name == name)
387       return (Attribute *)&attr;
388
389   return NULL;
390 }
391
392 void AttributeSet::remove(ustring name)
393 {
394   Attribute *attr = find(name);
395
396   if (attr) {
397     list<Attribute>::iterator it;
398
399     for (it = attributes.begin(); it != attributes.end(); it++) {
400       if (&*it == attr) {
401         attributes.erase(it);
402         return;
403       }
404     }
405   }
406 }
407
408 Attribute *AttributeSet::add(AttributeStandard std, ustring name)
409 {
410   Attribute *attr = NULL;
411
412   if (name == ustring())
413     name = Attribute::standard_name(std);
414
415   if (triangle_mesh || subd_mesh) {
416     switch (std) {
417       case ATTR_STD_VERTEX_NORMAL:
418         attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_VERTEX);
419         break;
420       case ATTR_STD_FACE_NORMAL:
421         attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_FACE);
422         break;
423       case ATTR_STD_UV:
424         attr = add(name, TypeFloat2, ATTR_ELEMENT_CORNER);
425         break;
426       case ATTR_STD_UV_TANGENT:
427         attr = add(name, TypeDesc::TypeVector, ATTR_ELEMENT_CORNER);
428         break;
429       case ATTR_STD_UV_TANGENT_SIGN:
430         attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CORNER);
431         break;
432       case ATTR_STD_GENERATED:
433       case ATTR_STD_POSITION_UNDEFORMED:
434       case ATTR_STD_POSITION_UNDISPLACED:
435         attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
436         break;
437       case ATTR_STD_MOTION_VERTEX_POSITION:
438         attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX_MOTION);
439         break;
440       case ATTR_STD_MOTION_VERTEX_NORMAL:
441         attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_VERTEX_MOTION);
442         break;
443       case ATTR_STD_PTEX_FACE_ID:
444         attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_FACE);
445         break;
446       case ATTR_STD_PTEX_UV:
447         attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
448         break;
449       case ATTR_STD_GENERATED_TRANSFORM:
450         attr = add(name, TypeDesc::TypeMatrix, ATTR_ELEMENT_MESH);
451         break;
452       case ATTR_STD_VOLUME_DENSITY:
453       case ATTR_STD_VOLUME_FLAME:
454       case ATTR_STD_VOLUME_HEAT:
455       case ATTR_STD_VOLUME_TEMPERATURE:
456         attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_VOXEL);
457         break;
458       case ATTR_STD_VOLUME_COLOR:
459         attr = add(name, TypeDesc::TypeColor, ATTR_ELEMENT_VOXEL);
460         break;
461       case ATTR_STD_VOLUME_VELOCITY:
462         attr = add(name, TypeDesc::TypeVector, ATTR_ELEMENT_VOXEL);
463         break;
464       case ATTR_STD_POINTINESS:
465         attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_VERTEX);
466         break;
467       default:
468         assert(0);
469         break;
470     }
471   }
472   else if (curve_mesh) {
473     switch (std) {
474       case ATTR_STD_UV:
475         attr = add(name, TypeFloat2, ATTR_ELEMENT_CURVE);
476         break;
477       case ATTR_STD_GENERATED:
478         attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE);
479         break;
480       case ATTR_STD_MOTION_VERTEX_POSITION:
481         attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE_KEY_MOTION);
482         break;
483       case ATTR_STD_CURVE_INTERCEPT:
484         attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CURVE_KEY);
485         break;
486       case ATTR_STD_CURVE_RANDOM:
487         attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CURVE);
488         break;
489       case ATTR_STD_GENERATED_TRANSFORM:
490         attr = add(name, TypeDesc::TypeMatrix, ATTR_ELEMENT_MESH);
491         break;
492       case ATTR_STD_POINTINESS:
493         attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_VERTEX);
494         break;
495       default:
496         assert(0);
497         break;
498     }
499   }
500
501   attr->std = std;
502
503   return attr;
504 }
505
506 Attribute *AttributeSet::find(AttributeStandard std) const
507 {
508   foreach (const Attribute &attr, attributes)
509     if (attr.std == std)
510       return (Attribute *)&attr;
511
512   return NULL;
513 }
514
515 void AttributeSet::remove(AttributeStandard std)
516 {
517   Attribute *attr = find(std);
518
519   if (attr) {
520     list<Attribute>::iterator it;
521
522     for (it = attributes.begin(); it != attributes.end(); it++) {
523       if (&*it == attr) {
524         attributes.erase(it);
525         return;
526       }
527     }
528   }
529 }
530
531 Attribute *AttributeSet::find(AttributeRequest &req)
532 {
533   if (req.std == ATTR_STD_NONE)
534     return find(req.name);
535   else
536     return find(req.std);
537 }
538
539 void AttributeSet::remove(Attribute *attribute)
540 {
541   if (attribute->std == ATTR_STD_NONE) {
542     remove(attribute->name);
543   }
544   else {
545     remove(attribute->std);
546   }
547 }
548
549 void AttributeSet::resize(bool reserve_only)
550 {
551   foreach (Attribute &attr, attributes) {
552     if (triangle_mesh)
553       attr.resize(triangle_mesh, ATTR_PRIM_TRIANGLE, reserve_only);
554     if (curve_mesh)
555       attr.resize(curve_mesh, ATTR_PRIM_CURVE, reserve_only);
556     if (subd_mesh)
557       attr.resize(subd_mesh, ATTR_PRIM_SUBD, reserve_only);
558   }
559 }
560
561 void AttributeSet::clear(bool preserve_voxel_data)
562 {
563   if (preserve_voxel_data) {
564     list<Attribute>::iterator it;
565
566     for (it = attributes.begin(); it != attributes.end();) {
567       if (it->element == ATTR_ELEMENT_VOXEL || it->std == ATTR_STD_GENERATED_TRANSFORM) {
568         it++;
569       }
570       else {
571         attributes.erase(it++);
572       }
573     }
574   }
575   else {
576     attributes.clear();
577   }
578 }
579
580 /* AttributeRequest */
581
582 AttributeRequest::AttributeRequest(ustring name_)
583 {
584   name = name_;
585   std = ATTR_STD_NONE;
586
587   triangle_type = TypeDesc::TypeFloat;
588   triangle_desc.element = ATTR_ELEMENT_NONE;
589   triangle_desc.offset = 0;
590   triangle_desc.type = NODE_ATTR_FLOAT;
591
592   curve_type = TypeDesc::TypeFloat;
593   curve_desc.element = ATTR_ELEMENT_NONE;
594   curve_desc.offset = 0;
595   curve_desc.type = NODE_ATTR_FLOAT;
596
597   subd_type = TypeDesc::TypeFloat;
598   subd_desc.element = ATTR_ELEMENT_NONE;
599   subd_desc.offset = 0;
600   subd_desc.type = NODE_ATTR_FLOAT;
601 }
602
603 AttributeRequest::AttributeRequest(AttributeStandard std_)
604 {
605   name = ustring();
606   std = std_;
607
608   triangle_type = TypeDesc::TypeFloat;
609   triangle_desc.element = ATTR_ELEMENT_NONE;
610   triangle_desc.offset = 0;
611   triangle_desc.type = NODE_ATTR_FLOAT;
612
613   curve_type = TypeDesc::TypeFloat;
614   curve_desc.element = ATTR_ELEMENT_NONE;
615   curve_desc.offset = 0;
616   curve_desc.type = NODE_ATTR_FLOAT;
617
618   subd_type = TypeDesc::TypeFloat;
619   subd_desc.element = ATTR_ELEMENT_NONE;
620   subd_desc.offset = 0;
621   subd_desc.type = NODE_ATTR_FLOAT;
622 }
623
624 /* AttributeRequestSet */
625
626 AttributeRequestSet::AttributeRequestSet()
627 {
628 }
629
630 AttributeRequestSet::~AttributeRequestSet()
631 {
632 }
633
634 bool AttributeRequestSet::modified(const AttributeRequestSet &other)
635 {
636   if (requests.size() != other.requests.size())
637     return true;
638
639   for (size_t i = 0; i < requests.size(); i++) {
640     bool found = false;
641
642     for (size_t j = 0; j < requests.size() && !found; j++)
643       if (requests[i].name == other.requests[j].name && requests[i].std == other.requests[j].std) {
644         found = true;
645       }
646
647     if (!found) {
648       return true;
649     }
650   }
651
652   return false;
653 }
654
655 void AttributeRequestSet::add(ustring name)
656 {
657   foreach (AttributeRequest &req, requests) {
658     if (req.name == name) {
659       return;
660     }
661   }
662
663   requests.push_back(AttributeRequest(name));
664 }
665
666 void AttributeRequestSet::add(AttributeStandard std)
667 {
668   foreach (AttributeRequest &req, requests)
669     if (req.std == std)
670       return;
671
672   requests.push_back(AttributeRequest(std));
673 }
674
675 void AttributeRequestSet::add(AttributeRequestSet &reqs)
676 {
677   foreach (AttributeRequest &req, reqs.requests) {
678     if (req.std == ATTR_STD_NONE)
679       add(req.name);
680     else
681       add(req.std);
682   }
683 }
684
685 void AttributeRequestSet::add_standard(ustring name)
686 {
687   if (name.empty()) {
688     return;
689   }
690
691   AttributeStandard std = Attribute::name_standard(name.c_str());
692
693   if (std) {
694     add(std);
695   }
696   else {
697     add(name);
698   }
699 }
700
701 bool AttributeRequestSet::find(ustring name)
702 {
703   foreach (AttributeRequest &req, requests)
704     if (req.name == name)
705       return true;
706
707   return false;
708 }
709
710 bool AttributeRequestSet::find(AttributeStandard std)
711 {
712   foreach (AttributeRequest &req, requests)
713     if (req.std == std)
714       return true;
715
716   return false;
717 }
718
719 size_t AttributeRequestSet::size()
720 {
721   return requests.size();
722 }
723
724 void AttributeRequestSet::clear()
725 {
726   requests.clear();
727 }
728
729 CCL_NAMESPACE_END