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