From 505f5c58cea5a42d8567dc16229b61cbe66a6a1c Mon Sep 17 00:00:00 2001 From: Janne Karhu Date: Sun, 18 Oct 2009 16:55:33 +0000 Subject: [PATCH] Bug fixes: [#19596] Child particle in particle mode show for one redraw, then disappear [#19598] Draw actual particles options draws in wrong location --- source/blender/blenkernel/intern/particle.c | 75 +++++++++++++++++-- .../blender/editors/space_view3d/drawobject.c | 35 +++++---- .../makesrna/intern/rna_sculpt_paint.c | 2 +- 3 files changed, 89 insertions(+), 23 deletions(-) diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index ea8562c0ca8..322904136ea 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -2277,15 +2277,20 @@ static int psys_threads_init_path(ParticleThread *threads, Scene *scene, float c ParticleSettings *part = psys->part; ParticleEditSettings *pset = &scene->toolsettings->particle; int totparent=0, between=0; - int steps = (int)pow(2.0,(double)part->draw_step); + int steps = (int)pow(2.0, (double)part->draw_step); int totchild = psys->totchild; int i, seed, totthread= threads[0].tot; /*---start figuring out what is actually wanted---*/ - if(psys_in_edit_mode(scene, psys)) + if(psys_in_edit_mode(scene, psys)) { + ParticleEditSettings *pset = &scene->toolsettings->particle; + if(psys->renderdata==0 && (psys->edit==NULL || pset->flag & PE_DRAW_PART)==0) totchild=0; + steps = (int)pow(2.0, (double)pset->draw_step); + } + if(totchild && part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES){ totparent=(int)(totchild*part->parents*0.3); @@ -2360,7 +2365,7 @@ static void psys_thread_create_path(ParticleThread *thread, struct ChildParticle ParticleSystem *psys = ctx->sim.psys; ParticleSettings *part = psys->part; ParticleCacheKey **cache= psys->childcache; - ParticleCacheKey **pcache= psys->pathcache; + ParticleCacheKey **pcache= psys_in_edit_mode(ctx->sim.scene, psys) ? psys->edit->pathcache : psys->pathcache; ParticleCacheKey *state, *par = NULL, *key[4]; ParticleData *pa=NULL; ParticleTexture ptex; @@ -2372,6 +2377,9 @@ static void psys_thread_create_path(ParticleThread *thread, struct ChildParticle int k, cpa_num; short cpa_from; + if(!pcache) + return; + if(part->flag & PART_BRANCHING) { branch_begin=rng_getFloat(thread->rng_path); branch_end=branch_begin+(1.0f-branch_begin)*rng_getFloat(thread->rng_path); @@ -2954,7 +2962,7 @@ void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cf float birthtime = 0.0, dietime = 0.0; float t, time = 0.0, keytime = 0.0, frs_sec; - float hairmat[4][4]; + float hairmat[4][4], rotmat[3][3], prev_tangent[3]; int k,i; int steps = (int)pow(2.0, (double)pset->draw_step); int totpart = edit->totpoint; @@ -2998,8 +3006,12 @@ void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cf /*--get the first data points--*/ init_particle_interpolation(ob, psys, pa, &pind); - if(psys) + if(psys) { psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat); + VECCOPY(rotmat[0], hairmat[2]); + VECCOPY(rotmat[1], hairmat[1]); + VECCOPY(rotmat[2], hairmat[0]); + } birthtime = pind.birthtime; dietime = pind.dietime; @@ -3020,9 +3032,55 @@ void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cf do_particle_interpolation(psys, i, pa, t, frs_sec, &pind, &result); /* non-hair points are allready in global space */ - if(psys && !(psys->flag & PSYS_GLOBAL_HAIR)) + if(psys && !(psys->flag & PSYS_GLOBAL_HAIR)) { Mat4MulVecfl(hairmat, result.co); + /* create rotations for proper creation of children */ + if(k) { + float cosangle, angle, tangent[3], normal[3], q[4]; + + if(k == 1) { + /* calculate initial tangent for incremental rotations */ + VECSUB(tangent, ca->co, (ca - 1)->co); + VECCOPY(prev_tangent, tangent); + Normalize(prev_tangent); + + /* First rotation is based on emitting face orientation. */ + /* This is way better than having flipping rotations resulting */ + /* from using a global axis as a rotation pole (vec_to_quat()). */ + /* It's not an ideal solution though since it disregards the */ + /* initial tangent, but taking that in to account will allow */ + /* the possibility of flipping again. -jahka */ + Mat3ToQuat_is_ok(rotmat, (ca-1)->rot); + } + else { + VECSUB(tangent, ca->co, (ca - 1)->co); + Normalize(tangent); + + cosangle= Inpf(tangent, prev_tangent); + + /* note we do the comparison on cosangle instead of + * angle, since floating point accuracy makes it give + * different results across platforms */ + if(cosangle > 0.999999f) { + QUATCOPY((ca - 1)->rot, (ca - 2)->rot); + } + else { + angle= saacos(cosangle); + Crossf(normal, prev_tangent, tangent); + VecRotToQuat(normal, angle, q); + QuatMul((ca - 1)->rot, q, (ca - 2)->rot); + } + + VECCOPY(prev_tangent, tangent); + } + + if(k == steps) + QUATCOPY(ca->rot, (ca - 1)->rot); + } + + } + VECCOPY(ca->co, result.co); ca->vel[0] = ca->vel[1] = 0.0f; @@ -3053,6 +3111,11 @@ void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cf } edit->totcached = totpart; + + if(psys && psys->part->type == PART_HAIR) { + ParticleSimulationData sim = {scene, ob, psys, psys_get_modifier(ob, psys), NULL}; + psys_cache_child_paths(&sim, cfra, 1); + } } /************************************************/ /* Particle Key handling */ diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 78dd53e7271..d2988772abe 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -3658,7 +3658,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv //if(part->flag&PART_GLOB_TIME) cfra=bsystem_time(scene, 0, (float)CFRA, 0.0f); - if(draw_as==PART_DRAW_PATH && psys->pathcache==NULL) + if(draw_as==PART_DRAW_PATH && psys->pathcache==NULL && psys->childcache==NULL) draw_as=PART_DRAW_DOT; /* 3. */ @@ -4009,6 +4009,8 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv if(totchild && (part->draw&PART_DRAW_PARENT)==0) totpart=0; + else if(psys->pathcache==NULL) + totpart=0; /* draw actual/parent particles */ cache=psys->pathcache; @@ -5709,6 +5711,22 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag) } if(ob->pd && ob->pd->forcefield) draw_forcefield(scene, ob); + /* particle mode has to be drawn first so that possible child particles get cached in edit mode */ + if( (warning_recursive==0) && + (flag & DRAW_PICKING)==0 && + (!scene->obedit) + ) { + + if(ob->mode & OB_MODE_PARTICLE_EDIT && ob==OBACT) { + PTCacheEdit *edit = PE_get_current(scene, ob); + if(edit) { + wmLoadMatrix(rv3d->viewmat); + draw_ptcache_edit(scene, v3d, rv3d, ob, edit, dt); + wmMultMatrix(ob->obmat); + } + } + } + /* code for new particle system */ if( (warning_recursive==0) && (ob->particlesystem.first) && @@ -5733,21 +5751,6 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag) //glDepthMask(GL_TRUE); if(col) cpack(col); } - - if( (warning_recursive==0) && - (flag & DRAW_PICKING)==0 && - (!scene->obedit) - ) { - - if(ob->mode & OB_MODE_PARTICLE_EDIT && ob==OBACT) { - PTCacheEdit *edit = PE_get_current(scene, ob); - if(edit) { - wmLoadMatrix(rv3d->viewmat); - draw_ptcache_edit(scene, v3d, rv3d, ob, edit, dt); - wmMultMatrix(ob->obmat); - } - } - } /* draw code for smoke */ if((md = modifiers_findByType(ob, eModifierType_Smoke))) diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.c b/source/blender/makesrna/intern/rna_sculpt_paint.c index 7f8ded7d3ee..481abc983c2 100644 --- a/source/blender/makesrna/intern/rna_sculpt_paint.c +++ b/source/blender/makesrna/intern/rna_sculpt_paint.c @@ -405,7 +405,7 @@ static void rna_def_particle_edit(BlenderRNA *brna) prop= RNA_def_property(srna, "draw_particles", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", PE_DRAW_PART); RNA_def_property_ui_text(prop, "Draw Particles", "Draw actual particles."); - RNA_def_property_update(prop, NC_OBJECT, NULL); + RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, NULL); prop= RNA_def_property(srna, "mirror_x", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", PE_X_MIRROR);