cd81c33a28fb77ce2fa891bde0c38cbe0c1957e4
[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 float3& 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 Transform& 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 VoxelAttribute& 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 size_t Attribute::data_sizeof() const
100 {
101         if(element == ATTR_ELEMENT_VOXEL)
102                 return sizeof(VoxelAttribute);
103         else if(type == TypeDesc::TypeFloat)
104                 return sizeof(float);
105         else if(type == TypeDesc::TypeMatrix)
106                 return sizeof(Transform);
107         else
108                 return sizeof(float3);
109 }
110
111 size_t Attribute::element_size(int numverts, int numtris, int numsteps, int numcurves, int numkeys) const
112 {
113         size_t size;
114         
115         switch(element) {
116                 case ATTR_ELEMENT_OBJECT:
117                 case ATTR_ELEMENT_MESH:
118                 case ATTR_ELEMENT_VOXEL:
119                         size = 1;
120                         break;
121                 case ATTR_ELEMENT_VERTEX:
122                         size = numverts;
123                         break;
124                 case ATTR_ELEMENT_VERTEX_MOTION:
125                         size = numverts * (numsteps - 1);
126                         break;
127                 case ATTR_ELEMENT_FACE:
128                         size = numtris;
129                         break;
130                 case ATTR_ELEMENT_CORNER:
131                         size = numtris*3;
132                         break;
133                 case ATTR_ELEMENT_CURVE:
134                         size = numcurves;
135                         break;
136                 case ATTR_ELEMENT_CURVE_KEY:
137                         size = numkeys;
138                         break;
139                 case ATTR_ELEMENT_CURVE_KEY_MOTION:
140                         size = numkeys * (numsteps - 1);
141                         break;
142                 default:
143                         size = 0;
144                         break;
145         }
146         
147         return size;
148 }
149
150 size_t Attribute::buffer_size(int numverts, int numtris, int numsteps, int numcurves, int numkeys) const
151 {
152         return element_size(numverts, numtris, numsteps, numcurves, numkeys)*data_sizeof();
153 }
154
155 bool Attribute::same_storage(TypeDesc a, TypeDesc b)
156 {
157         if(a == b)
158                 return true;
159         
160         if(a == TypeDesc::TypeColor || a == TypeDesc::TypePoint ||
161            a == TypeDesc::TypeVector || a == TypeDesc::TypeNormal)
162         {
163                 if(b == TypeDesc::TypeColor || b == TypeDesc::TypePoint ||
164                    b == TypeDesc::TypeVector || b == TypeDesc::TypeNormal)
165                 {
166                         return true;
167                 }
168         }
169         return false;
170 }
171
172 const char *Attribute::standard_name(AttributeStandard std)
173 {
174         switch(std) {
175                 case ATTR_STD_VERTEX_NORMAL:
176                         return "N";
177                 case ATTR_STD_FACE_NORMAL:
178                         return "Ng";
179                 case ATTR_STD_UV:
180                         return "uv";
181                 case ATTR_STD_GENERATED:
182                         return "generated";
183                 case ATTR_STD_GENERATED_TRANSFORM:
184                         return "generated_transform";
185                 case ATTR_STD_UV_TANGENT:
186                         return "tangent";
187                 case ATTR_STD_UV_TANGENT_SIGN:
188                         return "tangent_sign";
189                 case ATTR_STD_POSITION_UNDEFORMED:
190                         return "undeformed";
191                 case ATTR_STD_POSITION_UNDISPLACED:
192                         return "undisplaced";
193                 case ATTR_STD_MOTION_VERTEX_POSITION:
194                         return "motion_P";
195                 case ATTR_STD_MOTION_VERTEX_NORMAL:
196                         return "motion_N";
197                 case ATTR_STD_PARTICLE:
198                         return "particle";
199                 case ATTR_STD_CURVE_INTERCEPT:
200                         return "curve_intercept";
201                 case ATTR_STD_PTEX_FACE_ID:
202                         return "ptex_face_id";
203                 case ATTR_STD_PTEX_UV:
204                         return "ptex_uv";
205                 case ATTR_STD_NOT_FOUND:
206                 case ATTR_STD_NONE:
207                 case ATTR_STD_NUM:
208                         return "";
209         }
210         
211         return "";
212 }
213
214 AttributeStandard Attribute::name_standard(const char *name)
215 {
216         for(AttributeStandard std = ATTR_STD_NONE; std < ATTR_STD_NUM; std++)
217                 if(strcmp(name, Attribute::standard_name(std)) == 0)
218                         return std;
219
220         return ATTR_STD_NONE;
221 }
222
223 /* Attribute Set */
224
225 AttributeSet::AttributeSet()
226 {
227         triangle_mesh = NULL;
228         curve_mesh = NULL;
229 }
230
231 AttributeSet::~AttributeSet()
232 {
233 }
234
235 Attribute *AttributeSet::add(ustring name, TypeDesc type, AttributeElement element, bool resize)
236 {
237         Attribute *attr = find(name);
238
239         if(attr) {
240                 /* return if same already exists */
241                 if(attr->type == type && attr->element == element)
242                         return attr;
243
244                 /* overwrite attribute with same name but different type/element */
245                 remove(name);
246         }
247
248         attributes.push_back(Attribute());
249         attr = &attributes.back();
250
251         attr->set(name, type, element);
252         
253         /* this is weak .. */
254         if(triangle_mesh)
255                 attr->reserve(triangle_mesh->verts.size(), triangle_mesh->triangles.size(), triangle_mesh->motion_steps, 0, 0, resize);
256         if(curve_mesh)
257                 attr->reserve(0, 0, curve_mesh->motion_steps, curve_mesh->curves.size(), curve_mesh->curve_keys.size(), resize);
258         
259         return attr;
260 }
261
262 Attribute *AttributeSet::find(ustring name) const
263 {
264         foreach(const Attribute& attr, attributes)
265                 if(attr.name == name)
266                         return (Attribute*)&attr;
267
268         return NULL;
269 }
270
271 void AttributeSet::remove(ustring name)
272 {
273         Attribute *attr = find(name);
274
275         if(attr) {
276                 list<Attribute>::iterator it;
277
278                 for(it = attributes.begin(); it != attributes.end(); it++) {
279                         if(&*it == attr) {
280                                 attributes.erase(it);
281                                 return;
282                         }
283                 }
284         }
285 }
286
287 Attribute *AttributeSet::add(AttributeStandard std, ustring name)
288 {
289         Attribute *attr = NULL;
290
291         if(name == ustring())
292                 name = Attribute::standard_name(std);
293
294         if(triangle_mesh) {
295                 switch(std) {
296                         case ATTR_STD_VERTEX_NORMAL:
297                                 attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_VERTEX);
298                                 break;
299                         case ATTR_STD_FACE_NORMAL:
300                                 attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_FACE);
301                                 break;
302                         case ATTR_STD_UV:
303                                 attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CORNER);
304                                 break;
305                         case ATTR_STD_UV_TANGENT:
306                                 attr = add(name, TypeDesc::TypeVector, ATTR_ELEMENT_CORNER);
307                                 break;
308                         case ATTR_STD_UV_TANGENT_SIGN:
309                                 attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CORNER);
310                                 break;
311                         case ATTR_STD_GENERATED:
312                         case ATTR_STD_POSITION_UNDEFORMED:
313                         case ATTR_STD_POSITION_UNDISPLACED:
314                                 attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
315                                 break;
316                         case ATTR_STD_MOTION_VERTEX_POSITION:
317                                 attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX_MOTION);
318                                 break;
319                         case ATTR_STD_MOTION_VERTEX_NORMAL:
320                                 attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_VERTEX_MOTION);
321                                 break;
322                         case ATTR_STD_PTEX_FACE_ID:
323                                 attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_FACE);
324                                 break;
325                         case ATTR_STD_PTEX_UV:
326                                 attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
327                                 break;
328                         case ATTR_STD_GENERATED_TRANSFORM:
329                                 attr = add(name, TypeDesc::TypeMatrix, ATTR_ELEMENT_MESH);
330                                 break;
331                         default:
332                                 assert(0);
333                                 break;
334                 }
335         }
336         else if(curve_mesh) {
337                 switch(std) {
338                         case ATTR_STD_UV:
339                         case ATTR_STD_GENERATED:
340                                 attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE);
341                                 break;
342                         case ATTR_STD_MOTION_VERTEX_POSITION:
343                                 attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE_KEY_MOTION);
344                                 break;
345                         case ATTR_STD_CURVE_INTERCEPT:
346                                 attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CURVE_KEY);
347                                 break;
348                         case ATTR_STD_GENERATED_TRANSFORM:
349                                 attr = add(name, TypeDesc::TypeMatrix, ATTR_ELEMENT_MESH);
350                                 break;
351                         default:
352                                 assert(0);
353                                 break;
354                 }
355         }
356
357         attr->std = std;
358         
359         return attr;
360 }
361
362 Attribute *AttributeSet::find(AttributeStandard std) const
363 {
364         foreach(const Attribute& attr, attributes)
365                 if(attr.std == std)
366                         return (Attribute*)&attr;
367
368         return NULL;
369 }
370
371 void AttributeSet::remove(AttributeStandard std)
372 {
373         Attribute *attr = find(std);
374
375         if(attr) {
376                 list<Attribute>::iterator it;
377
378                 for(it = attributes.begin(); it != attributes.end(); it++) {
379                         if(&*it == attr) {
380                                 attributes.erase(it);
381                                 return;
382                         }
383                 }
384         }
385 }
386
387 Attribute *AttributeSet::find(AttributeRequest& req)
388 {
389         if(req.std == ATTR_STD_NONE)
390                 return find(req.name);
391         else
392                 return find(req.std);
393 }
394
395 void AttributeSet::reserve()
396 {
397         foreach(Attribute& attr, attributes) {
398                 if(triangle_mesh)
399                         attr.reserve(triangle_mesh->verts.size(), triangle_mesh->triangles.size(), triangle_mesh->motion_steps, 0, 0, true);
400                 if(curve_mesh)
401                         attr.reserve(0, 0, 0, curve_mesh->curves.size(), curve_mesh->curve_keys.size(), true);
402         }
403 }
404
405 void AttributeSet::clear()
406 {
407         attributes.clear();
408 }
409
410 /* AttributeRequest */
411
412 AttributeRequest::AttributeRequest(ustring name_)
413 {
414         name = name_;
415         std = ATTR_STD_NONE;
416
417         triangle_type = TypeDesc::TypeFloat;
418         triangle_element = ATTR_ELEMENT_NONE;
419         triangle_offset = 0;
420
421         curve_type = TypeDesc::TypeFloat;
422         curve_element = ATTR_ELEMENT_NONE;
423         curve_offset = 0;
424 }
425
426 AttributeRequest::AttributeRequest(AttributeStandard std_)
427 {
428         name = ustring();
429         std = std_;
430
431         triangle_type = TypeDesc::TypeFloat;
432         triangle_element = ATTR_ELEMENT_NONE;
433         triangle_offset = 0;
434
435         curve_type = TypeDesc::TypeFloat;
436         curve_element = ATTR_ELEMENT_NONE;
437         curve_offset = 0;
438 }
439
440 /* AttributeRequestSet */
441
442 AttributeRequestSet::AttributeRequestSet()
443 {
444 }
445
446 AttributeRequestSet::~AttributeRequestSet()
447 {
448 }
449
450 bool AttributeRequestSet::modified(const AttributeRequestSet& other)
451 {
452         if(requests.size() != other.requests.size())
453                 return true;
454
455         for(size_t i = 0; i < requests.size(); i++) {
456                 bool found = false;
457
458                 for(size_t j = 0; j < requests.size() && !found; j++)
459                         if(requests[i].name == other.requests[j].name &&
460                            requests[i].std == other.requests[j].std)
461                         {
462                                 found = true;
463                         }
464
465                 if(!found) {
466                         return true;
467                 }
468         }
469
470         return false;
471 }
472
473 void AttributeRequestSet::add(ustring name)
474 {
475         foreach(AttributeRequest& req, requests)
476                 if(req.name == name)
477                         return;
478
479         requests.push_back(AttributeRequest(name));
480 }
481
482 void AttributeRequestSet::add(AttributeStandard std)
483 {
484         foreach(AttributeRequest& req, requests)
485                 if(req.std == std)
486                         return;
487
488         requests.push_back(AttributeRequest(std));
489 }
490
491 void AttributeRequestSet::add(AttributeRequestSet& reqs)
492 {
493         foreach(AttributeRequest& req, reqs.requests) {
494                 if(req.std == ATTR_STD_NONE)
495                         add(req.name);
496                 else
497                         add(req.std);
498         }
499 }
500
501 bool AttributeRequestSet::find(ustring name)
502 {
503         foreach(AttributeRequest& req, requests)
504                 if(req.name == name)
505                         return true;
506         
507         return false;
508 }
509
510 bool AttributeRequestSet::find(AttributeStandard std)
511 {
512         foreach(AttributeRequest& req, requests)
513                 if(req.std == std)
514                         return true;
515
516         return false;
517 }
518
519 size_t AttributeRequestSet::size()
520 {
521         return requests.size();
522 }
523
524 void AttributeRequestSet::clear()
525 {
526         requests.clear();
527 }
528
529 CCL_NAMESPACE_END
530