Cycles: Add support for uchar4 attributes.
[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_NOT_FOUND:
234                 case ATTR_STD_NONE:
235                 case ATTR_STD_NUM:
236                         return "";
237         }
238         
239         return "";
240 }
241
242 AttributeStandard Attribute::name_standard(const char *name)
243 {
244         for(int std = ATTR_STD_NONE; std < ATTR_STD_NUM; std++)
245                 if(strcmp(name, Attribute::standard_name((AttributeStandard)std)) == 0)
246                         return (AttributeStandard)std;
247
248         return ATTR_STD_NONE;
249 }
250
251 /* Attribute Set */
252
253 AttributeSet::AttributeSet()
254 {
255         triangle_mesh = NULL;
256         curve_mesh = NULL;
257 }
258
259 AttributeSet::~AttributeSet()
260 {
261 }
262
263 Attribute *AttributeSet::add(ustring name, TypeDesc type, AttributeElement element, bool resize)
264 {
265         Attribute *attr = find(name);
266
267         if(attr) {
268                 /* return if same already exists */
269                 if(attr->type == type && attr->element == element)
270                         return attr;
271
272                 /* overwrite attribute with same name but different type/element */
273                 remove(name);
274         }
275
276 #if __cplusplus >= 201103L
277         attributes.emplace_back();
278         attr = &attributes.back();
279         attr->set(name, type, element);
280 #else
281         {
282                 Attribute attr_temp;
283                 attr_temp.set(name, type, element);
284                 attributes.push_back(attr_temp);
285                 attr = &attributes.back();
286         }
287 #endif
288
289         /* this is weak .. */
290         if(triangle_mesh)
291                 attr->reserve(triangle_mesh->verts.size(), triangle_mesh->triangles.size(), triangle_mesh->motion_steps, 0, 0, resize);
292         if(curve_mesh)
293                 attr->reserve(0, 0, curve_mesh->motion_steps, curve_mesh->curves.size(), curve_mesh->curve_keys.size(), resize);
294         
295         return attr;
296 }
297
298 Attribute *AttributeSet::find(ustring name) const
299 {
300         foreach(const Attribute& attr, attributes)
301                 if(attr.name == name)
302                         return (Attribute*)&attr;
303
304         return NULL;
305 }
306
307 void AttributeSet::remove(ustring name)
308 {
309         Attribute *attr = find(name);
310
311         if(attr) {
312                 list<Attribute>::iterator it;
313
314                 for(it = attributes.begin(); it != attributes.end(); it++) {
315                         if(&*it == attr) {
316                                 attributes.erase(it);
317                                 return;
318                         }
319                 }
320         }
321 }
322
323 Attribute *AttributeSet::add(AttributeStandard std, ustring name)
324 {
325         Attribute *attr = NULL;
326
327         if(name == ustring())
328                 name = Attribute::standard_name(std);
329
330         if(triangle_mesh) {
331                 switch(std) {
332                         case ATTR_STD_VERTEX_NORMAL:
333                                 attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_VERTEX);
334                                 break;
335                         case ATTR_STD_FACE_NORMAL:
336                                 attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_FACE);
337                                 break;
338                         case ATTR_STD_UV:
339                                 attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CORNER);
340                                 break;
341                         case ATTR_STD_UV_TANGENT:
342                                 attr = add(name, TypeDesc::TypeVector, ATTR_ELEMENT_CORNER);
343                                 break;
344                         case ATTR_STD_UV_TANGENT_SIGN:
345                                 attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CORNER);
346                                 break;
347                         case ATTR_STD_GENERATED:
348                         case ATTR_STD_POSITION_UNDEFORMED:
349                         case ATTR_STD_POSITION_UNDISPLACED:
350                                 attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
351                                 break;
352                         case ATTR_STD_MOTION_VERTEX_POSITION:
353                                 attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX_MOTION);
354                                 break;
355                         case ATTR_STD_MOTION_VERTEX_NORMAL:
356                                 attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_VERTEX_MOTION);
357                                 break;
358                         case ATTR_STD_PTEX_FACE_ID:
359                                 attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_FACE);
360                                 break;
361                         case ATTR_STD_PTEX_UV:
362                                 attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
363                                 break;
364                         case ATTR_STD_GENERATED_TRANSFORM:
365                                 attr = add(name, TypeDesc::TypeMatrix, ATTR_ELEMENT_MESH);
366                                 break;
367                         case ATTR_STD_VOLUME_DENSITY:
368                         case ATTR_STD_VOLUME_FLAME:
369                         case ATTR_STD_VOLUME_HEAT:
370                                 attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_VOXEL);
371                                 break;
372                         case ATTR_STD_VOLUME_COLOR:
373                                 attr = add(name, TypeDesc::TypeColor, ATTR_ELEMENT_VOXEL);
374                                 break;
375                         case ATTR_STD_VOLUME_VELOCITY:
376                                 attr = add(name, TypeDesc::TypeVector, ATTR_ELEMENT_VOXEL);
377                                 break;
378                         default:
379                                 assert(0);
380                                 break;
381                 }
382         }
383         else if(curve_mesh) {
384                 switch(std) {
385                         case ATTR_STD_UV:
386                         case ATTR_STD_GENERATED:
387                                 attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE);
388                                 break;
389                         case ATTR_STD_MOTION_VERTEX_POSITION:
390                                 attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE_KEY_MOTION);
391                                 break;
392                         case ATTR_STD_CURVE_INTERCEPT:
393                                 attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CURVE_KEY);
394                                 break;
395                         case ATTR_STD_GENERATED_TRANSFORM:
396                                 attr = add(name, TypeDesc::TypeMatrix, ATTR_ELEMENT_MESH);
397                                 break;
398                         default:
399                                 assert(0);
400                                 break;
401                 }
402         }
403
404         attr->std = std;
405         
406         return attr;
407 }
408
409 Attribute *AttributeSet::find(AttributeStandard std) const
410 {
411         foreach(const Attribute& attr, attributes)
412                 if(attr.std == std)
413                         return (Attribute*)&attr;
414
415         return NULL;
416 }
417
418 void AttributeSet::remove(AttributeStandard std)
419 {
420         Attribute *attr = find(std);
421
422         if(attr) {
423                 list<Attribute>::iterator it;
424
425                 for(it = attributes.begin(); it != attributes.end(); it++) {
426                         if(&*it == attr) {
427                                 attributes.erase(it);
428                                 return;
429                         }
430                 }
431         }
432 }
433
434 Attribute *AttributeSet::find(AttributeRequest& req)
435 {
436         if(req.std == ATTR_STD_NONE)
437                 return find(req.name);
438         else
439                 return find(req.std);
440 }
441
442 void AttributeSet::reserve()
443 {
444         foreach(Attribute& attr, attributes) {
445                 if(triangle_mesh)
446                         attr.reserve(triangle_mesh->verts.size(), triangle_mesh->triangles.size(), triangle_mesh->motion_steps, 0, 0, true);
447                 if(curve_mesh)
448                         attr.reserve(0, 0, 0, curve_mesh->curves.size(), curve_mesh->curve_keys.size(), true);
449         }
450 }
451
452 void AttributeSet::clear()
453 {
454         attributes.clear();
455 }
456
457 /* AttributeRequest */
458
459 AttributeRequest::AttributeRequest(ustring name_)
460 {
461         name = name_;
462         std = ATTR_STD_NONE;
463
464         triangle_type = TypeDesc::TypeFloat;
465         triangle_element = ATTR_ELEMENT_NONE;
466         triangle_offset = 0;
467
468         curve_type = TypeDesc::TypeFloat;
469         curve_element = ATTR_ELEMENT_NONE;
470         curve_offset = 0;
471 }
472
473 AttributeRequest::AttributeRequest(AttributeStandard std_)
474 {
475         name = ustring();
476         std = std_;
477
478         triangle_type = TypeDesc::TypeFloat;
479         triangle_element = ATTR_ELEMENT_NONE;
480         triangle_offset = 0;
481
482         curve_type = TypeDesc::TypeFloat;
483         curve_element = ATTR_ELEMENT_NONE;
484         curve_offset = 0;
485 }
486
487 /* AttributeRequestSet */
488
489 AttributeRequestSet::AttributeRequestSet()
490 {
491 }
492
493 AttributeRequestSet::~AttributeRequestSet()
494 {
495 }
496
497 bool AttributeRequestSet::modified(const AttributeRequestSet& other)
498 {
499         if(requests.size() != other.requests.size())
500                 return true;
501
502         for(size_t i = 0; i < requests.size(); i++) {
503                 bool found = false;
504
505                 for(size_t j = 0; j < requests.size() && !found; j++)
506                         if(requests[i].name == other.requests[j].name &&
507                            requests[i].std == other.requests[j].std)
508                         {
509                                 found = true;
510                         }
511
512                 if(!found) {
513                         return true;
514                 }
515         }
516
517         return false;
518 }
519
520 void AttributeRequestSet::add(ustring name)
521 {
522         foreach(AttributeRequest& req, requests)
523                 if(req.name == name)
524                         return;
525
526         requests.push_back(AttributeRequest(name));
527 }
528
529 void AttributeRequestSet::add(AttributeStandard std)
530 {
531         foreach(AttributeRequest& req, requests)
532                 if(req.std == std)
533                         return;
534
535         requests.push_back(AttributeRequest(std));
536 }
537
538 void AttributeRequestSet::add(AttributeRequestSet& reqs)
539 {
540         foreach(AttributeRequest& req, reqs.requests) {
541                 if(req.std == ATTR_STD_NONE)
542                         add(req.name);
543                 else
544                         add(req.std);
545         }
546 }
547
548 bool AttributeRequestSet::find(ustring name)
549 {
550         foreach(AttributeRequest& req, requests)
551                 if(req.name == name)
552                         return true;
553         
554         return false;
555 }
556
557 bool AttributeRequestSet::find(AttributeStandard std)
558 {
559         foreach(AttributeRequest& req, requests)
560                 if(req.std == std)
561                         return true;
562
563         return false;
564 }
565
566 size_t AttributeRequestSet::size()
567 {
568         return requests.size();
569 }
570
571 void AttributeRequestSet::clear()
572 {
573         requests.clear();
574 }
575
576 CCL_NAMESPACE_END
577