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