diff options
author | Ton Roosendaal <ton@blender.org> | 2004-07-11 17:17:03 +0400 |
---|---|---|
committer | Ton Roosendaal <ton@blender.org> | 2004-07-11 17:17:03 +0400 |
commit | 612eb7c1931a903552ba9e7cc6c0a3e5a07c5e5e (patch) | |
tree | 04ebfbac5d85b9b19f85f2714fc7e15d8ca392e4 /source | |
parent | 6b092cf8adc27c671b5e0afcd919d20c1c42df1c (diff) |
- Simple optimizing for deflected (collision) particles. It now caches
transformation (from vertex -> world space), used defines for vecadd and
vecsub, and intersects quads more efficient.
Result is about 2 times faster.
- Added draw mode for empty used as forcefield
- added defines VECADD and VECSUB
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenkernel/BKE_utildefines.h | 5 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/effect.c | 230 | ||||
-rw-r--r-- | source/blender/include/blendef.h | 3 | ||||
-rw-r--r-- | source/blender/src/drawobject.c | 19 |
4 files changed, 175 insertions, 82 deletions
diff --git a/source/blender/blenkernel/BKE_utildefines.h b/source/blender/blenkernel/BKE_utildefines.h index 75b70d9e090..97cd46aa3fc 100644 --- a/source/blender/blenkernel/BKE_utildefines.h +++ b/source/blender/blenkernel/BKE_utildefines.h @@ -74,6 +74,11 @@ #define VECCOPY(v1,v2) {*(v1)= *(v2); *(v1+1)= *(v2+1); *(v1+2)= *(v2+2);} #define QUATCOPY(v1,v2) {*(v1)= *(v2); *(v1+1)= *(v2+1); *(v1+2)= *(v2+2); *(v1+3)= *(v2+3);} +#define VECADD(v1,v2,v3) {*(v1)= *(v2) + *(v3); *(v1+1)= *(v2+1) + *(v3+1); *(v1+2)= *(v2+2) + *(v3+2);} +#define VECSUB(v1,v2,v3) {*(v1)= *(v2) - *(v3); *(v1+1)= *(v2+1) - *(v3+1); *(v1+2)= *(v2+2) - *(v3+2);} + +#define INPR(v1, v2) ( (v1)[0]*(v2)[0] + (v1)[1]*(v2)[1] + (v1)[2]*(v2)[2] ) + #define INIT_MINMAX(min, max) (min)[0]= (min)[1]= (min)[2]= 1.0e30; (max)[0]= (max)[1]= (max)[2]= -1.0e30; #define DO_MINMAX(vec, min, max) if( (min)[0]>(vec)[0] ) (min)[0]= (vec)[0]; \ diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index b97b565b98d..699f6670a23 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -314,7 +314,7 @@ void particle_tex(MTex *mtex, PartEff *paf, float *co, float *no) float old; externtex(mtex, co); - + if(paf->texmap==PAF_TEXINT) { Tin*= paf->texfac; no[0]+= Tin*paf->defvec[0]; @@ -346,27 +346,33 @@ void particle_tex(MTex *mtex, PartEff *paf, float *co, float *no) } } -static float linetriangle(float p1[3], float p2[3], float v0[3], float v1[3], float v2[3]) +static int linetriangle(float p1[3], float p2[3], float v0[3], float v1[3], float v2[3], float *labda) { - float p[3], s[3], d[3], e1[3], e2[3], q[3]; - float a, f, u, v, t; - - VecSubf(e1, v1, v0); - VecSubf(e2, v2, v0); - VecSubf(d, p2, p1); - Crossf(p, d, e2); - a = Inpf(e1, p); - if ((a > -0.000001) && (a < 0.000001)) return -1; - f = 1/a; - VecSubf(s, p1, v0); - u = f * Inpf(s, p); - if ((u < 0.0)||(u > 1.0)) return -1; - Crossf(q, s, e1); - t = f * Inpf(e2, q); - if ((t < 0.0)||(t > 1.0)) return -1; - v = f * Inpf(d, q); - if ((v < 0.0)||((u + v) > 1.0)) return -1; - return t; + float p[3], s[3], d[3], e1[3], e2[3], q[3]; + float a, f, u, v; + + VECSUB(e1, v1, v0); + VECSUB(e2, v2, v0); + VECSUB(d, p2, p1); + + Crossf(p, d, e2); + a = INPR(e1, p); + if ((a > -0.000001) && (a < 0.000001)) return 0; + f = 1.0/a; + + VECSUB(s, p1, v0); + + Crossf(q, s, e1); + *labda = f * INPR(e2, q); + if ((*labda < 0.0)||(*labda > 1.0)) return 0; + + u = f * INPR(s, p); + if ((u < 0.0)||(u > 1.0)) return 0; + + v = f * INPR(d, q); + if ((v < 0.0)||((u + v) > 1.0)) return 0; + + return 1; } static void get_effector(float opco[], float force[], float speed[], float cur_time, unsigned int par_layer) @@ -424,7 +430,7 @@ static void get_effector(float opco[], float force[], float speed[], float cur_t ffall_val = ob->pd->f_power; /* Now calculate the gravitational force */ - VecSubf(vect_to_vert, obloc, opco); + VECSUB(vect_to_vert, obloc, opco); distance = Normalise(vect_to_vert); /* Limit minimum distance to vertex so that */ @@ -460,7 +466,7 @@ static void get_effector(float opco[], float force[], float speed[], float cur_t ffall_val = ob->pd->f_power; /* Now calculate the vortex force */ - VecSubf(vect_to_vert, obloc, opco); + VECSUB(vect_to_vert, obloc, opco); distance = Normalise(vect_to_vert); @@ -481,6 +487,27 @@ static void get_effector(float opco[], float force[], float speed[], float cur_t } } +static void cache_object_vertices(Object *ob) +{ + Mesh *me; + MVert *mvert; + float *fp; + int a; + + me= ob->data; + if(me->totvert==0) return; + + fp= ob->sumohandle= MEM_mallocN(3*sizeof(float)*me->totvert, "cache particles"); + mvert= me->mvert; + a= me->totvert; + while(a--) { + VECCOPY(fp, mvert->co); + Mat4MulVecfl(ob->obmat, fp); + mvert++; + fp+= 3; + } +} + static int get_deflection(float opco[3], float npco[3], float opno[3], float npno[3], float life, float force[3], int def_depth, float cur_time, unsigned int par_layer, int *last_object, @@ -496,7 +523,7 @@ static int get_deflection(float opco[3], float npco[3], float opno[3], Object *ob, *deflection_object = NULL; Mesh *def_mesh; MFace *mface, *deflection_face = NULL; - float *v1, *v2, *v3, *v4; + float *v1, *v2, *v3, *v4, *vcache=NULL; float nv1[3], nv2[3], nv3[3], nv4[3], edge1[3], edge2[3]; float dv1[3], dv2[3], dv3[3]; float vect_to_int[3], refl_vel[3]; @@ -535,58 +562,83 @@ static int get_deflection(float opco[3], float npco[3], float opno[3], d_face = d_face + 1; mface= def_mesh->mface; a = def_mesh->totface; - /*Find out where the object is at this time*/ - cur_frame = G.scene->r.cfra; - G.scene->r.cfra = (short)cur_time; - where_is_object_time(ob, cur_time); - G.scene->r.cfra = cur_frame; - /*Pass the values from ob->obmat to mat*/ - /*and the location values to obloc */ - Mat3CpyMat4(mat,ob->obmat); - obloc[0] = ob->obmat[3][0]; - obloc[1] = ob->obmat[3][1]; - obloc[2] = ob->obmat[3][2]; - + + + if(ob->parent==NULL && ob->ipo==NULL) { // static + if(ob->sumohandle==NULL) cache_object_vertices(ob); + vcache= ob->sumohandle; + } + else { + /*Find out where the object is at this time*/ + cur_frame = G.scene->r.cfra; + G.scene->r.cfra = (short)cur_time; + where_is_object_time(ob, cur_time); + G.scene->r.cfra = cur_frame; + + /*Pass the values from ob->obmat to mat*/ + /*and the location values to obloc */ + Mat3CpyMat4(mat,ob->obmat); + obloc[0] = ob->obmat[3][0]; + obloc[1] = ob->obmat[3][1]; + obloc[2] = ob->obmat[3][2]; + } + while (a--) { - /* Calculate the global co-ordinates of the vertices*/ - v1= (def_mesh->mvert+(mface->v1))->co; - v2= (def_mesh->mvert+(mface->v2))->co; - v3= (def_mesh->mvert+(mface->v3))->co; - v4= (def_mesh->mvert+(mface->v4))->co; - - VECCOPY(nv1, v1); - VECCOPY(nv2, v2); - VECCOPY(nv3, v3); - VECCOPY(nv4, v4); - - /*Apply the objects deformation matrix*/ - Mat3MulVecfl(mat, nv1); - Mat3MulVecfl(mat, nv2); - Mat3MulVecfl(mat, nv3); - Mat3MulVecfl(mat, nv4); - - VecAddf(nv1, nv1, obloc); - VecAddf(nv2, nv2, obloc); - VecAddf(nv3, nv3, obloc); - VecAddf(nv4, nv4, obloc); - + if(vcache) { + v1= vcache+ 3*(mface->v1); + VECCOPY(nv1, v1); + v1= vcache+ 3*(mface->v2); + VECCOPY(nv2, v1); + v1= vcache+ 3*(mface->v3); + VECCOPY(nv3, v1); + v1= vcache+ 3*(mface->v4); + VECCOPY(nv4, v1); + } + else { + /* Calculate the global co-ordinates of the vertices*/ + v1= (def_mesh->mvert+(mface->v1))->co; + v2= (def_mesh->mvert+(mface->v2))->co; + v3= (def_mesh->mvert+(mface->v3))->co; + v4= (def_mesh->mvert+(mface->v4))->co; + + VECCOPY(nv1, v1); + VECCOPY(nv2, v2); + VECCOPY(nv3, v3); + VECCOPY(nv4, v4); + + /*Apply the objects deformation matrix*/ + Mat3MulVecfl(mat, nv1); + Mat3MulVecfl(mat, nv2); + Mat3MulVecfl(mat, nv3); + Mat3MulVecfl(mat, nv4); + + VECADD(nv1, nv1, obloc); + VECADD(nv2, nv2, obloc); + VECADD(nv3, nv3, obloc); + VECADD(nv4, nv4, obloc); + } + deflected_now = 0; - - t = - 1; - t = linetriangle(opco, npco, nv1, nv2, nv3); - if ((t > 0)&&(t < min_t)) { - deflected = 1; - deflected_now = 1; + + t= 0.5; // this is labda of line, can use it optimize quad intersection + + if( linetriangle(opco, npco, nv1, nv2, nv3, &t) ) { + if (t < min_t) { + deflected = 1; + deflected_now = 1; + } } - else if (mface->v4) { - t = linetriangle(opco, npco, nv1, nv3, nv4); - if ((t > 0)&&(t < min_t)) { - deflected = 1; - deflected_now = 2; + else if (mface->v4 && (t>=0.0 && t<=1.0)) { + if( linetriangle(opco, npco, nv1, nv3, nv4, &t) ) { + if (t < min_t) { + deflected = 1; + deflected_now = 2; + } } } - if ((deflected_now > 0)&&(t < min_t)) { + + if ((deflected_now > 0) && (t < min_t)) { min_t = t; ds_object = d_object; ds_face = d_face; @@ -629,14 +681,14 @@ static int get_deflection(float opco[3], float npco[3], float opno[3], /* Now for the second part of the deflection code - work out the new speed */ /* and position of the particle if a collision occurred */ if (deflected) { - VecSubf(edge1, dv1, dv2); - VecSubf(edge2, dv3, dv2); + VECSUB(edge1, dv1, dv2); + VECSUB(edge2, dv3, dv2); Crossf(d_nvect, edge2, edge1); n_mag = Normalise(d_nvect); - dk_plane = Inpf(d_nvect, nv1); - dk_point1 = Inpf(d_nvect,opco); + dk_plane = INPR(d_nvect, nv1); + dk_point1 = INPR(d_nvect,opco); - VecSubf(d_intersect_vect, npco, opco); + VECSUB(d_intersect_vect, npco, opco); d_intersect_co[0] = opco[0] + (min_t * (npco[0] - opco[0])); d_intersect_co[1] = opco[1] + (min_t * (npco[1] - opco[1])); @@ -648,7 +700,7 @@ static int get_deflection(float opco[3], float npco[3], float opno[3], mag_iv = Normalise(d_intersect_vect); VECCOPY(npco, d_intersect_co); - VecSubf(vect_to_int, opco, d_intersect_co); + VECSUB(vect_to_int, opco, d_intersect_co); first_dist = Normalise(vect_to_int); /* Work out the lengths of time before and after collision*/ @@ -685,7 +737,7 @@ static int get_deflection(float opco[3], float npco[3], float opno[3], damping = damping + ((1 - damping) * (BLI_drand()*rdamp_val)); damping = damping * damping; - ref_plane_mag = Inpf(refl_vel,d_nvect); + ref_plane_mag = INPR(refl_vel,d_nvect); if (damping > 0.999) damping = 0.999; @@ -709,7 +761,7 @@ static int get_deflection(float opco[3], float npco[3], float opno[3], /* Increment same_face */ *same_face = *same_face + 1; if ((*same_face > 3) && (def_depth > 3)) { - force_mag_norm = Inpf(forcec, d_nvect); + force_mag_norm = INPR(forcec, d_nvect); forcec[0] = forcec[0] - (d_nvect[0] * force_mag_norm); forcec[1] = forcec[1] - (d_nvect[1] * force_mag_norm); forcec[2] = forcec[2] - (d_nvect[2] * force_mag_norm); @@ -746,7 +798,7 @@ static int get_deflection(float opco[3], float npco[3], float opno[3], /* But only do this as a last resort, if we've got to the end of the */ /* number of collisions allowed */ if (def_depth==9) { - k_point3 = Inpf(d_nvect,npco); + k_point3 = INPR(d_nvect,npco); if (((dk_plane > k_point3) && (dk_plane < dk_point1))||((dk_plane < k_point3) && (dk_plane > dk_point1))) { /* Yup, the pesky particle may have fallen through a hole!!! */ @@ -879,7 +931,7 @@ void make_particle_keys(int depth, int nr, PartEff *paf, Particle *part, float * /* speed: texture */ if(mtex && paf->texfac!=0.0) { - particle_tex(mtex, paf, opa->co, opa->no); + particle_tex(mtex, paf, pa->co, pa->no); } if(damp!=1.0) { pa->no[0]*= damp; @@ -1069,6 +1121,7 @@ void give_mesh_mvert(Mesh *me, int nr, float *co, short *no, float seed2) void build_particle_system(Object *ob) { + Base *base; Object *par; PartEff *paf; Particle *pa; @@ -1103,6 +1156,11 @@ void build_particle_system(Object *ob) paf->keys= NULL; new_particle(paf); + /* reset deflector cache, sumohandle is free, but its still sorta abuse... (ton) */ + for(base= G.scene->base.first; base; base= base->next) { + base->object->sumohandle= NULL; + } + cfraont= G.scene->r.cfra; cfralast= -1000; framelenont= G.scene->r.framelen; @@ -1241,7 +1299,7 @@ void build_particle_system(Object *ob) Mat4MulVecfl(prevobmat, vec); /* first start speed: object */ - VecSubf(pa->no, pa->co, vec); + VECSUB(pa->no, pa->co, vec); VecMulf(pa->no, paf->obfac); /* calculate the correct inter-frame */ @@ -1261,7 +1319,7 @@ void build_particle_system(Object *ob) Normalise(vec); VecMulf(vec, paf->normfac); - VecAddf(pa->no, pa->no, vec); + VECADD(pa->no, pa->no, vec); } pa->lifetime= paf->lifetime; if(paf->randlife!=0.0) { @@ -1298,6 +1356,14 @@ void build_particle_system(Object *ob) par= par->parent; } + /* reset deflector cache */ + for(base= G.scene->base.first; base; base= base->next) { + if(base->object->sumohandle) { + MEM_freeN(base->object->sumohandle); + base->object->sumohandle= NULL; + } + } + /* restore: AFTER popfirst */ ob->sf= sfraont; diff --git a/source/blender/include/blendef.h b/source/blender/include/blendef.h index 2ff08352d0d..cd3218c03ab 100644 --- a/source/blender/include/blendef.h +++ b/source/blender/include/blendef.h @@ -63,6 +63,9 @@ #define VECCOPY(v1,v2) {*(v1)= *(v2); *(v1+1)= *(v2+1); *(v1+2)= *(v2+2);} #define QUATCOPY(v1,v2) {*(v1)= *(v2); *(v1+1)= *(v2+1); *(v1+2)= *(v2+2); *(v1+3)= *(v2+3);} +#define VECADD(v1,v2,v3) {*(v1)= *(v2) + *(v3); *(v1+1)= *(v2+1) + *(v3+1); *(v1+2)= *(v2+2) + *(v3+2);} +#define VECSUB(v1,v2,v3) {*(v1)= *(v2) - *(v3); *(v1+1)= *(v2+1) - *(v3+1); *(v1+2)= *(v2+2) - *(v3+2);} + #define INPR(v1, v2) ( (v1)[0]*(v2)[0] + (v1)[1]*(v2)[1] + (v1)[2]*(v2)[2] ) #define CLAMP(a, b, c) if((a)<(b)) (a)=(b); else if((a)>(c)) (a)=(c) #define CLAMPIS(a, b, c) ((a)<(b) ? (b) : (a)>(c) ? (c) : (a)) diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c index e4aae91701c..87f2b1c0014 100644 --- a/source/blender/src/drawobject.c +++ b/source/blender/src/drawobject.c @@ -3176,6 +3176,24 @@ static void drawmball(Object *ob, int dt) } } +static void draw_forcefield(Object *ob) +{ + float imat[4][4], tmat[4][4]; + float vec[3]= {0.0, 0.0, 0.0}; + + mygetmatrix(tmat); + Mat4Invert(imat, tmat); + Normalise(imat[0]); + Normalise(imat[1]); + + BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.4); + drawcircball(vec, 0.5, imat); + BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.65); + drawcircball(vec, 1.0, imat); + BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.8); + drawcircball(vec, 1.5, imat); +} + static void draw_bb_box(BoundBox *bb) { float *vec; @@ -3763,6 +3781,7 @@ void draw_object(Base *base) break; case OB_EMPTY: drawaxes(1.0); + if(ob->pd && ob->pd->forcefield) draw_forcefield(ob); break; case OB_LAMP: /* does a myloadmatrix */ |