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