Cycles: Anisotropic BSDF enabled, with tangents now computed from the active UV map.
[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_TANGENT)
166                 attr = add(name, TypeDesc::TypeVector, Attribute::VERTEX);
167         else if(std == ATTR_STD_GENERATED)
168                 attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX);
169         else if(std == ATTR_STD_POSITION_UNDEFORMED)
170                 attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX);
171         else if(std == ATTR_STD_POSITION_UNDISPLACED)
172                 attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX);
173         else if(std == ATTR_STD_MOTION_PRE)
174                 attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX);
175         else if(std == ATTR_STD_MOTION_POST)
176                 attr = add(name, TypeDesc::TypePoint, Attribute::VERTEX);
177         else
178                 assert(0);
179
180         attr->std = std;
181         
182         return attr;
183 }
184
185 Attribute *AttributeSet::find(AttributeStandard std)
186 {
187         foreach(Attribute& attr, attributes)
188                 if(attr.std == std)
189                         return &attr;
190
191         return NULL;
192 }
193
194 void AttributeSet::remove(AttributeStandard std)
195 {
196         Attribute *attr = find(std);
197
198         if(attr) {
199                 list<Attribute>::iterator it;
200
201                 for(it = attributes.begin(); it != attributes.end(); it++) {
202                         if(&*it == attr) {
203                                 attributes.erase(it);
204                                 return;
205                         }
206                 }
207         }
208 }
209
210 Attribute *AttributeSet::find(AttributeRequest& req)
211 {
212         if(req.std == ATTR_STD_NONE)
213                 return find(req.name);
214         else
215                 return find(req.std);
216 }
217
218 void AttributeSet::reserve(int numverts, int numtris)
219 {
220         foreach(Attribute& attr, attributes)
221                 attr.reserve(numverts, numtris);
222 }
223
224 void AttributeSet::clear()
225 {
226         attributes.clear();
227 }
228
229 /* AttributeRequest */
230
231 AttributeRequest::AttributeRequest(ustring name_)
232 {
233         name = name_;
234         std = ATTR_STD_NONE;
235
236         type = TypeDesc::TypeFloat;
237         element = ATTR_ELEMENT_NONE;
238         offset = 0;
239 }
240
241 AttributeRequest::AttributeRequest(AttributeStandard std_)
242 {
243         name = ustring();
244         std = std_;
245
246         type = TypeDesc::TypeFloat;
247         element = ATTR_ELEMENT_NONE;
248         offset = 0;
249 }
250
251 /* AttributeRequestSet */
252
253 AttributeRequestSet::AttributeRequestSet()
254 {
255 }
256
257 AttributeRequestSet::~AttributeRequestSet()
258 {
259 }
260
261 bool AttributeRequestSet::modified(const AttributeRequestSet& other)
262 {
263         if(requests.size() != other.requests.size())
264                 return true;
265
266         for(size_t i = 0; i < requests.size(); i++) {
267                 bool found = false;
268
269                 for(size_t j = 0; j < requests.size() && !found; j++)
270                         if(requests[i].name == other.requests[j].name &&
271                            requests[i].std == other.requests[j].std)
272                         {
273                                 found = true;
274                         }
275
276                 if(!found) {
277                         return true;
278                 }
279         }
280
281         return false;
282 }
283
284 void AttributeRequestSet::add(ustring name)
285 {
286         foreach(AttributeRequest& req, requests)
287                 if(req.name == name)
288                         return;
289
290         requests.push_back(AttributeRequest(name));
291 }
292
293 void AttributeRequestSet::add(AttributeStandard std)
294 {
295         foreach(AttributeRequest& req, requests)
296                 if(req.std == std)
297                         return;
298
299         requests.push_back(AttributeRequest(std));
300 }
301
302 void AttributeRequestSet::add(AttributeRequestSet& reqs)
303 {
304         foreach(AttributeRequest& req, reqs.requests) {
305                 if(req.std == ATTR_STD_NONE)
306                         add(req.name);
307                 else
308                         add(req.std);
309         }
310 }
311
312 bool AttributeRequestSet::find(ustring name)
313 {
314         foreach(AttributeRequest& req, requests)
315                 if(req.name == name)
316                         return true;
317         
318         return false;
319 }
320
321 bool AttributeRequestSet::find(AttributeStandard std)
322 {
323         foreach(AttributeRequest& req, requests)
324                 if(req.std == std)
325                         return true;
326
327         return false;
328 }
329
330 size_t AttributeRequestSet::size()
331 {
332         return requests.size();
333 }
334
335 void AttributeRequestSet::clear()
336 {
337         requests.clear();
338 }
339
340 CCL_NAMESPACE_END
341