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