Cycles: add "density", "flame" and "color" attributes for smoke domains.
[blender.git] / intern / cycles / render / attribute.cpp
1 /*
2  * Copyright 2011-2013 Blender Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License
15  */
16
17 #include "image.h"
18 #include "mesh.h"
19 #include "attribute.h"
20
21 #include "util_debug.h"
22 #include "util_foreach.h"
23 #include "util_transform.h"
24
25 CCL_NAMESPACE_BEGIN
26
27 /* Attribute */
28
29 Attribute::~Attribute()
30 {
31         /* for voxel data, we need to remove the image from the image manager */
32         if(element == ATTR_ELEMENT_VOXEL) {
33                 VoxelAttribute *voxel_data = data_voxel();
34
35                 if(voxel_data)
36                         voxel_data->manager->remove_image(voxel_data->slot);
37         }
38 }
39
40 void Attribute::set(ustring name_, TypeDesc type_, AttributeElement element_)
41 {
42         name = name_;
43         type = type_;
44         element = element_;
45         std = ATTR_STD_NONE;
46
47         /* string and matrix not supported! */
48         assert(type == TypeDesc::TypeFloat || type == TypeDesc::TypeColor ||
49                 type == TypeDesc::TypePoint || type == TypeDesc::TypeVector ||
50                 type == TypeDesc::TypeNormal || type == TypeDesc::TypeMatrix);
51 }
52
53 void Attribute::reserve(int numverts, int numtris, int numsteps, int numcurves, int numkeys, bool resize)
54 {
55         if (resize) {
56                 buffer.resize(buffer_size(numverts, numtris, numsteps, numcurves, numkeys), 0);
57         }
58         else {
59                 buffer.reserve(buffer_size(numverts, numtris, numsteps, numcurves, numkeys));
60         }
61 }
62
63 void Attribute::add(const float& f)
64 {
65         char *data = (char*)&f;
66         size_t size = sizeof(f);
67
68         for(size_t i = 0; i < size; i++)
69                 buffer.push_back(data[i]);
70 }
71
72 void Attribute::add(const float3& f)
73 {
74         char *data = (char*)&f;
75         size_t size = sizeof(f);
76
77         for(size_t i = 0; i < size; i++)
78                 buffer.push_back(data[i]);
79 }
80
81 void Attribute::add(const Transform& f)
82 {
83         char *data = (char*)&f;
84         size_t size = sizeof(f);
85
86         for(size_t i = 0; i < size; i++)
87                 buffer.push_back(data[i]);
88 }
89
90 void Attribute::add(const VoxelAttribute& f)
91 {
92         char *data = (char*)&f;
93         size_t size = sizeof(f);
94
95         for(size_t i = 0; i < size; i++)
96                 buffer.push_back(data[i]);
97 }
98
99 size_t Attribute::data_sizeof() const
100 {
101         if(element == ATTR_ELEMENT_VOXEL)
102                 return sizeof(VoxelAttribute);
103         else if(type == TypeDesc::TypeFloat)
104                 return sizeof(float);
105         else if(type == TypeDesc::TypeMatrix)
106                 return sizeof(Transform);
107         else
108                 return sizeof(float3);
109 }
110
111 size_t Attribute::element_size(int numverts, int numtris, int numsteps, int numcurves, int numkeys) const
112 {
113         size_t size;
114         
115         switch(element) {
116                 case ATTR_ELEMENT_OBJECT:
117                 case ATTR_ELEMENT_MESH:
118                 case ATTR_ELEMENT_VOXEL:
119                         size = 1;
120                         break;
121                 case ATTR_ELEMENT_VERTEX:
122                         size = numverts;
123                         break;
124                 case ATTR_ELEMENT_VERTEX_MOTION:
125                         size = numverts * (numsteps - 1);
126                         break;
127                 case ATTR_ELEMENT_FACE:
128                         size = numtris;
129                         break;
130                 case ATTR_ELEMENT_CORNER:
131                         size = numtris*3;
132                         break;
133                 case ATTR_ELEMENT_CURVE:
134                         size = numcurves;
135                         break;
136                 case ATTR_ELEMENT_CURVE_KEY:
137                         size = numkeys;
138                         break;
139                 case ATTR_ELEMENT_CURVE_KEY_MOTION:
140                         size = numkeys * (numsteps - 1);
141                         break;
142                 default:
143                         size = 0;
144                         break;
145         }
146         
147         return size;
148 }
149
150 size_t Attribute::buffer_size(int numverts, int numtris, int numsteps, int numcurves, int numkeys) const
151 {
152         return element_size(numverts, numtris, numsteps, numcurves, numkeys)*data_sizeof();
153 }
154
155 bool Attribute::same_storage(TypeDesc a, TypeDesc b)
156 {
157         if(a == b)
158                 return true;
159         
160         if(a == TypeDesc::TypeColor || a == TypeDesc::TypePoint ||
161            a == TypeDesc::TypeVector || a == TypeDesc::TypeNormal)
162         {
163                 if(b == TypeDesc::TypeColor || b == TypeDesc::TypePoint ||
164                    b == TypeDesc::TypeVector || b == TypeDesc::TypeNormal)
165                 {
166                         return true;
167                 }
168         }
169         return false;
170 }
171
172 const char *Attribute::standard_name(AttributeStandard std)
173 {
174         switch(std) {
175                 case ATTR_STD_VERTEX_NORMAL:
176                         return "N";
177                 case ATTR_STD_FACE_NORMAL:
178                         return "Ng";
179                 case ATTR_STD_UV:
180                         return "uv";
181                 case ATTR_STD_GENERATED:
182                         return "generated";
183                 case ATTR_STD_GENERATED_TRANSFORM:
184                         return "generated_transform";
185                 case ATTR_STD_UV_TANGENT:
186                         return "tangent";
187                 case ATTR_STD_UV_TANGENT_SIGN:
188                         return "tangent_sign";
189                 case ATTR_STD_POSITION_UNDEFORMED:
190                         return "undeformed";
191                 case ATTR_STD_POSITION_UNDISPLACED:
192                         return "undisplaced";
193                 case ATTR_STD_MOTION_VERTEX_POSITION:
194                         return "motion_P";
195                 case ATTR_STD_MOTION_VERTEX_NORMAL:
196                         return "motion_N";
197                 case ATTR_STD_PARTICLE:
198                         return "particle";
199                 case ATTR_STD_CURVE_INTERCEPT:
200                         return "curve_intercept";
201                 case ATTR_STD_PTEX_FACE_ID:
202                         return "ptex_face_id";
203                 case ATTR_STD_PTEX_UV:
204                         return "ptex_uv";
205                 case ATTR_STD_VOLUME_DENSITY:
206                         return "density";
207                 case ATTR_STD_VOLUME_COLOR:
208                         return "color";
209                 case ATTR_STD_VOLUME_FLAME:
210                         return "flame";
211                 case ATTR_STD_VOLUME_HEAT:
212                         return "heat";
213                 case ATTR_STD_VOLUME_VELOCITY:
214                         return "velocity";
215                 case ATTR_STD_NOT_FOUND:
216                 case ATTR_STD_NONE:
217                 case ATTR_STD_NUM:
218                         return "";
219         }
220         
221         return "";
222 }
223
224 AttributeStandard Attribute::name_standard(const char *name)
225 {
226         for(AttributeStandard std = ATTR_STD_NONE; std < ATTR_STD_NUM; std++)
227                 if(strcmp(name, Attribute::standard_name(std)) == 0)
228                         return std;
229
230         return ATTR_STD_NONE;
231 }
232
233 /* Attribute Set */
234
235 AttributeSet::AttributeSet()
236 {
237         triangle_mesh = NULL;
238         curve_mesh = NULL;
239 }
240
241 AttributeSet::~AttributeSet()
242 {
243 }
244
245 Attribute *AttributeSet::add(ustring name, TypeDesc type, AttributeElement element, bool resize)
246 {
247         Attribute *attr = find(name);
248
249         if(attr) {
250                 /* return if same already exists */
251                 if(attr->type == type && attr->element == element)
252                         return attr;
253
254                 /* overwrite attribute with same name but different type/element */
255                 remove(name);
256         }
257
258         attributes.push_back(Attribute());
259         attr = &attributes.back();
260
261         attr->set(name, type, element);
262         
263         /* this is weak .. */
264         if(triangle_mesh)
265                 attr->reserve(triangle_mesh->verts.size(), triangle_mesh->triangles.size(), triangle_mesh->motion_steps, 0, 0, resize);
266         if(curve_mesh)
267                 attr->reserve(0, 0, curve_mesh->motion_steps, curve_mesh->curves.size(), curve_mesh->curve_keys.size(), resize);
268         
269         return attr;
270 }
271
272 Attribute *AttributeSet::find(ustring name) const
273 {
274         foreach(const Attribute& attr, attributes)
275                 if(attr.name == name)
276                         return (Attribute*)&attr;
277
278         return NULL;
279 }
280
281 void AttributeSet::remove(ustring name)
282 {
283         Attribute *attr = find(name);
284
285         if(attr) {
286                 list<Attribute>::iterator it;
287
288                 for(it = attributes.begin(); it != attributes.end(); it++) {
289                         if(&*it == attr) {
290                                 attributes.erase(it);
291                                 return;
292                         }
293                 }
294         }
295 }
296
297 Attribute *AttributeSet::add(AttributeStandard std, ustring name)
298 {
299         Attribute *attr = NULL;
300
301         if(name == ustring())
302                 name = Attribute::standard_name(std);
303
304         if(triangle_mesh) {
305                 switch(std) {
306                         case ATTR_STD_VERTEX_NORMAL:
307                                 attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_VERTEX);
308                                 break;
309                         case ATTR_STD_FACE_NORMAL:
310                                 attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_FACE);
311                                 break;
312                         case ATTR_STD_UV:
313                                 attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CORNER);
314                                 break;
315                         case ATTR_STD_UV_TANGENT:
316                                 attr = add(name, TypeDesc::TypeVector, ATTR_ELEMENT_CORNER);
317                                 break;
318                         case ATTR_STD_UV_TANGENT_SIGN:
319                                 attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CORNER);
320                                 break;
321                         case ATTR_STD_GENERATED:
322                         case ATTR_STD_POSITION_UNDEFORMED:
323                         case ATTR_STD_POSITION_UNDISPLACED:
324                                 attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
325                                 break;
326                         case ATTR_STD_MOTION_VERTEX_POSITION:
327                                 attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX_MOTION);
328                                 break;
329                         case ATTR_STD_MOTION_VERTEX_NORMAL:
330                                 attr = add(name, TypeDesc::TypeNormal, ATTR_ELEMENT_VERTEX_MOTION);
331                                 break;
332                         case ATTR_STD_PTEX_FACE_ID:
333                                 attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_FACE);
334                                 break;
335                         case ATTR_STD_PTEX_UV:
336                                 attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX);
337                                 break;
338                         case ATTR_STD_GENERATED_TRANSFORM:
339                                 attr = add(name, TypeDesc::TypeMatrix, ATTR_ELEMENT_MESH);
340                                 break;
341                         case ATTR_STD_VOLUME_DENSITY:
342                         case ATTR_STD_VOLUME_FLAME:
343                         case ATTR_STD_VOLUME_HEAT:
344                                 attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_VOXEL);
345                                 break;
346                         case ATTR_STD_VOLUME_COLOR:
347                                 attr = add(name, TypeDesc::TypeColor, ATTR_ELEMENT_VOXEL);
348                                 break;
349                         case ATTR_STD_VOLUME_VELOCITY:
350                                 attr = add(name, TypeDesc::TypeVector, ATTR_ELEMENT_VOXEL);
351                                 break;
352                         default:
353                                 assert(0);
354                                 break;
355                 }
356         }
357         else if(curve_mesh) {
358                 switch(std) {
359                         case ATTR_STD_UV:
360                         case ATTR_STD_GENERATED:
361                                 attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE);
362                                 break;
363                         case ATTR_STD_MOTION_VERTEX_POSITION:
364                                 attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE_KEY_MOTION);
365                                 break;
366                         case ATTR_STD_CURVE_INTERCEPT:
367                                 attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CURVE_KEY);
368                                 break;
369                         case ATTR_STD_GENERATED_TRANSFORM:
370                                 attr = add(name, TypeDesc::TypeMatrix, ATTR_ELEMENT_MESH);
371                                 break;
372                         default:
373                                 assert(0);
374                                 break;
375                 }
376         }
377
378         attr->std = std;
379         
380         return attr;
381 }
382
383 Attribute *AttributeSet::find(AttributeStandard std) const
384 {
385         foreach(const Attribute& attr, attributes)
386                 if(attr.std == std)
387                         return (Attribute*)&attr;
388
389         return NULL;
390 }
391
392 void AttributeSet::remove(AttributeStandard std)
393 {
394         Attribute *attr = find(std);
395
396         if(attr) {
397                 list<Attribute>::iterator it;
398
399                 for(it = attributes.begin(); it != attributes.end(); it++) {
400                         if(&*it == attr) {
401                                 attributes.erase(it);
402                                 return;
403                         }
404                 }
405         }
406 }
407
408 Attribute *AttributeSet::find(AttributeRequest& req)
409 {
410         if(req.std == ATTR_STD_NONE)
411                 return find(req.name);
412         else
413                 return find(req.std);
414 }
415
416 void AttributeSet::reserve()
417 {
418         foreach(Attribute& attr, attributes) {
419                 if(triangle_mesh)
420                         attr.reserve(triangle_mesh->verts.size(), triangle_mesh->triangles.size(), triangle_mesh->motion_steps, 0, 0, true);
421                 if(curve_mesh)
422                         attr.reserve(0, 0, 0, curve_mesh->curves.size(), curve_mesh->curve_keys.size(), true);
423         }
424 }
425
426 void AttributeSet::clear()
427 {
428         attributes.clear();
429 }
430
431 /* AttributeRequest */
432
433 AttributeRequest::AttributeRequest(ustring name_)
434 {
435         name = name_;
436         std = ATTR_STD_NONE;
437
438         triangle_type = TypeDesc::TypeFloat;
439         triangle_element = ATTR_ELEMENT_NONE;
440         triangle_offset = 0;
441
442         curve_type = TypeDesc::TypeFloat;
443         curve_element = ATTR_ELEMENT_NONE;
444         curve_offset = 0;
445 }
446
447 AttributeRequest::AttributeRequest(AttributeStandard std_)
448 {
449         name = ustring();
450         std = std_;
451
452         triangle_type = TypeDesc::TypeFloat;
453         triangle_element = ATTR_ELEMENT_NONE;
454         triangle_offset = 0;
455
456         curve_type = TypeDesc::TypeFloat;
457         curve_element = ATTR_ELEMENT_NONE;
458         curve_offset = 0;
459 }
460
461 /* AttributeRequestSet */
462
463 AttributeRequestSet::AttributeRequestSet()
464 {
465 }
466
467 AttributeRequestSet::~AttributeRequestSet()
468 {
469 }
470
471 bool AttributeRequestSet::modified(const AttributeRequestSet& other)
472 {
473         if(requests.size() != other.requests.size())
474                 return true;
475
476         for(size_t i = 0; i < requests.size(); i++) {
477                 bool found = false;
478
479                 for(size_t j = 0; j < requests.size() && !found; j++)
480                         if(requests[i].name == other.requests[j].name &&
481                            requests[i].std == other.requests[j].std)
482                         {
483                                 found = true;
484                         }
485
486                 if(!found) {
487                         return true;
488                 }
489         }
490
491         return false;
492 }
493
494 void AttributeRequestSet::add(ustring name)
495 {
496         foreach(AttributeRequest& req, requests)
497                 if(req.name == name)
498                         return;
499
500         requests.push_back(AttributeRequest(name));
501 }
502
503 void AttributeRequestSet::add(AttributeStandard std)
504 {
505         foreach(AttributeRequest& req, requests)
506                 if(req.std == std)
507                         return;
508
509         requests.push_back(AttributeRequest(std));
510 }
511
512 void AttributeRequestSet::add(AttributeRequestSet& reqs)
513 {
514         foreach(AttributeRequest& req, reqs.requests) {
515                 if(req.std == ATTR_STD_NONE)
516                         add(req.name);
517                 else
518                         add(req.std);
519         }
520 }
521
522 bool AttributeRequestSet::find(ustring name)
523 {
524         foreach(AttributeRequest& req, requests)
525                 if(req.name == name)
526                         return true;
527         
528         return false;
529 }
530
531 bool AttributeRequestSet::find(AttributeStandard std)
532 {
533         foreach(AttributeRequest& req, requests)
534                 if(req.std == std)
535                         return true;
536
537         return false;
538 }
539
540 size_t AttributeRequestSet::size()
541 {
542         return requests.size();
543 }
544
545 void AttributeRequestSet::clear()
546 {
547         requests.clear();
548 }
549
550 CCL_NAMESPACE_END
551