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