Revision: 44044
          
http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=44044
Author:   jhk
Date:     2012-02-12 00:25:52 +0000 (Sun, 12 Feb 2012)
Log Message:
-----------
Fix [#29265] Particle Instance: Create Along Paths + Children inconsistent with 
actual children hair particles
* Hair particle rotations weren't calculated properly for particle locations 
along a path and the "particle on path" calculations were not correct in many 
other ways too.
* Now the particle's location along a path is interpolated directly from the 
cached paths if it exist. These paths are always correctly calculated.
* Paths are now cached if a particle instance modifier using the particle 
system with the path option exists.

Modified Paths:
--------------
    trunk/blender/source/blender/blenkernel/intern/particle.c
    trunk/blender/source/blender/blenkernel/intern/particle_system.c

Modified: trunk/blender/source/blender/blenkernel/intern/particle.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/particle.c   2012-02-12 
00:09:48 UTC (rev 44043)
+++ trunk/blender/source/blender/blenkernel/intern/particle.c   2012-02-12 
00:25:52 UTC (rev 44044)
@@ -1365,6 +1365,35 @@
        if(pind->keyed || pind->cache || point_vel)
                mul_v3_fl(result->vel, 1.f/invdt);
 }
+
+static void interpolate_pathcache(ParticleCacheKey *first, float t, 
ParticleCacheKey *result)
+{
+       int i=0;
+       ParticleCacheKey *cur = first;
+
+       /* scale the requested time to fit the entire path even if the path is 
cut early */
+       t *= (first+first->steps)->time;
+
+       while(i<first->steps && cur->time < t)
+               cur++;
+
+       if(cur->time == t)
+               *result = *cur;
+       else {
+               float dt = (t-(cur-1)->time)/(cur->time-(cur-1)->time);
+               interp_v3_v3v3(result->co, (cur-1)->co, cur->co, dt);
+               interp_v3_v3v3(result->vel, (cur-1)->vel, cur->vel, dt);
+               interp_qt_qtqt(result->rot, (cur-1)->rot, cur->rot, dt);
+               result->time = t;
+       }
+
+       /* first is actual base rotation, others are incremental from first */
+       if(cur==first || cur-1==first)
+               copy_qt_qt(result->rot, first->rot);
+       else
+               mul_qt_qtqt(result->rot, first->rot, result->rot);
+}
+
 /************************************************/
 /*                     Particles on a dm                                       
*/
 /************************************************/
@@ -2648,6 +2677,8 @@
                        /* offset the child from the parent position */
                        offset_child(cpa, (ParticleKey*)(key[0]+k), par_rot, 
(ParticleKey*)child, part->childflat, part->childrad);
                }
+
+               child->time = (float)k/(float)ctx->steps;
        }
 
        /* apply effectors */
@@ -3009,6 +3040,8 @@
 
                        if(k==1)
                                copy_v3_v3((ca-1)->vel, ca->vel);
