diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2013-01-03 16:08:54 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2013-01-03 16:08:54 +0400 |
commit | 57cf48e7c6fd04f864072c21433a822907774f78 (patch) | |
tree | 45f3fa51f532a03e25c4d8ffa0c1be58027d01b2 /intern/cycles/blender/blender_curves.cpp | |
parent | 8ca977b16e745f716d044a5b6ccbb5be4a70ac94 (diff) |
Cycles Hair: refactoring to support generic attributes for hair curves. There
should be no functional changes yet. UV, tangent and intercept are now stored
as attributes, with the intention to add more like multiple uv's, vertex
colors, generated coordinates and motion vectors later.
Things got a bit messy due to having both triangle and curve data in the same
mesh data structure, which also gives us two sets of attributes. This will get
cleaned up when we split the mesh class.
Diffstat (limited to 'intern/cycles/blender/blender_curves.cpp')
-rw-r--r-- | intern/cycles/blender/blender_curves.cpp | 160 |
1 files changed, 79 insertions, 81 deletions
diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp index 68b5d18a093..61628aae535 100644 --- a/intern/cycles/blender/blender_curves.cpp +++ b/intern/cycles/blender/blender_curves.cpp @@ -67,8 +67,7 @@ ParticleCurveData::~ParticleCurveData() curve_firstkey.clear(); curve_keynum.clear(); curve_length.clear(); - curve_u.clear(); - curve_v.clear(); + curve_uv.clear(); curvekey_co.clear(); curvekey_time.clear(); @@ -78,13 +77,13 @@ void interp_weights(float t, float data[4], int type) { float t2, t3, fc; - if (type == CURVE_LINEAR) { + 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) { + else if(type == CURVE_CARDINAL) { t2 = t * t; t3 = t2 * t; fc = 0.71f; @@ -94,7 +93,7 @@ void interp_weights(float t, float data[4], int type) 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) { + else if(type == CURVE_BSPLINE) { t2 = t * t; t3 = t2 * t; @@ -115,8 +114,8 @@ void curveinterp_v3_v3v3v3v3(float3 *p, float3 *v1, float3 *v2, float3 *v3, floa float shaperadius(float shape, float root, float tip, float time) { float radius = 1.0f - time; - if (shape != 0.0f) { - if (shape < 0.0f) + 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)); @@ -133,10 +132,10 @@ void InterpolateKeySegments(int seg, int segno, int key, int curve, float3 *keyl float3 ckey_loc3 = CData->curvekey_co[key+1]; float3 ckey_loc4 = ckey_loc3; - if (key > CData->curve_firstkey[curve]) + if(key > CData->curve_firstkey[curve]) ckey_loc1 = CData->curvekey_co[key - 1]; - if (key < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) + if(key < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) ckey_loc4 = CData->curvekey_co[key + 2]; @@ -167,7 +166,7 @@ bool ObtainParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Particle 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())) { + if((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && (b_mod->show_viewport()) && (b_mod->show_render())) { BL::ParticleSystemModifier psmd(b_mod->ptr); @@ -213,7 +212,7 @@ bool ObtainParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Particle 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) + if(step_no > 0) curve_length += len(cKey - pcKey); CData->curvekey_co.push_back(cKey); CData->curvekey_time.push_back(curve_length); @@ -227,11 +226,10 @@ bool ObtainParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Particle BL::Mesh::tessface_uv_textures_iterator l; b_mesh->tessface_uv_textures.begin(l); - float uvs[3] = {0,0}; + float3 uv = make_float3(0.0f, 0.0f, 0.0f); if(b_mesh->tessface_uv_textures.length()) - b_pa->uv_on_emitter(psmd,uvs); - CData->curve_u.push_back(uvs[0]); - CData->curve_v.push_back(uvs[1]); + b_pa->uv_on_emitter(psmd,&uv.x); + CData->curve_uv.push_back(uv); curvenum++; @@ -258,7 +256,7 @@ bool ObtainCacheParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Par 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())) { + 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); @@ -277,10 +275,10 @@ bool ObtainCacheParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Par 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) + if(use_parents || b_psys.settings().child_type() == 0) totcurves += totparts; - if (totcurves == 0) + if(totcurves == 0) continue; PointerRNA cpsys = RNA_pointer_get(&b_part.ptr, "cycles"); @@ -314,7 +312,7 @@ bool ObtainCacheParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Par 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) + if(step_no > 0) curve_length += len(cKey - pcKey); CData->curvekey_co.push_back(cKey); CData->curvekey_time.push_back(curve_length); @@ -327,17 +325,14 @@ bool ObtainCacheParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, Par BL::Mesh::tessface_uv_textures_iterator l; b_mesh->tessface_uv_textures.begin(l); - float uvs[2] = {0,0}; + 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, uvs); - + 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; - CData->curve_u.push_back(uvs[0]); - CData->curve_v.push_back(uvs[1]); - curvenum++; } @@ -365,11 +360,11 @@ void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, int interpo float3 v1; - if (curvekey == CData->curve_firstkey[curve]) { + if(curvekey == CData->curve_firstkey[curve]) { subv = 0; v1 = CData->curvekey_co[curvekey+2] - CData->curvekey_co[curvekey]; } - else if (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) + else if(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey - 2]; else v1 = CData->curvekey_co[curvekey + 1] - CData->curvekey_co[curvekey - 1]; @@ -387,10 +382,10 @@ void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, int interpo 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)) + if(CData->psys_closetip[sys] && (subv == segments) && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2)) radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], 0.0f, 0.95f); - if ((curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) && (subv == segments)) + if((curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) && (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)); @@ -408,7 +403,7 @@ void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, int interpo } } - mesh->reserve(mesh->verts.size(), mesh->triangles.size()); + 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(); @@ -439,11 +434,11 @@ void ExportCurveTriangleRibbons(Mesh *mesh, ParticleCurveData *CData, int interp float3 v1; float3 v2; - if (curvekey == CData->curve_firstkey[curve]) { + if(curvekey == CData->curve_firstkey[curve]) { v1 = CData->curvekey_co[curvekey+2] - 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] - 2) { + else if(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) { v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1]; v2 = CData->curvekey_co[curvekey-1] - CData->curvekey_co[curvekey-2]; } @@ -467,12 +462,12 @@ void ExportCurveTriangleRibbons(Mesh *mesh, ParticleCurveData *CData, int interp float3 v2; float3 xbasis; - if (curvekey == CData->curve_firstkey[curve]) { + if(curvekey == CData->curve_firstkey[curve]) { subv = 0; v1 = CData->curvekey_co[curvekey+2] - 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] - 2) { + else if(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) { v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1]; v2 = CData->curvekey_co[curvekey-1] - CData->curvekey_co[curvekey-2]; } @@ -502,10 +497,10 @@ void ExportCurveTriangleRibbons(Mesh *mesh, ParticleCurveData *CData, int interp 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)) + if(CData->psys_closetip[sys] && (subv == segments) && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2)) radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], 0.0f, 0.95f); - if ((curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) && (subv == segments)) + if((curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) && (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; @@ -522,7 +517,7 @@ void ExportCurveTriangleRibbons(Mesh *mesh, ParticleCurveData *CData, int interp } } - mesh->reserve(mesh->verts.size(), mesh->triangles.size()); + 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(); @@ -553,11 +548,11 @@ void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int inter float3 v1; float3 v2; - if (curvekey == CData->curve_firstkey[curve]) { + if(curvekey == CData->curve_firstkey[curve]) { v1 = CData->curvekey_co[curvekey+2] - 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] - 2) { + else if(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) { v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1]; v2 = CData->curvekey_co[curvekey-1] - CData->curvekey_co[curvekey-2]; } @@ -582,12 +577,12 @@ void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int inter float3 v1; float3 v2; - if (curvekey == CData->curve_firstkey[curve]) { + if(curvekey == CData->curve_firstkey[curve]) { subv = 0; v1 = CData->curvekey_co[curvekey+2] - 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] - 2) { + else if(curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) { v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey-1]; v2 = CData->curvekey_co[curvekey-1] - CData->curvekey_co[curvekey-2]; } @@ -619,10 +614,10 @@ void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int inter 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)) + if(CData->psys_closetip[sys] && (subv == segments) && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2)) radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], 0.0f, 0.95f); - if ((curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) && (subv == segments)) + if((curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) && (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; @@ -645,7 +640,7 @@ void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int inter } } - mesh->reserve(mesh->verts.size(), mesh->triangles.size()); + 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(); @@ -661,9 +656,12 @@ void ExportCurveSegments(Mesh *mesh, ParticleCurveData *CData, int interpolation int curs = 0; int segs = 0; - if(!(mesh->curve_segs.empty() && mesh->curve_keys.empty() && mesh->curve_attrib.empty())) + if(!(mesh->curve_segments.empty() && mesh->curve_keys.empty())) return; + Attribute *attr_uv = mesh->curve_attributes.add(ATTR_STD_UV); + Attribute *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) @@ -677,7 +675,7 @@ void ExportCurveSegments(Mesh *mesh, ParticleCurveData *CData, int interpolation 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]) + if(curvekey == CData->curve_firstkey[curve]) subv = 0; for (; subv <= segments; subv++) { @@ -685,20 +683,22 @@ void ExportCurveSegments(Mesh *mesh, ParticleCurveData *CData, int interpolation 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)) + 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)) + if(CData->psys_closetip[sys] && (subv == segments) && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2)) radius =0.0f; - mesh->add_curvekey(ickey_loc, radius, time); + mesh->add_curve_key(ickey_loc, radius); + attr_intercept->add(time); if(subv != 0) { - mesh->add_curve(cks - 1, cks, CData->psys_shader[sys], curs); + attr_uv->add(CData->curve_uv[curve]); + mesh->add_curve_segment(cks - 1, cks, CData->psys_shader[sys], curs); segs++; } @@ -706,18 +706,17 @@ void ExportCurveSegments(Mesh *mesh, ParticleCurveData *CData, int interpolation } } - mesh->add_curveattrib(CData->curve_u[curve], CData->curve_v[curve]); curs++; } } /* check allocation*/ - if((mesh->curve_keys.size() != cks) || (mesh->curve_segs.size() != segs) || (mesh->curve_attrib.size() != curs)) { + if((mesh->curve_keys.size() != cks) || (mesh->curve_segments.size() != segs)) { /* allocation failed -> clear data */ mesh->curve_keys.clear(); - mesh->curve_segs.clear(); - mesh->curve_attrib.clear(); + mesh->curve_segments.clear(); + mesh->curve_attributes.clear(); } } @@ -734,7 +733,7 @@ void BlenderSync::sync_curve_settings() curve_system_manager->use_curves = get_boolean(csscene, "use_curves"); - if (preset == CURVE_CUSTOM) { + if(preset == CURVE_CUSTOM) { /*custom properties*/ curve_system_manager->primitive = get_enum(csscene, "primitive"); curve_system_manager->line_method = get_enum(csscene, "line_method"); @@ -824,15 +823,18 @@ void BlenderSync::sync_curve_settings() void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool object_updated) { /* Clear stored curve data */ - mesh->curve_attrib.clear(); mesh->curve_keys.clear(); - mesh->curve_keysCD.clear(); - mesh->curve_segs.clear(); + mesh->curve_segments.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) { + 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; @@ -845,12 +847,12 @@ void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool /* extract particle hair data - should be combined with connecting to mesh later*/ - ParticleCurveData *CData = new ParticleCurveData(); + ParticleCurveData CData; - if (use_cache) - ObtainCacheParticleData(mesh, &b_mesh, &b_ob, CData, use_parents); + if(use_cache) + ObtainCacheParticleData(mesh, &b_mesh, &b_ob, &CData, use_parents); else - ObtainParticleData(mesh, &b_mesh, &b_ob, CData); + ObtainParticleData(mesh, &b_mesh, &b_ob, &CData); /* attach strands to mesh */ BL::Object b_CamOb = b_scene.camera(); @@ -862,37 +864,33 @@ void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool RotCam = transform_point(&itfm, make_float3(ctfm.x.w, ctfm.y.w, ctfm.z.w)); } - if (primitive == CURVE_TRIANGLES){ - if (triangle_method == CURVE_CAMERA) - ExportCurveTrianglePlanes(mesh, CData, interpolation, use_smooth, segments, RotCam); - else if (triangle_method == CURVE_RIBBONS) - ExportCurveTriangleRibbons(mesh, CData, interpolation, use_smooth, segments); + if(primitive == CURVE_TRIANGLES){ + if(triangle_method == CURVE_CAMERA) + ExportCurveTrianglePlanes(mesh, &CData, interpolation, use_smooth, segments, RotCam); + else if(triangle_method == CURVE_RIBBONS) + ExportCurveTriangleRibbons(mesh, &CData, interpolation, use_smooth, segments); else - ExportCurveTriangleGeometry(mesh, CData, interpolation, use_smooth, resolution, segments); + ExportCurveTriangleGeometry(mesh, &CData, interpolation, use_smooth, resolution, segments); } else { - ExportCurveSegments(mesh, CData, interpolation, segments); + ExportCurveSegments(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) { + 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++) { - Mesh::CurveData SCD; - SCD.tg = normalize(normalize(mesh->curve_keys[min(ck + 1, ckey_num - 1)].loc - mesh->curve_keys[ck].loc) - - normalize(mesh->curve_keys[max(ck - 1, 0)].loc - mesh->curve_keys[ck].loc)); - mesh->curve_keysCD.push_back(SCD); + 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; } } } - - delete CData; - - } - mesh->compute_bounds(); - } |