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