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