Merge branch 'master' into blender2.8
[blender.git] / intern / cycles / blender / blender_curves.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 "render/attribute.h"
18 #include "render/camera.h"
19 #include "render/curves.h"
20 #include "render/mesh.h"
21 #include "render/object.h"
22 #include "render/scene.h"
23
24 #include "blender/blender_sync.h"
25 #include "blender/blender_util.h"
26
27 #include "util/util_foreach.h"
28 #include "util/util_hash.h"
29 #include "util/util_logging.h"
30
31 CCL_NAMESPACE_BEGIN
32
33 ParticleCurveData::ParticleCurveData()
34 {
35 }
36
37 ParticleCurveData::~ParticleCurveData()
38 {
39 }
40
41 static void interp_weights(float t, float data[4])
42 {
43         /* Cardinal curve interpolation */
44         float t2 = t * t;
45         float t3 = t2 * t;
46         float fc = 0.71f;
47
48         data[0] = -fc          * t3  + 2.0f * fc          * t2 - fc * t;
49         data[1] =  (2.0f - fc) * t3  + (fc - 3.0f)        * t2 + 1.0f;
50         data[2] =  (fc - 2.0f) * t3  + (3.0f - 2.0f * fc) * t2 + fc * t;
51         data[3] =  fc          * t3  - fc * t2;
52 }
53
54 static void curveinterp_v3_v3v3v3v3(float3 *p,
55                                     float3 *v1, float3 *v2, float3 *v3, float3 *v4,
56                                     const float w[4])
57 {
58         p->x = v1->x * w[0] + v2->x * w[1] + v3->x * w[2] + v4->x * w[3];
59         p->y = v1->y * w[0] + v2->y * w[1] + v3->y * w[2] + v4->y * w[3];
60         p->z = v1->z * w[0] + v2->z * w[1] + v3->z * w[2] + v4->z * w[3];
61 }
62
63 static float shaperadius(float shape, float root, float tip, float time)
64 {
65         assert(time >= 0.0f);
66         assert(time <= 1.0f);
67         float radius = 1.0f - time;
68
69         if(shape != 0.0f) {
70                 if(shape < 0.0f)
71                         radius = powf(radius, 1.0f + shape);
72                 else
73                         radius = powf(radius, 1.0f / (1.0f - shape));
74         }
75         return (radius * (root - tip)) + tip;
76 }
77
78 /* curve functions */
79
80 static void InterpolateKeySegments(int seg,
81                                    int segno,
82                                    int key,
83                                    int curve,
84                                    float3 *keyloc,
85                                    float *time,
86                                    ParticleCurveData *CData)
87 {
88         float3 ckey_loc1 = CData->curvekey_co[key];
89         float3 ckey_loc2 = ckey_loc1;
90         float3 ckey_loc3 = CData->curvekey_co[key+1];
91         float3 ckey_loc4 = ckey_loc3;
92
93         if(key > CData->curve_firstkey[curve])
94                 ckey_loc1 = CData->curvekey_co[key - 1];
95
96         if(key < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2)
97                 ckey_loc4 = CData->curvekey_co[key + 2];
98
99         float time1 = CData->curvekey_time[key]/CData->curve_length[curve];
100         float time2 = CData->curvekey_time[key + 1]/CData->curve_length[curve];
101
102         float dfra = (time2 - time1) / (float)segno;
103
104         if(time)
105                 *time = (dfra * seg) + time1;
106
107         float t[4];
108
109         interp_weights((float)seg / (float)segno, t);
110
111         if(keyloc)
112                 curveinterp_v3_v3v3v3v3(keyloc, &ckey_loc1, &ckey_loc2, &ckey_loc3, &ckey_loc4, t);
113 }
114
115 static bool ObtainCacheParticleData(Mesh *mesh,
116                                     BL::Mesh *b_mesh,
117                                     BL::Object *b_ob,
118                                     ParticleCurveData *CData,
119                                     bool background)
120 {
121         int curvenum = 0;
122         int keyno = 0;
123
124         if(!(mesh && b_mesh && b_ob && CData))
125                 return false;
126
127         Transform tfm = get_transform(b_ob->matrix_world());
128         Transform itfm = transform_quick_inverse(tfm);
129
130         BL::Object::modifiers_iterator b_mod;
131         for(b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) {
132                 if((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && (background ? b_mod->show_render() : b_mod->show_viewport())) {
133                         BL::ParticleSystemModifier psmd((const PointerRNA)b_mod->ptr);
134                         BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr);
135                         BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr);
136
137                         if((b_part.render_type() == BL::ParticleSettings::render_type_PATH) && (b_part.type() == BL::ParticleSettings::type_HAIR)) {
138                                 int shader = clamp(b_part.material()-1, 0, mesh->used_shaders.size()-1);
139                                 int display_step = background ? b_part.render_step() : b_part.display_step();
140                                 int totparts = b_psys.particles.length();
141                                 int totchild = background ? b_psys.child_particles.length() : (int)((float)b_psys.child_particles.length() * (float)b_part.display_percentage() / 100.0f);
142                                 int totcurves = totchild;
143
144                                 if(b_part.child_type() == 0 || totchild == 0)
145                                         totcurves += totparts;
146
147                                 if(totcurves == 0)
148                                         continue;
149
150                                 int ren_step = (1 << display_step) + 1;
151                                 if(b_part.kink() == BL::ParticleSettings::kink_SPIRAL)
152                                         ren_step += b_part.kink_extra_steps();
153
154                                 CData->psys_firstcurve.push_back_slow(curvenum);
155                                 CData->psys_curvenum.push_back_slow(totcurves);
156                                 CData->psys_shader.push_back_slow(shader);
157
158                                 float radius = b_part.radius_scale() * 0.5f;
159
160                                 CData->psys_rootradius.push_back_slow(radius * b_part.root_radius());
161                                 CData->psys_tipradius.push_back_slow(radius * b_part.tip_radius());
162                                 CData->psys_shape.push_back_slow(b_part.shape());
163                                 CData->psys_closetip.push_back_slow(b_part.use_close_tip());
164
165                                 int pa_no = 0;
166                                 if(!(b_part.child_type() == 0) && totchild != 0)
167                                         pa_no = totparts;
168
169                                 int num_add = (totparts+totchild - pa_no);
170                                 CData->curve_firstkey.reserve(CData->curve_firstkey.size() + num_add);
171                                 CData->curve_keynum.reserve(CData->curve_keynum.size() + num_add);
172                                 CData->curve_length.reserve(CData->curve_length.size() + num_add);
173                                 CData->curvekey_co.reserve(CData->curvekey_co.size() + num_add*ren_step);
174                                 CData->curvekey_time.reserve(CData->curvekey_time.size() + num_add*ren_step);
175
176                                 for(; pa_no < totparts+totchild; pa_no++) {
177                                         int keynum = 0;
178                                         CData->curve_firstkey.push_back_slow(keyno);
179
180                                         float curve_length = 0.0f;
181                                         float3 pcKey;
182                                         for(int step_no = 0; step_no < ren_step; step_no++) {
183                                                 float nco[3];
184                                                 b_psys.co_hair(*b_ob, pa_no, step_no, nco);
185                                                 float3 cKey = make_float3(nco[0], nco[1], nco[2]);
186                                                 cKey = transform_point(&itfm, cKey);
187                                                 if(step_no > 0) {
188                                                         float step_length = len(cKey - pcKey);
189                                                         if(step_length == 0.0f)
190                                                                 continue;
191                                                         curve_length += step_length;
192                                                 }
193                                                 CData->curvekey_co.push_back_slow(cKey);
194                                                 CData->curvekey_time.push_back_slow(curve_length);
195                                                 pcKey = cKey;
196                                                 keynum++;
197                                         }
198                                         keyno += keynum;
199
200                                         CData->curve_keynum.push_back_slow(keynum);
201                                         CData->curve_length.push_back_slow(curve_length);
202                                         curvenum++;
203                                 }
204                         }
205                 }
206         }
207
208         return true;
209 }
210
211 static bool ObtainCacheParticleUV(Mesh *mesh,
212                                   BL::Mesh *b_mesh,
213                                   BL::Object *b_ob,
214                                   ParticleCurveData *CData,
215                                   bool background,
216                                   int uv_num)
217 {
218         if(!(mesh && b_mesh && b_ob && CData))
219                 return false;
220
221         CData->curve_uv.clear();
222
223         BL::Object::modifiers_iterator b_mod;
224         for(b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) {
225                 if((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && (background ? b_mod->show_render() : b_mod->show_viewport())) {
226                         BL::ParticleSystemModifier psmd((const PointerRNA)b_mod->ptr);
227                         BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr);
228                         BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr);
229
230                         if((b_part.render_type() == BL::ParticleSettings::render_type_PATH) && (b_part.type() == BL::ParticleSettings::type_HAIR)) {
231                                 int totparts = b_psys.particles.length();
232                                 int totchild = background ? b_psys.child_particles.length() : (int)((float)b_psys.child_particles.length() * (float)b_part.display_percentage() / 100.0f);
233                                 int totcurves = totchild;
234
235                                 if(b_part.child_type() == 0 || totchild == 0)
236                                         totcurves += totparts;
237
238                                 if(totcurves == 0)
239                                         continue;
240
241                                 int pa_no = 0;
242                                 if(!(b_part.child_type() == 0) && totchild != 0)
243                                         pa_no = totparts;
244
245                                 int num_add = (totparts+totchild - pa_no);
246                                 CData->curve_uv.reserve(CData->curve_uv.size() + num_add);
247
248                                 BL::ParticleSystem::particles_iterator b_pa;
249                                 b_psys.particles.begin(b_pa);
250                                 for(; pa_no < totparts+totchild; pa_no++) {
251                                         /* Add UVs */
252                                         BL::Mesh::uv_layers_iterator l;
253                                         b_mesh->uv_layers.begin(l);
254
255                                         float3 uv = make_float3(0.0f, 0.0f, 0.0f);
256                                         if(b_mesh->uv_layers.length())
257                                                 b_psys.uv_on_emitter(psmd, *b_pa, pa_no, uv_num, &uv.x);
258                                         CData->curve_uv.push_back_slow(uv);
259
260                                         if(pa_no < totparts && b_pa != b_psys.particles.end())
261                                                 ++b_pa;
262                                 }
263                         }
264                 }
265         }
266
267         return true;
268 }
269
270 static bool ObtainCacheParticleVcol(Mesh *mesh,
271                                     BL::Mesh *b_mesh,
272                                     BL::Object *b_ob,
273                                     ParticleCurveData *CData,
274                                     bool background,
275                                     int vcol_num)
276 {
277         if(!(mesh && b_mesh && b_ob && CData))
278                 return false;
279
280         CData->curve_vcol.clear();
281
282         BL::Object::modifiers_iterator b_mod;
283         for(b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) {
284                 if((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && (background ? b_mod->show_render() : b_mod->show_viewport())) {
285                         BL::ParticleSystemModifier psmd((const PointerRNA)b_mod->ptr);
286                         BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr);
287                         BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr);
288
289                         if((b_part.render_type() == BL::ParticleSettings::render_type_PATH) && (b_part.type() == BL::ParticleSettings::type_HAIR)) {
290                                 int totparts = b_psys.particles.length();
291                                 int totchild = background ? b_psys.child_particles.length() : (int)((float)b_psys.child_particles.length() * (float)b_part.display_percentage() / 100.0f);
292                                 int totcurves = totchild;
293
294                                 if(b_part.child_type() == 0 || totchild == 0)
295                                         totcurves += totparts;
296
297                                 if(totcurves == 0)
298                                         continue;
299
300                                 int pa_no = 0;
301                                 if(!(b_part.child_type() == 0) && totchild != 0)
302                                         pa_no = totparts;
303
304                                 int num_add = (totparts+totchild - pa_no);
305                                 CData->curve_vcol.reserve(CData->curve_vcol.size() + num_add);
306
307                                 BL::ParticleSystem::particles_iterator b_pa;
308                                 b_psys.particles.begin(b_pa);
309                                 for(; pa_no < totparts+totchild; pa_no++) {
310                                         /* Add vertex colors */
311                                         BL::Mesh::vertex_colors_iterator l;
312                                         b_mesh->vertex_colors.begin(l);
313
314                                         float3 vcol = make_float3(0.0f, 0.0f, 0.0f);
315                                         if(b_mesh->vertex_colors.length())
316                                                 b_psys.mcol_on_emitter(psmd, *b_pa, pa_no, vcol_num, &vcol.x);
317                                         CData->curve_vcol.push_back_slow(vcol);
318
319                                         if(pa_no < totparts && b_pa != b_psys.particles.end())
320                                                 ++b_pa;
321                                 }
322                         }
323                 }
324         }
325
326         return true;
327 }
328
329 static void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData,
330                                       float3 RotCam, bool is_ortho)
331 {
332         int vertexno = mesh->verts.size();
333         int vertexindex = vertexno;
334         int numverts = 0, numtris = 0;
335
336         /* compute and reserve size of arrays */
337         for(int sys = 0; sys < CData->psys_firstcurve.size(); sys++) {
338                 for(int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys]; curve++) {
339                         if(CData->curve_keynum[curve] <= 1 || CData->curve_length[curve] == 0.0f)
340                                 continue;
341
342                         numverts += 2 + (CData->curve_keynum[curve] - 1)*2;
343                         numtris += (CData->curve_keynum[curve] - 1)*2;
344                 }
345         }
346
347         mesh->reserve_mesh(mesh->verts.size() + numverts, mesh->num_triangles() + numtris);
348
349         /* actually export */
350         for(int sys = 0; sys < CData->psys_firstcurve.size(); sys++) {
351                 for(int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys]; curve++) {
352                         if(CData->curve_keynum[curve] <= 1 || CData->curve_length[curve] == 0.0f)
353                                 continue;
354
355                         float3 xbasis;
356                         float3 v1;
357                         float time = 0.0f;
358                         float3 ickey_loc = CData->curvekey_co[CData->curve_firstkey[curve]];
359                         float radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], 0.0f);
360                         v1 = CData->curvekey_co[CData->curve_firstkey[curve] + 1] - CData->curvekey_co[CData->curve_firstkey[curve]];
361                         if(is_ortho)
362                                 xbasis = normalize(cross(RotCam, v1));
363                         else
364                                 xbasis = normalize(cross(RotCam - ickey_loc, v1));
365                         float3 ickey_loc_shfl = ickey_loc - radius * xbasis;
366                         float3 ickey_loc_shfr = ickey_loc + radius * xbasis;
367                         mesh->add_vertex(ickey_loc_shfl);
368                         mesh->add_vertex(ickey_loc_shfr);
369                         vertexindex += 2;
370
371                         for(int curvekey = CData->curve_firstkey[curve] + 1; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve]; curvekey++) {
372                                 ickey_loc = CData->curvekey_co[curvekey];
373
374                                 if(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)
375                                         v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[max(curvekey - 1, CData->curve_firstkey[curve])];
376                                 else
377                                         v1 = CData->curvekey_co[curvekey + 1] - CData->curvekey_co[curvekey - 1];
378
379                                 time = CData->curvekey_time[curvekey]/CData->curve_length[curve];
380                                 radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], time);
381
382                                 if(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)
383                                         radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], 0.95f);
384
385                                 if(CData->psys_closetip[sys] && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1))
386                                         radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], 0.0f, 0.95f);
387
388                                 if(is_ortho)
389                                         xbasis = normalize(cross(RotCam, v1));
390                                 else
391                                         xbasis = normalize(cross(RotCam - ickey_loc, v1));
392                                 float3 ickey_loc_shfl = ickey_loc - radius * xbasis;
393                                 float3 ickey_loc_shfr = ickey_loc + radius * xbasis;
394                                 mesh->add_vertex(ickey_loc_shfl);
395                                 mesh->add_vertex(ickey_loc_shfr);
396                                 mesh->add_triangle(vertexindex-2, vertexindex, vertexindex-1, CData->psys_shader[sys], true);
397                                 mesh->add_triangle(vertexindex+1, vertexindex-1, vertexindex, CData->psys_shader[sys], true);
398                                 vertexindex += 2;
399                         }
400                 }
401         }
402
403         mesh->resize_mesh(mesh->verts.size(), mesh->num_triangles());
404         mesh->attributes.remove(ATTR_STD_VERTEX_NORMAL);
405         mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
406         mesh->add_face_normals();
407         mesh->add_vertex_normals();
408         mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
409
410         /* texture coords still needed */
411 }
412
413 static void ExportCurveTriangleGeometry(Mesh *mesh,
414                                         ParticleCurveData *CData,
415                                         int resolution)
416 {
417         int vertexno = mesh->verts.size();
418         int vertexindex = vertexno;
419         int numverts = 0, numtris = 0;
420
421         /* compute and reserve size of arrays */
422         for(int sys = 0; sys < CData->psys_firstcurve.size(); sys++) {
423                 for(int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys]; curve++) {
424                         if(CData->curve_keynum[curve] <= 1 || CData->curve_length[curve] == 0.0f)
425                                 continue;
426
427                         numverts += (CData->curve_keynum[curve] - 1)*resolution + resolution;
428                         numtris += (CData->curve_keynum[curve] - 1)*2*resolution;
429                 }
430         }
431
432         mesh->reserve_mesh(mesh->verts.size() + numverts, mesh->num_triangles() + numtris);
433
434         /* actually export */
435         for(int sys = 0; sys < CData->psys_firstcurve.size(); sys++) {
436                 for(int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys]; curve++) {
437                         if(CData->curve_keynum[curve] <= 1 || CData->curve_length[curve] == 0.0f)
438                                 continue;
439
440                         float3 firstxbasis = cross(make_float3(1.0f,0.0f,0.0f),CData->curvekey_co[CData->curve_firstkey[curve]+1] - CData->curvekey_co[CData->curve_firstkey[curve]]);
441                         if(!is_zero(firstxbasis))
442                                 firstxbasis = normalize(firstxbasis);
443                         else
444                                 firstxbasis = normalize(cross(make_float3(0.0f,1.0f,0.0f),CData->curvekey_co[CData->curve_firstkey[curve]+1] - CData->curvekey_co[CData->curve_firstkey[curve]]));
445
446                         for(int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) {
447                                 float3 xbasis = firstxbasis;
448                                 float3 v1;
449                                 float3 v2;
450
451                                 if(curvekey == CData->curve_firstkey[curve]) {
452                                         v1 = CData->curvekey_co[min(curvekey+2,CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)] - CData->curvekey_co[curvekey+1];
453                                         v2 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
454                                 }
455                                 else if(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1) {
456                                         v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
457                                         v2 = CData->curvekey_co[curvekey-1] - CData->curvekey_co[max(curvekey-2,CData->curve_firstkey[curve])];
458                                 }
459                                 else {
460                                         v1 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
461                                         v2 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
462                                 }
463
464                                 xbasis = cross(v1, v2);
465
466                                 if(len_squared(xbasis) >= 0.05f * len_squared(v1) * len_squared(v2)) {
467                                         firstxbasis = normalize(xbasis);
468                                         break;
469                                 }
470                         }
471
472                         for(int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) {
473                                 int subv = 1;
474                                 float3 xbasis;
475                                 float3 ybasis;
476                                 float3 v1;
477                                 float3 v2;
478
479                                 if(curvekey == CData->curve_firstkey[curve]) {
480                                         subv = 0;
481                                         v1 = CData->curvekey_co[min(curvekey+2,CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)] - CData->curvekey_co[curvekey+1];
482                                         v2 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
483                                 }
484                                 else if(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1) {
485                                         v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
486                                         v2 = CData->curvekey_co[curvekey-1] - CData->curvekey_co[max(curvekey-2,CData->curve_firstkey[curve])];
487                                 }
488                                 else {
489                                         v1 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
490                                         v2 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
491                                 }
492
493                                 xbasis = cross(v1, v2);
494
495                                 if(len_squared(xbasis) >= 0.05f * len_squared(v1) * len_squared(v2)) {
496                                         xbasis = normalize(xbasis);
497                                         firstxbasis = xbasis;
498                                 }
499                                 else
500                                         xbasis = firstxbasis;
501
502                                 ybasis = normalize(cross(xbasis, v2));
503
504                                 for(; subv <= 1; subv++) {
505                                         float3 ickey_loc = make_float3(0.0f,0.0f,0.0f);
506                                         float time = 0.0f;
507
508                                         InterpolateKeySegments(subv, 1, curvekey, curve, &ickey_loc, &time, CData);
509
510                                         float radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], time);
511
512                                         if((curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) && (subv == 1))
513                                                 radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], 0.95f);
514
515                                         if(CData->psys_closetip[sys] && (subv == 1) && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2))
516                                                 radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], 0.0f, 0.95f);
517
518                                         float angle = M_2PI_F / (float)resolution;
519                                         for(int section = 0; section < resolution; section++) {
520                                                 float3 ickey_loc_shf = ickey_loc + radius * (cosf(angle * section) * xbasis + sinf(angle * section) * ybasis);
521                                                 mesh->add_vertex(ickey_loc_shf);
522                                         }
523
524                                         if(subv != 0) {
525                                                 for(int section = 0; section < resolution - 1; section++) {
526                                                         mesh->add_triangle(vertexindex - resolution + section, vertexindex + section, vertexindex - resolution + section + 1, CData->psys_shader[sys], true);
527                                                         mesh->add_triangle(vertexindex + section + 1, vertexindex - resolution + section + 1, vertexindex + section, CData->psys_shader[sys], true);
528                                                 }
529                                                 mesh->add_triangle(vertexindex-1, vertexindex + resolution - 1, vertexindex - resolution, CData->psys_shader[sys], true);
530                                                 mesh->add_triangle(vertexindex, vertexindex - resolution , vertexindex + resolution - 1, CData->psys_shader[sys], true);
531                                         }
532                                         vertexindex += resolution;
533                                 }
534                         }
535                 }
536         }
537
538         mesh->resize_mesh(mesh->verts.size(), mesh->num_triangles());
539         mesh->attributes.remove(ATTR_STD_VERTEX_NORMAL);
540         mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
541         mesh->add_face_normals();
542         mesh->add_vertex_normals();
543         mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
544
545         /* texture coords still needed */
546 }
547
548 static void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CData)
549 {
550         int num_keys = 0;
551         int num_curves = 0;
552
553         if(mesh->num_curves())
554                 return;
555
556         Attribute *attr_intercept = NULL;
557         Attribute *attr_random = NULL;
558
559         if(mesh->need_attribute(scene, ATTR_STD_CURVE_INTERCEPT))
560                 attr_intercept = mesh->curve_attributes.add(ATTR_STD_CURVE_INTERCEPT);
561         if(mesh->need_attribute(scene, ATTR_STD_CURVE_RANDOM))
562                 attr_random = mesh->curve_attributes.add(ATTR_STD_CURVE_RANDOM);
563
564         /* compute and reserve size of arrays */
565         for(int sys = 0; sys < CData->psys_firstcurve.size(); sys++) {
566                 for(int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys]; curve++) {
567                         if(CData->curve_keynum[curve] <= 1 || CData->curve_length[curve] == 0.0f)
568                                 continue;
569
570                         num_keys += CData->curve_keynum[curve];
571                         num_curves++;
572                 }
573         }
574
575         if(num_curves > 0) {
576                 VLOG(1) << "Exporting curve segments for mesh " << mesh->name;
577         }
578
579         mesh->reserve_curves(mesh->num_curves() + num_curves, mesh->curve_keys.size() + num_keys);
580
581         num_keys = 0;
582         num_curves = 0;
583
584         /* actually export */
585         for(int sys = 0; sys < CData->psys_firstcurve.size(); sys++) {
586                 for(int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys]; curve++) {
587                         if(CData->curve_keynum[curve] <= 1 || CData->curve_length[curve] == 0.0f)
588                                 continue;
589
590                         size_t num_curve_keys = 0;
591
592                         for(int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve]; curvekey++) {
593                                 float3 ickey_loc = CData->curvekey_co[curvekey];
594                                 float time = CData->curvekey_time[curvekey]/CData->curve_length[curve];
595                                 float radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], time);
596
597                                 if(CData->psys_closetip[sys] && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1))
598                                         radius = 0.0f;
599
600                                 mesh->add_curve_key(ickey_loc, radius);
601                                 if(attr_intercept)
602                                         attr_intercept->add(time);
603
604                                 num_curve_keys++;
605                         }
606
607                         if(attr_random != NULL) {
608                                 attr_random->add(hash_int_01(num_curves));
609                         }
610
611                         mesh->add_curve(num_keys, CData->psys_shader[sys]);
612                         num_keys += num_curve_keys;
613                         num_curves++;
614                 }
615         }
616
617         /* check allocation */
618         if((mesh->curve_keys.size() != num_keys) || (mesh->num_curves() != num_curves)) {
619                 VLOG(1) << "Allocation failed, clearing data";
620                 mesh->clear();
621         }
622 }
623
624 static float4 CurveSegmentMotionCV(ParticleCurveData *CData, int sys, int curve, int curvekey)
625 {
626         float3 ickey_loc = CData->curvekey_co[curvekey];
627         float time = CData->curvekey_time[curvekey]/CData->curve_length[curve];
628         float radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], time);
629
630         if(CData->psys_closetip[sys] && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1))
631                 radius = 0.0f;
632
633         /* curve motion keys store both position and radius in float4 */
634         float4 mP = float3_to_float4(ickey_loc);
635         mP.w = radius;
636         return mP;
637 }
638
639 static float4 LerpCurveSegmentMotionCV(ParticleCurveData *CData, int sys, int curve, float step)
640 {
641         assert(step >= 0.0f);
642         assert(step <= 1.0f);
643         const int first_curve_key = CData->curve_firstkey[curve];
644         const float curve_key_f = step * (CData->curve_keynum[curve] - 1);
645         int curvekey = (int)floorf(curve_key_f);
646         const float remainder = curve_key_f - curvekey;
647         if(remainder == 0.0f) {
648                 return CurveSegmentMotionCV(CData, sys, curve, first_curve_key + curvekey);
649         }
650         int curvekey2 = curvekey + 1;
651         if(curvekey2 >= (CData->curve_keynum[curve] - 1)) {
652                 curvekey2 = (CData->curve_keynum[curve] - 1);
653                 curvekey = curvekey2 - 1;
654         }
655         const float4 mP = CurveSegmentMotionCV(
656                 CData, sys, curve, first_curve_key + curvekey);
657         const float4 mP2 = CurveSegmentMotionCV(
658                 CData, sys, curve, first_curve_key + curvekey2);
659         return lerp(mP, mP2, remainder);
660 }
661
662 static void ExportCurveSegmentsMotion(Mesh *mesh, ParticleCurveData *CData, int motion_step)
663 {
664         VLOG(1) << "Exporting curve motion segments for mesh " << mesh->name
665                 << ", motion step " << motion_step;
666
667         /* find attribute */
668         Attribute *attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
669         bool new_attribute = false;
670
671         /* add new attribute if it doesn't exist already */
672         if(!attr_mP) {
673                 VLOG(1) << "Creating new motion vertex position attribute";
674                 attr_mP = mesh->curve_attributes.add(ATTR_STD_MOTION_VERTEX_POSITION);
675                 new_attribute = true;
676         }
677
678         /* export motion vectors for curve keys */
679         size_t numkeys = mesh->curve_keys.size();
680         float4 *mP = attr_mP->data_float4() + motion_step*numkeys;
681         bool have_motion = false;
682         int i = 0;
683         int num_curves = 0;
684
685         for(int sys = 0; sys < CData->psys_firstcurve.size(); sys++) {
686                 if(CData->psys_curvenum[sys] == 0)
687                         continue;
688
689                 for(int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys]; curve++) {
690                         if(CData->curve_keynum[curve] <= 1 || CData->curve_length[curve] == 0.0f)
691                                 continue;
692
693                         /* Curve lengths may not match! Curves can be clipped. */
694                         int curve_key_end = (num_curves+1 < (int)mesh->curve_first_key.size() ? mesh->curve_first_key[num_curves+1] : (int)mesh->curve_keys.size());
695                         const int num_center_curve_keys = curve_key_end - mesh->curve_first_key[num_curves];
696                         const int is_num_keys_different = CData->curve_keynum[curve] - num_center_curve_keys;
697
698                         if(!is_num_keys_different) {
699                                 for(int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve]; curvekey++) {
700                                         if(i < mesh->curve_keys.size()) {
701                                                 mP[i] = CurveSegmentMotionCV(CData, sys, curve, curvekey);
702                                                 if(!have_motion) {
703                                                         /* unlike mesh coordinates, these tend to be slightly different
704                                                          * between frames due to particle transforms into/out of object
705                                                          * space, so we use an epsilon to detect actual changes */
706                                                         float4 curve_key = float3_to_float4(mesh->curve_keys[i]);
707                                                         curve_key.w = mesh->curve_radius[i];
708                                                         if(len_squared(mP[i] - curve_key) > 1e-5f*1e-5f)
709                                                                 have_motion = true;
710                                                 }
711                                         }
712                                         i++;
713                                 }
714                         }
715                         else {
716                                 /* Number of keys has changed. Genereate an interpolated version
717                                  * to preserve motion blur. */
718                                 float step_size = 1.0f / (num_center_curve_keys-1);
719                                 for(int step_index = 0;
720                                     step_index < num_center_curve_keys;
721                                     ++step_index)
722                                 {
723                                         const float step = step_index * step_size;
724                                         mP[i] = LerpCurveSegmentMotionCV(CData, sys, curve, step);
725                                         i++;
726                                 }
727                                 have_motion = true;
728                         }
729                         num_curves++;
730                 }
731         }
732
733         /* in case of new attribute, we verify if there really was any motion */
734         if(new_attribute) {
735                 if(i != numkeys || !have_motion) {
736                         /* No motion or hair "topology" changed, remove attributes again. */
737                         if(i != numkeys) {
738                                 VLOG(1) << "Hair topology changed, removing attribute.";
739                         }
740                         else {
741                                 VLOG(1) << "No motion, removing attribute.";
742                         }
743                         mesh->curve_attributes.remove(ATTR_STD_MOTION_VERTEX_POSITION);
744                 }
745                 else if(motion_step > 0) {
746                         VLOG(1) << "Filling in new motion vertex position for motion_step "
747                                 << motion_step;
748                         /* motion, fill up previous steps that we might have skipped because
749                          * they had no motion, but we need them anyway now */
750                         for(int step = 0; step < motion_step; step++) {
751                                 float4 *mP = attr_mP->data_float4() + step*numkeys;
752
753                                 for(int key = 0; key < numkeys; key++) {
754                                         mP[key] = float3_to_float4(mesh->curve_keys[key]);
755                                         mP[key].w = mesh->curve_radius[key];
756                                 }
757                         }
758                 }
759         }
760 }
761
762 static void ExportCurveTriangleUV(ParticleCurveData *CData,
763                                   int vert_offset,
764                                   int resol,
765                                   float3 *uvdata)
766 {
767         if(uvdata == NULL)
768                 return;
769
770         float time = 0.0f;
771         float prevtime = 0.0f;
772
773         int vertexindex = vert_offset;
774
775         for(int sys = 0; sys < CData->psys_firstcurve.size(); sys++) {
776                 for(int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys]; curve++) {
777                         if(CData->curve_keynum[curve] <= 1 || CData->curve_length[curve] == 0.0f)
778                                 continue;
779
780                         for(int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) {
781                                 time = CData->curvekey_time[curvekey]/CData->curve_length[curve];
782
783                                 for(int section = 0; section < resol; section++) {
784                                         uvdata[vertexindex] = CData->curve_uv[curve];
785                                         uvdata[vertexindex].z = prevtime;
786                                         vertexindex++;
787                                         uvdata[vertexindex] = CData->curve_uv[curve];
788                                         uvdata[vertexindex].z = time;
789                                         vertexindex++;
790                                         uvdata[vertexindex] = CData->curve_uv[curve];
791                                         uvdata[vertexindex].z = prevtime;
792                                         vertexindex++;
793                                         uvdata[vertexindex] = CData->curve_uv[curve];
794                                         uvdata[vertexindex].z = time;
795                                         vertexindex++;
796                                         uvdata[vertexindex] = CData->curve_uv[curve];
797                                         uvdata[vertexindex].z = prevtime;
798                                         vertexindex++;
799                                         uvdata[vertexindex] = CData->curve_uv[curve];
800                                         uvdata[vertexindex].z = time;
801                                         vertexindex++;
802                                 }
803
804                                 prevtime = time;
805                         }
806                 }
807         }
808 }
809
810 static void ExportCurveTriangleVcol(ParticleCurveData *CData,
811                                     int vert_offset,
812                                     int resol,
813                                     uchar4 *cdata)
814 {
815         if(cdata == NULL)
816                 return;
817
818         int vertexindex = vert_offset;
819
820         for(int sys = 0; sys < CData->psys_firstcurve.size(); sys++) {
821                 for(int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys]; curve++) {
822                         if(CData->curve_keynum[curve] <= 1 || CData->curve_length[curve] == 0.0f)
823                                 continue;
824
825                         for(int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) {
826                                 for(int section = 0; section < resol; section++) {
827                                         /* Encode vertex color using the sRGB curve. */
828                                         cdata[vertexindex] = color_float_to_byte(color_srgb_to_linear_v3(CData->curve_vcol[curve]));
829                                         vertexindex++;
830                                         cdata[vertexindex] = color_float_to_byte(color_srgb_to_linear_v3(CData->curve_vcol[curve]));
831                                         vertexindex++;
832                                         cdata[vertexindex] = color_float_to_byte(color_srgb_to_linear_v3(CData->curve_vcol[curve]));
833                                         vertexindex++;
834                                         cdata[vertexindex] = color_float_to_byte(color_srgb_to_linear_v3(CData->curve_vcol[curve]));
835                                         vertexindex++;
836                                         cdata[vertexindex] = color_float_to_byte(color_srgb_to_linear_v3(CData->curve_vcol[curve]));
837                                         vertexindex++;
838                                         cdata[vertexindex] = color_float_to_byte(color_srgb_to_linear_v3(CData->curve_vcol[curve]));
839                                         vertexindex++;
840                                 }
841                         }
842                 }
843         }
844 }
845
846 /* Hair Curve Sync */
847
848 void BlenderSync::sync_curve_settings()
849 {
850         PointerRNA csscene = RNA_pointer_get(&b_scene.ptr, "cycles_curves");
851
852         CurveSystemManager *curve_system_manager = scene->curve_system_manager;
853         CurveSystemManager prev_curve_system_manager = *curve_system_manager;
854
855         curve_system_manager->use_curves = get_boolean(csscene, "use_curves");
856         curve_system_manager->minimum_width = get_float(csscene, "minimum_width");
857         curve_system_manager->maximum_width = get_float(csscene, "maximum_width");
858
859         curve_system_manager->primitive =
860                 (CurvePrimitiveType)get_enum(csscene,
861                                              "primitive",
862                                              CURVE_NUM_PRIMITIVE_TYPES,
863                                              CURVE_LINE_SEGMENTS);
864         curve_system_manager->curve_shape =
865                 (CurveShapeType)get_enum(csscene,
866                                          "shape",
867                                          CURVE_NUM_SHAPE_TYPES,
868                                          CURVE_THICK);
869         curve_system_manager->resolution = get_int(csscene, "resolution");
870         curve_system_manager->subdivisions = get_int(csscene, "subdivisions");
871         curve_system_manager->use_backfacing = !get_boolean(csscene, "cull_backfacing");
872
873         /* Triangles */
874         if(curve_system_manager->primitive == CURVE_TRIANGLES) {
875                 /* camera facing planes */
876                 if(curve_system_manager->curve_shape == CURVE_RIBBON) {
877                         curve_system_manager->triangle_method = CURVE_CAMERA_TRIANGLES;
878                         curve_system_manager->resolution = 1;
879                 }
880                 else if(curve_system_manager->curve_shape == CURVE_THICK) {
881                         curve_system_manager->triangle_method = CURVE_TESSELATED_TRIANGLES;
882                 }
883         }
884         /* Line Segments */
885         else if(curve_system_manager->primitive == CURVE_LINE_SEGMENTS) {
886                 if(curve_system_manager->curve_shape == CURVE_RIBBON) {
887                         /* tangent shading */
888                         curve_system_manager->line_method = CURVE_UNCORRECTED;
889                         curve_system_manager->use_encasing = true;
890                         curve_system_manager->use_backfacing = false;
891                         curve_system_manager->use_tangent_normal_geometry = true;
892                 }
893                 else if(curve_system_manager->curve_shape == CURVE_THICK) {
894                         curve_system_manager->line_method = CURVE_ACCURATE;
895                         curve_system_manager->use_encasing = false;
896                         curve_system_manager->use_tangent_normal_geometry = false;
897                 }
898         }
899         /* Curve Segments */
900         else if(curve_system_manager->primitive == CURVE_SEGMENTS) {
901                 if(curve_system_manager->curve_shape == CURVE_RIBBON) {
902                         curve_system_manager->primitive = CURVE_RIBBONS;
903                         curve_system_manager->use_backfacing = false;
904                 }
905         }
906
907         if(curve_system_manager->modified_mesh(prev_curve_system_manager)) {
908                 BL::BlendData::objects_iterator b_ob;
909
910                 for(b_data.objects.begin(b_ob); b_ob != b_data.objects.end(); ++b_ob) {
911                         if(object_is_mesh(*b_ob)) {
912                                 BL::Object::particle_systems_iterator b_psys;
913                                 for(b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys) {
914                                         if((b_psys->settings().render_type()==BL::ParticleSettings::render_type_PATH)&&(b_psys->settings().type()==BL::ParticleSettings::type_HAIR)) {
915                                                 BL::ID key = BKE_object_is_modified(*b_ob)? *b_ob: b_ob->data();
916                                                 mesh_map.set_recalc(key);
917                                                 object_map.set_recalc(*b_ob);
918                                         }
919                                 }
920                         }
921                 }
922         }
923
924         if(curve_system_manager->modified(prev_curve_system_manager))
925                 curve_system_manager->tag_update(scene);
926 }
927
928 void BlenderSync::sync_curves(Mesh *mesh,
929                               BL::Mesh& b_mesh,
930                               BL::Object& b_ob,
931                               bool motion,
932                               int motion_step)
933 {
934         if(!motion) {
935                 /* Clear stored curve data */
936                 mesh->curve_keys.clear();
937                 mesh->curve_radius.clear();
938                 mesh->curve_first_key.clear();
939                 mesh->curve_shader.clear();
940                 mesh->curve_attributes.clear();
941         }
942
943         /* obtain general settings */
944         const bool use_curves = scene->curve_system_manager->use_curves;
945
946         if(!(use_curves && b_ob.mode() != b_ob.mode_PARTICLE_EDIT)) {
947                 if(!motion)
948                         mesh->compute_bounds();
949                 return;
950         }
951
952         const int primitive = scene->curve_system_manager->primitive;
953         const int triangle_method = scene->curve_system_manager->triangle_method;
954         const int resolution = scene->curve_system_manager->resolution;
955         const size_t vert_num = mesh->verts.size();
956         const size_t tri_num = mesh->num_triangles();
957         int used_res = 1;
958
959         /* extract particle hair data - should be combined with connecting to mesh later*/
960
961         ParticleCurveData CData;
962
963         ObtainCacheParticleData(mesh, &b_mesh, &b_ob, &CData, !preview);
964
965         /* add hair geometry to mesh */
966         if(primitive == CURVE_TRIANGLES) {
967                 if(triangle_method == CURVE_CAMERA_TRIANGLES) {
968                         /* obtain camera parameters */
969                         float3 RotCam;
970                         Camera *camera = scene->camera;
971                         Transform &ctfm = camera->matrix;
972                         if(camera->type == CAMERA_ORTHOGRAPHIC) {
973                                 RotCam = -make_float3(ctfm.x.z, ctfm.y.z, ctfm.z.z);
974                         }
975                         else {
976                                 Transform tfm = get_transform(b_ob.matrix_world());
977                                 Transform itfm = transform_quick_inverse(tfm);
978                                 RotCam = transform_point(&itfm, make_float3(ctfm.x.w,
979                                                                             ctfm.y.w,
980                                                                             ctfm.z.w));
981                         }
982                         bool is_ortho = camera->type == CAMERA_ORTHOGRAPHIC;
983                         ExportCurveTrianglePlanes(mesh, &CData, RotCam, is_ortho);
984                 }
985                 else {
986                         ExportCurveTriangleGeometry(mesh, &CData, resolution);
987                         used_res = resolution;
988                 }
989         }
990         else {
991                 if(motion)
992                         ExportCurveSegmentsMotion(mesh, &CData, motion_step);
993                 else
994                         ExportCurveSegments(scene, mesh, &CData);
995         }
996
997         /* generated coordinates from first key. we should ideally get this from
998          * blender to handle deforming objects */
999         if(!motion) {
1000                 if(mesh->need_attribute(scene, ATTR_STD_GENERATED)) {
1001                         float3 loc, size;
1002                         mesh_texture_space(b_mesh, loc, size);
1003
1004                         if(primitive == CURVE_TRIANGLES) {
1005                                 Attribute *attr_generated = mesh->attributes.add(ATTR_STD_GENERATED);
1006                                 float3 *generated = attr_generated->data_float3();
1007
1008                                 for(size_t i = vert_num; i < mesh->verts.size(); i++)
1009                                         generated[i] = mesh->verts[i]*size - loc;
1010                         }
1011                         else {
1012                                 Attribute *attr_generated = mesh->curve_attributes.add(ATTR_STD_GENERATED);
1013                                 float3 *generated = attr_generated->data_float3();
1014
1015                                 for(size_t i = 0; i < mesh->num_curves(); i++) {
1016                                         float3 co = mesh->curve_keys[mesh->get_curve(i).first_key];
1017                                         generated[i] = co*size - loc;
1018                                 }
1019                         }
1020                 }
1021         }
1022
1023         /* create vertex color attributes */
1024         if(!motion) {
1025                 BL::Mesh::vertex_colors_iterator l;
1026                 int vcol_num = 0;
1027
1028                 for(b_mesh.vertex_colors.begin(l); l != b_mesh.vertex_colors.end(); ++l, vcol_num++) {
1029                         if(!mesh->need_attribute(scene, ustring(l->name().c_str())))
1030                                 continue;
1031
1032                         ObtainCacheParticleVcol(mesh, &b_mesh, &b_ob, &CData, !preview, vcol_num);
1033
1034                         if(primitive == CURVE_TRIANGLES) {
1035                                 Attribute *attr_vcol = mesh->attributes.add(
1036                                         ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CORNER_BYTE);
1037
1038                                 uchar4 *cdata = attr_vcol->data_uchar4();
1039
1040                                 ExportCurveTriangleVcol(&CData, tri_num * 3, used_res, cdata);
1041                         }
1042                         else {
1043                                 Attribute *attr_vcol = mesh->curve_attributes.add(
1044                                         ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CURVE);
1045
1046                                 float3 *fdata = attr_vcol->data_float3();
1047
1048                                 if(fdata) {
1049                                         size_t i = 0;
1050
1051                                         /* Encode vertex color using the sRGB curve. */
1052                                         for(size_t curve = 0; curve < CData.curve_vcol.size(); curve++)
1053                                                 if(!(CData.curve_keynum[curve] <= 1 || CData.curve_length[curve] == 0.0f))
1054                                                         fdata[i++] = color_srgb_to_linear_v3(CData.curve_vcol[curve]);
1055                                 }
1056                         }
1057                 }
1058         }
1059
1060         /* create UV attributes */
1061         if(!motion) {
1062                 BL::Mesh::uv_layers_iterator l;
1063                 int uv_num = 0;
1064
1065                 for(b_mesh.uv_layers.begin(l); l != b_mesh.uv_layers.end(); ++l, uv_num++) {
1066                         bool active_render = l->active_render();
1067                         AttributeStandard std = (active_render)? ATTR_STD_UV: ATTR_STD_NONE;
1068                         ustring name = ustring(l->name().c_str());
1069
1070                         /* UV map */
1071                         if(mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std)) {
1072                                 Attribute *attr_uv;
1073
1074                                 ObtainCacheParticleUV(mesh, &b_mesh, &b_ob, &CData, !preview, uv_num);
1075
1076                                 if(primitive == CURVE_TRIANGLES) {
1077                                         if(active_render)
1078                                                 attr_uv = mesh->attributes.add(std, name);
1079                                         else
1080                                                 attr_uv = mesh->attributes.add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CORNER);
1081
1082                                         float3 *uv = attr_uv->data_float3();
1083
1084                                         ExportCurveTriangleUV(&CData, tri_num * 3, used_res, uv);
1085                                 }
1086                                 else {
1087                                         if(active_render)
1088                                                 attr_uv = mesh->curve_attributes.add(std, name);
1089                                         else
1090                                                 attr_uv = mesh->curve_attributes.add(name, TypeDesc::TypePoint,  ATTR_ELEMENT_CURVE);
1091
1092                                         float3 *uv = attr_uv->data_float3();
1093
1094                                         if(uv) {
1095                                                 size_t i = 0;
1096
1097                                                 for(size_t curve = 0; curve < CData.curve_uv.size(); curve++)
1098                                                         if(!(CData.curve_keynum[curve] <= 1 || CData.curve_length[curve] == 0.0f))
1099                                                                 uv[i++] = CData.curve_uv[curve];
1100                                         }
1101                                 }
1102                         }
1103                 }
1104         }
1105
1106         mesh->compute_bounds();
1107 }
1108
1109 CCL_NAMESPACE_END