diff options
Diffstat (limited to 'intern/cycles/blender/blender_curves.cpp')
-rw-r--r-- | intern/cycles/blender/blender_curves.cpp | 717 |
1 files changed, 480 insertions, 237 deletions
diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp index dba801fc4df..4ed0b910f35 100644 --- a/intern/cycles/blender/blender_curves.cpp +++ b/intern/cycles/blender/blender_curves.cpp @@ -37,15 +37,14 @@ void curveinterp_v3_v3v3v3v3(float3 *p, float3 *v1, float3 *v2, float3 *v3, floa void interp_weights(float t, float data[4]); 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); -bool ObtainCacheParticleUV(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool background, int uv_num); -bool ObtainCacheParticleVcol(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool background, int vcol_num); -bool ObtainCacheParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool background); void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CData); void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData, float3 RotCam, bool is_ortho); void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int resolution); void ExportCurveTriangleUV(ParticleCurveData *CData, int vert_offset, int resol, float3 *uvdata); +void ExportCurveUV(Mesh *mesh, ParticleCurveData *CData, ustring name, bool active_render, int primitive, int vert_offset, int resol); void ExportCurveTriangleVcol(ParticleCurveData *CData, int vert_offset, int resol, uchar4 *cdata); +void ExportCurveVcol(Mesh *mesh, ParticleCurveData *CData, ustring name, int primitive, int vert_offset, int resol); ParticleCurveData::ParticleCurveData() { @@ -119,206 +118,330 @@ void InterpolateKeySegments(int seg, int segno, int key, int curve, float3 *keyl curveinterp_v3_v3v3v3v3(keyloc, &ckey_loc1, &ckey_loc2, &ckey_loc3, &ckey_loc4, t); } -bool ObtainCacheParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool background) +static void ObtainCacheParticleData(Mesh *mesh, BL::Object b_ob, BL::ParticleSystem b_psys, const Transform &itfm, + ParticleCurveData *CData, bool background) { - int curvenum = 0; - int keyno = 0; + BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr); + int mi = clamp(b_part.material()-1, 0, mesh->used_shaders.size()-1); + int shader = mesh->used_shaders[mi]; + int draw_step = background ? b_part.render_step() : b_part.draw_step(); + int totparts = b_psys.particles.length(); + int totchild = background ? b_psys.child_particles.length() : (int)((float)b_psys.child_particles.length() * (float)b_part.draw_percentage() / 100.0f); + int totcurves = totchild; + + if(b_part.child_type() == 0) + totcurves += totparts; - if(!(mesh && b_mesh && b_ob && CData)) - return false; + if(totcurves == 0) + return; - Transform tfm = get_transform(b_ob->matrix_world()); - Transform itfm = transform_quick_inverse(tfm); + int ren_step = (1 << draw_step) + 1; + if(b_part.kink() == BL::ParticleSettings::kink_SPIRAL) + ren_step += b_part.kink_extra_steps(); - 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) && (background ? b_mod->show_render() : b_mod->show_viewport())) { - 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); + PointerRNA cpsys = RNA_pointer_get(&b_part.ptr, "cycles"); + + int keyno = CData->curvekey_co.size(); + int curvenum = CData->curve_keynum.size(); + + CData->psys_firstcurve.push_back(curvenum); + CData->psys_curvenum.push_back(totcurves); + CData->psys_shader.push_back(shader); + + float radius = get_float(cpsys, "radius_scale") * 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(!(b_part.child_type() == 0)) + pa_no = totparts; + + int num_add = (totparts+totchild - pa_no); + CData->curve_firstkey.reserve(CData->curve_firstkey.size() + num_add); + CData->curve_keynum.reserve(CData->curve_keynum.size() + num_add); + CData->curve_length.reserve(CData->curve_length.size() + num_add); + CData->curvekey_co.reserve(CData->curvekey_co.size() + num_add*ren_step); + CData->curvekey_time.reserve(CData->curvekey_time.size() + num_add*ren_step); + + for(; pa_no < totparts+totchild; pa_no++) { + int keynum = 0; + CData->curve_firstkey.push_back(keyno); + + 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, pa_no, step_no, nco); + float3 cKey = make_float3(nco[0], nco[1], nco[2]); + cKey = transform_point(&itfm, cKey); + if(step_no > 0) { + float step_length = len(cKey - pcKey); + if(step_length == 0.0f) + continue; + curve_length += step_length; + } + CData->curvekey_co.push_back(cKey); + CData->curvekey_time.push_back(curve_length); + pcKey = cKey; + keynum++; + } + keyno += keynum; - if((b_part.render_type() == BL::ParticleSettings::render_type_PATH) && (b_part.type() == BL::ParticleSettings::type_HAIR)) { - int mi = clamp(b_part.material()-1, 0, mesh->used_shaders.size()-1); - int shader = mesh->used_shaders[mi]; - int draw_step = background ? b_part.render_step() : b_part.draw_step(); - int totparts = b_psys.particles.length(); - int totchild = background ? b_psys.child_particles.length() : (int)((float)b_psys.child_particles.length() * (float)b_part.draw_percentage() / 100.0f); - int totcurves = totchild; - - if(b_part.child_type() == 0) - totcurves += totparts; + CData->curve_keynum.push_back(keynum); + CData->curve_length.push_back(curve_length); + curvenum++; + } +} - if(totcurves == 0) - continue; +static void ObtainCacheParticleUV(Mesh * /*mesh*/, BL::Object /*b_ob*/, BL::Mesh b_mesh, BL::ParticleSystem b_psys, BL::ParticleSystemModifier b_psmd, + ParticleCurveData *CData, bool background, int uv_num) +{ + BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr); + int totparts = b_psys.particles.length(); + int totchild = background ? b_psys.child_particles.length() : (int)((float)b_psys.child_particles.length() * (float)b_part.draw_percentage() / 100.0f); + int totcurves = totchild; + + if(b_part.child_type() == 0) + totcurves += totparts; - int ren_step = (1 << draw_step) + 1; - if(b_part.kink() == BL::ParticleSettings::kink_SPIRAL) - ren_step += b_part.kink_extra_steps(); + if(totcurves == 0) + return; - PointerRNA cpsys = RNA_pointer_get(&b_part.ptr, "cycles"); + int pa_no = 0; + if(!(b_part.child_type() == 0)) + pa_no = totparts; - CData->psys_firstcurve.push_back(curvenum); - CData->psys_curvenum.push_back(totcurves); - CData->psys_shader.push_back(shader); + int num_add = (totparts+totchild - pa_no); + CData->curve_uv.reserve(CData->curve_uv.size() + num_add); - float radius = get_float(cpsys, "radius_scale") * 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(!(b_part.child_type() == 0)) - pa_no = totparts; - - int num_add = (totparts+totchild - pa_no); - CData->curve_firstkey.reserve(CData->curve_firstkey.size() + num_add); - CData->curve_keynum.reserve(CData->curve_keynum.size() + num_add); - CData->curve_length.reserve(CData->curve_length.size() + num_add); - CData->curvekey_co.reserve(CData->curvekey_co.size() + num_add*ren_step); - CData->curvekey_time.reserve(CData->curvekey_time.size() + num_add*ren_step); - - for(; pa_no < totparts+totchild; pa_no++) { - int keynum = 0; - CData->curve_firstkey.push_back(keyno); - - 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, pa_no, step_no, nco); - float3 cKey = make_float3(nco[0], nco[1], nco[2]); - cKey = transform_point(&itfm, cKey); - if(step_no > 0) { - float step_length = len(cKey - pcKey); - if(step_length == 0.0f) - continue; - curve_length += step_length; - } - CData->curvekey_co.push_back(cKey); - CData->curvekey_time.push_back(curve_length); - pcKey = cKey; - keynum++; - } - keyno += keynum; + 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); - CData->curve_keynum.push_back(keynum); - CData->curve_length.push_back(curve_length); - curvenum++; - } - } - } - } + float3 uv = make_float3(0.0f, 0.0f, 0.0f); + if(b_mesh.tessface_uv_textures.length()) + b_psys.uv_on_emitter(b_psmd, *b_pa, pa_no, uv_num, &uv.x); + CData->curve_uv.push_back(uv); - return true; + if(pa_no < totparts && b_pa != b_psys.particles.end()) + ++b_pa; + } } -bool ObtainCacheParticleUV(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool background, int uv_num) +static void ObtainCacheParticleVcol(Mesh * /*mesh*/, BL::Object /*b_ob*/, BL::Mesh b_mesh, BL::ParticleSystem b_psys, BL::ParticleSystemModifier b_psmd, + ParticleCurveData *CData, bool background, int vcol_num) { - if(!(mesh && b_mesh && b_ob && CData)) - return false; + BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr); + int totparts = b_psys.particles.length(); + int totchild = background ? b_psys.child_particles.length() : (int)((float)b_psys.child_particles.length() * (float)b_part.draw_percentage() / 100.0f); + int totcurves = totchild; + + if(b_part.child_type() == 0) + totcurves += totparts; - CData->curve_uv.clear(); + if(totcurves == 0) + return; - 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) && (background ? b_mod->show_render() : b_mod->show_viewport())) { - 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); + int pa_no = 0; + if(!(b_part.child_type() == 0)) + pa_no = totparts; - if((b_part.render_type() == BL::ParticleSettings::render_type_PATH) && (b_part.type() == BL::ParticleSettings::type_HAIR)) { - int totparts = b_psys.particles.length(); - int totchild = background ? b_psys.child_particles.length() : (int)((float)b_psys.child_particles.length() * (float)b_part.draw_percentage() / 100.0f); - int totcurves = totchild; - - if(b_part.child_type() == 0) - totcurves += totparts; + int num_add = (totparts+totchild - pa_no); + CData->curve_vcol.reserve(CData->curve_vcol.size() + num_add); - if(totcurves == 0) - continue; + BL::ParticleSystem::particles_iterator b_pa; + b_psys.particles.begin(b_pa); + for(; pa_no < totparts+totchild; pa_no++) { + /* Add vertex colors */ + BL::Mesh::tessface_vertex_colors_iterator l; + b_mesh.tessface_vertex_colors.begin(l); - int pa_no = 0; - if(!(b_part.child_type() == 0)) - pa_no = totparts; + float3 vcol = make_float3(0.0f, 0.0f, 0.0f); + if(b_mesh.tessface_vertex_colors.length()) + b_psys.mcol_on_emitter(b_psmd, *b_pa, pa_no, vcol_num, &vcol.x); + CData->curve_vcol.push_back(vcol); - int num_add = (totparts+totchild - pa_no); - CData->curve_uv.reserve(CData->curve_uv.size() + num_add); + if(pa_no < totparts && b_pa != b_psys.particles.end()) + ++b_pa; + } +} + +/* A little bit of templated code here to avoid much duplication for parent/child strands: + * Most attributes are the same for both types, but some are handled slightly differently. + * These attributes are handled by templated utility functions that automatically get selected by type. + */ +template <typename StrandsT> +struct StrandsTraits; - 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); +template<> +struct StrandsTraits<BL::Strands> +{ + typedef BL::StrandsCurve curve_t; + typedef BL::StrandsVertex vertex_t; + + static float3 get_location(BL::Strands b_strands, int index) + { + float *co = (b_strands.has_motion_state())? b_strands.motion_state[index].location() : b_strands.vertices[index].location(); + return make_float3(co[0], co[1], co[2]); + } + static float3 get_uv(BL::Strands /*b_strands*/, int /*index*/, int /*uv_num*/) + { + return make_float3(0.0f, 0.0f, 0.0f); + } + static float3 get_vcol(BL::Strands /*b_strands*/, int /*index*/, int /*vcol_num*/) + { + return make_float3(0.0f, 0.0f, 0.0f); + } +}; - 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_num, &uv.x); - CData->curve_uv.push_back(uv); +template<> +struct StrandsTraits<BL::StrandsChildren> +{ + typedef BL::StrandsChildCurve curve_t; + typedef BL::StrandsChildVertex vertex_t; + + static float3 get_location(BL::StrandsChildren b_strands, int index) + { + float *co = b_strands.vertices[index].location(); + return make_float3(co[0], co[1], co[2]); + } + static float3 get_uv(BL::StrandsChildren b_strands, int index, int uv_num) + { + if (uv_num < b_strands.num_curve_uv_layers()) { + size_t offset = uv_num * b_strands.curves.length(); + float *uv = b_strands.curve_uvs[offset + index].uv(); + return make_float3(uv[0], uv[1], 0.0f); + } + else + return make_float3(0.0f, 0.0f, 0.0f); + } + static float3 get_vcol(BL::StrandsChildren b_strands, int index, int vcol_num) + { + if (vcol_num < b_strands.num_curve_vcol_layers()) { + size_t offset = vcol_num * b_strands.curves.length(); + float *vcol = b_strands.curve_vcols[offset + index].vcol(); + return make_float3(vcol[0], vcol[1], vcol[2]); + } + else + return make_float3(0.0f, 0.0f, 0.0f); + } +}; - if(pa_no < totparts && b_pa != b_psys.particles.end()) - ++b_pa; - } +template <typename StrandsT> +static bool ObtainCacheStrandsData(Mesh *mesh, BL::Scene /*b_scene*/, BL::Object /*b_parent*/, BL::DupliObject /*b_dupli_ob*/, BL::ParticleSystem b_psys, StrandsT b_strands, const Transform &/*itfm*/, + ParticleCurveData *CData, bool /*background*/) +{ + typedef StrandsTraits<StrandsT> traits; + typedef typename traits::curve_t CurveT; + + BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr); + PointerRNA cpsys = RNA_pointer_get(&b_part.ptr, "cycles"); + + int mi = clamp(b_part.material()-1, 0, mesh->used_shaders.size()-1); + int shader = mesh->used_shaders[mi]; + + int totcurves = b_strands.curves.length(); + int totvert = b_strands.vertices.length(); + + int keyno = CData->curvekey_co.size(); + int curvenum = CData->curve_keynum.size(); + + CData->psys_firstcurve.push_back(curvenum); + CData->psys_curvenum.push_back(totcurves); + CData->psys_shader.push_back(shader); + + float radius = get_float(cpsys, "radius_scale") * 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")); + + CData->curve_firstkey.reserve(CData->curve_firstkey.size() + totcurves); + CData->curve_keynum.reserve(CData->curve_keynum.size() + totcurves); + CData->curve_length.reserve(CData->curve_length.size() + totcurves); + CData->curvekey_co.reserve(CData->curvekey_co.size() + totvert); + CData->curvekey_time.reserve(CData->curvekey_time.size() + totvert); + + int icurve = 0; + int ivert = 0; + for(; icurve < totcurves; ++icurve) { + CurveT b_curve = b_strands.curves[icurve]; + int numverts = b_curve.size(); + int showverts = b_curve.render_size(); + int usedverts = 0; + CData->curve_firstkey.push_back(keyno); + + float curve_length = 0.0f; + float3 pcKey; + for(int cvert = 0; cvert < showverts; ++cvert) { + float3 cKey = traits::get_location(b_strands, ivert + cvert); + + if(cvert > 0) { + float step_length = len(cKey - pcKey); + if(step_length == 0.0f) + continue; + curve_length += step_length; } + CData->curvekey_co.push_back(cKey); + CData->curvekey_time.push_back(curve_length); + pcKey = cKey; + usedverts++; } - } + keyno += usedverts; + ivert += numverts; + CData->curve_keynum.push_back(usedverts); + CData->curve_length.push_back(curve_length); + curvenum++; + } + return true; } -bool ObtainCacheParticleVcol(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool background, int vcol_num) +template <typename StrandsT> +static bool ObtainCacheStrandsUV(Mesh * /*mesh*/, BL::Scene /*b_scene*/, BL::Object /*b_parent*/, BL::DupliObject /*b_dupli_ob*/, BL::ParticleSystem /*b_psys*/, StrandsT b_strands, + ParticleCurveData *CData, bool /*background*/, int uv_num) { - if(!(mesh && b_mesh && b_ob && CData)) - return false; - - CData->curve_vcol.clear(); - - 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) && (background ? b_mod->show_render() : b_mod->show_viewport())) { - 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_part.render_type() == BL::ParticleSettings::render_type_PATH) && (b_part.type() == BL::ParticleSettings::type_HAIR)) { - int totparts = b_psys.particles.length(); - int totchild = background ? b_psys.child_particles.length() : (int)((float)b_psys.child_particles.length() * (float)b_part.draw_percentage() / 100.0f); - int totcurves = totchild; - - if(b_part.child_type() == 0) - totcurves += totparts; - - if(totcurves == 0) - continue; - - int pa_no = 0; - if(!(b_part.child_type() == 0)) - pa_no = totparts; - - int num_add = (totparts+totchild - pa_no); - CData->curve_vcol.reserve(CData->curve_vcol.size() + num_add); + typedef StrandsTraits<StrandsT> traits; + +// BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr); - BL::ParticleSystem::particles_iterator b_pa; - b_psys.particles.begin(b_pa); - for(; pa_no < totparts+totchild; pa_no++) { - /* Add vertex colors */ - BL::Mesh::tessface_vertex_colors_iterator l; - b_mesh->tessface_vertex_colors.begin(l); + int totcurves = b_strands.curves.length(); - 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); + CData->curve_uv.reserve(CData->curve_uv.size() + totcurves); - if(pa_no < totparts && b_pa != b_psys.particles.end()) - ++b_pa; - } - } - } + int icurve = 0; + for(; icurve < totcurves; ++icurve) { + CData->curve_uv.push_back(traits::get_uv(b_strands, icurve, uv_num)); } + + return true; +} +template <typename StrandsT> +static bool ObtainCacheStrandsVcol(Mesh * /*mesh*/, BL::Scene /*b_scene*/, BL::Object /*b_parent*/, BL::DupliObject /*b_dupli_ob*/, BL::ParticleSystem /*b_psys*/, StrandsT b_strands, + ParticleCurveData *CData, bool /*background*/, int vcol_num) +{ + typedef StrandsTraits<StrandsT> traits; + +// BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr); + + int totcurves = b_strands.curves.length(); + + CData->curve_vcol.reserve(CData->curve_vcol.size() + totcurves); + + int icurve = 0; + for(; icurve < totcurves; ++icurve) { + CData->curve_vcol.push_back(traits::get_vcol(b_strands, icurve, vcol_num)); + } + return true; } @@ -750,6 +873,39 @@ void ExportCurveTriangleUV(ParticleCurveData *CData, int vert_offset, int resol, } } +void ExportCurveUV(Mesh *mesh, ParticleCurveData *CData, ustring name, bool active_render, int primitive, int vert_offset, int resol) +{ + AttributeStandard std = (active_render)? ATTR_STD_UV: ATTR_STD_NONE; + Attribute *attr_uv; + + if(primitive == CURVE_TRIANGLES) { + if(active_render) + attr_uv = mesh->attributes.add(std, name); + else + attr_uv = mesh->attributes.add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CORNER); + + float3 *uv = attr_uv->data_float3(); + + ExportCurveTriangleUV(CData, vert_offset, resol, uv); + } + else { + if(active_render) + attr_uv = mesh->curve_attributes.add(std, name); + else + attr_uv = mesh->curve_attributes.add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE); + + float3 *uv = attr_uv->data_float3(); + + if(uv) { + size_t i = 0; + + for(size_t curve = 0; curve < CData->curve_uv.size(); curve++) + if(!(CData->curve_keynum[curve] <= 1 || CData->curve_length[curve] == 0.0f)) + uv[i++] = CData->curve_uv[curve]; + } + } +} + void ExportCurveTriangleVcol(ParticleCurveData *CData, int vert_offset, int resol, uchar4 *cdata) { if(cdata == NULL) @@ -782,6 +938,31 @@ void ExportCurveTriangleVcol(ParticleCurveData *CData, int vert_offset, int reso } } +void ExportCurveVcol(Mesh *mesh, ParticleCurveData *CData, ustring name, int primitive, int vert_offset, int resol) +{ + if(primitive == CURVE_TRIANGLES) { + Attribute *attr_vcol = mesh->attributes.add(name, TypeDesc::TypeColor, ATTR_ELEMENT_CORNER_BYTE); + + uchar4 *cdata = attr_vcol->data_uchar4(); + + ExportCurveTriangleVcol(CData, vert_offset, resol, cdata); + } + else { + Attribute *attr_vcol = mesh->curve_attributes.add(name, TypeDesc::TypeColor, ATTR_ELEMENT_CURVE); + + float3 *fdata = attr_vcol->data_float3(); + + if(fdata) { + size_t i = 0; + + for(size_t curve = 0; curve < CData->curve_vcol.size(); curve++) + if(!(CData->curve_keynum[curve] <= 1 || CData->curve_length[curve] == 0.0f)) + fdata[i++] = color_srgb_to_scene_linear(CData->curve_vcol[curve]); + } + } +} + + /* Hair Curve Sync */ void BlenderSync::sync_curve_settings() @@ -856,8 +1037,61 @@ void BlenderSync::sync_curve_settings() curve_system_manager->tag_update(scene); } -void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool motion, int time_index) +struct CurvesPSysData { + CurvesPSysData(BL::ParticleSystemModifier b_psmd=PointerRNA_NULL, BL::ParticleSystem b_psys=PointerRNA_NULL, + BL::Strands b_strands=PointerRNA_NULL, BL::StrandsChildren b_strands_children=PointerRNA_NULL) : + b_psmd(b_psmd), b_psys(b_psys), b_strands(b_strands), b_strands_children(b_strands_children) + {} + + BL::ParticleSystemModifier b_psmd; + BL::ParticleSystem b_psys; + BL::Strands b_strands; + BL::StrandsChildren b_strands_children; +}; + +static void curves_get_psys_data(std::vector<CurvesPSysData> &b_psys_list, BL::Scene b_scene, BL::Object b_ob, BL::Object b_parent, BL::DupliObject b_dupli_ob, bool preview) +{ + 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) && (preview ? b_mod->show_viewport() : b_mod->show_render())) { + BL::ParticleSystemModifier b_psmd((const PointerRNA)b_mod->ptr); + BL::ParticleSystem b_psys((const PointerRNA)b_psmd.particle_system().ptr); + BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr); + + if((b_part.render_type() == BL::ParticleSettings::render_type_PATH) && (b_part.type() == BL::ParticleSettings::type_HAIR)) { + int settings = preview ? 1 : 2; + + BL::StrandsChildren b_strands_children = PointerRNA_NULL; + BL::Strands b_strands = PointerRNA_NULL; + + if (b_dupli_ob && b_parent) { + b_strands_children = b_dupli_ob.strands_children_new(b_scene, b_parent, b_psys, settings); + if (!b_strands_children) + b_strands = b_dupli_ob.strands_new(b_scene, b_parent, b_psys, settings); + } + + b_psys_list.push_back(CurvesPSysData(b_psmd, b_psys, b_strands, b_strands_children)); + } + } + } +} + +static void curves_free_psys_data(std::vector<CurvesPSysData> &b_psys_list, BL::DupliObject b_dupli_ob) +{ + /* free temporary strands data */ + for (int i = 0; i < b_psys_list.size(); ++i) { + CurvesPSysData &psys_data = b_psys_list[i]; + if (psys_data.b_strands) + b_dupli_ob.strands_free(psys_data.b_strands); + if (psys_data.b_strands_children) + b_dupli_ob.strands_children_free(psys_data.b_strands_children); + } +} + +void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_parent, bool motion, int time_index, BL::DupliObject b_dupli_ob) { + BL::Object b_ob = (b_dupli_ob ? b_dupli_ob.object() : b_parent); + if(!motion) { /* Clear stored curve data */ mesh->curve_keys.clear(); @@ -888,27 +1122,46 @@ void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool if(!preview) set_resolution(&b_ob, &b_scene, true); - ObtainCacheParticleData(mesh, &b_mesh, &b_ob, &CData, !preview); + Transform tfm = get_transform(b_ob.matrix_world()); + Transform itfm = transform_quick_inverse(tfm); + + /* obtain camera parameters */ + float3 RotCam; + Camera *camera = scene->camera; + if(camera->type == CAMERA_ORTHOGRAPHIC) { + Transform &ctfm = camera->matrix; + RotCam = -make_float3(ctfm.x.z, ctfm.y.z, ctfm.z.z); + } + else { + Transform &ctfm = camera->matrix; + RotCam = transform_point(&itfm, make_float3(ctfm.x.w, ctfm.y.w, ctfm.z.w)); + } + bool is_ortho_camera = camera->type == CAMERA_ORTHOGRAPHIC; + + std::vector<CurvesPSysData> b_psys_list; + curves_get_psys_data(b_psys_list, b_scene, b_ob, b_parent, b_dupli_ob, preview); + + for (int i = 0; i < b_psys_list.size(); ++i) { + CurvesPSysData &psys_data = b_psys_list[i]; + if (psys_data.b_strands_children) + /* use child strands cache */ + ObtainCacheStrandsData(mesh, b_scene, b_parent, b_dupli_ob, psys_data.b_psys, psys_data.b_strands_children, + itfm, &CData, !preview); + else if (psys_data.b_strands) + /* use parent strands cache */ + ObtainCacheStrandsData(mesh, b_scene, b_parent, b_dupli_ob, psys_data.b_psys, psys_data.b_strands, + itfm, &CData, !preview); + else { + /* use object data */ + ObtainCacheParticleData(mesh, b_ob, psys_data.b_psys, + itfm, &CData, !preview); + } + } /* add hair geometry to mesh */ if(primitive == CURVE_TRIANGLES) { if(triangle_method == CURVE_CAMERA_TRIANGLES) { - /* obtain camera parameters */ - float3 RotCam; - Camera *camera = scene->camera; - Transform &ctfm = camera->matrix; - if(camera->type == CAMERA_ORTHOGRAPHIC) { - RotCam = -make_float3(ctfm.x.z, ctfm.y.z, ctfm.z.z); - } - else { - 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)); - } - bool is_ortho = camera->type == CAMERA_ORTHOGRAPHIC; - ExportCurveTrianglePlanes(mesh, &CData, RotCam, is_ortho); + ExportCurveTrianglePlanes(mesh, &CData, RotCam, is_ortho_camera); } else { ExportCurveTriangleGeometry(mesh, &CData, resolution); @@ -955,33 +1208,31 @@ void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool int vcol_num = 0; for(b_mesh.tessface_vertex_colors.begin(l); l != b_mesh.tessface_vertex_colors.end(); ++l, vcol_num++) { + ustring name = ustring(l->name().c_str()); + if(!mesh->need_attribute(scene, ustring(l->name().c_str()))) continue; - ObtainCacheParticleVcol(mesh, &b_mesh, &b_ob, &CData, !preview, vcol_num); - - if(primitive == CURVE_TRIANGLES) { - Attribute *attr_vcol = mesh->attributes.add( - ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CORNER_BYTE); - - uchar4 *cdata = attr_vcol->data_uchar4(); - - ExportCurveTriangleVcol(&CData, tri_num * 3, used_res, cdata); - } - else { - Attribute *attr_vcol = mesh->curve_attributes.add( - ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CURVE); - - float3 *fdata = attr_vcol->data_float3(); - - if(fdata) { - size_t i = 0; - - for(size_t curve = 0; curve < CData.curve_vcol.size(); curve++) - if(!(CData.curve_keynum[curve] <= 1 || CData.curve_length[curve] == 0.0f)) - fdata[i++] = color_srgb_to_scene_linear(CData.curve_vcol[curve]); + CData.curve_vcol.clear(); + + for (int i = 0; i < b_psys_list.size(); ++i) { + CurvesPSysData &psys_data = b_psys_list[i]; + if (psys_data.b_strands_children) + /* use child strands cache */ + ObtainCacheStrandsVcol(mesh, b_scene, b_parent, b_dupli_ob, psys_data.b_psys, psys_data.b_strands_children, + &CData, !preview, vcol_num); + else if (psys_data.b_strands) + /* use parent strands cache */ + ObtainCacheStrandsVcol(mesh, b_scene, b_parent, b_dupli_ob, psys_data.b_psys, psys_data.b_strands, + &CData, !preview, vcol_num); + else { + /* use object data */ + ObtainCacheParticleVcol(mesh, b_ob, b_mesh, psys_data.b_psys, psys_data.b_psmd, + &CData, !preview, vcol_num); } } + + ExportCurveVcol(mesh, &CData, name, primitive, tri_num * 3, used_res); } } @@ -992,45 +1243,37 @@ void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool for(b_mesh.tessface_uv_textures.begin(l); l != b_mesh.tessface_uv_textures.end(); ++l, uv_num++) { bool active_render = l->active_render(); - AttributeStandard std = (active_render)? ATTR_STD_UV: ATTR_STD_NONE; ustring name = ustring(l->name().c_str()); /* UV map */ - if(mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std)) { - Attribute *attr_uv; - - ObtainCacheParticleUV(mesh, &b_mesh, &b_ob, &CData, !preview, uv_num); - - if(primitive == CURVE_TRIANGLES) { - if(active_render) - attr_uv = mesh->attributes.add(std, name); - else - attr_uv = mesh->attributes.add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CORNER); - - float3 *uv = attr_uv->data_float3(); - - ExportCurveTriangleUV(&CData, tri_num * 3, used_res, uv); - } + if(!(mesh->need_attribute(scene, name) || (active_render && mesh->need_attribute(scene, ATTR_STD_UV)))) + continue; + + CData.curve_uv.clear(); + + for (int i = 0; i < b_psys_list.size(); ++i) { + CurvesPSysData &psys_data = b_psys_list[i]; + if (psys_data.b_strands_children) + /* use child strands cache */ + ObtainCacheStrandsUV(mesh, b_scene, b_parent, b_dupli_ob, psys_data.b_psys, psys_data.b_strands_children, + &CData, !preview, uv_num); + else if (psys_data.b_strands) + /* use parent strands cache */ + ObtainCacheStrandsUV(mesh, b_scene, b_parent, b_dupli_ob, psys_data.b_psys, psys_data.b_strands, + &CData, !preview, uv_num); else { - if(active_render) - attr_uv = mesh->curve_attributes.add(std, name); - else - attr_uv = mesh->curve_attributes.add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE); - - float3 *uv = attr_uv->data_float3(); - - if(uv) { - size_t i = 0; - - for(size_t curve = 0; curve < CData.curve_uv.size(); curve++) - if(!(CData.curve_keynum[curve] <= 1 || CData.curve_length[curve] == 0.0f)) - uv[i++] = CData.curve_uv[curve]; - } + /* use object data */ + ObtainCacheParticleUV(mesh, b_ob, b_mesh, psys_data.b_psys, psys_data.b_psmd, + &CData, !preview, uv_num); } } + + ExportCurveUV(mesh, &CData, name, active_render, primitive, tri_num * 3, used_res); } } + curves_free_psys_data(b_psys_list, b_dupli_ob); + if(!preview) set_resolution(&b_ob, &b_scene, false); |