Merging r59182 through r59257 from trunk into soc-2013-depsgraph_mt
[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 "mesh.h"
18 #include "attribute.h"
19
20 #include "util_debug.h"
21 #include "util_foreach.h"
22
23 CCL_NAMESPACE_BEGIN
24
25 /* Attribute */
26
27 void Attribute::set(ustring name_, TypeDesc type_, AttributeElement element_)
28 {
29         name = name_;
30         type = type_;
31         element = element_;
32         std = ATTR_STD_NONE;
33
34         /* string and matrix not supported! */
35         assert(type == TypeDesc::TypeFloat || type == TypeDesc::TypeColor ||
36                 type == TypeDesc::TypePoint || type == TypeDesc::TypeVector ||
37                 type == TypeDesc::TypeNormal);
38 }
39
40 void Attribute::reserve(int numverts, int numtris, int numcurves, int numkeys)
41 {
42         buffer.resize(buffer_size(numverts, numtris, numcurves, numkeys), 0);
43 }
44
45 void Attribute::add(const float& f)
46 {
47         char *data = (char*)&f;
48         size_t size = sizeof(f);
49
50         for(size_t i = 0; i < size; i++)
51                 buffer.push_back(data[i]);
52 }
53
54 void Attribute::add(const float3& f)
55 {
56         char *data = (char*)&f;
57         size_t size = sizeof(f);
58
59         for(size_t i = 0; i < size; i++)
60                 buffer.push_back(data[i]);
61 }
62
63 size_t Attribute::data_sizeof() const
64 {
65         if(type == TypeDesc::TypeFloat)
66                 return sizeof(float);
67         else
68                 return sizeof(float3);
69 }
70
71 size_t Attribute::element_size(int numverts, int numtris, int numcurves, int numkeys) const
72 {
73         size_t size;
74         
75         switch(element) {
76                 case ATTR_ELEMENT_VALUE:
77                         size = 1;
78                         break;
79                 case ATTR_ELEMENT_VERTEX:
80                         size = numverts;
81                         break;
82                 case ATTR_ELEMENT_FACE:
83                         size = numtris;
84                         break;
85                 case ATTR_ELEMENT_CORNER:
86                         size = numtris*3;
87                         break;
88                 case ATTR_ELEMENT_CURVE:
89                         size = numcurves;
90                         break;
91                 case ATTR_ELEMENT_CURVE_KEY:
92                         size = numkeys;
93                         break;
94                 default:
95                         size = 0;
96                         break;
97         }
98         
99         return size;
100 }
101
102 size_t Attribute::buffer_size(int numverts, int numtris, int numcurves, int numkeys) const
103 {
104         return element_size(numverts, numtris, numcurves, numkeys)*data_sizeof();
105 }
106
107 bool Attribute::same_storage(TypeDesc a, TypeDesc b)
108 {
109         if(a == b)
110                 return true;
111         
112         if(a == TypeDesc::TypeColor || a == TypeDesc::TypePoint ||
113            a == TypeDesc::TypeVector || a == TypeDesc::TypeNormal)
114         {
115                 if(b == TypeDesc::TypeColor || b == TypeDesc::TypePoint ||
116                    b == TypeDesc::TypeVector || b == TypeDesc::TypeNormal)
117                 {
118                         return true;
119                 }
120         }
121         return false;
122 }
123
124 const char *Attribute::standard_name(AttributeStandard std)
125 {
126         if(std == ATTR_STD_VERTEX_NORMAL)
127                 return "N";
128         else if(std == ATTR_STD_FACE_NORMAL)
129                 return "Ng";
130         else if(std == ATTR_STD_UV)
131                 return "uv";
132         else if(std == ATTR_STD_GENERATED)
133                 return "generated";
134         else if(std == ATTR_STD_UV_TANGENT)
135                 return "tangent";
136         else if(std == ATTR_STD_UV_TANGENT_SIGN)
137                 return "tangent_sign";
138         else if(std == ATTR_STD_POSITION_UNDEFORMED)
139                 return "undeformed";
140         else if(std == ATTR_STD_POSITION_UNDISPLACED)
141                 return "undisplaced";
142         else if(std == ATTR_STD_MOTION_PRE)
143                 return "motion_pre";
144         else if(std == ATTR_STD_MOTION_POST)
145                 return "motion_post";
146         else if(std == ATTR_STD_PARTICLE)
147                 return "particle";
148         else if(std == ATTR_STD_CURVE_INTERCEPT)
149                 return "curve_intercept";
150         
151         return "";
152 }
153
154 /* Attribute Set */
155
156 AttributeSet::AttributeSet()
157 {
158         triangle_mesh = NULL;
159         curve_mesh = NULL;
160 }
161
162 AttributeSet::~AttributeSet()
163 {
164 }
165
166 Attribute *AttributeSet::add(ustring name, TypeDesc type, AttributeElement element)
167 {
168         Attribute *attr = find(name);
169
170         if(attr) {
171                 /* return if same already exists */
172                 if(attr->type == type && attr->element == element)
173                         return attr;
174
175                 /* overwrite attribute with same name but different type/element */
176                 remove(name);
177         }
178
179         attributes.push_back(Attribute());
180         attr = &attributes.back();
181
182         attr->set(name, type, element);
183         
184         /* this is weak .. */
185         if(triangle_mesh)
186                 attr->reserve(triangle_mesh->verts.size(), triangle_mesh->triangles.size(), 0, 0);
187         if(curve_mesh)
188                 attr->reserve(0, 0, curve_mesh->curves.size(), curve_mesh->curve_keys.size());
189         
190         return attr;
191 }
192
193 Attribute *AttributeSet::find(ustring name) const
194 {
195         foreach(const Attribute& attr, attributes)
196                 if(attr.name == name)
197                         return (Attribute*)&attr;
198
199         return NULL;
200 }
201
202 void AttributeSet::remove(ustring name)
203 {
204         Attribute *attr = find(name);
205
206         if(attr) {
207                 list<Attribute>::iterator it;
208
209                 for(it = attributes.begin(); it != attributes.end(); it++) {
210                         if(&*it == attr) {
211                                 attributes.erase(it);
212                                 return;
213                         }
214                 }
215         }
216 }
217
218 Attribute *AttributeSet::add(AttributeStandard std, ustring name)
219 {
220         Attribute *attr = NULL;
221
222         if(name == ustring())
223                 name = Attribute::standard_name(std);
224
225         if(triangle_mesh) {
226                 switch(std) {
227                         case ATTR_STD_VERTEX_NORMAL:
228                                 attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_VERTEX);
229                                 break;
230                         case ATTR_STD_FACE_NORMAL:
231                                 attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_FACE);
232                                 break;
233                         case ATTR_STD_UV:
234                                 attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CORNER);
235                                 break;
236                         case ATTR_STD_UV_TANGENT:
237                                 attr = add(name, TypeDesc::TypeVector, ATTR_ELEMENT_CORNER);
238                                 break;
239                         case ATTR_STD_UV_TANGENT_SIGN:
240                                 attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CORNER);
241                                 break;
242                         case ATTR_STD_GENERATED:
243                                 attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
244                                 break;
245                         case ATTR_STD_POSITION_UNDEFORMED:
246                                 attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
247                                 break;
248                         case ATTR_STD_POSITION_UNDISPLACED:
249                                 attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
250                                 break;
251                         case ATTR_STD_MOTION_PRE:
252                                 attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
253                                 break;
254                         case ATTR_STD_MOTION_POST:
255                                 attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
256                                 break;
257                         default:
258                                 assert(0);
259                                 break;
260                 }
261         }
262         else if(curve_mesh) {
263                 switch(std) {
264                         case ATTR_STD_UV:
265                                 attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE);
266                                 break;
267                         case ATTR_STD_GENERATED:
268                                 attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE);
269                                 break;
270                         case ATTR_STD_MOTION_PRE:
271                                 attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE_KEY);
272                                 break;
273                         case ATTR_STD_MOTION_POST:
274                                 attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE_KEY);
275                                 break;
276                         case ATTR_STD_CURVE_INTERCEPT:
277                                 attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CURVE_KEY);
278                                 break;
279                         default:
280                                 assert(0);
281                                 break;
282                 }
283         }
284
285         attr->std = std;
286         
287         return attr;
288 }
289
290 Attribute *AttributeSet::find(AttributeStandard std) const
291 {
292         foreach(const Attribute& attr, attributes)
293                 if(attr.std == std)
294                         return (Attribute*)&attr;
295
296         return NULL;
297 }
298
299 void AttributeSet::remove(AttributeStandard std)
300 {
301         Attribute *attr = find(std);
302
303         if(attr) {
304                 list<Attribute>::iterator it;
305
306                 for(it = attributes.begin(); it != attributes.end(); it++) {
307                         if(&*it == attr) {
308                                 attributes.erase(it);
309                                 return;
310                         }
311                 }
312         }
313 }
314
315 Attribute *AttributeSet::find(AttributeRequest& req)
316 {
317         if(req.std == ATTR_STD_NONE)
318                 return find(req.name);
319         else
320                 return find(req.std);
321 }
322
323 void AttributeSet::reserve()
324 {
325         foreach(Attribute& attr, attributes) {
326                 if(triangle_mesh)
327                         attr.reserve(triangle_mesh->verts.size(), triangle_mesh->triangles.size(), 0, 0);
328                 if(curve_mesh)
329                         attr.reserve(0, 0, curve_mesh->curves.size(), curve_mesh->curve_keys.size());
330         }
331 }
332
333 void AttributeSet::clear()
334 {
335         attributes.clear();
336 }
337
338 /* AttributeRequest */
339
340 AttributeRequest::AttributeRequest(ustring name_)
341 {
342         name = name_;
343         std = ATTR_STD_NONE;
344
345         triangle_type = TypeDesc::TypeFloat;
346         triangle_element = ATTR_ELEMENT_NONE;
347         triangle_offset = 0;
348
349         curve_type = TypeDesc::TypeFloat;
350         curve_element = ATTR_ELEMENT_NONE;
351         curve_offset = 0;
352 }
353
354 AttributeRequest::AttributeRequest(AttributeStandard std_)
355 {
356         name = ustring();
357         std = std_;
358
359         triangle_type = TypeDesc::TypeFloat;
360         triangle_element = ATTR_ELEMENT_NONE;
361         triangle_offset = 0;
362
363         curve_type = TypeDesc::TypeFloat;
364         curve_element = ATTR_ELEMENT_NONE;
365         curve_offset = 0;
366 }
367
368 /* AttributeRequestSet */
369
370 AttributeRequestSet::AttributeRequestSet()
371 {
372 }
373
374 AttributeRequestSet::~AttributeRequestSet()
375 {
376 }
377
378 bool AttributeRequestSet::modified(const AttributeRequestSet& other)
379 {
380         if(requests.size() != other.requests.size())
381                 return true;
382
383         for(size_t i = 0; i < requests.size(); i++) {
384                 bool found = false;
385
386                 for(size_t j = 0; j < requests.size() && !found; j++)
387                         if(requests[i].name == other.requests[j].name &&
388                            requests[i].std == other.requests[j].std)
389                         {
390                                 found = true;
391                         }
392
393                 if(!found) {
394                         return true;
395                 }
396         }
397
398         return false;
399 }
400
401 void AttributeRequestSet::add(ustring name)
402 {
403         foreach(AttributeRequest& req, requests)
404                 if(req.name == name)
405                         return;
406
407         requests.push_back(AttributeRequest(name));
408 }
409
410 void AttributeRequestSet::add(AttributeStandard std)
411 {
412         foreach(AttributeRequest& req, requests)
413                 if(req.std == std)
414                         return;
415
416         requests.push_back(AttributeRequest(std));
417 }
418
419 void AttributeRequestSet::add(AttributeRequestSet& reqs)
420 {
421         foreach(AttributeRequest& req, reqs.requests) {
422                 if(req.std == ATTR_STD_NONE)
423                         add(req.name);
424                 else
425                         add(req.std);
426         }
427 }
428
429 bool AttributeRequestSet::find(ustring name)
430 {
431         foreach(AttributeRequest& req, requests)
432                 if(req.name == name)
433                         return true;
434         
435         return false;
436 }
437
438 bool AttributeRequestSet::find(AttributeStandard std)
439 {
440         foreach(AttributeRequest& req, requests)
441                 if(req.std == std)
442                         return true;
443
444         return false;
445 }
446
447 size_t AttributeRequestSet::size()
448 {
449         return requests.size();
450 }
451
452 void AttributeRequestSet::clear()
453 {
454         requests.clear();
455 }
456
457 CCL_NAMESPACE_END
458