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