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