Merged changes in the trunk up to revision 53584.
[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         if(element == ATTR_ELEMENT_VALUE)
76                 return 1;
77         if(element == ATTR_ELEMENT_VERTEX)
78                 return numverts;
79         else if(element == ATTR_ELEMENT_FACE)
80                 return numtris;
81         else if(element == ATTR_ELEMENT_CORNER)
82                 return numtris*3;
83         else if(element == ATTR_ELEMENT_CURVE)
84                 return numcurves;
85         else if(element == ATTR_ELEMENT_CURVE_KEY)
86                 return numkeys;
87         
88         return 0;
89 }
90
91 size_t Attribute::buffer_size(int numverts, int numtris, int numcurves, int numkeys) const
92 {
93         return element_size(numverts, numtris, numcurves, numkeys)*data_sizeof();
94 }
95
96 bool Attribute::same_storage(TypeDesc a, TypeDesc b)
97 {
98         if(a == b)
99                 return true;
100         
101         if(a == TypeDesc::TypeColor || a == TypeDesc::TypePoint ||
102            a == TypeDesc::TypeVector || a == TypeDesc::TypeNormal)
103         {
104                 if(b == TypeDesc::TypeColor || b == TypeDesc::TypePoint ||
105                    b == TypeDesc::TypeVector || b == TypeDesc::TypeNormal)
106                 {
107                         return true;
108                 }
109         }
110         return false;
111 }
112
113 const char *Attribute::standard_name(AttributeStandard std)
114 {
115         if(std == ATTR_STD_VERTEX_NORMAL)
116                 return "N";
117         else if(std == ATTR_STD_FACE_NORMAL)
118                 return "Ng";
119         else if(std == ATTR_STD_UV)
120                 return "uv";
121         else if(std == ATTR_STD_GENERATED)
122                 return "generated";
123         else if(std == ATTR_STD_UV_TANGENT)
124                 return "tangent";
125         else if(std == ATTR_STD_UV_TANGENT_SIGN)
126                 return "tangent_sign";
127         else if(std == ATTR_STD_POSITION_UNDEFORMED)
128                 return "undeformed";
129         else if(std == ATTR_STD_POSITION_UNDISPLACED)
130                 return "undisplaced";
131         else if(std == ATTR_STD_MOTION_PRE)
132                 return "motion_pre";
133         else if(std == ATTR_STD_MOTION_POST)
134                 return "motion_post";
135         else if(std == ATTR_STD_PARTICLE)
136                 return "particle";
137         else if(std == ATTR_STD_CURVE_TANGENT)
138                 return "curve_tangent";
139         else if(std == ATTR_STD_CURVE_INTERCEPT)
140                 return "curve_intercept";
141         
142         return "";
143 }
144
145 /* Attribute Set */
146
147 AttributeSet::AttributeSet()
148 {
149         triangle_mesh = NULL;
150         curve_mesh = NULL;
151 }
152
153 AttributeSet::~AttributeSet()
154 {
155 }
156
157 Attribute *AttributeSet::add(ustring name, TypeDesc type, AttributeElement element)
158 {
159         Attribute *attr = find(name);
160
161         if(attr) {
162                 /* return if same already exists */
163                 if(attr->type == type && attr->element == element)
164                         return attr;
165
166                 /* overwrite attribute with same name but different type/element */
167                 remove(name);
168         }
169
170         attributes.push_back(Attribute());
171         attr = &attributes.back();
172
173         attr->set(name, type, element);
174         
175         /* this is weak .. */
176         if(triangle_mesh)
177                 attr->reserve(triangle_mesh->verts.size(), triangle_mesh->triangles.size(), 0, 0);
178         if(curve_mesh)
179                 attr->reserve(0, 0, curve_mesh->curves.size(), curve_mesh->curve_keys.size());
180         
181         return attr;
182 }
183
184 Attribute *AttributeSet::find(ustring name) const
185 {
186         foreach(const Attribute& attr, attributes)
187                 if(attr.name == name)
188                         return (Attribute*)&attr;
189
190         return NULL;
191 }
192
193 void AttributeSet::remove(ustring name)
194 {
195         Attribute *attr = find(name);
196
197         if(attr) {
198                 list<Attribute>::iterator it;
199
200                 for(it = attributes.begin(); it != attributes.end(); it++) {
201                         if(&*it == attr) {
202                                 attributes.erase(it);
203                                 return;
204                         }
205                 }
206         }
207 }
208
209 Attribute *AttributeSet::add(AttributeStandard std, ustring name)
210 {
211         Attribute *attr = NULL;
212
213         if(name == ustring())
214                 name = Attribute::standard_name(std);
215
216         if(triangle_mesh) {
217                 if(std == ATTR_STD_VERTEX_NORMAL)
218                         attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_VERTEX);
219                 else if(std == ATTR_STD_FACE_NORMAL)
220                         attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_FACE);
221                 else if(std == ATTR_STD_UV)
222                         attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CORNER);
223                 else if(std == ATTR_STD_UV_TANGENT)
224                         attr = add(name, TypeDesc::TypeVector, ATTR_ELEMENT_CORNER);
225                 else if(std == ATTR_STD_UV_TANGENT_SIGN)
226                         attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CORNER);
227                 else if(std == ATTR_STD_GENERATED)
228                         attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
229                 else if(std == ATTR_STD_POSITION_UNDEFORMED)
230                         attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
231                 else if(std == ATTR_STD_POSITION_UNDISPLACED)
232                         attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
233                 else if(std == ATTR_STD_MOTION_PRE)
234                         attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
235                 else if(std == ATTR_STD_MOTION_POST)
236                         attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
237                 else
238                         assert(0);
239         }
240         else if(curve_mesh) {
241                 if(std == ATTR_STD_UV)
242                         attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE);
243                 else if(std == ATTR_STD_GENERATED)
244                         attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE);
245                 else if(std == ATTR_STD_MOTION_PRE)
246                         attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE_KEY);
247                 else if(std == ATTR_STD_MOTION_POST)
248                         attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE_KEY);
249                 else if(std == ATTR_STD_CURVE_TANGENT)
250                         attr = add(name, TypeDesc::TypeVector, ATTR_ELEMENT_CURVE_KEY);
251                 else if(std == ATTR_STD_CURVE_INTERCEPT)
252                         attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CURVE_KEY);
253                 else
254                         assert(0);
255         }
256
257         attr->std = std;
258         
259         return attr;
260 }
261
262 Attribute *AttributeSet::find(AttributeStandard std) const
263 {
264         foreach(const Attribute& attr, attributes)
265                 if(attr.std == std)
266                         return (Attribute*)&attr;
267
268         return NULL;
269 }
270
271 void AttributeSet::remove(AttributeStandard std)
272 {
273         Attribute *attr = find(std);
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::find(AttributeRequest& req)
288 {
289         if(req.std == ATTR_STD_NONE)
290                 return find(req.name);
291         else
292                 return find(req.std);
293 }
294
295 void AttributeSet::reserve()
296 {
297         foreach(Attribute& attr, attributes) {
298                 if(triangle_mesh)
299                         attr.reserve(triangle_mesh->verts.size(), triangle_mesh->triangles.size(), 0, 0);
300                 if(curve_mesh)
301                         attr.reserve(0, 0, curve_mesh->curves.size(), curve_mesh->curve_keys.size());
302         }
303 }
304
305 void AttributeSet::clear()
306 {
307         attributes.clear();
308 }
309
310 /* AttributeRequest */
311
312 AttributeRequest::AttributeRequest(ustring name_)
313 {
314         name = name_;
315         std = ATTR_STD_NONE;
316
317         triangle_type = TypeDesc::TypeFloat;
318         triangle_element = ATTR_ELEMENT_NONE;
319         triangle_offset = 0;
320
321         curve_type = TypeDesc::TypeFloat;
322         curve_element = ATTR_ELEMENT_NONE;
323         curve_offset = 0;
324 }
325
326 AttributeRequest::AttributeRequest(AttributeStandard std_)
327 {
328         name = ustring();
329         std = std_;
330
331         triangle_type = TypeDesc::TypeFloat;
332         triangle_element = ATTR_ELEMENT_NONE;
333         triangle_offset = 0;
334
335         curve_type = TypeDesc::TypeFloat;
336         curve_element = ATTR_ELEMENT_NONE;
337         curve_offset = 0;
338 }
339
340 /* AttributeRequestSet */
341
342 AttributeRequestSet::AttributeRequestSet()
343 {
344 }
345
346 AttributeRequestSet::~AttributeRequestSet()
347 {
348 }
349
350 bool AttributeRequestSet::modified(const AttributeRequestSet& other)
351 {
352         if(requests.size() != other.requests.size())
353                 return true;
354
355         for(size_t i = 0; i < requests.size(); i++) {
356                 bool found = false;
357
358                 for(size_t j = 0; j < requests.size() && !found; j++)
359                         if(requests[i].name == other.requests[j].name &&
360                            requests[i].std == other.requests[j].std)
361                         {
362                                 found = true;
363                         }
364
365                 if(!found) {
366                         return true;
367                 }
368         }
369
370         return false;
371 }
372
373 void AttributeRequestSet::add(ustring name)
374 {
375         foreach(AttributeRequest& req, requests)
376                 if(req.name == name)
377                         return;
378
379         requests.push_back(AttributeRequest(name));
380 }
381
382 void AttributeRequestSet::add(AttributeStandard std)
383 {
384         foreach(AttributeRequest& req, requests)
385                 if(req.std == std)
386                         return;
387
388         requests.push_back(AttributeRequest(std));
389 }
390
391 void AttributeRequestSet::add(AttributeRequestSet& reqs)
392 {
393         foreach(AttributeRequest& req, reqs.requests) {
394                 if(req.std == ATTR_STD_NONE)
395                         add(req.name);
396                 else
397                         add(req.std);
398         }
399 }
400
401 bool AttributeRequestSet::find(ustring name)
402 {
403         foreach(AttributeRequest& req, requests)
404                 if(req.name == name)
405                         return true;
406         
407         return false;
408 }
409
410 bool AttributeRequestSet::find(AttributeStandard std)
411 {
412         foreach(AttributeRequest& req, requests)
413                 if(req.std == std)
414                         return true;
415
416         return false;
417 }
418
419 size_t AttributeRequestSet::size()
420 {
421         return requests.size();
422 }
423
424 void AttributeRequestSet::clear()
425 {
426         requests.clear();
427 }
428
429 CCL_NAMESPACE_END
430