Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/cycles/blender/blender_curves.cpp')
-rw-r--r--intern/cycles/blender/blender_curves.cpp1130
1 files changed, 1130 insertions, 0 deletions
diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp
new file mode 100644
index 00000000000..4fad7d45162
--- /dev/null
+++ b/intern/cycles/blender/blender_curves.cpp
@@ -0,0 +1,1130 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "attribute.h"
+#include "mesh.h"
+#include "object.h"
+#include "scene.h"
+#include "curves.h"
+
+#include "blender_sync.h"
+#include "blender_util.h"
+
+#include "util_foreach.h"
+
+CCL_NAMESPACE_BEGIN
+
+/* Utilities */
+
+/* Hair curve functions */
+
+void curveinterp_v3_v3v3v3v3(float3 *p, float3 *v1, float3 *v2, float3 *v3, float3 *v4, const float w[4]);
+void interp_weights(float t, float data[4], int type);
+float shaperadius(float shape, float root, float tip, float time);
+void InterpolateKeySegments(int seg, int segno, int key, int curve, float3 *keyloc, float *time, ParticleCurveData *CData, int interpolation);
+bool ObtainParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData);
+bool ObtainCacheParticleUV(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool use_parents);
+bool ObtainCacheParticleVcol(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool use_parents, int vcol_num);
+bool ObtainCacheParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool use_parents);
+void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, int interpolation, bool use_smooth, int segments, float3 RotCam);
+void ExportCurveTriangleRibbons(Mesh *mesh, ParticleCurveData *CData, int interpolation, bool use_smooth, int segments);
+void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int interpolation, bool use_smooth, int resolution, int segments);
+void ExportCurveSegments(Mesh *mesh, ParticleCurveData *CData, int interpolation, int segments);
+void ExportCurveTriangleUVs(Mesh *mesh, ParticleCurveData *CData, int interpolation, bool use_smooth, int segments, int vert_offset, int resol);
+
+ParticleCurveData::ParticleCurveData()
+{
+}
+
+ParticleCurveData::~ParticleCurveData()
+{
+ psys_firstcurve.clear();
+ psys_curvenum.clear();
+ psys_shader.clear();
+ psys_rootradius.clear();
+ psys_tipradius.clear();
+ psys_shape.clear();
+
+ curve_firstkey.clear();
+ curve_keynum.clear();
+ curve_length.clear();
+ curve_uv.clear();
+ curve_vcol.clear();
+
+ curvekey_co.clear();
+ curvekey_time.clear();
+}
+
+void interp_weights(float t, float data[4], int type)
+{
+ float t2, t3, fc;
+
+ if(type == CURVE_LINEAR) {
+ data[0] = 0.0f;
+ data[1] = -t + 1.0f;
+ data[2] = t;
+ data[3] = 0.0f;
+ }
+ else if(type == CURVE_CARDINAL) {
+ t2 = t * t;
+ t3 = t2 * t;
+ fc = 0.71f;
+
+ data[0] = -fc * t3 + 2.0f * fc * t2 - fc * t;
+ data[1] = (2.0f - fc) * t3 + (fc - 3.0f) * t2 + 1.0f;
+ data[2] = (fc - 2.0f) * t3 + (3.0f - 2.0f * fc) * t2 + fc * t;
+ data[3] = fc * t3 - fc * t2;
+ }
+ else if(type == CURVE_BSPLINE) {
+ t2 = t * t;
+ t3 = t2 * t;
+
+ data[0] = -0.16666666f * t3 + 0.5f * t2 - 0.5f * t + 0.16666666f;
+ data[1] = 0.5f * t3 - t2 + 0.66666666f;
+ data[2] = -0.5f * t3 + 0.5f * t2 + 0.5f * t + 0.16666666f;
+ data[3] = 0.16666666f * t3;
+ }
+}
+
+void curveinterp_v3_v3v3v3v3(float3 *p, float3 *v1, float3 *v2, float3 *v3, float3 *v4, const float w[4])
+{
+ p->x = v1->x * w[0] + v2->x * w[1] + v3->x * w[2] + v4->x * w[3];
+ p->y = v1->y * w[0] + v2->y * w[1] + v3->y * w[2] + v4->y * w[3];
+ p->z = v1->z * w[0] + v2->z * w[1] + v3->z * w[2] + v4->z * w[3];
+}
+
+float shaperadius(float shape, float root, float tip, float time)
+{
+ float radius = 1.0f - time;
+ if(shape != 0.0f) {
+ if(shape < 0.0f)
+ radius = (float)pow(1.0f - time, 1.f + shape);
+ else
+ radius = (float)pow(1.0f - time, 1.f / (1.f - shape));
+ }
+ return (radius * (root - tip)) + tip;
+}
+
+/* curve functions */
+
+void InterpolateKeySegments(int seg, int segno, int key, int curve, float3 *keyloc, float *time, ParticleCurveData *CData, int interpolation)
+{
+ float3 ckey_loc1 = CData->curvekey_co[key];
+ float3 ckey_loc2 = ckey_loc1;
+ float3 ckey_loc3 = CData->curvekey_co[key+1];
+ float3 ckey_loc4 = ckey_loc3;
+
+ if(key > CData->curve_firstkey[curve])
+ ckey_loc1 = CData->curvekey_co[key - 1];
+
+ if(key < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2)
+ ckey_loc4 = CData->curvekey_co[key + 2];
+
+
+ float time1 = CData->curvekey_time[key]/CData->curve_length[curve];
+ float time2 = CData->curvekey_time[key + 1]/CData->curve_length[curve];
+
+ float dfra = (time2 - time1) / (float)segno;
+
+ if(time)
+ *time = (dfra * seg) + time1;
+
+ float t[4];
+
+ interp_weights((float)seg / (float)segno, t, interpolation);
+
+ if(keyloc)
+ curveinterp_v3_v3v3v3v3(keyloc, &ckey_loc1, &ckey_loc2, &ckey_loc3, &ckey_loc4, t);
+}
+
+bool ObtainParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData)
+{
+
+ int curvenum = 0;
+ int keyno = 0;
+
+ if(!(mesh && b_mesh && b_ob && CData))
+ return false;
+
+ BL::Object::modifiers_iterator b_mod;
+ for(b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) {
+ if((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && (b_mod->show_viewport()) && (b_mod->show_render())) {
+
+ BL::ParticleSystemModifier psmd(b_mod->ptr);
+
+ BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr);
+
+ BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr);
+
+ if((b_psys.settings().render_type()==BL::ParticleSettings::render_type_PATH)&&(b_psys.settings().type()==BL::ParticleSettings::type_HAIR)) {
+
+ int mi = clamp(b_psys.settings().material()-1, 0, mesh->used_shaders.size()-1);
+ int shader = mesh->used_shaders[mi];
+
+ int totcurves = b_psys.particles.length();
+
+ if(totcurves == 0)
+ continue;
+
+ PointerRNA cpsys = RNA_pointer_get(&b_part.ptr, "cycles");
+
+ CData->psys_firstcurve.push_back(curvenum);
+ CData->psys_curvenum.push_back(totcurves);
+ CData->psys_shader.push_back(shader);
+
+ float radius = b_psys.settings().particle_size() * 0.5f;
+
+ CData->psys_rootradius.push_back(radius * get_float(cpsys, "root_width"));
+ CData->psys_tipradius.push_back(radius * get_float(cpsys, "tip_width"));
+ CData->psys_shape.push_back(get_float(cpsys, "shape"));
+ CData->psys_closetip.push_back(get_boolean(cpsys, "use_closetip"));
+
+ BL::ParticleSystem::particles_iterator b_pa;
+ for(b_psys.particles.begin(b_pa); b_pa != b_psys.particles.end(); ++b_pa) {
+ CData->curve_firstkey.push_back(keyno);
+
+ int keylength = b_pa->hair_keys.length();
+ CData->curve_keynum.push_back(keylength);
+
+ float curve_length = 0.0f;
+ float3 pcKey;
+ int step_no = 0;
+ BL::Particle::hair_keys_iterator b_cKey;
+ for(b_pa->hair_keys.begin(b_cKey); b_cKey != b_pa->hair_keys.end(); ++b_cKey) {
+ float nco[3];
+ b_cKey->co_object( *b_ob, psmd, *b_pa, nco);
+ float3 cKey = make_float3(nco[0],nco[1],nco[2]);
+ if(step_no > 0)
+ curve_length += len(cKey - pcKey);
+ CData->curvekey_co.push_back(cKey);
+ CData->curvekey_time.push_back(curve_length);
+ pcKey = cKey;
+ keyno++;
+ step_no++;
+ }
+
+ CData->curve_length.push_back(curve_length);
+ /*add uvs*/
+ BL::Mesh::tessface_uv_textures_iterator l;
+ b_mesh->tessface_uv_textures.begin(l);
+
+ float3 uv = make_float3(0.0f, 0.0f, 0.0f);
+ if(b_mesh->tessface_uv_textures.length())
+ b_pa->uv_on_emitter(psmd,&uv.x);
+ CData->curve_uv.push_back(uv);
+
+ curvenum++;
+
+ }
+ }
+ }
+ }
+
+ return true;
+
+}
+
+bool ObtainCacheParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool use_parents)
+{
+
+ int curvenum = 0;
+ int keyno = 0;
+
+ if(!(mesh && b_mesh && b_ob && CData))
+ return false;
+
+ Transform tfm = get_transform(b_ob->matrix_world());
+ Transform itfm = transform_quick_inverse(tfm);
+
+ BL::Object::modifiers_iterator b_mod;
+ for(b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) {
+ if((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && (b_mod->show_viewport()) && (b_mod->show_render())) {
+ BL::ParticleSystemModifier psmd((const PointerRNA)b_mod->ptr);
+
+ BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr);
+
+ BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr);
+
+ if((b_psys.settings().render_type()==BL::ParticleSettings::render_type_PATH)&&(b_psys.settings().type()==BL::ParticleSettings::type_HAIR)) {
+
+ int mi = clamp(b_psys.settings().material()-1, 0, mesh->used_shaders.size()-1);
+ int shader = mesh->used_shaders[mi];
+ int draw_step = b_psys.settings().draw_step();
+ int ren_step = (int)pow((float)2.0f,(float)draw_step);
+ /*b_psys.settings().render_step(draw_step);*/
+
+ int totparts = b_psys.particles.length();
+ int totchild = b_psys.child_particles.length() * b_psys.settings().draw_percentage() / 100;
+ int totcurves = totchild;
+
+ if(use_parents || b_psys.settings().child_type() == 0)
+ totcurves += totparts;
+
+ if(totcurves == 0)
+ continue;
+
+ PointerRNA cpsys = RNA_pointer_get(&b_part.ptr, "cycles");
+
+ CData->psys_firstcurve.push_back(curvenum);
+ CData->psys_curvenum.push_back(totcurves);
+ CData->psys_shader.push_back(shader);
+
+ float radius = b_psys.settings().particle_size() * 0.5f;
+
+ CData->psys_rootradius.push_back(radius * get_float(cpsys, "root_width"));
+ CData->psys_tipradius.push_back(radius * get_float(cpsys, "tip_width"));
+ CData->psys_shape.push_back(get_float(cpsys, "shape"));
+ CData->psys_closetip.push_back(get_boolean(cpsys, "use_closetip"));
+
+ int pa_no = 0;
+ if(!use_parents && !(b_psys.settings().child_type() == 0))
+ pa_no = totparts;
+
+ for(; pa_no < totparts+totchild; pa_no++) {
+
+ CData->curve_firstkey.push_back(keyno);
+ CData->curve_keynum.push_back(ren_step+1);
+
+ float curve_length = 0.0f;
+ float3 pcKey;
+ for(int step_no = 0; step_no <= ren_step; step_no++) {
+ float nco[3];
+ b_psys.co_hair(*b_ob, psmd, pa_no, step_no, nco);
+ float3 cKey = make_float3(nco[0],nco[1],nco[2]);
+ cKey = transform_point(&itfm, cKey);
+ if(step_no > 0)
+ curve_length += len(cKey - pcKey);
+ CData->curvekey_co.push_back(cKey);
+ CData->curvekey_time.push_back(curve_length);
+ pcKey = cKey;
+ keyno++;
+ }
+ CData->curve_length.push_back(curve_length);
+
+ curvenum++;
+
+ }
+ }
+
+ }
+ }
+
+ return true;
+
+}
+
+bool ObtainCacheParticleUV(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool use_parents)
+{
+ int keyno = 0;
+
+ if(!(mesh && b_mesh && b_ob && CData))
+ return false;
+
+ Transform tfm = get_transform(b_ob->matrix_world());
+ Transform itfm = transform_quick_inverse(tfm);
+
+ BL::Object::modifiers_iterator b_mod;
+ for(b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) {
+ if ((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && (b_mod->show_viewport()) && (b_mod->show_render())) {
+ BL::ParticleSystemModifier psmd((const PointerRNA)b_mod->ptr);
+
+ BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr);
+
+ BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr);
+
+ if((b_psys.settings().render_type()==BL::ParticleSettings::render_type_PATH)&&(b_psys.settings().type()==BL::ParticleSettings::type_HAIR)) {
+
+ int mi = clamp(b_psys.settings().material()-1, 0, mesh->used_shaders.size()-1);
+ int shader = mesh->used_shaders[mi];
+ int draw_step = b_psys.settings().draw_step();
+ int ren_step = (int)pow((float)2.0f,(float)draw_step);
+ /*b_psys.settings().render_step(draw_step);*/
+
+ int totparts = b_psys.particles.length();
+ int totchild = b_psys.child_particles.length() * b_psys.settings().draw_percentage() / 100;
+ int totcurves = totchild;
+
+ if (use_parents || b_psys.settings().child_type() == 0)
+ totcurves += totparts;
+
+ if (totcurves == 0)
+ continue;
+
+ int pa_no = 0;
+ if(!use_parents && !(b_psys.settings().child_type() == 0))
+ pa_no = totparts;
+
+ BL::ParticleSystem::particles_iterator b_pa;
+ b_psys.particles.begin(b_pa);
+ for(; pa_no < totparts+totchild; pa_no++) {
+
+ /*add uvs*/
+ BL::Mesh::tessface_uv_textures_iterator l;
+ b_mesh->tessface_uv_textures.begin(l);
+
+ float3 uv = make_float3(0.0f, 0.0f, 0.0f);
+ if(b_mesh->tessface_uv_textures.length())
+ b_psys.uv_on_emitter(psmd, *b_pa, pa_no, &uv.x);
+ CData->curve_uv.push_back(uv);
+
+ if(pa_no < totparts && b_pa != b_psys.particles.end())
+ ++b_pa;
+
+ }
+ }
+
+ }
+ }
+
+ return true;
+
+}
+
+bool ObtainCacheParticleVcol(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool use_parents, int vcol_num)
+{
+ int keyno = 0;
+
+ if(!(mesh && b_mesh && b_ob && CData))
+ return false;
+
+ Transform tfm = get_transform(b_ob->matrix_world());
+ Transform itfm = transform_quick_inverse(tfm);
+
+ BL::Object::modifiers_iterator b_mod;
+ for(b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) {
+ if ((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && (b_mod->show_viewport()) && (b_mod->show_render())) {
+ BL::ParticleSystemModifier psmd((const PointerRNA)b_mod->ptr);
+
+ BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr);
+
+ BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr);
+
+ if((b_psys.settings().render_type()==BL::ParticleSettings::render_type_PATH)&&(b_psys.settings().type()==BL::ParticleSettings::type_HAIR)) {
+
+ int mi = clamp(b_psys.settings().material()-1, 0, mesh->used_shaders.size()-1);
+ int shader = mesh->used_shaders[mi];
+ int draw_step = b_psys.settings().draw_step();
+ int ren_step = (int)pow((float)2.0f,(float)draw_step);
+ /*b_psys.settings().render_step(draw_step);*/
+
+ int totparts = b_psys.particles.length();
+ int totchild = b_psys.child_particles.length() * b_psys.settings().draw_percentage() / 100;
+ int totcurves = totchild;
+
+ if (use_parents || b_psys.settings().child_type() == 0)
+ totcurves += totparts;
+
+ if (totcurves == 0)
+ continue;
+
+ int pa_no = 0;
+ if(!use_parents && !(b_psys.settings().child_type() == 0))
+ pa_no = totparts;
+
+ BL::ParticleSystem::particles_iterator b_pa;
+ b_psys.particles.begin(b_pa);
+ for(; pa_no < totparts+totchild; pa_no++) {
+
+ /*add uvs*/
+ BL::Mesh::tessface_vertex_colors_iterator l;
+ b_mesh->tessface_vertex_colors.begin(l);
+
+ float3 vcol = make_float3(0.0f, 0.0f, 0.0f);
+ if(b_mesh->tessface_vertex_colors.length())
+ b_psys.mcol_on_emitter(psmd, *b_pa, pa_no, vcol_num, &vcol.x);
+ CData->curve_vcol.push_back(vcol);
+
+ if(pa_no < totparts && b_pa != b_psys.particles.end())
+ ++b_pa;
+
+ }
+ }
+
+ }
+ }
+
+ return true;
+
+}
+
+void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, int interpolation, bool use_smooth, int segments, float3 RotCam)
+{
+ int vertexno = mesh->verts.size();
+ int vertexindex = vertexno;
+
+ for( int sys = 0; sys < CData->psys_firstcurve.size() ; sys++) {
+ for( int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys] ; curve++) {
+
+ for( int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) {
+
+ int subv = 1;
+ float3 xbasis;
+
+ float3 v1;
+
+ if(curvekey == CData->curve_firstkey[curve]) {
+ subv = 0;
+ v1 = CData->curvekey_co[min(curvekey+2,CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)] - CData->curvekey_co[curvekey];
+ }
+ else if(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)
+ v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[max(curvekey - 2, CData->curve_firstkey[curve])];
+ else
+ v1 = CData->curvekey_co[curvekey + 1] - CData->curvekey_co[curvekey - 1];
+
+
+ for (; subv <= segments; subv++) {
+
+ float3 ickey_loc = make_float3(0.0f,0.0f,0.0f);
+ float time = 0.0f;
+
+ if ((interpolation == CURVE_BSPLINE) && (curvekey == CData->curve_firstkey[curve]) && (subv == 0))
+ ickey_loc = CData->curvekey_co[curvekey];
+ else
+ InterpolateKeySegments(subv, segments, curvekey, curve, &ickey_loc, &time, CData , interpolation);
+
+ float radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], time);
+
+ if(CData->psys_closetip[sys] && (subv == segments) && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1))
+ radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], 0.0f, 0.95f);
+
+ if((curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1) && (subv == segments))
+ radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], 0.95f);
+
+ xbasis = normalize(cross(v1,RotCam - ickey_loc));
+ float3 ickey_loc_shfl = ickey_loc - radius * xbasis;
+ float3 ickey_loc_shfr = ickey_loc + radius * xbasis;
+ mesh->verts.push_back(ickey_loc_shfl);
+ mesh->verts.push_back(ickey_loc_shfr);
+ if(subv!=0) {
+ mesh->add_triangle(vertexindex-2, vertexindex, vertexindex-1, CData->psys_shader[sys], use_smooth);
+ mesh->add_triangle(vertexindex+1, vertexindex-1, vertexindex, CData->psys_shader[sys], use_smooth);
+ }
+ vertexindex += 2;
+ }
+ }
+ }
+ }
+
+ mesh->reserve(mesh->verts.size(), mesh->triangles.size(), 0, 0);
+ mesh->attributes.remove(ATTR_STD_VERTEX_NORMAL);
+ mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
+ mesh->add_face_normals();
+ mesh->add_vertex_normals();
+ mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
+
+ /* texture coords still needed */
+}
+
+void ExportCurveTriangleRibbons(Mesh *mesh, ParticleCurveData *CData, int interpolation, bool use_smooth, int segments)
+{
+ int vertexno = mesh->verts.size();
+ int vertexindex = vertexno;
+
+ for( int sys = 0; sys < CData->psys_firstcurve.size() ; sys++) {
+ for( int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys] ; curve++) {
+
+ float3 firstxbasis = cross(make_float3(1.0f,0.0f,0.0f),CData->curvekey_co[CData->curve_firstkey[curve]+1] - CData->curvekey_co[CData->curve_firstkey[curve]]);
+ if(len_squared(firstxbasis)!= 0.0f)
+ firstxbasis = normalize(firstxbasis);
+ else
+ firstxbasis = normalize(cross(make_float3(0.0f,1.0f,0.0f),CData->curvekey_co[CData->curve_firstkey[curve]+1] - CData->curvekey_co[CData->curve_firstkey[curve]]));
+
+ for( int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) {
+
+ float3 xbasis = firstxbasis;
+ float3 v1;
+ float3 v2;
+
+ if(curvekey == CData->curve_firstkey[curve]) {
+ v1 = CData->curvekey_co[min(curvekey+2,CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)] - CData->curvekey_co[curvekey+1];
+ v2 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
+ }
+ else if(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1) {
+ v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
+ v2 = CData->curvekey_co[curvekey-1] - CData->curvekey_co[max(curvekey-2,CData->curve_firstkey[curve])];
+ }
+ else {
+ v1 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
+ v2 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
+ }
+
+ xbasis = cross(v1,v2);
+
+ if(len_squared(xbasis) >= 0.05f * len_squared(v1) * len_squared(v2)) {
+ firstxbasis = normalize(xbasis);
+ break;
+ }
+ }
+
+ for( int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) {
+
+ int subv = 1;
+ float3 v1;
+ float3 v2;
+ float3 xbasis;
+
+ if(curvekey == CData->curve_firstkey[curve]) {
+ subv = 0;
+ v1 = CData->curvekey_co[min(curvekey+2,CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)] - CData->curvekey_co[curvekey+1];
+ v2 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
+ }
+ else if(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1) {
+ v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
+ v2 = CData->curvekey_co[curvekey-1] - CData->curvekey_co[max(curvekey-2,CData->curve_firstkey[curve])];
+ }
+ else {
+ v1 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
+ v2 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
+ }
+
+ xbasis = cross(v1,v2);
+
+ if(len_squared(xbasis) >= 0.05f * len_squared(v1) * len_squared(v2)) {
+ xbasis = normalize(xbasis);
+ firstxbasis = xbasis;
+ }
+ else
+ xbasis = firstxbasis;
+
+ for (; subv <= segments; subv++) {
+
+ float3 ickey_loc = make_float3(0.0f,0.0f,0.0f);
+ float time = 0.0f;
+
+ if ((interpolation == CURVE_BSPLINE) && (curvekey == CData->curve_firstkey[curve]) && (subv == 0))
+ ickey_loc = CData->curvekey_co[curvekey];
+ else
+ InterpolateKeySegments(subv, segments, curvekey, curve, &ickey_loc, &time, CData , interpolation);
+
+ float radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], time);
+
+ if(CData->psys_closetip[sys] && (subv == segments) && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1))
+ radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], 0.0f, 0.95f);
+
+ if((curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1) && (subv == segments))
+ radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], 0.95f);
+
+ float3 ickey_loc_shfl = ickey_loc - radius * xbasis;
+ float3 ickey_loc_shfr = ickey_loc + radius * xbasis;
+ mesh->verts.push_back(ickey_loc_shfl);
+ mesh->verts.push_back(ickey_loc_shfr);
+ if(subv!=0) {
+ mesh->add_triangle(vertexindex-2, vertexindex, vertexindex-1, CData->psys_shader[sys], use_smooth);
+ mesh->add_triangle(vertexindex+1, vertexindex-1, vertexindex, CData->psys_shader[sys], use_smooth);
+ }
+ vertexindex += 2;
+ }
+ }
+ }
+ }
+
+ mesh->reserve(mesh->verts.size(), mesh->triangles.size(), 0, 0);
+ mesh->attributes.remove(ATTR_STD_VERTEX_NORMAL);
+ mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
+ mesh->add_face_normals();
+ mesh->add_vertex_normals();
+ mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
+ /* texture coords still needed */
+
+}
+
+void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int interpolation, bool use_smooth, int resolution, int segments)
+{
+ int vertexno = mesh->verts.size();
+ int vertexindex = vertexno;
+
+ for( int sys = 0; sys < CData->psys_firstcurve.size() ; sys++) {
+ for( int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys] ; curve++) {
+
+ float3 firstxbasis = cross(make_float3(1.0f,0.0f,0.0f),CData->curvekey_co[CData->curve_firstkey[curve]+1] - CData->curvekey_co[CData->curve_firstkey[curve]]);
+ if(len_squared(firstxbasis)!= 0.0f)
+ firstxbasis = normalize(firstxbasis);
+ else
+ firstxbasis = normalize(cross(make_float3(0.0f,1.0f,0.0f),CData->curvekey_co[CData->curve_firstkey[curve]+1] - CData->curvekey_co[CData->curve_firstkey[curve]]));
+
+
+ for( int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) {
+
+ float3 xbasis = firstxbasis;
+ float3 v1;
+ float3 v2;
+
+ if(curvekey == CData->curve_firstkey[curve]) {
+ v1 = CData->curvekey_co[min(curvekey+2,CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)] - CData->curvekey_co[curvekey+1];
+ v2 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
+ }
+ else if(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1) {
+ v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
+ v2 = CData->curvekey_co[curvekey-1] - CData->curvekey_co[max(curvekey-2,CData->curve_firstkey[curve])];
+ }
+ else {
+ v1 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
+ v2 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
+ }
+
+ xbasis = cross(v1,v2);
+
+ if(len_squared(xbasis) >= 0.05f * len_squared(v1) * len_squared(v2)) {
+ firstxbasis = normalize(xbasis);
+ break;
+ }
+ }
+
+ for( int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) {
+
+ int subv = 1;
+ float3 xbasis;
+ float3 ybasis;
+ float3 v1;
+ float3 v2;
+
+ if(curvekey == CData->curve_firstkey[curve]) {
+ subv = 0;
+ v1 = CData->curvekey_co[min(curvekey+2,CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)] - CData->curvekey_co[curvekey+1];
+ v2 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
+ }
+ else if(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1) {
+ v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
+ v2 = CData->curvekey_co[curvekey-1] - CData->curvekey_co[max(curvekey-2,CData->curve_firstkey[curve])];
+ }
+ else {
+ v1 = CData->curvekey_co[curvekey+1] - CData->curvekey_co[curvekey];
+ v2 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1];
+ }
+
+ xbasis = cross(v1,v2);
+
+ if(len_squared(xbasis) >= 0.05f * len_squared(v1) * len_squared(v2)) {
+ xbasis = normalize(xbasis);
+ firstxbasis = xbasis;
+ }
+ else
+ xbasis = firstxbasis;
+
+ ybasis = normalize(cross(xbasis,v2));
+
+ for (; subv <= segments; subv++) {
+
+ float3 ickey_loc = make_float3(0.0f,0.0f,0.0f);
+ float time = 0.0f;
+
+ if ((interpolation == CURVE_BSPLINE) && (curvekey == CData->curve_firstkey[curve]) && (subv == 0))
+ ickey_loc = CData->curvekey_co[curvekey];
+ else
+ InterpolateKeySegments(subv, segments, curvekey, curve, &ickey_loc, &time, CData , interpolation);
+
+ float radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], time);
+
+ if(CData->psys_closetip[sys] && (subv == segments) && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1))
+ radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], 0.0f, 0.95f);
+
+ if((curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1) && (subv == segments))
+ radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], 0.95f);
+
+ float angle = 2 * M_PI_F / (float)resolution;
+ for(int section = 0 ; section < resolution; section++) {
+ float3 ickey_loc_shf = ickey_loc + radius * (cosf(angle * section) * xbasis + sinf(angle * section) * ybasis);
+ mesh->verts.push_back(ickey_loc_shf);
+ }
+
+ if(subv!=0) {
+ for(int section = 0 ; section < resolution - 1; section++) {
+ mesh->add_triangle(vertexindex - resolution + section, vertexindex + section, vertexindex - resolution + section + 1, CData->psys_shader[sys], use_smooth);
+ mesh->add_triangle(vertexindex + section + 1, vertexindex - resolution + section + 1, vertexindex + section, CData->psys_shader[sys], use_smooth);
+ }
+ mesh->add_triangle(vertexindex-1, vertexindex + resolution - 1, vertexindex - resolution, CData->psys_shader[sys], use_smooth);
+ mesh->add_triangle(vertexindex, vertexindex - resolution , vertexindex + resolution - 1, CData->psys_shader[sys], use_smooth);
+ }
+ vertexindex += resolution;
+ }
+ }
+ }
+ }
+
+ mesh->reserve(mesh->verts.size(), mesh->triangles.size(), 0, 0);
+ mesh->attributes.remove(ATTR_STD_VERTEX_NORMAL);
+ mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
+ mesh->add_face_normals();
+ mesh->add_vertex_normals();
+ mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
+
+ /* texture coords still needed */
+}
+
+static void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CData, int interpolation, int segments)
+{
+ int num_keys = 0;
+ int num_curves = 0;
+
+ if(!(mesh->curves.empty() && mesh->curve_keys.empty()))
+ return;
+
+ Attribute *attr_uv = NULL, *attr_intercept = NULL;
+
+ if(mesh->need_attribute(scene, ATTR_STD_UV))
+ attr_uv = mesh->curve_attributes.add(ATTR_STD_UV);
+ if(mesh->need_attribute(scene, ATTR_STD_CURVE_INTERCEPT))
+ attr_intercept = mesh->curve_attributes.add(ATTR_STD_CURVE_INTERCEPT);
+
+ for( int sys = 0; sys < CData->psys_firstcurve.size() ; sys++) {
+
+ if(CData->psys_curvenum[sys] == 0)
+ continue;
+
+ for( int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys] ; curve++) {
+
+ if(CData->curve_keynum[curve] <= 1)
+ continue;
+
+ size_t num_curve_keys = 0;
+
+ for( int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) {
+
+ int subv = 1;
+ if(curvekey == CData->curve_firstkey[curve])
+ subv = 0;
+
+ for (; subv <= segments; subv++) {
+
+ float3 ickey_loc = make_float3(0.0f,0.0f,0.0f);
+ float time = 0.0f;
+
+ if((interpolation == CURVE_BSPLINE) && (curvekey == CData->curve_firstkey[curve]) && (subv == 0))
+ ickey_loc = CData->curvekey_co[curvekey];
+ else
+ InterpolateKeySegments(subv, segments, curvekey, curve, &ickey_loc, &time, CData , interpolation);
+
+ float radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], time);
+
+ if(CData->psys_closetip[sys] && (subv == segments) && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2))
+ radius =0.0f;
+
+ mesh->add_curve_key(ickey_loc, radius);
+ if(attr_intercept)
+ attr_intercept->add(time);
+
+ num_curve_keys++;
+ }
+ }
+
+ mesh->add_curve(num_keys, num_curve_keys, CData->psys_shader[sys]);
+ if(attr_uv)
+ attr_uv->add(CData->curve_uv[curve]);
+
+ num_keys += num_curve_keys;
+ num_curves++;
+ }
+ }
+
+ /* check allocation*/
+ if((mesh->curve_keys.size() != num_keys) || (mesh->curves.size() != num_curves)) {
+ /* allocation failed -> clear data */
+ mesh->curve_keys.clear();
+ mesh->curves.clear();
+ mesh->curve_attributes.clear();
+ }
+}
+
+void ExportCurveTriangleUVs(Mesh *mesh, ParticleCurveData *CData, int interpolation, bool use_smooth, int segments, int vert_offset, int resol)
+{
+ float time = 0.0f;
+ float prevtime = 0.0f;
+
+ Attribute *attr = mesh->attributes.find(ATTR_STD_UV);
+ if (attr == NULL)
+ return;
+
+ float3 *uvdata = attr->data_float3();
+
+ int vertexindex = vert_offset;
+
+ for( int sys = 0; sys < CData->psys_firstcurve.size() ; sys++) {
+ for( int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys] ; curve++) {
+
+ for( int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1; curvekey++) {
+
+ int subv = 1;
+
+ if (curvekey == CData->curve_firstkey[curve])
+ subv = 0;
+
+ for (; subv <= segments; subv++) {
+
+ float3 ickey_loc = make_float3(0.0f,0.0f,0.0f);
+
+ InterpolateKeySegments(subv, segments, curvekey, curve, &ickey_loc, &time, CData , interpolation);
+
+ if(subv!=0) {
+ for(int section = 0 ; section < resol; section++) {
+ uvdata[vertexindex] = CData->curve_uv[curve];
+ uvdata[vertexindex].z = prevtime;
+ vertexindex++;
+ uvdata[vertexindex] = CData->curve_uv[curve];
+ uvdata[vertexindex].z = time;
+ vertexindex++;
+ uvdata[vertexindex] = CData->curve_uv[curve];
+ uvdata[vertexindex].z = prevtime;
+ vertexindex++;
+ uvdata[vertexindex] = CData->curve_uv[curve];
+ uvdata[vertexindex].z = time;
+ vertexindex++;
+ uvdata[vertexindex] = CData->curve_uv[curve];
+ uvdata[vertexindex].z = prevtime;
+ vertexindex++;
+ uvdata[vertexindex] = CData->curve_uv[curve];
+ uvdata[vertexindex].z = time;
+ vertexindex++;
+ }
+ }
+
+ prevtime = time;
+ }
+ }
+ }
+ }
+
+}
+/* Hair Curve Sync */
+
+void BlenderSync::sync_curve_settings()
+{
+ PointerRNA csscene = RNA_pointer_get(&b_scene.ptr, "cycles_curves");
+
+ int preset = get_enum(csscene, "preset");
+
+ CurveSystemManager *curve_system_manager = scene->curve_system_manager;
+ CurveSystemManager prev_curve_system_manager = *curve_system_manager;
+
+ curve_system_manager->use_curves = get_boolean(csscene, "use_curves");
+
+ if(preset == CURVE_CUSTOM) {
+ /*custom properties*/
+ curve_system_manager->primitive = get_enum(csscene, "primitive");
+ curve_system_manager->line_method = get_enum(csscene, "line_method");
+ curve_system_manager->interpolation = get_enum(csscene, "interpolation");
+ curve_system_manager->triangle_method = get_enum(csscene, "triangle_method");
+ curve_system_manager->resolution = get_int(csscene, "resolution");
+ curve_system_manager->segments = get_int(csscene, "segments");
+ curve_system_manager->use_smooth = get_boolean(csscene, "use_smooth");
+
+ curve_system_manager->normalmix = get_float(csscene, "normalmix");
+ curve_system_manager->encasing_ratio = get_float(csscene, "encasing_ratio");
+
+ curve_system_manager->use_cache = get_boolean(csscene, "use_cache");
+ curve_system_manager->use_parents = get_boolean(csscene, "use_parents");
+ curve_system_manager->use_encasing = get_boolean(csscene, "use_encasing");
+ curve_system_manager->use_backfacing = get_boolean(csscene, "use_backfacing");
+ curve_system_manager->use_joined = get_boolean(csscene, "use_joined");
+ curve_system_manager->use_tangent_normal = get_boolean(csscene, "use_tangent_normal");
+ curve_system_manager->use_tangent_normal_geometry = get_boolean(csscene, "use_tangent_normal_geometry");
+ curve_system_manager->use_tangent_normal_correction = get_boolean(csscene, "use_tangent_normal_correction");
+ }
+ else {
+ curve_system_manager->primitive = CURVE_LINE_SEGMENTS;
+ curve_system_manager->interpolation = CURVE_CARDINAL;
+ curve_system_manager->normalmix = 1.0f;
+ curve_system_manager->encasing_ratio = 1.01f;
+ curve_system_manager->use_cache = true;
+ curve_system_manager->use_parents = false;
+ curve_system_manager->segments = 1;
+ curve_system_manager->use_joined = false;
+
+ switch(preset) {
+ case CURVE_TANGENT_SHADING:
+ /*tangent shading*/
+ curve_system_manager->line_method = CURVE_UNCORRECTED;
+ curve_system_manager->use_encasing = true;
+ curve_system_manager->use_backfacing = false;
+ curve_system_manager->use_tangent_normal = true;
+ curve_system_manager->use_tangent_normal_geometry = true;
+ curve_system_manager->use_tangent_normal_correction = false;
+ break;
+ case CURVE_TRUE_NORMAL:
+ /*True Normal*/
+ curve_system_manager->line_method = CURVE_CORRECTED;
+ curve_system_manager->use_encasing = true;
+ curve_system_manager->use_backfacing = false;
+ curve_system_manager->use_tangent_normal = false;
+ curve_system_manager->use_tangent_normal_geometry = false;
+ curve_system_manager->use_tangent_normal_correction = false;
+ break;
+ case CURVE_ACCURATE_PRESET:
+ /*Accurate*/
+ curve_system_manager->line_method = CURVE_ACCURATE;
+ curve_system_manager->use_encasing = false;
+ curve_system_manager->use_backfacing = true;
+ curve_system_manager->use_tangent_normal = false;
+ curve_system_manager->use_tangent_normal_geometry = false;
+ curve_system_manager->use_tangent_normal_correction = false;
+ break;
+ }
+
+ }
+
+ if(curve_system_manager->modified_mesh(prev_curve_system_manager))
+ {
+ BL::BlendData::objects_iterator b_ob;
+
+ for(b_data.objects.begin(b_ob); b_ob != b_data.objects.end(); ++b_ob) {
+ if(object_is_mesh(*b_ob)) {
+ BL::Object::particle_systems_iterator b_psys;
+ for(b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys) {
+ if((b_psys->settings().render_type()==BL::ParticleSettings::render_type_PATH)&&(b_psys->settings().type()==BL::ParticleSettings::type_HAIR)) {
+ BL::ID key = BKE_object_is_modified(*b_ob)? *b_ob: b_ob->data();
+ mesh_map.set_recalc(key);
+ object_map.set_recalc(*b_ob);
+ }
+ }
+ }
+ }
+ }
+
+ if(curve_system_manager->modified(prev_curve_system_manager))
+ curve_system_manager->tag_update(scene);
+
+}
+
+void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool object_updated)
+{
+ /* Clear stored curve data */
+ mesh->curve_keys.clear();
+ mesh->curves.clear();
+ mesh->curve_attributes.clear();
+
+ /* obtain general settings */
+ bool use_curves = scene->curve_system_manager->use_curves;
+
+ if(!(use_curves && b_ob.mode() == b_ob.mode_OBJECT)) {
+ mesh->compute_bounds();
+ return;
+ }
+
+ int primitive = scene->curve_system_manager->primitive;
+ int interpolation = scene->curve_system_manager->interpolation;
+ int triangle_method = scene->curve_system_manager->triangle_method;
+ int resolution = scene->curve_system_manager->resolution;
+ int segments = scene->curve_system_manager->segments;
+ bool use_smooth = scene->curve_system_manager->use_smooth;
+ bool use_cache = scene->curve_system_manager->use_cache;
+ bool use_parents = scene->curve_system_manager->use_parents;
+ bool export_tgs = scene->curve_system_manager->use_joined;
+
+ /* extract particle hair data - should be combined with connecting to mesh later*/
+
+ ParticleCurveData CData;
+
+ if(use_cache) {
+ ObtainCacheParticleData(mesh, &b_mesh, &b_ob, &CData, use_parents);
+ ObtainCacheParticleUV(mesh, &b_mesh, &b_ob, &CData, use_parents);
+ }
+ else
+ ObtainParticleData(mesh, &b_mesh, &b_ob, &CData);
+
+ /* attach strands to mesh */
+ BL::Object b_CamOb = b_scene.camera();
+ float3 RotCam = make_float3(0.0f, 0.0f, 0.0f);
+ if(b_CamOb) {
+ Transform ctfm = get_transform(b_CamOb.matrix_world());
+ Transform tfm = get_transform(b_ob.matrix_world());
+ Transform itfm = transform_quick_inverse(tfm);
+ RotCam = transform_point(&itfm, make_float3(ctfm.x.w, ctfm.y.w, ctfm.z.w));
+ }
+
+ if(primitive == CURVE_TRIANGLES){
+ int vert_num = mesh->triangles.size() * 3;
+ if(triangle_method == CURVE_CAMERA) {
+ ExportCurveTrianglePlanes(mesh, &CData, interpolation, use_smooth, segments, RotCam);
+ ExportCurveTriangleUVs(mesh, &CData, interpolation, use_smooth, segments, vert_num, 1);
+ }
+ else if(triangle_method == CURVE_RIBBONS) {
+ ExportCurveTriangleRibbons(mesh, &CData, interpolation, use_smooth, segments);
+ ExportCurveTriangleUVs(mesh, &CData, interpolation, use_smooth, segments, vert_num, 1);
+ }
+ else {
+ ExportCurveTriangleGeometry(mesh, &CData, interpolation, use_smooth, resolution, segments);
+ ExportCurveTriangleUVs(mesh, &CData, interpolation, use_smooth, segments, vert_num, resolution);
+ }
+
+ }
+ else {
+ ExportCurveSegments(scene, mesh, &CData, interpolation, segments);
+ int ckey_num = mesh->curve_keys.size();
+
+ /*export tangents or curve data? - not functional yet*/
+ if(export_tgs && ckey_num > 1) {
+ Attribute *attr_tangent = mesh->curve_attributes.add(ATTR_STD_CURVE_TANGENT);
+ float3 *data_tangent = attr_tangent->data_float3();
+
+ for(int ck = 0; ck < ckey_num; ck++) {
+ float3 tg = normalize(normalize(mesh->curve_keys[min(ck + 1, ckey_num - 1)].co - mesh->curve_keys[ck].co) -
+ normalize(mesh->curve_keys[max(ck - 1, 0)].co - mesh->curve_keys[ck].co));
+
+ data_tangent[ck] = tg;
+ }
+ }
+
+ /* generated coordinates from first key. we should ideally get this from
+ * blender to handle deforming objects */
+ if(mesh->need_attribute(scene, ATTR_STD_GENERATED)) {
+ float3 loc, size;
+ mesh_texture_space(b_mesh, loc, size);
+
+ Attribute *attr_generated = mesh->curve_attributes.add(ATTR_STD_GENERATED);
+ float3 *generated = attr_generated->data_float3();
+ size_t i = 0;
+
+ foreach(Mesh::Curve& curve, mesh->curves) {
+ float3 co = mesh->curve_keys[curve.first_key].co;
+ generated[i++] = co*size - loc;
+ }
+ }
+
+ /* create vertex color attributes */
+ BL::Mesh::tessface_vertex_colors_iterator l;
+ int vcol_num = 0;
+
+ for(b_mesh.tessface_vertex_colors.begin(l); l != b_mesh.tessface_vertex_colors.end(); ++l, vcol_num++) {
+ if(!mesh->need_attribute(scene, ustring(l->name().c_str())))
+ continue;
+
+ /*error occurs with more than one vertex colour attribute so avoided*/
+ if(vcol_num!=0)
+ break;
+
+ Attribute *attr_vcol = mesh->curve_attributes.add(
+ ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CURVE);
+
+ ObtainCacheParticleVcol(mesh, &b_mesh, &b_ob, &CData, use_parents, 0);
+
+ float3 *vcol = attr_vcol->data_float3();
+
+ if(vcol) {
+ for(size_t curve = 0; curve < CData.curve_vcol.size() ;curve++)
+ vcol[curve] = color_srgb_to_scene_linear(CData.curve_vcol[curve]);
+ }
+
+ }
+
+ }
+
+ mesh->compute_bounds();
+}
+
+
+CCL_NAMESPACE_END
+