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