+
+                       ca->time = (float)k/(float)steps;
                }
                /* First rotation is based on emitting face orientation.
                 * This is way better than having flipping rotations resulting
@@ -4013,84 +4046,105 @@
        CLAMP(t, 0.0f, 1.0f);
 
        if(p<totpart){
-               pa = psys->particles + p;
-               pind.keyed = keyed;
-               pind.cache = cached ? psys->pointcache : NULL;
-               pind.epoint = NULL;
-               pind.bspline = (psys->part->flag & PART_HAIR_BSPLINE);
-               /* pind.dm disabled in editmode means we dont get effectors 
taken into
-                * account when subdividing for instance */
-               pind.dm = psys_in_edit_mode(sim->scene, psys) ? NULL : 
psys->hair_out_dm;
-               init_particle_interpolation(sim->ob, psys, pa, &pind);
-               do_particle_interpolation(psys, p, pa, t, &pind, state);
-
-               if(pind.dm) {
-                       mul_m4_v3(sim->ob->obmat, state->co);
-                       mul_mat3_m4_v3(sim->ob->obmat, state->vel);
+               /* interpolate pathcache directly if it exist */
+               if(psys->pathcache) {
+                       ParticleCacheKey result;
+                       interpolate_pathcache(psys->pathcache[p], t, &result);
+                       copy_v3_v3(state->co, result.co);
+                       copy_v3_v3(state->vel, result.vel);
+                       copy_qt_qt(state->rot, result.rot);
                }
-               else if(!keyed && !cached && !(psys->flag & PSYS_GLOBAL_HAIR)) {
-                       if((pa->flag & PARS_REKEY)==0) {
-                               psys_mat_hair_to_global(sim->ob, sim->psmd->dm, 
part->from, pa, hairmat);
-                               mul_m4_v3(hairmat, state->co);
-                               mul_mat3_m4_v3(hairmat, state->vel);
+               /* otherwise interpolate with other means */
+               else {
+                       pa = psys->particles + p;
 
-                               if(sim->psys->effectors && (part->flag & 
PART_CHILD_GUIDE)==0) {
-                                       do_guides(sim->psys->effectors, state, 
p, state->time);
-                                       /* TODO: proper velocity handling */
-                               }
+                       pind.keyed = keyed;
+                       pind.cache = cached ? psys->pointcache : NULL;
+                       pind.epoint = NULL;
+                       pind.bspline = (psys->part->flag & PART_HAIR_BSPLINE);
+                       /* pind.dm disabled in editmode means we dont get 
effectors taken into
+                        * account when subdividing for instance */
+                       pind.dm = psys_in_edit_mode(sim->scene, psys) ? NULL : 
psys->hair_out_dm;
+                       init_particle_interpolation(sim->ob, psys, pa, &pind);
+                       do_particle_interpolation(psys, p, pa, t, &pind, state);
 
-                               if(psys->lattice && edit==0)
-                                       calc_latt_deform(psys->lattice, 
state->co,1.0f);
+                       if(pind.dm) {
+                               mul_m4_v3(sim->ob->obmat, state->co);
+                               mul_mat3_m4_v3(sim->ob->obmat, state->vel);
                        }
+                       else if(!keyed && !cached && !(psys->flag & 
PSYS_GLOBAL_HAIR)) {
+                               if((pa->flag & PARS_REKEY)==0) {
+                                       psys_mat_hair_to_global(sim->ob, 
sim->psmd->dm, part->from, pa, hairmat);
+                                       mul_m4_v3(hairmat, state->co);
+                                       mul_mat3_m4_v3(hairmat, state->vel);
+
+                                       if(sim->psys->effectors && (part->flag 
& PART_CHILD_GUIDE)==0) {
+                                               do_guides(sim->psys->effectors, 
state, p, state->time);
+                                               /* TODO: proper velocity 
handling */
+                                       }
+
+                                       if(psys->lattice && edit==0)
+                                               calc_latt_deform(psys->lattice, 
state->co,1.0f);
+                               }
+                       }
                }
        }
        else if(totchild){
                //invert_m4_m4(imat,ob->obmat);
 
-               cpa=psys->child+p-totpart;
+               /* interpolate childcache directly if it exists */
+               if(psys->childcache) {
+                       ParticleCacheKey result;
+                       interpolate_pathcache(psys->childcache[p-totpart], t, 
&result);
+                       copy_v3_v3(state->co, result.co);
+                       copy_v3_v3(state->vel, result.vel);
+                       copy_qt_qt(state->rot, result.rot);
+               }
+               else {
+                       cpa=psys->child+p-totpart;
 
-               if(state->time < 0.0f)
-                       t = psys_get_child_time(psys, cpa, -state->time, NULL, 
NULL);
+                       if(state->time < 0.0f)
+                               t = psys_get_child_time(psys, cpa, 
-state->time, NULL, NULL);
                
-               if(totchild && part->childtype==PART_CHILD_FACES){
-                       /* part->parents could still be 0 so we can't test with 
totparent */
-                       between=1;
-               }
-               if(between){
-                       int w = 0;
-                       float foffset;
-
-                       /* get parent states */
-                       while(w<4 && cpa->pa[w]>=0){
-                               keys[w].time = state->time;
-                               psys_get_particle_on_path(sim, cpa->pa[w], 
keys+w, 1);
-                               w++;
+                       if(totchild && part->childtype==PART_CHILD_FACES){
+                               /* part->parents could still be 0 so we can't 
test with totparent */
+                               between=1;
                        }
+                       if(between){
+                               int w = 0;
+                               float foffset;
 
-                       /* get the original coordinates (orco) for texture 
usage */
-                       cpa_num=cpa->num;
+                               /* get parent states */
+                               while(w<4 && cpa->pa[w]>=0){
+                                       keys[w].time = state->time;
+                                       psys_get_particle_on_path(sim, 
cpa->pa[w], keys+w, 1);
+                                       w++;
+                               }
+
+                               /* get the original coordinates (orco) for 
texture usage */
+                               cpa_num=cpa->num;
                        
-                       foffset= cpa->foffset;
-                       cpa_fuv = cpa->fuv;
-                       cpa_from = PART_FROM_FACE;
+                               foffset= cpa->foffset;
+                               cpa_fuv = cpa->fuv;
+                               cpa_from = PART_FROM_FACE;
 
-                       
psys_particle_on_emitter(psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa->fuv,foffset,co,0,0,0,orco,0);
+                               
psys_particle_on_emitter(psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa->fuv,foffset,co,0,0,0,orco,0);
 
-                       /* we need to save the actual root position of the 
child for positioning it accurately to the surface of the emitter */
-                       //copy_v3_v3(cpa_1st,co);
+                               /* we need to save the actual root position of 
the child for positioning it accurately to the surface of the emitter */
+                               //copy_v3_v3(cpa_1st,co);
 
-                       //mul_m4_v3(ob->obmat,cpa_1st);
+                               //mul_m4_v3(ob->obmat,cpa_1st);
 
-                       pa = psys->particles + cpa->parent;
+                               pa = psys->particles + cpa->parent;
 
-                       if(part->type == PART_HAIR)
-                               psys_mat_hair_to_global(sim->ob, sim->psmd->dm, 
psys->part->from, pa, hairmat);
-                       else
-                               unit_m4(hairmat);
+                               if(part->type == PART_HAIR)
+                                       psys_mat_hair_to_global(sim->ob, 
sim->psmd->dm, psys->part->from, pa, hairmat);
+                               else
+                                       unit_m4(hairmat);
 
-                       pa=0;
-               }
-               else{
+                               pa=0;
+                       }
+                                                                               
                                                                                
        else{
                        /* get the parent state */
                        keys->time = state->time;
                        psys_get_particle_on_path(sim, cpa->parent, keys,1);
@@ -4114,74 +4168,75 @@
                        }
                }
 
-               /* correct child ipo timing */
-#if 0 // XXX old animation system
-               if((part->flag&PART_ABS_TIME)==0 && part->ipo){
-                       calc_ipo(part->ipo, 100.0f*t);
-                       execute_ipo((ID *)part, part->ipo);
-               }
-#endif // XXX old animation system
+                       /* correct child ipo timing */
+       #if 0 // XXX old animation system
+                       if((part->flag&PART_ABS_TIME)==0 && part->ipo){
+                               calc_ipo(part->ipo, 100.0f*t);
+                               execute_ipo((ID *)part, part->ipo);
+                       }
+       #endif // XXX old animation system
                
-               /* get different child parameters from textures & vgroups */
-               memset(&ctx, 0, sizeof(ParticleThreadContext));
-               ctx.sim = *sim;
-               ctx.dm = psmd->dm;
-               ctx.ma = ma;
-               /* TODO: assign vertex groups */
-               get_child_modifier_parameters(part, &ctx, cpa, cpa_from, 
cpa_num, cpa_fuv, orco, &ptex);
+                       /* get different child parameters from textures & 
vgroups */
+                       memset(&ctx, 0, sizeof(ParticleThreadContext));
+                       ctx.sim = *sim;
+                       ctx.dm = psmd->dm;
+                       ctx.ma = ma;
+                       /* TODO: assign vertex groups */
+                       get_child_modifier_parameters(part, &ctx, cpa, 
cpa_from, cpa_num, cpa_fuv, orco, &ptex);
 
-               if(between){
-                       int w=0;
+                       if(between){
+                               int w=0;
 
-                       state->co[0] = state->co[1] = state->co[2] = 0.0f;
-                       state->vel[0] = state->vel[1] = state->vel[2] = 0.0f;
+                               state->co[0] = state->co[1] = state->co[2] = 
0.0f;
+                               state->vel[0] = state->vel[1] = state->vel[2] = 
0.0f;
 
-                       /* child position is the weighted sum of parent 
positions */
-                       while(w<4 && cpa->pa[w]>=0){
-                               state->co[0] += cpa->w[w] * keys[w].co[0];
-                               state->co[1] += cpa->w[w] * keys[w].co[1];
-                               state->co[2] += cpa->w[w] * keys[w].co[2];
+                               /* child position is the weighted sum of parent 
positions */
+                               while(w<4 && cpa->pa[w]>=0){
+                                       state->co[0] += cpa->w[w] * 
keys[w].co[0];
+                                       state->co[1] += cpa->w[w] * 
keys[w].co[1];
+                                       state->co[2] += cpa->w[w] * 
keys[w].co[2];
 
-                               state->vel[0] += cpa->w[w] * keys[w].vel[0];
-                               state->vel[1] += cpa->w[w] * keys[w].vel[1];
-                               state->vel[2] += cpa->w[w] * keys[w].vel[2];
-                               w++;
+                                       state->vel[0] += cpa->w[w] * 
keys[w].vel[0];
+                                       state->vel[1] += cpa->w[w] * 
keys[w].vel[1];
+                                       state->vel[2] += cpa->w[w] * 
keys[w].vel[2];
+                                       w++;
+                               }
+                               /* apply offset for correct positioning */
+                               //add_v3_v3(state->co, cpa_1st);
                        }
-                       /* apply offset for correct positioning */
-                       //add_v3_v3(state->co, cpa_1st);
-               }
-               else{
-                       /* offset the child from the parent position */
-                       offset_child(cpa, keys, keys->rot, state, 
part->childflat, part->childrad);
-               }
+                       else{
+                               /* offset the child from the parent position */
+                               offset_child(cpa, keys, keys->rot, state, 
part->childflat, part->childrad);
+                       }
 
-               par = keys;
+                       par = keys;
 
-               if(vel)
-                       copy_particle_key(&tstate, state, 1);
+                       if(vel)
+                               copy_particle_key(&tstate, state, 1);
 
-               /* apply different deformations to the child path */

@@ Diff output truncated at 10240 characters. @@
_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to