[tuhopuu-devel] Fwd: particle deflection experiments..... - updated patch file

Leon Turner tuhopuu-devel@blender.org
Wed, 11 Feb 2004 08:39:49 +0000 (GMT)


--0-532408338-1076488789=:66055
Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: 8bit
Content-Id: 
Content-Disposition: inline

hi,

Just a quick update - this patch replaces the one in
the original mail (I've improved the "leaking" problem
a bit, and moved most of the particle deflection code
into it's own function). If you've already done
something with the original patch, ignore this one,
and I'll make these changes later....

Cheers

leon

 --- Leon Turner <leon_turneruk@yahoo.co.uk> wrote: >
Date: Sun, 8 Feb 2004 15:05:42 +0000 (GMT)
> From: Leon Turner <leon_turneruk@yahoo.co.uk>
> Subject: particle deflection experiments.....
> To: tuhopuu-devel@blender.org
> 
> hi,
> 
> As requested by Theeth in the blender.org forums ,
> here's the patch for the particle deflectors I've
> been
> playing with in Tuhopuu.
> 
> This is my first attempt at coding in Blender (and C
> really!) so please let me know all the things I need
> to fix / change!!
> 
> I've attached two text files, one is an explanation
> /
> summary, and the other is the patch file.
> 
> Cheers
> 
> Leon
> 


	
	
		
___________________________________________________________
BT Yahoo! Broadband - Free modem offer, sign up online today and save £80 http://btyahoo.yahoo.co.uk
--0-532408338-1076488789=:66055
Content-Type: text/plain; name="new_ppatch.txt"
Content-Description: new_ppatch.txt
Content-Disposition: inline; filename="new_ppatch.txt"

? obj
? user-def.mk
Index: source/blender/blenkernel/intern/effect.c
===================================================================
RCS file: /cvsroot/tuhopuu/tuhopuu2/source/blender/blenkernel/intern/effect.c,v
retrieving revision 1.2
diff -r1.2 effect.c
1c1
< /*  effect.c 
---
> /*  effect.c
52a53
> #include "MTC_vectorops.h"
61a63
> #include "BKE_main.h"
356a359,654
> float mag_vect(float n[3])
> {
> /* Just a simple function to get the magnitude of a vector without */
> /* normalising it */
>       float d;
>       d= n[0]*n[0]+n[1]*n[1]+n[2]*n[2];
>       d = sqrt(d);
>       return d;
> }
> 
> float pointintriangle(float p[3], float v1[3], float v2[3], float v3[3])
> {
> /* This function checks whether a point (p) is within a triangle formed by */
> /* three other points (v1, v2, v3. */
> /* It does this by checking the area of the total triangle compared to the areas of */
> /* the three triangles formed by the point and the three points */
> /* It assumes the points are all in the same plane, it doesn't check this */
> /* I'm sure this isn't a very good method, but it just about works!!! */
> /* Check whether the result is below is below a very small */
> /* number to see if the point is inside, since it won't ever be zero */
>       float total_area;
>       float a1,a2,a3;
>       float vect1[3], vect2[3], wvect[3];
>       float result;
>       /*First total area, between v1 and v2 will do*/
>       MTC_diff3Float(vect1, v1,v2);
>       MTC_diff3Float(vect2, v2,v3);
>       MTC_cross3Float(wvect,vect1,vect2);
>       total_area = mag_vect(wvect) / 2;
>       /*Now area 1 - p/v1, p/v2*/
>       MTC_diff3Float(vect1,p,v1);
>       MTC_diff3Float(vect2,p,v2);
>       MTC_cross3Float(wvect,vect1,vect2);
>       a1 = mag_vect(wvect) / 2;
>       /*Now area 2 - p/v2, p/v3*/
>       MTC_diff3Float(vect1,p,v2);
>       MTC_diff3Float(vect2,p,v3);
>       MTC_cross3Float(wvect,vect1,vect2);
>       a2 = mag_vect(wvect) / 2;
>       /*Now area 2 - p/v3, p/v1*/
>       MTC_diff3Float(vect1,p,v3);
>       MTC_diff3Float(vect2,p,v1);
>       MTC_cross3Float(wvect,vect1,vect2);
>       a3 = mag_vect(wvect) / 2;
>       result = total_area - a1 - a2 - a3;
>       result = abs(result);
>       return result;
> }
> 
> int get_deflection(float opco[3], float npco[3], float opno[3], float npno[3], float life, float force[3], int def_depth)
> {
> 	float *v1, *v2, *v3, *v4;
> 	float nv1[3], nv2[3], nv3[3], nv4[3], edge1[3], edge2[3], intersect_vect[3];
> 	float nvect[3], vect_to_int[3], intersect_co[3], refl_vel[3];
> 	float i_co_above[3];
> 	float k_plane, k_point1, k_point2, k_point3, dist_to_plane;
> 	float icalctop, icalcbot, int_u, n_mag;
> 	float mag_intersect, mag_iv, x_m,y_m,z_m;
> 	int a, deflected;
> 	int srch_up;
> 	float mat[3][3];
> 	float time_before, time_after, pintri;
> 	Mesh *def_mesh, *deflection_mesh = NULL;
> 	MFace *mface;
> 	Main *mn;
> 	Object *myobject, *deflection_object;
> 
> 
>         /* Particle deflection code     */
>         /* Code is in two parts - first establish if a collision  */
>         /* has taken place, second work out the new co-ordinates */
>         /* and speed of the particle*/
>         /* This has the limitation you can only have one collision */
>         /* per particle per key frame - so you do get "leaks" at */
>         /* joints between deflecting meshes*/
>         /* First part: loop through all meshes, and all faces of meshes*/
>         mn= G.main;
>         /* Cycle through the objects in different orders depending on the */
>         /* depth we are currently at. This makes it harder for particle to "leak" */
>         /* where objects overlap*/
>         srch_up = (def_depth % 2);
>         if (srch_up) {
>            myobject = mn->object.first;
>         }
>         else {
>            myobject = mn->object.last;
>         }
>         deflected = 0;
>         while (myobject) {
>                 def_mesh = get_mesh(myobject);
>                 /* Don't go any further if we've already got a collision */
>                 if (def_mesh!=0) {
>                     if(def_mesh->pdeflect && (deflected == 0)) {
>                         mface= def_mesh->mface;
>                         a = def_mesh->totface;
>                         object_to_mat3(myobject, mat);
>                         while (a--) {
>                               if (deflected == 0) {
> 
>                                  /* 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;
> 
>                                  nv1[0]= v1[0];
>                                  nv1[1]= v1[1];
>                                  nv1[2]= v1[2];
>                                  nv2[0]= v2[0];
>                                  nv2[1]= v2[1];
>                                  nv2[2]= v2[2];
>                                  nv3[0]= v3[0];
>                                  nv3[1]= v3[1];
>                                  nv3[2]= v3[2];
>                                  nv4[0]= v4[0];
>                                  nv4[1]= v4[1];
>                                  nv4[2]= v4[2];
> 
>                                  /*Apply the objects deformation matrix*/
>                                  Mat3MulVecfl(mat, nv1);
>                                  Mat3MulVecfl(mat, nv2);
>                                  Mat3MulVecfl(mat, nv3);
>                                  Mat3MulVecfl(mat, nv4);
> 
>                                  nv1[0]= nv1[0] + myobject->loc[0];
>                                  nv1[1]= nv1[1] + myobject->loc[1];
>                                  nv1[2]= nv1[2] + myobject->loc[2];
>                                  nv2[0]= nv2[0] + myobject->loc[0];
>                                  nv2[1]= nv2[1] + myobject->loc[1];
>                                  nv2[2]= nv2[2] + myobject->loc[2];
>                                  nv3[0]= nv3[0] + myobject->loc[0];
>                                  nv3[1]= nv3[1] + myobject->loc[1];
>                                  nv3[2]= nv3[2] + myobject->loc[2];
>                                  nv4[0]= nv4[0] + myobject->loc[0];
>                                  nv4[1]= nv4[1] + myobject->loc[1];
>                                  nv4[2]= nv4[2] + myobject->loc[2];
> 
>                                  /* Now calculate the normal vector of the face */
>                                  /* Just use the first three points */
>                                  /* First the edges */
>                                  MTC_diff3Float(edge1, nv1, nv2);
>                                  MTC_diff3Float(edge2, nv3, nv2);
> 
>                                  /*Now cross product and normalise*/
>                                  MTC_cross3Float(nvect, edge1, edge2);
>                                  n_mag = MTC_normalise3DF(nvect);
> 
>                                  /* Now calculate K */
>                                  k_plane = MTC_dot3Float(nvect, nv1);
>                                  k_point1 = MTC_dot3Float(nvect,npco);
>                                  k_point2 = MTC_dot3Float(nvect,opco);
> 
>                                  /* If the old co-ordinates and new co-ordinates were the same side of */
>                                  /* the plane, we don't need to go any further, since no collision is possible */
>                                  if (((k_plane > k_point1) && (k_plane < k_point2))||((k_plane < k_point1) && (k_plane > k_point2))) {
> 
>                                     /* Now check if the intersection point lies within */
>                                     /* any of the triangles of the face */
>                                     /* So first get the intersection point */
>                                     icalctop = (k_plane - (MTC_dot3Float(npco,nvect)));
>                                     MTC_diff3Float(intersect_vect, npco, opco);
>                                 icalcbot = (MTC_dot3Float(intersect_vect,nvect));
>                                 int_u = icalctop / icalcbot;
>                                 intersect_co[0] = (npco[0] + (int_u * intersect_vect[0]));
>                                 intersect_co[1] = (npco[1] + (int_u * intersect_vect[1]));
>                                 intersect_co[2] = (npco[2] + (int_u * intersect_vect[2]));
>                                 /* Work out a point just before the intersection */
>                                 
>                                 i_co_above[0] = (npco[0] + (int_u * 1.00001 * intersect_vect[0]));
>                                 i_co_above[1] = (npco[1] + (int_u * 1.00001 * intersect_vect[1]));
>                                 i_co_above[2] = (npco[2] + (int_u * 1.00001 * intersect_vect[2]));
> 
> 
>                                 /* Now check if intersection point is inside first three vertices */
>                                 pintri = pointintriangle(intersect_co, nv1, nv2, nv3);
>                                 if (pintri < 0.00001) {
>                                         deflected = 1;
>                                         deflection_mesh = def_mesh;
>                                         deflection_object = myobject;
>                                 }
>                                 else {
> 
>                                 /* Only check the other triangle if the face has 4 vertices */
>                                 if (mface->v4) {
>                                         pintri = pointintriangle(intersect_co, nv1, nv3, nv4);
>                                         if (pintri < 0.00001) {
>                                                 deflected = 1;
>                                                 deflection_mesh = def_mesh;
>                                                 deflection_object = myobject;
>                                         }
>                                         }
>                                         }
>                                     }
>                                 }
>                             mface++;
>                             }
>                         }
>                     }
>                     if (srch_up) {
>                        myobject = myobject->id.next;
>                     }
>                     else {
>                       myobject = myobject->id.prev;
>                     }
> 
>                 }
> 
>                   /* 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) {
>                       /* Just some preiliminary stuff*/
>                       mag_iv = MTC_normalise3DF(intersect_vect);
>                       MTC_diff3Float(vect_to_int, opco, intersect_co);
>                       mag_intersect = MTC_normalise3DF(vect_to_int);
>                       npco[0] = intersect_co[0];
>                       npco[1] = intersect_co[1];
>                       npco[2] = intersect_co[2];
> 
>                       /* Work out the lengths of time before and after collision*/
>                       time_before = (life*(mag_intersect / (mag_iv)));
>                       time_after =  (life*((mag_iv - mag_intersect) / (mag_iv)));
> 
>                       /* We have to recalculate what the speed would have been at the */
>                       /* point of collision, not the key frame time */
>                       npno[0]= opno[0] + time_before*force[0];
> 		      npno[1]= opno[1] + time_before*force[1];
> 		      npno[2]= opno[2] + time_before*force[2];
> 
>                       /* Reflect the speed vector in the face */
>                       x_m = (2 * npno[0] * nvect[0]);
>                       y_m = (2 * npno[1] * nvect[1]);
>                       z_m = (2 * npno[2] * nvect[2]);
>                       refl_vel[0] = npno[0] - (nvect[0] * (x_m + y_m + z_m));
>                       refl_vel[1] = npno[1] - (nvect[1] * (x_m + y_m + z_m));
>                       refl_vel[2] = npno[2] - (nvect[2] * (x_m + y_m + z_m));
> 
>                       /* Now add in the damping force - only damp in the direction of */
>                       /* the faces normal vector */
>                       npno[0] = (refl_vel[0] * (1 + (nvect[0] * deflection_mesh->pdef_damp)));
>                       npno[1] = (refl_vel[1] * (1 + (nvect[1] * deflection_mesh->pdef_damp)));
>                       npno[2] = (refl_vel[2] * (1 + (nvect[2] * deflection_mesh->pdef_damp)));
> 
>                       /* Now reset opno */
>                       opno[0] = npno[0];
> 		      opno[1] = npno[1];
> 		      opno[2] = npno[2];
> 
>                       /* We have the particles speed at the point of collision    */
>                       /* Now we want the particles speed at the current key frame */
>                       npno[0]= npno[0] + time_after*force[0];
> 		      npno[1]= npno[1] + time_after*force[1];
> 		      npno[2]= npno[2] + time_after*force[2];
> 
>                       /* Now we have to recalculate pa->co for the remainder*/
>                       /* of the time since the intersect*/
> 		      npco[0]= npco[0] + time_after*npno[0];
> 		      npco[1]= npco[1] + time_after*npno[1];
> 		      npco[2]= npco[2] + time_after*npno[2];
> 		      
> 		      /* And set the old co-ordinates back to the point just above the intersection */
> 		      opco[0] = i_co_above[0];
> 		      opco[1] = i_co_above[1];
> 		      opco[2] = i_co_above[2];
> 		      
> 		      /* Finally update the time */
> 		      life = time_after;
> 
>                       /* The particle may have fallen through the face again by now!!*/
>                       /* So check if the particle has changed sides of the plane compared*/
>                       /* the co-ordinates at the last keyframe*/
>                       /* But only do this as a last resort, if we've got to the end of the */
>                       /* number of collisions allowed */
>                       if (def_depth==4) {
>                         k_point3 = MTC_dot3Float(nvect,npco);
>                         if (((k_plane > k_point3) && (k_plane < k_point2))||((k_plane < k_point3) && (k_plane > k_point2))) {
> 
>                                 /* Yup, the pesky particle may have fallen through a hole!!! */
>                                 /* So we'll cheat a bit and move the particle along the normal vector */
>                                 /* until it's just the other side of the plane */
>                                 icalctop = (k_plane - nvect[0]*npco[0] - nvect[1]*npco[1] - nvect[2]*npco[2]);
>                                 icalcbot = (nvect[0]*nvect[0] + nvect[1]*nvect[1] + nvect[2]*nvect[2]);
>                                 dist_to_plane = icalctop / icalcbot;
> 
>                                 /*  Now just increase the distance a little to place */
>                                 /* the point the other side of the plane */
>                                 dist_to_plane *= 1.001;
>                                 npco[0]= npco[0] + (dist_to_plane * nvect[0]);
>                                 npco[1]= npco[1] + (dist_to_plane * nvect[1]);
>                                 npco[2]= npco[2] + (dist_to_plane * nvect[2]);
>                                 /* And hope it works!!! */
>                         }
>                       }
>                 }
>         return deflected;
> }
> 
360,362c658,661
< 	float damp, deltalife;
< 	int b, rt1, rt2;
< 	
---
> 	float damp, deltalife, life;
> 	float opco[3], opno[3], npco[3], npno[3];
> 	int b, rt1, rt2, deflected, deflection, finish_defs, def_count;
> 
365c664
< 	
---
> 
372c671
< 	
---
> 
377c676
< 	
---
> 
383c682
< 		
---
> 
398a698,744
>                 /* Particle deflection code                             */
>                 /* set initial variables                                */
>                 opco[0] = opa->co[0];
>                 opco[1] = opa->co[1];
>                 opco[2] = opa->co[2];
> 
>                 opno[0] = opa->no[0];
>                 opno[1] = opa->no[1];
>                 opno[2] = opa->no[2];
> 
>                 npco[0] = pa->co[0];
>                 npco[1] = pa->co[1];
>                 npco[2] = pa->co[2];
> 
>                 npno[0] = pa->no[0];
>                 npno[1] = pa->no[1];
>                 npno[2] = pa->no[2];
> 
>                 life = deltalife;
> 
>                 /* now loop until no deflection or limit reached        */
>                 /* If a deflection has occurred, update pa-co and pa-no */
>                 deflection = 0;
>                 finish_defs = 1;
>                 def_count = 0;
> 
>                 while (finish_defs) {
>                       deflected =  get_deflection(opco, npco, opno, npno, life, force, def_count);
>                       if (deflected) {
>                          def_count = def_count + 1;
>                          deflection = 1;
>                          if (def_count==5) finish_defs = 0;
>                       }
>                       else {
>                            finish_defs = 0;
>                       }
>                 }
> 
>                 if (deflection) {
>                    pa->co[0] = npco[0];
>                    pa->co[1] = npco[1];
>                    pa->co[2] = npco[2];
>                    pa->no[0] = npno[0];
>                    pa->no[1] = npno[1];
>                    pa->no[2] = npno[2];
>                 }
> 
408c754
< 	
---
> 
585c931
< 	
---
> 
Index: source/blender/include/butspace.h
===================================================================
RCS file: /cvsroot/tuhopuu/tuhopuu2/source/blender/include/butspace.h,v
retrieving revision 1.5
diff -r1.5 butspace.h
338a339,340
> #define B_ISDEFLECTOR   2085
> #define B_PDEFDAMPING   2086
Index: source/blender/makesdna/DNA_mesh_types.h
===================================================================
RCS file: /cvsroot/tuhopuu/tuhopuu2/source/blender/makesdna/DNA_mesh_types.h,v
retrieving revision 1.7
diff -r1.7 DNA_mesh_types.h
134c134,137
< 	
---
> 
> 	int pdeflect;        /* Deflection flag - does mesh deflect particles*/
> 	float pdef_damp;     /* Damping factor for particle deflection       */
> 
Index: source/blender/src/buttons_editing.c
===================================================================
RCS file: /cvsroot/tuhopuu/tuhopuu2/source/blender/src/buttons_editing.c,v
retrieving revision 1.11
diff -r1.11 buttons_editing.c
1604a1605,1608
> 		case B_ISDEFLECTOR:      /*Not sure if this is needed!!!*/
> 		        break;
> 		case B_PDEFDAMPING:      /*Ditto!!!*/
> 		        break;
1752a1757,1781
> static void editing_panel_deflectors(Object *ob)
> {
> /* A new panel for particle interaction settings */
> 	uiBlock *block;
> 	ID *id, *idfrom;
> 	int *poin, xco=143;
> 	float min;
> 	char str[64];
> 	uiBut *but;
> 	Mesh *me;
> 
> 	block= uiNewBlock(&curarea->uiblocks, "editing_panel_deflectors", UI_EMBOSS, UI_HELV, curarea->win);
> 	if(uiNewPanel(curarea, block, "Particle Interaction", "Editing", 640, 0, 174, 204)==0) return;
> 
> 	buttons_active_id(&id, &idfrom);
> 
> 	/* vertex group... partially editmode... */
> 	if(ob->type==OB_MESH) {
> 	  me= get_mesh(ob);
>           uiDefButI(block, TOG|BIT|0, B_ISDEFLECTOR, "Deflection",	143,40,140,20, &me->pdeflect, 0, 0, 0, 0, "Deflects particles");
>           uiDefButF(block, NUM, B_PDEFDAMPING, "Surface damping",	143,15,140,20, &me->pdef_damp, 0, 1, 0, 0, "Amount of damping during particle collision");
>         }
> 
> 	
> }
2190c2219
< 			if(G.f & (G_VERTEXPAINT | G_TEXTUREPAINT | G_WEIGHTPAINT) )
---
> 			if(G.f & (G_VERTEXPAINT | G_TEXTUREPAINT | G_WEIGHTPAINT) ) {
2191a2221,2224
> 			}
> 			else if(!(G.f & G_FACESELECT)) {
> 			     editing_panel_deflectors(ob);  /* Particle deflectors */
> 			}

--0-532408338-1076488789=:66055--