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