📄 billmove.c
字号:
dv = vec_scale(wall->n,vec_mul(wall->n,ball->v)*(1.0+sqrt(1.0-CUSHION_LOSS))); ball->v = vec_diff(ball->v,dv); /* maybe some angular momentum loss has to be implemented here */ /* ... */}#endif#define MU_OMEGA 0.1 /* transmitted ang. mom. ratio (at hit) */#define MU_BALL 0.1 /* friction const between ball and ball */static void ball_ball_interaction( BallType * b1, BallType * b2 ){ BallType b1s, b2s; /* balls in coord system of b1 */ myvec dvec, duvec, dvn, dvp, dw1, dw2; myvec dw1max, dw2max; myvec dpp, dpn, fric_dir,perimeter_speed_b1, perimeter_speed_b2; dvec = vec_diff(b1->r,b2->r); duvec = vec_unit(dvec); /* stoss */ b1s=*b1; b2s=*b2; b2s.v.x-=b1s.v.x; b2s.v.y-=b1s.v.y; b2s.v.z-=b1s.v.z; b1s.v.x=0.0; b1s.v.y=0.0; b1s.v.z=0.0; dvn = vec_scale(duvec,vec_mul(duvec,b2s.v)); dvp = vec_diff( b2s.v, dvn ); b2s.v = vec_diff( b2s.v, dvn ); b2s.v = vec_add ( b2s.v, vec_scale(dvn,(b2s.m-b1s.m)/(b1s.m+b2s.m)) ); b1s.v = vec_scale( dvn, 2.0*b2s.m/(b1s.m+b2s.m) ); /* (momentum transfer)/m1 */ b2->v = vec_add( b1->v, b2s.v ); b1->v = vec_add( b1->v, b1s.v );// dw1 = vec_scale(b1->w,MU_OMEGA);// dw2 = vec_scale(b2->w,MU_OMEGA); /* angular momentum transfer */ dpn = vec_scale(b1s.v,b1s.m); /* momentum transfer from ball2 to ball1 */ perimeter_speed_b1=vec_cross( b1->w, vec_scale(duvec,-b1->d/2.0) ); perimeter_speed_b2=vec_cross( b2->w, vec_scale(duvec, b2->d/2.0) ); fric_dir = vec_unit(vec_add(vec_diff(perimeter_speed_b2,perimeter_speed_b1),dvp)); dpp = vec_scale(fric_dir,-vec_abs(dpn)*MU_BALL); /* dp parallel of ball2 */ dw2 = vec_scale( vec_cross(dpp,duvec), b2->d/b2->I ); dw1 = vec_scale( vec_cross(dpp,duvec), b1->d/b1->I ); dw2max = vec_scale(vec_proj(vec_diff(b2->w,b1->w),dw2),0.5); dw1max = vec_scale(vec_proj(vec_diff(b1->w,b2->w),dw2),0.5); if( vec_abs(dw1)>vec_abs(dw1max) || vec_abs(dw2)>vec_abs(dw2max) ){ /* correct momentum transfer to max */ dpp = vec_scale(dpp,vec_abs(dw2max)/vec_abs(dw2)); /* correct amg mom transfer to max */ dw2=dw2max; dw1=dw1max; } b1->w = vec_diff( b1->w,dw1 ); b2->w = vec_diff( b2->w,dw2 ); /* parallel momentum transfer due to friction between balls */ { myvec dv1, dv2; dv1 = vec_scale(dpp,-b1->m); dv2 = vec_scale(dpp, b2->m); dv1.z=0.0; dv2.z=0.0; b1->v = vec_add( b1->v, dv1 ); b2->v = vec_add( b2->v, dv2 ); }// b1->w = vec_diff( vec_diff(b1->w,dw1), vec_scale(dw2,(b2->I)/(b1->I)) );// b2->w = vec_diff( vec_diff(b2->w,dw2), vec_scale(dw1,(b1->I)/(b2->I)) );}#define D_MIN 1.0E-5 /* 1E-5 = 1/100 mm */#define V_MIN 1.0E-2 /* 1E-3 = 1 mm/s */#define SLIDE_THRESH_SPEED 1.0E-2 /* 1E-2 = 1 cm/s */static int ball_in_hole(BallType *ball, BordersType *borders){ int i; for(i=0;i<borders->holenr;i++){ if( vec_abs(vec_diff(borders->hole[i].pos,ball->r)) < borders->hole[i].r/* - ball->d/2.0*/ ){ return i+1; } } return 0;}int ball_outside( BallType *ball, BordersType *borders ){ int rval=0; int i; for(i=0;i<borders->nr;i++){ rval = rval || BALL_WALL_DIST_I(ball[0],borders->border[i])<0.0; } return rval;}void remove_balls_from_game( BallsType *balls, BordersType *borders ){ int i; for(i=0;i<balls->nr;i++){/* if( ball_in_hole(&balls->ball[i], borders) ){ balls->ball[i].v.z-= }*//* if( ball_outside(&balls->ball[i],borders) ){*/ if( balls->ball[i].r.z < -0.1 ){ balls->ball[i].in_game=0; balls->ball[i].in_hole=0; balls->ball[i].v = vec_xyz( 0.0, 0.0, 0.0 ); balls->ball[i].r = vec_xyz( 0.0, 0.0, 0.0 ); if( balls->ball[i].nr==0 ) move_log.out_white=1; if( balls->ball[i].nr==8 ) move_log.out_black=1; if( balls->ball[i].nr<8 && balls->ball[i].nr!=0 ) move_log.out_full++; if( balls->ball[i].nr>8 && balls->ball[i].nr!=0 ) move_log.out_half++;/* move_log.event[move_log.eventnr].event=BALL_out; move_log.event[move_log.eventnr].ballnr=balls->ball[i].nr; move_log.event[move_log.eventnr].ballnr2=0; move_log.event[move_log.eventnr].pos=balls->ball[i].r; move_log.event[move_log.eventnr].timestep_nr=move_log.timestep_nr; move_log.eventnr++;*/ record_move_log_event( BALL_out, balls->ball[i].nr, 0, balls, 0.0 ); } }}static int proceed_dt_euler(BallsType *balls, BordersType *borders, BMfloat dt, int depth)/* this one does not remove fallen balls */{ myvec dx; BMfloat dphi, dt1; int i,j,k; int rnd[100]; int collided=0;// if (depth>500) return 0;// fprintf(stderr,"proceed_dt_euler: depth=%d\n",depth); /* move all balls */ for(i=0;i<balls->nr;i++){ /* translate ball */ dx = vec_scale(balls->ball[i].v,dt); balls->ball[i].r = vec_add(balls->ball[i].r,dx); /* perform rotation */ dphi = vec_abs(balls->ball[i].w)*dt; // rot_ax( balls->ball[i].w, balls->ball[i].b, 3, -dphi ); if( dphi > 1.0E-30 ) rot_ax( balls->ball[i].w, balls->ball[i].b, 3, dphi ); } calc_rand_table(rnd,balls->nr); /* checks */ for(i=0;i<balls->nr;i++) if(balls->ball[i].in_game){ /* check for one collision */ /* check wall collisions */ for(j=0;j<borders->nr;j++){// fprintf(stderr,"1:bwdist=%f\n",BALL_WALL_DIST(balls->ball[i],borders->border[j])); if( BALL_WALL_DIST(balls->ball[i],borders->border[j]) < balls->ball[i].d/2.0 && !ball_in_hole(&(balls->ball[i]),borders) ){// fprintf(stderr,"found ball-border collision\n"); dt1=calc_wall_collision_time(&balls->ball[i],&borders->border[j]); /* dt1 should be negative *///#endif// fprintf(stderr,"dt1=%f j=%d\n",dt1,j); if( dt1>0.0 || fabs(dt)>dt ){ if( dt1>0.0 ){// fprintf(stderr,"wall: dt1>0 !!!\n"); } if( fabs(dt)>dt ){// fprintf(stderr,"wall: |dt1| > dt\n"); } } else { proceed_dt_euler(balls,borders,dt1,depth+1); /* move back to coll. */// fprintf(stderr,"bwdist=%f\n",fabs(BALL_WALL_DIST(balls->ball[i],borders->border[j]))); if ( fabs(BALL_WALL_DIST(balls->ball[i],borders->border[j])-balls->ball[i].d/2.0) < 1E-5 /*1E-5 = 1/100 mm*/ ){ /* only if ball still interacts */ /* (ball may seem to collide with wall but when stepping back out of */ /* wall region (wall border)) */ ball_wall_interaction(&balls->ball[i],&borders->border[j]); collided=1; } proceed_dt_euler(balls,borders,-dt1,depth+1); /* move rest */// if( collided ) break; /*break;*/ /* no break because of second freeze bug */ } } } /* check ball collision */ if (!collided) for(j=0,k=rnd[0];j<balls->nr;j++,k=rnd[j]) if(k!=i){ if( BALL_BALL_DIST( balls->ball[i], balls->ball[k] ) < (balls->ball[i].d+balls->ball[k].d)/2.0 ){// fprintf(stderr,"found ball-ball collision\n"); dt1=calc_ball_collision_time(&balls->ball[i],&balls->ball[k]); /* dt1 should be negative */ if( dt1>0.0 || fabs(dt)>dt ){ if( dt1>0.0 ){// fprintf(stderr,"ball: dt1>0 !!!\n"); } if( fabs(dt)>dt ){// fprintf(stderr,"ball: |dt1| > dt\n"); } } else { proceed_dt_euler(balls,borders,dt1,depth+1); /* move back to coll. */ if ( fabs( BALL_BALL_DIST( balls->ball[i], balls->ball[k] ) - (balls->ball[i].d+balls->ball[k].d)/2.0 ) < 1E-5 /*1E-5 = 1/100 mm*/ ){ /* only if balls still interact */ ball_ball_interaction(&balls->ball[i],&balls->ball[k]); } proceed_dt_euler(balls,borders,-dt1,depth+1); /* move rest */ break; } } } }// fprintf(stderr,"proceed_dt_euler: end: depth=%d\n",depth); return(0);}static void proceed_dt_only(BallsType *balls, BordersType *borders, BMfloat dt){ myvec dx; BMfloat dphi; int i; for(i=0;i<balls->nr;i++){ /* translate ball */ dx = vec_scale(balls->ball[i].v,dt); balls->ball[i].r = vec_add(balls->ball[i].r,dx); /* perform rotation */ dphi = vec_abs(balls->ball[i].w)*dt; // rot_ax( balls->ball[i].w, balls->ball[i].b, 3, -dphi ); if( dphi > 1.0E-30 ) rot_ax( balls->ball[i].w, balls->ball[i].b, 3, dphi ); }}static int wall_dv_pos( BallType * ball, BorderType * wall, BMfloat dt )/* returns 1 if border and ball strobe away fromeach other, 0 else (at time dt) */{ static VMvect ballpos; if ( wall->pnr == 3 ){ return( vec_mul(ball->v,wall->n) > 0.0 ); } else if( wall->pnr == 2 ){ ballpos = vec_add(ball->r,vec_scale(ball->v,dt)); return( vec_mul(ball->v, vec_ncomp( vec_diff(ballpos, wall->r1), vec_diff(wall->r2,wall->r1) ) ) > 0.0 ); } else if( wall->pnr == 1 ){ ballpos = vec_add(ball->r,vec_scale(ball->v,dt)); return( vec_mul(vec_diff(ballpos,wall->r1),ball->v) > 0.0 ); } return 1;}static int ball_dv_pos( BallType * b1, BallType * b2, BMfloat dt )/* returns 1 if balls strobe away fromeach other, 0 else (at time dt) */{ static VMvect b1pos, b2pos; b1pos = vec_add(b1->r,vec_scale(b1->v,dt)); b2pos = vec_add(b2->r,vec_scale(b2->v,dt)); return( vec_mul(vec_diff(b2pos,b1pos),vec_diff(b2->v,b1->v)) > 0.0 );}static int proceed_dt_euler_new(BallsType *balls, BordersType *borders, BMfloat dt, int depth)/* this one does not remove fallen balls */{ static BMfloat logtime; BMfloat dt1, dtmin; int i,j;// int rnd[100];// int collided=0;// int overlapnr,walloverlap,ball1overlap,ball2overlap; int colltype, collnr, collnr2;#define COLLTYPE_WALL 1#define COLLTYPE_BALL 2#define COLLTYPE_NONE 0 if(depth==0){ logtime=dt; } else { logtime+=dt; }// if (depth>500) return 0;// fprintf(stderr,"proceed_dt_euler: depth=%d\n",depth); /* move all balls */// fprintf(stderr,"proceed_dt_euler: dt=%f depth=%d\n",dt, depth); proceed_dt_only(balls,borders,dt); /* checks */ colltype=COLLTYPE_NONE; collnr=-1; collnr2=-1; dtmin=0.0; for(i=0;i<balls->nr;i++) if(balls->ball[i].in_game){ /* check for one collision */ /* check wall collisions */ for(j=0;j<borders->nr;j++){ dt1=calc_wall_collision_time(&balls->ball[i],&borders->border[j]); if( dt1<dtmin && dt1>-dt ){ if( !wall_dv_pos(&balls->ball[i],&borders->border[j],-dt*1.0) ){ /* dont strobe apart */ dtmin=dt1; colltype=COLLTYPE_WALL; collnr=j; collnr2=i; } } } /* check ball collisions */ for(j=0;j<balls->nr;j++) if( j!=i && balls->ball[j].in_game ){ dt1=calc_ball_collision_time(&balls->ball[i],&balls->ball[j]); /* dt1 should be negative */ if( dt1<dtmin && dt1>-dt ){ if( !ball_dv_pos(&balls->ball[j],&balls->ball[i],-dt*1.0) ){ /* dont strobe apart */ dtmin=dt1; colltype=COLLTYPE_BALL; collnr=j; collnr2=i; } } } } if( colltype==COLLTYPE_NONE ){ } else if( colltype==COLLTYPE_WALL ){// fprintf(stderr,"proceed_dt_euler: wall collision dtmin=%f\n",dtmin);// if( !wall_dv_pos(&balls->ball[collnr2],&borders->border[collnr]) ){ /* dont strobe apart *//* record_move_log_event(BALL_wall, collnr, balls->ball[collnr2].nr, vec_xyz(0,0,0), balls->ball[collnr2].r);*//* move_log.event[move_log.eventnr].event=BALL_wall; move_log.event[move_log.eventnr].ballnr=collnr; move_log.event[move_log.eventnr].ballnr2=balls->ball[collnr2].nr; move_log.event[move_log.eventnr].pos2=balls->ball[collnr2].r; move_log.event[move_log.eventnr].timestep_nr=move_log.timestep_nr; move_log.eventnr++;*/ record_move_log_event( BALL_wall, collnr, balls->ball[collnr2].nr, balls, logtime+dtmin ); logtime+=dtmin; proceed_dt_only(balls,borders,dtmin); ball_wall_interaction(&balls->ball[collnr2],&borders->border[collnr]); proceed_dt_euler_new(balls,borders,-dtmin,depth+1);// } } else if( colltype==COLLTYPE_BALL ){// fprintf(stderr,"proceed_dt_euler: ball collision\n");// if( !ball_dv_pos(&balls->ball[collnr],&balls->ball[collnr2]) ){ /* dont strobe apart *//* move_log.event[move_log.eventnr].event=BALL_ball; move_log.event[move_log.eventnr].ballnr=balls->ball[collnr].nr; move_log.event[move_log.eventnr].ballnr2=balls->ball[collnr2].nr; move_log.event[move_log.eventnr].pos=balls->ball[collnr].r; move_log.event[move_log.eventnr].pos2=balls->ball[collnr2].r; move_log.event[move_log.eventnr].timestep_nr=move_log.timestep_nr; move_log.eventnr++;*/ record_move_log_event( BALL_ball, balls->ball[collnr].nr, balls->ball[collnr2].nr, balls, logtime+dtmin ); logtime+=dtmin; proceed_dt_only(balls,borders,dtmin); ball_ball_interaction(&balls->ball[collnr],&balls->ball[collnr2]); proceed_dt_euler_new(balls,borders,-dtmin,depth+1);// } }/* if(depth!=0){ logtime-=dt; }*/ return(0);}#define GRAVITY 9.81 /* m/s^2 *///#define MU_ROLL 0.01 /* table roll-friction const *///#define MU_SLIDE 0.1 /* table slide-friction const *///#define SPOT_R 6.0e-3 /* 3mm radius der auflageflaeche - not used for rollmom (only rotational-friction around spot) */#define MU_ROLL 0.03 /* table roll-friction const */#define MU_SLIDE 0.2 /* table slide-friction const */#define SPOT_R 12.0e-3 /* 3mm radius der auflageflaeche - not used for rollmom (only rotational-friction around spot) *///#define OMEGA_MIN M_PI/8.0 /* 22.5
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -