Cycles: implement pointiness geometry attribute
[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 "image.h"
18 #include "mesh.h"
19 #include "attribute.h"
20
21 #include "util_debug.h"
22 #include "util_foreach.h"
23 #include "util_transform.h"
24
25 CCL_NAMESPACE_BEGIN
26
27 /* Attribute */
28
29 Attribute::~Attribute()
30 {
31         /* for voxel data, we need to remove the image from the image manager */
32         if(element == ATTR_ELEMENT_VOXEL) {
33                 VoxelAttribute *voxel_data = data_voxel();
34
35                 if(voxel_data)
36                         voxel_data->manager->remove_image(voxel_data->slot);
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
47         /* string and matrix not supported! */
48         assert(type == TypeDesc::TypeFloat || type == TypeDesc::TypeColor ||
49                 type == TypeDesc::TypePoint || type == TypeDesc::TypeVector ||
50                 type == TypeDesc::TypeNormal || type == TypeDesc::TypeMatrix);
51 }
52
53 void Attribute::reserve(int numverts, int numtris, int numsteps, int numcurves, int numkeys, bool resize)
54 {
55         if (resize) {
56                 buffer.resize(buffer_size(numverts, numtris, numsteps, numcurves, numkeys), 0);
57         }
58         else {
59                 buffer.reserve(buffer_size(numverts, numtris, numsteps, numcurves, numkeys));
60         }
61 }
62
63 void Attribute::add(const float& f)
64 {
65         char *data = (char*)&f;
66         size_t size = sizeof(f);
67
68         for(size_t i = 0; i < size; i++)
69                 buffer.push_back(data[i]);
70 }
71
72 void Attribute::add(const uchar4& f)
73 {
74         char *data = (char*)&f;
75         size_t size = sizeof(f);
76
77         for(size_t i = 0; i < size; i++)
78                 buffer.push_back(data[i]);
79 }
80
81 void Attribute::add(const float3& f)
82 {
83         char *data = (char*)&f;
84         size_t size = sizeof(f);
85
86         for(size_t i = 0; i < size; i++)
87                 buffer.push_back(data[i]);
88 }
89
90 void Attribute::add(const Transform& f)
91 {
92         char *data = (char*)&f;
93         size_t size = sizeof(f);
94
95         for(size_t i = 0; i < size; i++)
96                 buffer.push_back(data[i]);
97 }
98
99 void Attribute::add(const VoxelAttribute& f)
100 {
101         char *data = (char*)&f;
102         size_t size = sizeof(f);
103
104         for(size_t i = 0; i < size; i++)
105                 buffer.push_back(data[i]);
106 }
107
108 void Attribute::add(const char *data)
109 {
110         size_t size = data_sizeof();
111
112         for(size_t i = 0; i < size; i++)
113                 buffer.push_back(data[i]);
114 }
115
116 size_t Attribute::data_sizeof() const
117 {
118         if(element == ATTR_ELEMENT_VOXEL)
119                 return sizeof(VoxelAttribute);
120         else if(type == TypeDesc::TypeFloat)
121                 return sizeof(float);
122         else if(type == TypeDesc::TypeMatrix)
123                 return sizeof(Transform);
124         else
125                 return sizeof(float3);
126 }
127
128 size_t Attribute::element_size(int numverts, int numtris, int numsteps, int numcurves, int numkeys) const
129 {
130         size_t size;
131         
132         switch(element) {
133                 case ATTR_ELEMENT_OBJECT:
134                 case ATTR_ELEMENT_MESH:
135                 case ATTR_ELEMENT_VOXEL:
136                         size = 1;
137                         break;
138                 case ATTR_ELEMENT_VERTEX:
139                         size = numverts;
140                         break;
141                 case ATTR_ELEMENT_VERTEX_MOTION:
142                         size = numverts * (numsteps - 1);
143                         break;
144                 case ATTR_ELEMENT_FACE:
145                         size = numtris;
146                         break;
147                 case ATTR_ELEMENT_CORNER:
148                 case ATTR_ELEMENT_CORNER_BYTE:
149                         size = numtris*3;
150                         break;
151                 case ATTR_ELEMENT_CURVE:
152                         size = numcurves;
153                         break;
154                 case ATTR_ELEMENT_CURVE_KEY:
155                         size = numkeys;
156                         break;
157                 case ATTR_ELEMENT_CURVE_KEY_MOTION:
158                         size = numkeys * (numsteps - 1);
159                         break;
160                 default:
161                         size = 0;
162                         break;
163         }
164         
165         return size;
166 }
167
168 size_t Attribute::buffer_size(int numverts, int numtris, int numsteps, int numcurves, int numkeys) const
169 {
170         return element_size(numverts, numtris, numsteps, numcurves, numkeys)*data_sizeof();
171 }
172
173 bool Attribute::same_storage(TypeDesc a, TypeDesc b)
174 {
175         if(a == b)
176                 return true;
177         
178         if(a == TypeDesc::TypeColor || a == TypeDesc::TypePoint ||
179            a == TypeDesc::TypeVector || a == TypeDesc::TypeNormal)
180         {
181                 if(b == TypeDesc::TypeColor || b == TypeDesc::TypePoint ||
182                    b == TypeDesc::TypeVector || b == TypeDesc::TypeNormal)
183                 {
184                         return true;
185                 }
186         }
187         return false;
188 }
189
190 const char *Attribute::standard_name(AttributeStandard std)
191 {
192         switch(std) {
193                 case ATTR_STD_VERTEX_NORMAL:
194                         return "N";
195                 case ATTR_STD_FACE_NORMAL:
196                         return "Ng";
197                 case ATTR_STD_UV:
198                         return "uv";
199                 case ATTR_STD_GENERATED:
200                         return "generated";
201                 case ATTR_STD_GENERATED_TRANSFORM:
202                         return "generated_transform";
203                 case ATTR_STD_UV_TANGENT:
204                         return "tangent";
205                 case ATTR_STD_UV_TANGENT_SIGN:
206                         return "tangent_sign";
207                 case ATTR_STD_POSITION_UNDEFORMED:
208                         return "undeformed";
209                 case ATTR_STD_POSITION_UNDISPLACED:
210                         return "undisplaced";
211                 case ATTR_STD_MOTION_VERTEX_POSITION:
212                         return "motion_P";
213                 case ATTR_STD_MOTION_VERTEX_NORMAL:
214                         return "motion_N";
215                 case ATTR_STD_PARTICLE:
216                         return "particle";
217                 case ATTR_STD_CURVE_INTERCEPT:
218                         return "curve_intercept";
219                 case ATTR_STD_PTEX_FACE_ID:
220                         return "ptex_face_id";
221                 case ATTR_STD_PTEX_UV:
222                         return "ptex_uv";
223                 case ATTR_STD_VOLUME_DENSITY:
224                         return "density";
225                 case ATTR_STD_VOLUME_COLOR:
226                         return "color";
227                 case ATTR_STD_VOLUME_FLAME:
228                         return "flame";
229                 case ATTR_STD_VOLUME_HEAT:
230                         return "heat";
231                 case ATTR_STD_VOLUME_VELOCITY:
232                         return "velocity";
233                 case ATTR_STD_POINTINESS:
234                         return "pointiness";
235                 case ATTR_STD_NOT_FOUND:
236                 case ATTR_STD_NONE:
237                 case ATTR_STD_NUM:
238                         return "";
239         }
240         
241         return "";
242 }
243
244 AttributeStandard Attribute::name_standard(const char *name)
245 {
246         for(int std = ATTR_STD_NONE; std < ATTR_STD_NUM; std++)
247                 if(strcmp(name, Attribute::standard_name((AttributeStandard)std)) == 0)
248                         return (AttributeStandard)std;
249
250         return ATTR_STD_NONE;
251 }
252
253 /* Attribute Set */
254
255 AttributeSet::AttributeSet()
256 {
257         triangle_mesh = NULL;
258         curve_mesh = NULL;
259 }
260
261 AttributeSet::~AttributeSet()
262 {
263 }
264
265 Attribute *AttributeSet::add(ustring name, TypeDesc type, AttributeElement element, bool resize)
266 {
267         Attribute *attr = find(name);
268
269         if(attr) {
270                 /* return if same already exists */
271                 if(attr->type == type && attr->element == element)
272                         return attr;
273
274                 /* overwrite attribute with same name but different type/element */
275                 remove(name);
276         }
277
278 #if __cplusplus >= 201103L
279         attributes.emplace_back();
280         attr = &attributes.back();
281         attr->set(name, type, element);
282 #else
283         {
284                 Attribute attr_temp;
285                 attr_temp.set(name, type, element);
286                 attributes.push_back(attr_temp);
287                 attr = &attributes.back();
288         }
289 #endif
290
291         /* this is weak .. */
292         if(triangle_mesh)
293                 attr->reserve(triangle_mesh->verts.size(), triangle_mesh->triangles.size(), triangle_mesh->motion_steps, 0, 0, resize);
294         if(curve_mesh)
295                 attr->reserve(0, 0, curve_mesh->motion_steps, curve_mesh->curves.size(), curve_mesh->curve_keys.size(), resize);
296         
297         return attr;
298 }
299
300 Attribute *AttributeSet::find(ustring name) const
301 {
302         foreach(const Attribute& attr, attributes)
303                 if(attr.name == name)
304                         return (Attribute*)&attr;
305
306         return NULL;
307 }
308
309 void AttributeSet::remove(ustring name)
310 {
311         Attribute *attr = find(name);
312
313         if(attr) {
314                 list<Attribute>::iterator it;
315
316                 for(it = attributes.begin(); it != attributes.end(); it++) {
317                         if(&*it == attr) {
318                                 attributes.erase(it);
319                                 return;
320                         }
321                 }
322         }
323 }
324
325 Attribute *AttributeSet::add(AttributeStandard std, ustring name)
326 {
327         Attribute *attr = NULL;
328
329         if(name == ustring())
330                 name = Attribute::standard_name(std);
331
332         if(triangle_mesh) {
333                 switch(std) {
334                         case ATTR_STD_VERTEX_NORMAL:
335                                 attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_VERTEX);
336                                 break;
337                         case ATTR_STD_FACE_NORMAL:
338                                 attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_FACE);
339                                 break;
340                         case ATTR_STD_UV:
341                                 attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CORNER);
342                                 break;
343                         case ATTR_STD_UV_TANGENT:
344                                 attr = add(name, TypeDesc::TypeVector, ATTR_ELEMENT_CORNER);
345                                 break;
346                         case ATTR_STD_UV_TANGENT_SIGN:
347                                 attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CORNER);
348                                 break;
349                         case ATTR_STD_GENERATED:
350                         case ATTR_STD_POSITION_UNDEFORMED:
351                         case ATTR_STD_POSITION_UNDISPLACED:
352                                 attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
353                                 break;
354                         case ATTR_STD_MOTION_VERTEX_POSITION:
355                                 attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX_MOTION);
356                                 break;
357                         case ATTR_STD_MOTION_VERTEX_NORMAL:
358                                 attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_VERTEX_MOTION);
359                                 break;
360                         case ATTR_STD_PTEX_FACE_ID:
361                                 attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_FACE);
362                                 break;
363                         case ATTR_STD_PTEX_UV:
364                                 attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
365                                 break;
366                         case ATTR_STD_GENERATED_TRANSFORM:
367                                 attr = add(name, TypeDesc::TypeMatrix, ATTR_ELEMENT_MESH);
368                                 break;
369                         case ATTR_STD_VOLUME_DENSITY:
370                         case ATTR_STD_VOLUME_FLAME:
371                         case ATTR_STD_VOLUME_HEAT:
372                                 attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_VOXEL);
373                                 break;
374                         case ATTR_STD_VOLUME_COLOR:
375                                 attr = add(name, TypeDesc::TypeColor, ATTR_ELEMENT_VOXEL);
376                                 break;
377                         case ATTR_STD_VOLUME_VELOCITY:
378                                 attr = add(name, TypeDesc::TypeVector, ATTR_ELEMENT_VOXEL);
379                                 break;
380                         case ATTR_STD_POINTINESS:
381                                 attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_VERTEX);
382                                 break;
383                         default:
384                                 assert(0);
385                                 break;
386                 }
387         }
388         else if(curve_mesh) {
389                 switch(std) {
390                         case ATTR_STD_UV:
391                         case ATTR_STD_GENERATED:
392                                 attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE);
393                                 break;
394                         case ATTR_STD_MOTION_VERTEX_POSITION:
395                                 attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE_KEY_MOTION);
396                                 break;
397                         case ATTR_STD_CURVE_INTERCEPT:
398                                 attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CURVE_KEY);
399                                 break;
400                         case ATTR_STD_GENERATED_TRANSFORM:
401                                 attr = add(name, TypeDesc::TypeMatrix, ATTR_ELEMENT_MESH);
402                                 break;
403                         case ATTR_STD_POINTINESS:
404                                 attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_VERTEX);
405                                 break;
406                         default:
407                                 assert(0);
408                                 break;
409                 }
410         }
411
412         attr->std = std;
413         
414         return attr;
415 }
416
417 Attribute *AttributeSet::find(AttributeStandard std) const
418 {
419         foreach(const Attribute& attr, attributes)
420                 if(attr.std == std)
421                         return (Attribute*)&attr;
422
423         return NULL;
424 }
425
426 void AttributeSet::remove(AttributeStandard std)
427 {
428         Attribute *attr = find(std);
429
430         if(attr) {
431                 list<Attribute>::iterator it;
432
433                 for(it = attributes.begin(); it != attributes.end(); it++) {
434                         if(&*it == attr) {
435                                 attributes.erase(it);
436                                 return;
437                         }
438                 }
439         }
440 }
441
442 Attribute *AttributeSet::find(AttributeRequest& req)
443 {
444         if(req.std == ATTR_STD_NONE)
445                 return find(req.name);
446         else
447                 return find(req.std);
448 }
449
450 void AttributeSet::reserve()
451 {
452         foreach(Attribute& attr, attributes) {
453                 if(triangle_mesh)
454                         attr.reserve(triangle_mesh->verts.size(), triangle_mesh->triangles.size(), triangle_mesh->motion_steps, 0, 0, true);
455                 if(curve_mesh)
456                         attr.reserve(0, 0, 0, curve_mesh->curves.size(), curve_mesh->curve_keys.size(), true);
457         }
458 }
459
460 void AttributeSet::clear()
461 {
462         attributes.clear();
463 }
464
465 /* AttributeRequest */
466
467 AttributeRequest::AttributeRequest(ustring name_)
468 {
469         name = name_;
470         std = ATTR_STD_NONE;
471
472         triangle_type = TypeDesc::TypeFloat;
473         triangle_element = ATTR_ELEMENT_NONE;
474         triangle_offset = 0;
475
476         curve_type = TypeDesc::TypeFloat;
477         curve_element = ATTR_ELEMENT_NONE;
478         curve_offset = 0;
479 }
480
481 AttributeRequest::AttributeRequest(AttributeStandard std_)
482 {
483         name = ustring();
484         std = std_;
485
486         triangle_type = TypeDesc::TypeFloat;
487         triangle_element = ATTR_ELEMENT_NONE;
488         triangle_offset = 0;
489
490         curve_type = TypeDesc::TypeFloat;
491         curve_element = ATTR_ELEMENT_NONE;
492         curve_offset = 0;
493 }
494
495 /* AttributeRequestSet */
496
497 AttributeRequestSet::AttributeRequestSet()
498 {
499 }
500
501 AttributeRequestSet::~AttributeRequestSet()
502 {
503 }
504
505 bool AttributeRequestSet::modified(const AttributeRequestSet& other)
506 {
507         if(requests.size() != other.requests.size())
508                 return true;
509
510         for(size_t i = 0; i < requests.size(); i++) {
511                 bool found = false;
512
513                 for(size_t j = 0; j < requests.size() && !found; j++)
514                         if(requests[i].name == other.requests[j].name &&
515                            requests[i].std == other.requests[j].std)
516                         {
517                                 found = true;
518                         }
519
520                 if(!found) {
521                         return true;
522                 }
523         }
524
525         return false;
526 }
527
528 void AttributeRequestSet::add(ustring name)
529 {
530         foreach(AttributeRequest& req, requests)
531                 if(req.name == name)
532                         return;
533
534         requests.push_back(AttributeRequest(name));
535 }
536
537 void AttributeRequestSet::add(AttributeStandard std)
538 {
539         foreach(AttributeRequest& req, requests)
540                 if(req.std == std)
541                         return;
542
543         requests.push_back(AttributeRequest(std));
544 }
545
546 void AttributeRequestSet::add(AttributeRequestSet& reqs)
547 {
548         foreach(AttributeRequest& req, reqs.requests) {
549                 if(req.std == ATTR_STD_NONE)
550                         add(req.name);
551                 else
552                         add(req.std);
553         }
554 }
555
556 bool AttributeRequestSet::find(ustring name)
557 {
558         foreach(AttributeRequest& req, requests)
559                 if(req.name == name)
560                         return true;
561         
562         return false;
563 }
564
565 bool AttributeRequestSet::find(AttributeStandard std)
566 {
567         foreach(AttributeRequest& req, requests)
568                 if(req.std == std)
569                         return true;
570
571         return false;
572 }
573
574 size_t AttributeRequestSet::size()
575 {
576         return requests.size();
577 }
578
579 void AttributeRequestSet::clear()
580 {
581         requests.clear();
582 }
583
584 CCL_NAMESPACE_END
585