diff options
author | Lukas Tönne <lukas.toenne@gmail.com> | 2015-05-28 16:25:00 +0300 |
---|---|---|
committer | Lukas Tönne <lukas.toenne@gmail.com> | 2015-05-28 16:25:00 +0300 |
commit | f1bd802b118c20eead0be075f5ec7bd59b0610c3 (patch) | |
tree | c6af749812eacb35d315e43c019c5c73170ba5cb /source/blender/blenkernel/intern | |
parent | e233e5f2a89208c2042894b5e9fdf6fecbae9118 (diff) |
Moved child strand deformation into the general cache processing
function.
Strands processing now has 3 main steps:
1) apply parent modifiers
2) deform child strands
3) apply child modifiers
Diffstat (limited to 'source/blender/blenkernel/intern')
-rw-r--r-- | source/blender/blenkernel/intern/cache_library.c | 132 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/object_dupli.c | 39 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/strands.c | 71 |
3 files changed, 100 insertions, 142 deletions
diff --git a/source/blender/blenkernel/intern/cache_library.c b/source/blender/blenkernel/intern/cache_library.c index 4ac1142776e..1a1672c3e4c 100644 --- a/source/blender/blenkernel/intern/cache_library.c +++ b/source/blender/blenkernel/intern/cache_library.c @@ -573,7 +573,8 @@ void BKE_cache_modifier_foreachIDLink(struct CacheLibrary *cachelib, struct Cach } void BKE_cache_process_dupli_cache(CacheLibrary *cachelib, CacheProcessData *data, - Scene *scene, Group *dupgroup, float frame_prev, float frame) + Scene *scene, Group *dupgroup, float frame_prev, float frame, + bool do_modifiers, bool do_strands_child_deform, bool do_strands_motion) { CacheProcessContext ctx; CacheModifier *md; @@ -583,11 +584,41 @@ void BKE_cache_process_dupli_cache(CacheLibrary *cachelib, CacheProcessData *dat ctx.cachelib = cachelib; ctx.group = dupgroup; - for (md = cachelib->modifiers.first; md; md = md->next) { - CacheModifierTypeInfo *mti = cache_modifier_type_get(md->type); + if (do_modifiers) { + for (md = cachelib->modifiers.first; md; md = md->next) { + CacheModifierTypeInfo *mti = cache_modifier_type_get(md->type); + + // TODO parent modifiers only here + if (mti->process) + mti->process(md, &ctx, data, frame, frame_prev, eCacheProcessFlag_DoStrands); + } + } + + /* deform child strands to follow parent motion */ + if (do_modifiers || do_strands_child_deform) { + struct DupliCacheIterator *it; - if (mti->process) - mti->process(md, &ctx, data, frame, frame_prev); + it = BKE_dupli_cache_iter_new(data->dupcache); + for (; BKE_dupli_cache_iter_valid(it); BKE_dupli_cache_iter_next(it)) { + DupliObjectData *dobdata = BKE_dupli_cache_iter_get(it); + DupliObjectDataStrands *link; + + for (link = dobdata->strands.first; link; link = link->next) { + if (link->strands_children) + BKE_strands_children_deform(link->strands_children, link->strands, do_strands_motion); + } + } + BKE_dupli_cache_iter_free(it); + } + + if (do_modifiers) { + for (md = cachelib->modifiers.first; md; md = md->next) { + CacheModifierTypeInfo *mti = cache_modifier_type_get(md->type); + + // TODO child modifiers only here + if (mti->process) + mti->process(md, &ctx, data, frame, frame_prev, eCacheProcessFlag_DoStrandsChildren); + } } } @@ -1115,7 +1146,7 @@ static void hairsim_foreach_id_link(HairSimCacheModifier *hsmd, CacheLibrary *ca walk(userdata, cachelib, &hsmd->modifier, (ID **)(&hsmd->sim_params.effector_weights->group)); } -static void hairsim_process(HairSimCacheModifier *hsmd, CacheProcessContext *ctx, CacheProcessData *data, int frame, int frame_prev) +static void hairsim_process(HairSimCacheModifier *hsmd, CacheProcessContext *ctx, CacheProcessData *data, int frame, int frame_prev, int process_flag) { #define MAX_CACHE_EFFECTORS 64 @@ -1127,9 +1158,9 @@ static void hairsim_process(HairSimCacheModifier *hsmd, CacheProcessContext *ctx int tot_cache_effectors; struct Implicit_Data *solver_data; - /* only perform hair sim once */ -// if (eval_mode != CACHE_LIBRARY_EVAL_REALTIME) -// return; + /* only applies to parent strands */ + if (!(process_flag & eCacheProcessFlag_DoStrands)) + return; if (!BKE_cache_modifier_find_strands(data->dupcache, ob, hsmd->hair_system, NULL, &strands, NULL, NULL)) return; @@ -1438,25 +1469,25 @@ static void shrinkwrap_apply(ShrinkWrapCacheModifier *smd, ShrinkWrapCacheData * } } -static void shrinkwrap_process(ShrinkWrapCacheModifier *smd, CacheProcessContext *ctx, CacheProcessData *data, int UNUSED(frame), int UNUSED(frame_prev)) +static void shrinkwrap_process(ShrinkWrapCacheModifier *smd, CacheProcessContext *ctx, CacheProcessData *data, int UNUSED(frame), int UNUSED(frame_prev), int process_flag) { bool do_strands_motion = true; - bool do_strands_children = true; const bool dupli_target = smd->flag & eShrinkWrapCacheModifier_Flag_InternalTarget; Object *ob = smd->object; DupliObject *dob; Strands *strands = NULL; - StrandsChildren *children = NULL; DerivedMesh *target_dm; float mat[4][4]; ShrinkWrapCacheData shrinkwrap; - if (do_strands_children) { - BKE_cache_modifier_find_strands(data->dupcache, ob, smd->hair_system, NULL, NULL, &children, NULL); - } - BKE_cache_modifier_find_strands(data->dupcache, ob, smd->hair_system, NULL, &strands, NULL, NULL); + /* only applies to parent strands */ + if (!(process_flag & eCacheProcessFlag_DoStrands)) + return; + + if (!BKE_cache_modifier_find_strands(data->dupcache, ob, smd->hair_system, NULL, &strands, NULL, NULL)) + return; if (dupli_target) { DupliObjectData *target_data; @@ -1489,7 +1520,7 @@ static void shrinkwrap_process(ShrinkWrapCacheModifier *smd, CacheProcessContext shrinkwrap_data_get_instances(&shrinkwrap, smd->target, mat, NULL); } - shrinkwrap_apply(smd, &shrinkwrap, strands, children, do_strands_motion); + shrinkwrap_apply(smd, &shrinkwrap, strands, NULL, do_strands_motion); shrinkwrap_data_free(&shrinkwrap); @@ -1544,7 +1575,7 @@ static void strandskey_foreach_id_link(StrandsKeyCacheModifier *skmd, CacheLibra walk(userdata, cachelib, &skmd->modifier, (ID **)(&skmd->object)); } -static void strandskey_process(StrandsKeyCacheModifier *skmd, CacheProcessContext *UNUSED(ctx), CacheProcessData *data, int UNUSED(frame), int UNUSED(frame_prev)) +static void strandskey_process(StrandsKeyCacheModifier *skmd, CacheProcessContext *UNUSED(ctx), CacheProcessData *data, int UNUSED(frame), int UNUSED(frame_prev), int process_flag) { const bool use_motion = skmd->flag & eStrandsKeyCacheModifier_Flag_UseMotionState; Object *ob = skmd->object; @@ -1552,6 +1583,9 @@ static void strandskey_process(StrandsKeyCacheModifier *skmd, CacheProcessContex KeyBlock *actkb; float *shape; + /* only applies to parents */ + if (!(process_flag & eCacheProcessFlag_DoStrands)) + return; if (!BKE_cache_modifier_find_strands(data->dupcache, ob, skmd->hair_system, NULL, &strands, NULL, NULL)) return; if (use_motion && !strands->state) @@ -1878,13 +1912,14 @@ static bool haircut_find_segment_cut(HaircutCacheModifier *hmd, HaircutCacheData return false; } -static bool haircut_find_first_strand_cut(HaircutCacheModifier *hmd, HaircutCacheData *data, StrandChildIterator *it_strand, float (*strand_deform)[3], float *r_cutoff) +static bool haircut_find_first_strand_cut(HaircutCacheModifier *hmd, HaircutCacheData *data, StrandChildIterator *it_strand, float *r_cutoff) { StrandChildVertexIterator it_vert; int vprev = -1; float cutoff = 0.0f; for (BKE_strand_child_vertex_iter_init(&it_vert, it_strand); BKE_strand_child_vertex_iter_valid(&it_vert); BKE_strand_child_vertex_iter_next(&it_vert)) { + StrandsChildVertex *verts = it_strand->verts; bool found_cut = false; float lambda_min = 1.0f; HaircutCacheInstance *inst; @@ -1892,7 +1927,7 @@ static bool haircut_find_first_strand_cut(HaircutCacheModifier *hmd, HaircutCach if (it_vert.index == 0) { for (inst = data->instances.first; inst; inst = inst->next) { /* test root vertex */ - if (haircut_test_point(hmd, data, inst, strand_deform[it_vert.index])) { + if (haircut_test_point(hmd, data, inst, verts[it_vert.index].co)) { if (r_cutoff) *r_cutoff = 0.0f; return true; } @@ -1901,7 +1936,7 @@ static bool haircut_find_first_strand_cut(HaircutCacheModifier *hmd, HaircutCach else { for (inst = data->instances.first; inst; inst = inst->next) { float lambda; - if (haircut_find_segment_cut(hmd, data, inst, strand_deform[vprev], strand_deform[it_vert.index], &lambda)) { + if (haircut_find_segment_cut(hmd, data, inst, verts[vprev].co, verts[it_vert.index].co, &lambda)) { found_cut = true; if (lambda < lambda_min) lambda_min = lambda; @@ -1924,46 +1959,57 @@ static bool haircut_find_first_strand_cut(HaircutCacheModifier *hmd, HaircutCach return false; } -static void haircut_apply(HaircutCacheModifier *hmd, CacheProcessContext *UNUSED(ctx), HaircutCacheData *data, Strands *parents, StrandsChildren *strands) +/* shortens the last visible segment to have exact cutoff length */ +static void haircut_strand_adjust_tip(StrandChildIterator *it_strand, float cutoff) { - StrandChildIterator it_strand; - bool do_strands_motion = true; + StrandsChildCurve *curve = it_strand->curve; - /* Note: the child data here is not yet deformed by parents, so the intersections won't be correct. - * We deform each strand individually on-the-fly to avoid duplicating memory. - */ - int *vertstart = BKE_strands_calc_vertex_start(parents); - int maxlen = BKE_strands_children_max_length(strands); - float (*strand_deform)[3] = (float (*)[3])MEM_mallocN(sizeof(float) * 3 * maxlen, "child strand buffer"); + int last, end; + float *a, *b; + float t; + + if (cutoff < 0 || cutoff >= (float)(curve->numverts-1)) + return; + + last = (int)cutoff; + end = last + 1; + BLI_assert(last < curve->numverts); + BLI_assert(end < curve->numverts); + a = it_strand->verts[last].co; + b = it_strand->verts[end].co; + t = cutoff - floorf(cutoff); + interp_v3_v3v3(b, a, b, t); +} + +static void haircut_apply(HaircutCacheModifier *hmd, CacheProcessContext *UNUSED(ctx), HaircutCacheData *data, StrandsChildren *strands) +{ + StrandChildIterator it_strand; for (BKE_strand_child_iter_init(&it_strand, strands); BKE_strand_child_iter_valid(&it_strand); BKE_strand_child_iter_next(&it_strand)) { float cutoff = -1.0f; - - BKE_strands_children_strand_deform(&it_strand, parents, vertstart, do_strands_motion, strand_deform); - - if (haircut_find_first_strand_cut(hmd, data, &it_strand, strand_deform, &cutoff)) + if (haircut_find_first_strand_cut(hmd, data, &it_strand, &cutoff)) { it_strand.curve->cutoff = cutoff; + haircut_strand_adjust_tip(&it_strand, cutoff); + } } - - if (vertstart) - MEM_freeN(vertstart); - if (strand_deform) - MEM_freeN(strand_deform); } -static void haircut_process(HaircutCacheModifier *hmd, CacheProcessContext *ctx, CacheProcessData *data, int UNUSED(frame), int UNUSED(frame_prev)) +static void haircut_process(HaircutCacheModifier *hmd, CacheProcessContext *ctx, CacheProcessData *data, int UNUSED(frame), int UNUSED(frame_prev), int process_flag) { + bool do_strands_children = (process_flag & eCacheProcessFlag_DoStrandsChildren); const bool dupli_target = hmd->flag & eHaircutCacheModifier_Flag_InternalTarget; Object *ob = hmd->object; DupliObject *dob; - Strands *parents; StrandsChildren *strands; DerivedMesh *target_dm; float mat[4][4]; HaircutCacheData haircut; - if (!BKE_cache_modifier_find_strands(data->dupcache, ob, hmd->hair_system, NULL, &parents, &strands, NULL)) + /* only applies to children */ + if (!do_strands_children) + return; + if (!BKE_cache_modifier_find_strands(data->dupcache, ob, hmd->hair_system, NULL, NULL, do_strands_children ? &strands : NULL, NULL)) return; if (dupli_target) { @@ -1996,7 +2042,7 @@ static void haircut_process(HaircutCacheModifier *hmd, CacheProcessContext *ctx, haircut_data_get_instances(&haircut, hmd->target, mat, NULL); } - haircut_apply(hmd, ctx, &haircut, parents, strands); + haircut_apply(hmd, ctx, &haircut, strands); haircut_data_free(&haircut); diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c index 0f400d9ca6c..da245506a87 100644 --- a/source/blender/blenkernel/intern/object_dupli.c +++ b/source/blender/blenkernel/intern/object_dupli.c @@ -1732,19 +1732,6 @@ void BKE_dupli_cache_from_group(Scene *scene, Group *group, CacheLibrary *cachel /* ------------------------------------------------------------------------- */ -static void object_dupli_cache_apply_modifiers(Object *ob, Scene *scene) -{ - CacheLibrary *cachelib = ob->cache_library; - int frame = scene->r.cfra; - CacheProcessData process_data; - - process_data.lay = ob->lay; - copy_m4_m4(process_data.mat, ob->obmat); - process_data.dupcache = ob->dup_cache; - - BKE_cache_process_dupli_cache(cachelib, &process_data, scene, ob->dup_group, (float)frame, (float)frame); -} - void BKE_object_dupli_cache_update(Scene *scene, Object *ob, EvaluationContext *eval_ctx, float frame) { bool use_render = (eval_ctx->mode == DAG_EVAL_RENDER); @@ -1772,33 +1759,19 @@ void BKE_object_dupli_cache_update(Scene *scene, Object *ob, EvaluationContext * /* skip reading when the cachelib is baking, avoids unnecessary memory allocation */ if (!(ob->cache_library->flag & CACHE_LIBRARY_BAKING)) { bool do_strands_motion, do_strands_children; + CacheLibrary *cachelib = ob->cache_library; + CacheProcessData process_data; BKE_cache_library_get_read_flags(ob->cache_library, use_render, true, &do_strands_motion, &do_strands_children); /* TODO at this point we could apply animation offset */ BKE_cache_read_dupli_cache(ob->cache_library, ob->dup_cache, scene, ob->dup_group, frame, use_render, true); - if (do_modifiers) { - object_dupli_cache_apply_modifiers(ob, scene); - } + process_data.lay = ob->lay; + copy_m4_m4(process_data.mat, ob->obmat); + process_data.dupcache = ob->dup_cache; - /* Deform child strands to follow parent motion. - * Note that this is an optional feature for viewport/render display, - * strand motion is not applied to raw child data in caches. - */ - if (do_strands_children) { - struct DupliCacheIterator *it = BKE_dupli_cache_iter_new(ob->dup_cache); - for (; BKE_dupli_cache_iter_valid(it); BKE_dupli_cache_iter_next(it)) { - DupliObjectData *dobdata = BKE_dupli_cache_iter_get(it); - DupliObjectDataStrands *link; - - for (link = dobdata->strands.first; link; link = link->next) { - if (link->strands_children) - BKE_strands_children_deform(link->strands_children, link->strands, do_strands_motion); - } - } - BKE_dupli_cache_iter_free(it); - } + BKE_cache_process_dupli_cache(cachelib, &process_data, scene, ob->dup_group, (float)scene->r.cfra, frame, do_modifiers, do_strands_children, do_strands_motion); } ob->dup_cache->flag &= ~DUPCACHE_FLAG_DIRTY; diff --git a/source/blender/blenkernel/intern/strands.c b/source/blender/blenkernel/intern/strands.c index 40e31c5a867..38d35a7309e 100644 --- a/source/blender/blenkernel/intern/strands.c +++ b/source/blender/blenkernel/intern/strands.c @@ -244,18 +244,7 @@ void BKE_strands_children_add_vcols(StrandsChildren *strands, int num_layers) } } -int BKE_strands_children_max_length(StrandsChildren *strands) -{ - StrandChildIterator it_strand; - int maxlen = 0; - for (BKE_strand_child_iter_init(&it_strand, strands); BKE_strand_child_iter_valid(&it_strand); BKE_strand_child_iter_next(&it_strand)) { - if (maxlen < it_strand.curve->numverts) - maxlen = it_strand.curve->numverts; - } - return maxlen; -} - -int *BKE_strands_calc_vertex_start(Strands *strands) +static int *strands_calc_vertex_start(Strands *strands) { int *vertstart = MEM_mallocN(sizeof(int) * strands->totcurves, "strand curves vertex start"); StrandIterator it_strand; @@ -270,35 +259,11 @@ int *BKE_strands_calc_vertex_start(Strands *strands) return vertstart; } -/* shortens the last visible segment to have exact cutoff length */ -static void strands_children_apply_cutoff(StrandChildIterator *it_strand) -{ - StrandsChildCurve *curve = it_strand->curve; - const float cutoff = curve->cutoff; - - int last, end; - float *a, *b; - float t; - - if (cutoff < 0 || cutoff >= (float)(curve->numverts-1)) - return; - - last = (int)cutoff; - end = last + 1; - BLI_assert(last < curve->numverts); - BLI_assert(end < curve->numverts); - - a = it_strand->verts[last].co; - b = it_strand->verts[end].co; - t = cutoff - floorf(cutoff); - interp_v3_v3v3(b, a, b, t); -} - /* 'out' is an optional array to write final positions to, instead of writing back to vertex locations. * It must be at least as large as the number of vertices. */ -static void strands_children_strand_deform_intern(StrandChildIterator *it_strand, Strands *parents, int *vertstart, bool use_motion, float (*out)[3]) +static void strands_children_strand_deform(StrandChildIterator *it_strand, Strands *parents, int *vertstart, bool use_motion, float (*out)[3]) { int i; @@ -357,48 +322,22 @@ static void strands_children_strand_deform_intern(StrandChildIterator *it_strand } } -/* Deform a single strand on-the-fly for intermediate processing. - * 'out' is an optional array to write final positions to, instead of writing back to vertex locations. - * It must be at least as large as the number of vertices. - */ -void BKE_strands_children_strand_deform(StrandChildIterator *it_strand, Strands *parents, int *vertstart, bool use_motion, float (*out)[3]) -{ - StrandChildVertexIterator it_vert; - - /* move child strands from their local root space to object space */ - if (out) { - StrandChildVertexIterator it_vert; - for (BKE_strand_child_vertex_iter_init(&it_vert, it_strand); BKE_strand_child_vertex_iter_valid(&it_vert); BKE_strand_child_vertex_iter_next(&it_vert)) { - mul_v3_m4v3(out[it_vert.index], it_strand->curve->root_matrix, it_vert.vertex->co); - } - } - else { - for (BKE_strand_child_vertex_iter_init(&it_vert, it_strand); BKE_strand_child_vertex_iter_valid(&it_vert); BKE_strand_child_vertex_iter_next(&it_vert)) { - mul_m4_v3(it_strand->curve->root_matrix, it_vert.vertex->co); - } - } - - strands_children_strand_deform_intern(it_strand, parents, vertstart, use_motion, out); -} - void BKE_strands_children_deform(StrandsChildren *strands, Strands *parents, bool use_motion) { int *vertstart = NULL; StrandChildIterator it_strand; if (parents) - vertstart = BKE_strands_calc_vertex_start(parents); + vertstart = strands_calc_vertex_start(parents); for (BKE_strand_child_iter_init(&it_strand, strands); BKE_strand_child_iter_valid(&it_strand); BKE_strand_child_iter_next(&it_strand)) { /* move child strands from their local root space to object space */ StrandChildVertexIterator it_vert; for (BKE_strand_child_vertex_iter_init(&it_vert, &it_strand); BKE_strand_child_vertex_iter_valid(&it_vert); BKE_strand_child_vertex_iter_next(&it_vert)) { - mul_m4_v3(it_strand.curve->root_matrix, it_vert.vertex->co); + mul_v3_m4v3(it_vert.vertex->co, it_strand.curve->root_matrix, it_vert.vertex->base); } - strands_children_strand_deform_intern(&it_strand, parents, vertstart, use_motion, NULL); - - strands_children_apply_cutoff(&it_strand); + strands_children_strand_deform(&it_strand, parents, vertstart, use_motion, NULL); } if (vertstart) |