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