Cycles: svn merge -r41205:41225 ^/trunk/blender
[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_, 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(Mesh *mesh_)
105 {
106         mesh = mesh_;
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         attr->reserve(mesh->verts.size(), mesh->triangles.size());
137         
138         return attr;
139 }
140
141 Attribute *AttributeSet::find(ustring name)
142 {
143         foreach(Attribute& attr, attributes)
144                 if(attr.name == name)
145                         return &attr;
146
147         return NULL;
148 }
149
150 void AttributeSet::remove(ustring name)
151 {
152         Attribute *attr = find(name);
153
154         if(attr) {
155                 list<Attribute>::iterator it;
156
157                 for(it = attributes.begin(); it != attributes.end(); it++) {
158                         if(&*it == attr) {
159                                 attributes.erase(it);
160                                 return;
161                         }
162                 }
163         }
164 }
165
166 Attribute *AttributeSet::add(Attribute::Standard std, ustring name)
167 {
168         Attribute *attr = NULL;
169
170         if(name == ustring())
171                 name = Attribute::standard_name(std);
172
173         if(std == Attribute::STD_VERTEX_NORMAL)
174                 attr = add(name, TypeDesc::TypeNormal, Attribute::VERTEX);
175         else if(std == Attribute::STD_FACE_NORMAL)
176                 attr = add(name, TypeDesc::TypeNormal, Attribute::FACE);
177         else if(std == Attribute::STD_UV)
178                 attr = add(name, TypeDesc::TypePoint, Attribute::CORNER);
179         else if(std == Attribute::STD_GENERATED)
180                 attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX);
181         else if(std == Attribute::STD_POSITION_UNDEFORMED)
182                 attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX);
183         else if(std == Attribute::STD_POSITION_UNDISPLACED)
184                 attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX);
185         else
186                 assert(0);
187
188         attr->std = std;
189         
190         return attr;
191 }
192
193 Attribute *AttributeSet::find(Attribute::Standard std)
194 {
195         foreach(Attribute& attr, attributes)
196                 if(attr.std == std)
197                         return &attr;
198
199         return NULL;
200 }
201
202 void AttributeSet::remove(Attribute::Standard std)
203 {
204         Attribute *attr = find(std);
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::find(AttributeRequest& req)
219 {
220         if(req.std == Attribute::STD_NONE)
221                 return find(req.name);
222         else
223                 return find(req.std);
224 }
225
226 void AttributeSet::reserve(int numverts, int numtris)
227 {
228         foreach(Attribute& attr, attributes)
229                 attr.reserve(numverts, numtris);
230 }
231
232 void AttributeSet::clear()
233 {
234         attributes.clear();
235 }
236
237 /* AttributeRequest */
238
239 AttributeRequest::AttributeRequest(ustring name_)
240 {
241         name = name_;
242         std = Attribute::STD_NONE;
243
244         type = TypeDesc::TypeFloat;
245         element = ATTR_ELEMENT_NONE;
246         offset = 0;
247 }
248
249 AttributeRequest::AttributeRequest(Attribute::Standard std_)
250 {
251         name = ustring();
252         std = std_;
253
254         type = TypeDesc::TypeFloat;
255         element = ATTR_ELEMENT_NONE;
256         offset = 0;
257 }
258
259 /* AttributeRequestSet */
260
261 AttributeRequestSet::AttributeRequestSet()
262 {
263 }
264
265 AttributeRequestSet::~AttributeRequestSet()
266 {
267 }
268
269 bool AttributeRequestSet::modified(const AttributeRequestSet& other)
270 {
271         if(requests.size() != other.requests.size())
272                 return true;
273
274         for(size_t i = 0; i < requests.size(); i++) {
275                 bool found = false;
276
277                 for(size_t j = 0; j < requests.size() && !found; j++)
278                         if(requests[i].name == other.requests[j].name &&
279                            requests[i].std == other.requests[j].std)
280                                 found = true;
281
282                 if(!found)
283                         return true;
284         }
285
286         return false;
287 }
288
289 void AttributeRequestSet::add(ustring name)
290 {
291         foreach(AttributeRequest& req, requests)
292                 if(req.name == name)
293                         return;
294
295         requests.push_back(AttributeRequest(name));
296 }
297
298 void AttributeRequestSet::add(Attribute::Standard std)
299 {
300         foreach(AttributeRequest& req, requests)
301                 if(req.std == std)
302                         return;
303
304         requests.push_back(AttributeRequest(std));
305 }
306
307 void AttributeRequestSet::add(AttributeRequestSet& reqs)
308 {
309         foreach(AttributeRequest& req, reqs.requests) {
310                 if(req.std == Attribute::STD_NONE)
311                         add(req.name);
312                 else
313                         add(req.std);
314         }
315 }
316
317 bool AttributeRequestSet::find(ustring name)
318 {
319         foreach(AttributeRequest& req, requests)
320                 if(req.name == name)
321                         return true;
322         
323         return false;
324 }
325
326 bool AttributeRequestSet::find(Attribute::Standard std)
327 {
328         foreach(AttributeRequest& req, requests)
329                 if(req.std == std)
330                         return true;
331
332         return false;
333 }
334
335 size_t AttributeRequestSet::size()
336 {
337         return requests.size();
338 }
339
340 void AttributeRequestSet::clear()
341 {
342         requests.clear();
343 }
344
345 CCL_NAMESPACE_END
346