Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJanne Karhu <jhkarh@gmail.com>2009-10-05 17:25:56 +0400
committerJanne Karhu <jhkarh@gmail.com>2009-10-05 17:25:56 +0400
commit3816554cbc1a40dc5199c8e56e45817ec09128d5 (patch)
tree2005de53d609273352eb2d4054cc03b8df258610 /source/blender/blenkernel
parenta3449771476955fd4a27eadd17ff4dce2655cc16 (diff)
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;
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r--source/blender/blenkernel/BKE_bvhutils.h4
-rw-r--r--source/blender/blenkernel/BKE_effect.h1
-rw-r--r--source/blender/blenkernel/BKE_particle.h2
-rw-r--r--source/blender/blenkernel/intern/anim.c43
-rw-r--r--source/blender/blenkernel/intern/boids.c5
-rw-r--r--source/blender/blenkernel/intern/bvhutils.c88
-rw-r--r--source/blender/blenkernel/intern/effect.c21
-rw-r--r--source/blender/blenkernel/intern/modifier.c8
-rw-r--r--source/blender/blenkernel/intern/particle.c81
-rw-r--r--source/blender/blenkernel/intern/particle_system.c28
-rw-r--r--source/blender/blenkernel/intern/pointcache.c24
11 files changed, 270 insertions, 35 deletions
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; a<totgroup; a++, go=go->next) {
- oblist[a] = go->ob;
- obcopylist[a] = *go->ob;
+
+ if(part->draw & PART_DRAW_COUNT_GR && totgroup) {
+ dw = part->dupliweights.first;
+
+ for(a=0; a<totgroup; dw=dw->next) {
+ for(b=0; b<dw->count; b++, a++) {
+ oblist[a] = dw->ob;
+ obcopylist[a] = *dw->ob;
+ }
+ }
+ }
+ else {
+ go = part->dup_group->gobject.first;
+ for(a=0; a<totgroup; a++, go=go->next) {
+ 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<<BPHYS_DATA_AVELOCITY) | (1<<BPHYS_DATA_ROTATION) | (1<<BPHYS_DATA_BOIDS);
- if(psys->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<<BPHYS_DATA_AVELOCITY) | (1<<BPHYS_DATA_ROTATION);
if(psys->part->flag & PART_ROT_DYN)