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