Merging r46096 through r46110 from trunk into soc-2011-tomato
[blender-staging.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_, Element element_)
30 {
31         name = name_;
32         type = type_;
33         element = element_;
34         std = 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)
43 {
44         buffer.resize(buffer_size(numverts, numtris), 0);
45 }
46
47 size_t Attribute::data_sizeof()
48 {
49         if(type == TypeDesc::TypeFloat)
50                 return sizeof(float);
51         else
52                 return sizeof(float3);
53 }
54
55 size_t Attribute::element_size(int numverts, int numtris)
56 {
57         if(element == VERTEX)
58                 return numverts;
59         else if(element == FACE)
60                 return numtris;
61         else
62                 return numtris*3;
63 }
64
65 size_t Attribute::buffer_size(int numverts, int numtris)
66 {
67         return element_size(numverts, numtris)*data_sizeof();
68 }
69
70 bool Attribute::same_storage(TypeDesc a, TypeDesc b)
71 {
72         if(a == b)
73                 return true;
74         
75         if(a == TypeDesc::TypeColor || a == TypeDesc::TypePoint ||
76            a == TypeDesc::TypeVector || a == TypeDesc::TypeNormal)
77                 if(b == TypeDesc::TypeColor || b == TypeDesc::TypePoint ||
78                    b == TypeDesc::TypeVector || b == TypeDesc::TypeNormal)
79                         return true;
80         
81         return false;
82 }
83
84 ustring Attribute::standard_name(Attribute::Standard std)
85 {
86         if(std == Attribute::STD_VERTEX_NORMAL)
87                 return ustring("N");
88         else if(std == Attribute::STD_FACE_NORMAL)
89                 return ustring("Ng");
90         else if(std == Attribute::STD_UV)
91                 return ustring("uv");
92         else if(std == Attribute::STD_GENERATED)
93                 return ustring("generated");
94         else if(std == Attribute::STD_POSITION_UNDEFORMED)
95                 return ustring("undeformed");
96         else if(std == Attribute::STD_POSITION_UNDISPLACED)
97                 return ustring("undisplaced");
98
99         return ustring();
100 }
101
102 /* Attribute Set */
103
104 AttributeSet::AttributeSet()
105 {
106         mesh = NULL;
107 }
108
109 AttributeSet::~AttributeSet()
110 {
111 }
112
113 Attribute *AttributeSet::add(ustring name, TypeDesc type, Attribute::Element element)
114 {
115         Attribute *attr = find(name);
116
117         if(attr) {
118                 /* return if same already exists */
119                 if(attr->type == type && attr->element == element)
120                         return attr;
121
122                 /* overwrite attribute with same name but different type/element */
123                 remove(name);
124         }
125
126         attributes.push_back(Attribute());
127         attr = &attributes.back();
128
129         if(element == Attribute::VERTEX)
130                 attr->set(name, type, element);
131         else if(element == Attribute::FACE)
132                 attr->set(name, type, element);
133         else if(element == Attribute::CORNER)
134                 attr->set(name, type, element);
135         
136         if(mesh)
137                 attr->reserve(mesh->verts.size(), mesh->triangles.size());
138         
139         return attr;
140 }
141
142 Attribute *AttributeSet::find(ustring name)
143 {
144         foreach(Attribute& attr, attributes)
145                 if(attr.name == name)
146                         return &attr;
147
148         return NULL;
149 }
150
151 void AttributeSet::remove(ustring name)
152 {
153         Attribute *attr = find(name);
154
155         if(attr) {
156                 list<Attribute>::iterator it;
157
158                 for(it = attributes.begin(); it != attributes.end(); it++) {
159                         if(&*it == attr) {
160                                 attributes.erase(it);
161                                 return;
162                         }
163                 }
164         }
165 }
166
167 Attribute *AttributeSet::add(Attribute::Standard std, ustring name)
168 {
169         Attribute *attr = NULL;
170
171         if(name == ustring())
172                 name = Attribute::standard_name(std);
173
174         if(std == Attribute::STD_VERTEX_NORMAL)
175                 attr = add(name, TypeDesc::TypeNormal, Attribute::VERTEX);
176         else if(std == Attribute::STD_FACE_NORMAL)
177                 attr = add(name, TypeDesc::TypeNormal, Attribute::FACE);
178         else if(std == Attribute::STD_UV)
179                 attr = add(name, TypeDesc::TypePoint, Attribute::CORNER);
180         else if(std == Attribute::STD_GENERATED)
181                 attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX);
182         else if(std == Attribute::STD_POSITION_UNDEFORMED)
183                 attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX);
184         else if(std == Attribute::STD_POSITION_UNDISPLACED)
185                 attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX);
186         else
187                 assert(0);
188
189         attr->std = std;
190         
191         return attr;
192 }
193
194 Attribute *AttributeSet::find(Attribute::Standard std)
195 {
196         foreach(Attribute& attr, attributes)
197                 if(attr.std == std)
198                         return &attr;
199
200         return NULL;
201 }
202
203 void AttributeSet::remove(Attribute::Standard std)
204 {
205         Attribute *attr = find(std);
206
207         if(attr) {
208                 list<Attribute>::iterator it;
209
210                 for(it = attributes.begin(); it != attributes.end(); it++) {
211                         if(&*it == attr) {
212                                 attributes.erase(it);
213                                 return;
214                         }
215                 }
216         }
217 }
218
219 Attribute *AttributeSet::find(AttributeRequest& req)
220 {
221         if(req.std == Attribute::STD_NONE)
222                 return find(req.name);
223         else
224                 return find(req.std);
225 }
226
227 void AttributeSet::reserve(int numverts, int numtris)
228 {
229         foreach(Attribute& attr, attributes)
230                 attr.reserve(numverts, numtris);
231 }
232
233 void AttributeSet::clear()
234 {
235         attributes.clear();
236 }
237
238 /* AttributeRequest */
239
240 AttributeRequest::AttributeRequest(ustring name_)
241 {
242         name = name_;
243         std = Attribute::STD_NONE;
244
245         type = TypeDesc::TypeFloat;
246         element = ATTR_ELEMENT_NONE;
247         offset = 0;
248 }
249
250 AttributeRequest::AttributeRequest(Attribute::Standard std_)
251 {
252         name = ustring();
253         std = std_;
254
255         type = TypeDesc::TypeFloat;
256         element = ATTR_ELEMENT_NONE;
257         offset = 0;
258 }
259
260 /* AttributeRequestSet */
261
262 AttributeRequestSet::AttributeRequestSet()
263 {
264 }
265
266 AttributeRequestSet::~AttributeRequestSet()
267 {
268 }
269
270 bool AttributeRequestSet::modified(const AttributeRequestSet& other)
271 {
272         if(requests.size() != other.requests.size())
273                 return true;
274
275         for(size_t i = 0; i < requests.size(); i++) {
276                 bool found = false;
277
278                 for(size_t j = 0; j < requests.size() && !found; j++)
279                         if(requests[i].name == other.requests[j].name &&
280                            requests[i].std == other.requests[j].std)
281                                 found = true;
282
283                 if(!found)
284                         return true;
285         }
286
287         return false;
288 }
289
290 void AttributeRequestSet::add(ustring name)
291 {
292         foreach(AttributeRequest& req, requests)
293                 if(req.name == name)
294                         return;
295
296         requests.push_back(AttributeRequest(name));
297 }
298
299 void AttributeRequestSet::add(Attribute::Standard std)
300 {
301         foreach(AttributeRequest& req, requests)
302                 if(req.std == std)
303                         return;
304
305         requests.push_back(AttributeRequest(std));
306 }
307
308 void AttributeRequestSet::add(AttributeRequestSet& reqs)
309 {
310         foreach(AttributeRequest& req, reqs.requests) {
311                 if(req.std == Attribute::STD_NONE)
312                         add(req.name);
313                 else
314                         add(req.std);
315         }
316 }
317
318 bool AttributeRequestSet::find(ustring name)
319 {
320         foreach(AttributeRequest& req, requests)
321                 if(req.name == name)
322                         return true;
323         
324         return false;
325 }
326
327 bool AttributeRequestSet::find(Attribute::Standard std)
328 {
329         foreach(AttributeRequest& req, requests)
330                 if(req.std == std)
331                         return true;
332
333         return false;
334 }
335
336 size_t AttributeRequestSet::size()
337 {
338         return requests.size();
339 }
340
341 void AttributeRequestSet::clear()
342 {
343         requests.clear();
344 }
345
346 CCL_NAMESPACE_END
347