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