From 3816554cbc1a40dc5199c8e56e45817ec09128d5 Mon Sep 17 00:00:00 2001 From: Janne Karhu Date: Mon, 5 Oct 2009 13:25:56 +0000 Subject: General particle bug fixes + few small goodies The goodies: * Curves can be used as normal dynamic effectors too with the new "curve" field shape. * Group visualization has optional duplication counts for each object in the specified group. * Object & group visualizations, which are done without taking the dupliobject's global position into account (unless the whole group is used). This is much nicer than the previous behavior, but I added a "Use Global Location" option for those who want to use it the old way. * The active particle system's particles are now drawn a with theme coloured outline instead of pure white. * Added object aligned velocity factors (buttons categorized and re-organized too). Bug fixes: * Absorption didn't work as the ui toggle button was forgotten. * Some other force field ui tweaks. * Crash after adding children and changing trails count. * Display types "cross" and "axis" crashed. * Particles weren't drawn with correct coloring. * Billboards didn't update properly in viewport to camera location changes. * Particle rotation wasn't recreated correctly from point cache. * Changing particles amount crashed sometimes. * Some files with child hair crashed on loading. * Compiler warning fixes. * Adding boids crashed on frame 1; --- source/blender/blenkernel/BKE_bvhutils.h | 4 + source/blender/blenkernel/BKE_effect.h | 1 + source/blender/blenkernel/BKE_particle.h | 2 + source/blender/blenkernel/intern/anim.c | 43 +++++++++-- source/blender/blenkernel/intern/boids.c | 5 +- source/blender/blenkernel/intern/bvhutils.c | 88 ++++++++++++++++++++++ source/blender/blenkernel/intern/effect.c | 21 ++++-- source/blender/blenkernel/intern/modifier.c | 8 +- source/blender/blenkernel/intern/particle.c | 81 ++++++++++++++++++-- source/blender/blenkernel/intern/particle_system.c | 28 +++++-- source/blender/blenkernel/intern/pointcache.c | 24 +++++- 11 files changed, 270 insertions(+), 35 deletions(-) (limited to 'source/blender/blenkernel') diff --git a/source/blender/blenkernel/BKE_bvhutils.h b/source/blender/blenkernel/BKE_bvhutils.h index 66c8d99959a..e2911a30b25 100644 --- a/source/blender/blenkernel/BKE_bvhutils.h +++ b/source/blender/blenkernel/BKE_bvhutils.h @@ -57,6 +57,7 @@ typedef struct BVHTreeFromMesh /* Vertex array, so that callbacks have instante access to data */ struct MVert *vert; + struct MEdge *edge; /* only used for BVHTreeFromMeshEdges */ struct MFace *face; /* radius for raycast */ @@ -96,6 +97,8 @@ BVHTree* bvhtree_from_mesh_verts(struct BVHTreeFromMesh *data, struct DerivedMes */ BVHTree* bvhtree_from_mesh_faces(struct BVHTreeFromMesh *data, struct DerivedMesh *mesh, float epsilon, int tree_type, int axis); +BVHTree* bvhtree_from_mesh_edges(struct BVHTreeFromMesh *data, struct DerivedMesh *mesh, float epsilon, int tree_type, int axis); + /* * Frees data allocated by a call to bvhtree_from_mesh_*. */ @@ -109,6 +112,7 @@ void free_bvhtree_from_mesh(struct BVHTreeFromMesh *data); //Using local coordinates #define BVHTREE_FROM_FACES 0 #define BVHTREE_FROM_VERTICES 1 +#define BVHTREE_FROM_EDGES 2 typedef LinkNode* BVHCache; diff --git a/source/blender/blenkernel/BKE_effect.h b/source/blender/blenkernel/BKE_effect.h index 83ec7c13946..9a0a724ab9a 100644 --- a/source/blender/blenkernel/BKE_effect.h +++ b/source/blender/blenkernel/BKE_effect.h @@ -138,6 +138,7 @@ int get_effector_data(struct EffectorCache *eff, struct EffectorData *efd, struc /* EffectedPoint->flag */ #define PE_WIND_AS_SPEED 1 #define PE_DYNAMIC_ROTATION 2 +#define PE_USE_NORMAL_DATA 4 /* EffectorData->flag */ #define PE_VELOCITY_TO_IMPULSE 1 diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index e0259ff10dd..e9285782a1e 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -201,6 +201,8 @@ struct Object *psys_get_lattice(struct ParticleSimulationData *sim); int psys_in_edit_mode(struct Scene *scene, struct ParticleSystem *psys); int psys_check_enabled(struct Object *ob, struct ParticleSystem *psys); +void psys_check_group_weights(struct ParticleSettings *part); + /* free */ void psys_free_settings(struct ParticleSettings *part); void psys_free_path_cache(struct ParticleSystem *psys, struct PTCacheEdit *edit); diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index bd779935d55..5cd901066f8 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -776,6 +776,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p GroupObject *go; Object *ob=0, **oblist=0, obcopy, *obcopylist=0; DupliObject *dob; + ParticleDupliWeight *dw; ParticleSimulationData sim = {scene, par, psys, psys_get_modifier(par, psys)}; ParticleSettings *part; ParticleData *pa; @@ -783,7 +784,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p ParticleKey state; ParticleCacheKey *cache; float ctime, pa_time, scale = 1.0f; - float tmat[4][4], mat[4][4], pamat[4][4], size=0.0; + float tmat[4][4], mat[4][4], pamat[4][4], vec[3], size=0.0; float (*obmat)[4], (*oldobmat)[4]; int lay, a, b, counter, hair = 0; int totpart, totchild, totgroup=0, pa_num; @@ -813,6 +814,8 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p ((part->ren_as == PART_DRAW_OB && part->dup_ob) || (part->ren_as == PART_DRAW_GR && part->dup_group && part->dup_group->gobject.first))) { + psys_check_group_weights(part); + /* if we have a hair particle system, use the path cache */ if(part->type == PART_HAIR) { if(psys->flag & PSYS_HAIR_DONE) @@ -831,18 +834,37 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p if(part->ren_as==PART_DRAW_GR) { group_handle_recalc_and_update(scene, par, part->dup_group); - for(go=part->dup_group->gobject.first; go; go=go->next) - totgroup++; + if(part->draw & PART_DRAW_COUNT_GR) { + for(dw=part->dupliweights.first; dw; dw=dw->next) + totgroup += dw->count; + } + else { + for(go=part->dup_group->gobject.first; go; go=go->next) + totgroup++; + } /* we also copy the actual objects to restore afterwards, since * where_is_object_time will change the object which breaks transform */ oblist = MEM_callocN(totgroup*sizeof(Object *), "dupgroup object list"); obcopylist = MEM_callocN(totgroup*sizeof(Object), "dupgroup copy list"); - go = part->dup_group->gobject.first; - for(a=0; anext) { - oblist[a] = go->ob; - obcopylist[a] = *go->ob; + + if(part->draw & PART_DRAW_COUNT_GR && totgroup) { + dw = part->dupliweights.first; + + for(a=0; anext) { + for(b=0; bcount; b++, a++) { + oblist[a] = dw->ob; + obcopylist[a] = *dw->ob; + } + } + } + else { + go = part->dup_group->gobject.first; + for(a=0; anext) { + oblist[a] = go->ob; + obcopylist[a] = *go->ob; + } } } else { @@ -936,11 +958,18 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p else { /* to give ipos in object correct offset */ where_is_object_time(scene, ob, ctime-pa_time); + + VECCOPY(vec, obmat[3]); + obmat[3][0] = obmat[3][1] = obmat[3][2] = 0.0f; Mat4CpyMat4(mat, pamat); Mat4MulMat4(tmat, obmat, mat); Mat4MulFloat3((float *)tmat, size*scale); + + if(part->draw & PART_DRAW_GLOBAL_OB) + VECADD(tmat[3], tmat[3], vec); + if(par_space_mat) Mat4MulMat4(mat, tmat, par_space_mat); else diff --git a/source/blender/blenkernel/intern/boids.c b/source/blender/blenkernel/intern/boids.c index 76824d3a34a..712fb13cfc0 100644 --- a/source/blender/blenkernel/intern/boids.c +++ b/source/blender/blenkernel/intern/boids.c @@ -73,13 +73,11 @@ static int rule_goal_avoid(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, { BoidRuleGoalAvoid *gabr = (BoidRuleGoalAvoid*) rule; BoidSettings *boids = bbd->part->boids; - Object *priority_ob = NULL; BoidParticle *bpa = pa->boid; EffectedPoint epoint; ListBase *effectors = bbd->sim->psys->effectors; EffectorCache *cur, *eff = NULL; EffectorData efd, cur_efd; - float vec[3] = {0.0f, 0.0f, 0.0f}, loc[3] = {0.0f, 0.0f, 0.0f}; float mul = (rule->type == eBoidRuleType_Avoid ? 1.0 : -1.0); float priority = 0.0f, len = 0.0f; int ret = 0; @@ -1051,9 +1049,8 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa) float wanted_dir[3]; float q[4], mat[3][3]; /* rotation */ float ground_co[3] = {0.0f, 0.0f, 0.0f}, ground_nor[3] = {0.0f, 0.0f, 1.0f}; - float force[3] = {0.0f, 0.0f, 0.0f}, tvel[3] = {0.0f, 0.0f, 1.0f}; + float force[3] = {0.0f, 0.0f, 0.0f}; float pa_mass=bbd->part->mass, dtime=bbd->dfra*bbd->timestep; - int p = pa - bbd->sim->psys->particles; set_boid_values(&val, boids, pa); diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c index d9e005811d0..f2526231d50 100644 --- a/source/blender/blenkernel/intern/bvhutils.c +++ b/source/blender/blenkernel/intern/bvhutils.c @@ -479,6 +479,32 @@ static void mesh_faces_spherecast(void *userdata, int index, const BVHTreeRay *r } while(t2); } +// Callback to bvh tree nearest point. The tree must bust have been built using bvhtree_from_mesh_edges. +// userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree. +static void mesh_edges_nearest_point(void *userdata, int index, const float *co, BVHTreeNearest *nearest) +{ + const BVHTreeFromMesh *data = (BVHTreeFromMesh*) userdata; + MVert *vert = data->vert; + MEdge *edge = data->edge + index; + float nearest_tmp[3], dist; + + float *t0, *t1; + t0 = vert[ edge->v1 ].co; + t1 = vert[ edge->v2 ].co; + + PclosestVL3Dfl(nearest_tmp, co, t0, t1); + dist = VecLenf(nearest_tmp, co); + + if(dist < nearest->dist) + { + nearest->index = index; + nearest->dist = dist; + VECCOPY(nearest->co, nearest_tmp); + VecSubf(nearest->no, t0, t1); + Normalize(nearest->no); + } +} + /* * BVH builders */ @@ -605,6 +631,68 @@ BVHTree* bvhtree_from_mesh_faces(BVHTreeFromMesh *data, DerivedMesh *mesh, float } +// Builds a bvh tree.. where nodes are the faces of the given mesh. +BVHTree* bvhtree_from_mesh_edges(BVHTreeFromMesh *data, DerivedMesh *mesh, float epsilon, int tree_type, int axis) +{ + BVHTree *tree = bvhcache_find(&mesh->bvhCache, BVHTREE_FROM_EDGES); + + //Not in cache + if(tree == NULL) + { + int i; + int numEdges= mesh->getNumEdges(mesh); + MVert *vert = mesh->getVertDataArray(mesh, CD_MVERT); + MEdge *edge = mesh->getEdgeDataArray(mesh, CD_MEDGE); + + if(vert != NULL && edge != NULL) + { + /* Create a bvh-tree of the given target */ + tree = BLI_bvhtree_new(numEdges, epsilon, tree_type, axis); + if(tree != NULL) + { + for(i = 0; i < numEdges; i++) + { + float co[4][3]; + VECCOPY(co[0], vert[ edge[i].v1 ].co); + VECCOPY(co[1], vert[ edge[i].v2 ].co); + + BLI_bvhtree_insert(tree, i, co[0], 2); + } + BLI_bvhtree_balance(tree); + + //Save on cache for later use +// printf("BVHTree built and saved on cache\n"); + bvhcache_insert(&mesh->bvhCache, tree, BVHTREE_FROM_EDGES); + } + } + } + else + { +// printf("BVHTree is already build, using cached tree\n"); + } + + + //Setup BVHTreeFromMesh + memset(data, 0, sizeof(*data)); + data->tree = tree; + + if(data->tree) + { + data->cached = TRUE; + + data->nearest_callback = mesh_edges_nearest_point; + data->raycast_callback = NULL; + + data->mesh = mesh; + data->vert = mesh->getVertDataArray(mesh, CD_MVERT); + data->edge = mesh->getEdgeDataArray(mesh, CD_MEDGE); + + data->sphere_radius = epsilon; + } + return data->tree; + +} + // Frees data allocated by a call to bvhtree_from_mesh_*. void free_bvhtree_from_mesh(struct BVHTreeFromMesh *data) { diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index 7cc65de827a..9b648e2c05c 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -228,6 +228,8 @@ static void precalculate_effector(EffectorCache *eff) } else if(eff->pd->shape == PFIELD_SHAPE_SURFACE) { eff->surmd = (SurfaceModifierData *)modifiers_findByType ( eff->ob, eModifierType_Surface ); + if(eff->ob->type == OB_CURVE) + eff->flag |= PE_USE_NORMAL_DATA; } else if(eff->psys) psys_update_particle_tree(eff->psys, eff->scene->r.cfra); @@ -518,7 +520,7 @@ float effector_falloff(EffectorCache *eff, EffectorData *efd, EffectedPoint *poi float falloff = weights ? weights->weight[0] * weights->weight[eff->pd->forcefield] : 1.0f; float fac, r_fac; - fac = Inpf(efd->nor, efd->vec_to_point); + fac = Inpf(efd->nor, efd->vec_to_point2); if(eff->pd->zdir == PFIELD_Z_POS && fac < 0.0f) falloff=0.0f; @@ -691,10 +693,16 @@ int get_effector_data(EffectorCache *eff, EffectorData *efd, EffectedPoint *poin VecSubf(efd->vec_to_point, point->loc, efd->loc); efd->distance = VecLength(efd->vec_to_point); - /* for some effectors we need the object center every time */ - VecSubf(efd->vec_to_point2, point->loc, eff->ob->obmat[3]); - VECCOPY(efd->nor2, eff->ob->obmat[2]); - Normalize(efd->nor2); + if(eff->flag & PE_USE_NORMAL_DATA) { + VECCOPY(efd->vec_to_point2, efd->vec_to_point); + VECCOPY(efd->nor2, efd->nor); + } + else { + /* for some effectors we need the object center every time */ + VecSubf(efd->vec_to_point2, point->loc, eff->ob->obmat[3]); + VECCOPY(efd->nor2, eff->ob->obmat[2]); + Normalize(efd->nor2); + } } return ret; @@ -835,8 +843,7 @@ void do_physical_effector(EffectorCache *eff, EffectorData *efd, EffectedPoint * switch(pd->forcefield){ case PFIELD_WIND: - Normalize(force); - strength *= (Inpf(force, efd->nor) >= 0.0f ? 1.0f : -1.0f); + VECCOPY(force, efd->nor); VecMulf(force, strength * efd->falloff); break; case PFIELD_FORCE: diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 3b47c2f1830..55fb9f45bb3 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -6211,7 +6211,8 @@ static void surfaceModifier_freeData(ModifierData *md) MEM_freeN(surmd->bvhtree); } - surmd->dm->release(surmd->dm); + if(surmd->dm) + surmd->dm->release(surmd->dm); if(surmd->x) MEM_freeN(surmd->x); @@ -6298,7 +6299,10 @@ static void surfaceModifier_deformVerts( else surmd->bvhtree = MEM_callocN(sizeof(BVHTreeFromMesh), "BVHTreeFromMesh"); - bvhtree_from_mesh_faces(surmd->bvhtree, surmd->dm, 0.0, 2, 6); + if(surmd->dm->getNumFaces(surmd->dm)) + bvhtree_from_mesh_faces(surmd->bvhtree, surmd->dm, 0.0, 2, 6); + else + bvhtree_from_mesh_edges(surmd->bvhtree, surmd->dm, 0.0, 2, 6); } } diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index f4f5a1364a3..011d5c3f134 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -37,6 +37,7 @@ #include "DNA_scene_types.h" #include "DNA_boid_types.h" +#include "DNA_group_types.h" #include "DNA_particle_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" @@ -63,6 +64,7 @@ #include "BKE_cloth.h" #include "BKE_effect.h" #include "BKE_global.h" +#include "BKE_group.h" #include "BKE_main.h" #include "BKE_lattice.h" #include "BKE_utildefines.h" @@ -296,6 +298,60 @@ int psys_check_enabled(Object *ob, ParticleSystem *psys) return 1; } +void psys_check_group_weights(ParticleSettings *part) +{ + ParticleDupliWeight *dw, *tdw; + GroupObject *go; + int current = 0; + + if(part->ren_as == PART_DRAW_GR && part->dup_group && part->dup_group->gobject.first) { + /* first remove all weights that don't have an object in the group */ + dw = part->dupliweights.first; + while(dw) { + if(!object_in_group(dw->ob, part->dup_group)) { + tdw = dw->next; + BLI_freelinkN(&part->dupliweights, dw); + dw = tdw; + } + else + dw = dw->next; + } + + /* then add objects in the group to new list */ + go = part->dup_group->gobject.first; + while(go) { + dw = part->dupliweights.first; + while(dw && dw->ob != go->ob) + dw = dw->next; + + if(!dw) { + dw = MEM_callocN(sizeof(ParticleDupliWeight), "ParticleDupliWeight"); + dw->ob = go->ob; + dw->count = 1; + BLI_addtail(&part->dupliweights, dw); + } + + go = go->next; + } + + dw = part->dupliweights.first; + for(; dw; dw=dw->next) { + if(dw->flag & PART_DUPLIW_CURRENT) { + current = 1; + break; + } + } + + if(!current) { + dw = part->dupliweights.first; + if(dw) + dw->flag |= PART_DUPLIW_CURRENT; + } + } + else { + BLI_freelistN(&part->dupliweights); + } +} /************************************************/ /* Freeing stuff */ /************************************************/ @@ -307,6 +363,8 @@ void psys_free_settings(ParticleSettings *part) if(part->effector_weights) MEM_freeN(part->effector_weights); + BLI_freelistN(&part->dupliweights); + boid_free_settings(part->boids); } @@ -439,6 +497,9 @@ void psys_free_pdd(ParticleSystem *psys) if(psys->pdd->vedata) MEM_freeN(psys->pdd->vedata); psys->pdd->vedata = NULL; + + psys->pdd->totpoint = 0; + psys->pdd->tot_vec_size = 0; } } /* free everything */ @@ -2047,10 +2108,10 @@ static void do_rough_end(float *loc, float mat[4][4], float t, float fac, float float roughfac; roughfac=fac*(float)pow((double)t,shape); - VECCOPY(rough,loc); + Vec2Copyf(rough,loc); rough[0]=-1.0f+2.0f*rough[0]; rough[1]=-1.0f+2.0f*rough[1]; - VecMulf(rough,roughfac); + Vec2Mulf(rough,roughfac); VECADDFAC(state->co,state->co,mat[0],rough[0]); VECADDFAC(state->co,state->co,mat[1],rough[1]); @@ -3235,6 +3296,9 @@ static void default_particle_settings(ParticleSettings *part) part->size=0.05; part->childsize=1.0; + part->rotmode = PART_ROT_VEL; + part->avemode = PART_AVE_SPIN; + part->child_nbr=10; part->ren_child_nbr=100; part->childrad=0.2f; @@ -3788,6 +3852,7 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey * /* 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 */ @@ -3856,6 +3921,7 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta ChildParticle *cpa = NULL; float cfra; int totpart = psys->totpart; + float timestep = psys_get_timestep(sim); /* negative time means "use current time" */ cfra = state->time > 0 ? state->time : bsystem_time(sim->scene, 0, (float)sim->scene->r.cfra, 0.0); @@ -3924,13 +3990,14 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta calc_latt_deform(sim->psys->lattice, state->co,1.0f); } else{ - if(pa->state.time==state->time || ELEM(part->phystype,PART_PHYS_NO,PART_PHYS_KEYED)) + if(pa->state.time==state->time || ELEM(part->phystype,PART_PHYS_NO,PART_PHYS_KEYED) + || pa->prev_state.time <= 0.0f) copy_particle_key(state, &pa->state, 1); else if(pa->prev_state.time==state->time) copy_particle_key(state, &pa->prev_state, 1); else { /* let's interpolate to try to be as accurate as possible */ - if(pa->state.time + 1.0f > state->time && pa->prev_state.time - 1.0f < state->time) { + if(pa->state.time + 2.0f > state->time && pa->prev_state.time - 2.0f < state->time) { ParticleKey keys[4]; float dfra, keytime, frs_sec = sim->scene->r.frs_sec; @@ -3949,13 +4016,13 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta keytime = (state->time - keys[1].time) / dfra; /* convert velocity to timestep size */ - VecMulf(keys[1].vel, dfra / frs_sec); - VecMulf(keys[2].vel, dfra / frs_sec); + VecMulf(keys[1].vel, dfra * timestep); + VecMulf(keys[2].vel, dfra * timestep); psys_interpolate_particle(-1, keys, keytime, state, 1); /* convert back to real velocity */ - VecMulf(state->vel, frs_sec / dfra); + VecMulf(state->vel, 1.0f / (dfra * timestep)); VecLerpf(state->ave, keys[1].ave, keys[2].ave, keytime); QuatInterpol(state->rot, keys[1].rot, keys[2].rot, keytime); diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index d757372f17b..45050127582 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -183,6 +183,8 @@ static void realloc_particles(ParticleSimulationData *sim, int new_totpart) if(totpart && totpart != psys->totpart) { newpars= MEM_callocN(totpart*sizeof(ParticleData), "particles"); + if(psys->part->phystype == PART_PHYS_BOIDS) + newboids= MEM_callocN(totpart*sizeof(BoidParticle), "boid particles"); if(psys->particles) { totsaved=MIN2(psys->totpart,totpart); @@ -215,13 +217,12 @@ static void realloc_particles(ParticleSimulationData *sim, int new_totpart) } psys->particles=newpars; + psys->totpart=totpart; if(newboids) { LOOP_PARTICLES pa->boid = newboids++; } - - psys->totpart=totpart; } if(psys->child) { @@ -1660,7 +1661,7 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime, ParticleKey state; //IpoCurve *icu=0; // XXX old animation system float fac, phasefac, nor[3]={0,0,0},loc[3],vel[3]={0.0,0.0,0.0},rot[4],q2[4]; - float r_vel[3],r_ave[3],r_rot[4],p_vel[3]={0.0,0.0,0.0}; + float r_vel[3],r_ave[3],r_rot[4],vec[3],p_vel[3]={0.0,0.0,0.0}; float x_vec[3]={1.0,0.0,0.0}, utan[3]={0.0,1.0,0.0}, vtan[3]={0.0,0.0,1.0}, rot_vec[3]={0.0,0.0,0.0}; float q_phase[4], r_phase; int p = pa - psys->particles; @@ -1773,7 +1774,7 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime, } } - if(part->phystype==PART_PHYS_BOIDS) { + if(part->phystype==PART_PHYS_BOIDS && pa->boid) { BoidParticle *bpa = pa->boid; float dvec[3], q[4], mat[3][3]; @@ -1839,6 +1840,23 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime, VECADDFAC(vel,vel,vtan,part->tanfac); //VECADDFAC(vel,vel,vtan,part->tanfac*(vg_tan?psys_particle_value_from_verts(sim->psmd->dm,part->from,pa,vg_tan):1.0f)); + /* *emitter object orientation */ + if(part->ob_vel[0]!=0.0) { + VECCOPY(vec, ob->obmat[0]); + Normalize(vec); + VECADDFAC(vel, vel, vec, part->ob_vel[0]); + } + if(part->ob_vel[1]!=0.0) { + VECCOPY(vec, ob->obmat[1]); + Normalize(vec); + VECADDFAC(vel, vel, vec, part->ob_vel[1]); + } + if(part->ob_vel[2]!=0.0) { + VECCOPY(vec, ob->obmat[2]); + Normalize(vec); + VECADDFAC(vel, vel, vec, part->ob_vel[2]); + } + /* *texture */ /* TODO */ @@ -3135,7 +3153,7 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra) ParticleSystem *psys = sim->psys; ParticleSettings *part=psys->part; KDTree *tree=0; - //IpoCurve *icu_esize= NULL; //=find_ipocurve(part->ipo,PART_EMIT_SIZE); // XXX old animation system + //IpoCurve *icu_esize=find_ipocurve(part->ipo,PART_EMIT_SIZE); // XXX old animation system /* Material *ma=give_current_material(sim->ob, part->omat); */ BoidBrainData bbd; PARTICLE_P; diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index bffe4566f74..fa0d5cba604 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -269,7 +269,7 @@ static void ptcache_read_particle(int index, void *psys_v, void **data, float fr /* determine rotation from velocity */ if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_ROTATION]) { - vectoquat(pa->state.vel, OB_POSX, OB_POSZ, pa->state.rot); + vectoquat(pa->state.vel, OB_NEGX, OB_POSZ, pa->state.rot); } } static void ptcache_interpolate_particle(int index, void *psys_v, void **data, float frs_sec, float cfra, float cfra1, float cfra2, float *old_data) @@ -292,6 +292,23 @@ static void ptcache_interpolate_particle(int index, void *psys_v, void **data, f else BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2); + /* determine velocity from previous location */ + if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_VELOCITY]) { + if(keys[1].time > keys[2].time) { + VecSubf(keys[2].vel, keys[1].co, keys[2].co); + VecMulf(keys[2].vel, (keys[1].time - keys[2].time) / frs_sec); + } + else { + VecSubf(keys[2].vel, keys[2].co, keys[1].co); + VecMulf(keys[2].vel, (keys[2].time - keys[1].time) / frs_sec); + } + } + + /* determine rotation from velocity */ + if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_ROTATION]) { + vectoquat(keys[2].vel, OB_NEGX, OB_POSZ, keys[2].rot); + } + if(cfra > pa->time) cfra1 = MAX2(cfra1, pa->time); @@ -301,7 +318,7 @@ static void ptcache_interpolate_particle(int index, void *psys_v, void **data, f VecMulf(keys[2].vel, dfra / frs_sec); psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, &pa->state, 1); - QuatInterpol(pa->state.rot, keys[1].rot,keys[2].rot, (cfra - cfra1) / dfra); + QuatInterpol(pa->state.rot, keys[1].rot, keys[2].rot, (cfra - cfra1) / dfra); VecMulf(pa->state.vel, frs_sec / dfra); @@ -594,7 +611,8 @@ void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *p if(psys->part->phystype == PART_PHYS_BOIDS) pid->data_types|= (1<part->rotmode || psys->part->avemode) + if(psys->part->rotmode!=PART_ROT_VEL + || psys->part->avemode!=PART_AVE_SPIN || psys->part->avefac!=0.0f) pid->data_types|= (1<part->flag & PART_ROT_DYN) -- cgit v1.2.3