hschumann2/TempleOS-Source-Code
0847
1 2class MyMass:CMass3{4 F64 radius;5};6 7class MySpring:CSpring8{9};10 11CMathODE *ode=NULL;12 13U0 DrawIt(CTask *,CDC *dc)14{15 MyMass *tmpm;16 MySpring *tmps;17 18 dc->color=RED;19 tmps=ode->next_spring;20 while (tmps!=&ode->next_spring) {21 GrLine(dc,tmps->end1->x,tmps->end1->y,tmps->end2->x,tmps->end2->y);22 tmps=tmps->next;23 }24 25 dc->color=BLACK;26 tmpm=ode->next_mass;27 while (tmpm!=&ode->next_mass) {28 GrCircle(dc,tmpm->x,tmpm->y,tmpm->radius);29 tmpm=tmpm->next;30 }31}32 33U0 MyDerivative(CMathODE *ode,F64,COrder2D3 *,COrder2D3 *)34{//The forces due to springs and drag are35//automatically handled by the ode code.36 //We can add new forces here.37 F64 d,dd;38 CD3 p;39 MyMass *tmpm1,*tmpm2;40 41 tmpm1=ode->next_mass;42 while (tmpm1!=&ode->next_mass) {43 tmpm2=tmpm1->next;44 while (tmpm2!=&ode->next_mass) {45 D3Sub(&p,&tmpm2->state->x,&tmpm1->state->x);46 dd=D3NormSqr(&p);47 if (dd<=Sqr(tmpm1->radius+tmpm2->radius)) {48 d=Sqrt(dd)+0.0001;49 dd=10.0*Sqr(Sqr(Sqr(tmpm1->radius+tmpm2->radius)-dd));50 D3MulEqu(&p,dd/d);51 D3AddEqu(&tmpm2->DstateDt->DxDt,&p);52 D3SubEqu(&tmpm1->DstateDt->DxDt,&p);53 }54 tmpm2=tmpm2->next;55 }56 tmpm1=tmpm1->next;57 }58}59 60U0 PlaceMass(I64 x, I64 y)61{62 MyMass *tmpm=CAlloc(sizeof(MyMass));63 tmpm->mass=1.0;64 tmpm->drag_profile_factor=100.0;65 tmpm->x=x;66 tmpm->y=y;67 tmpm->radius=10*(Rand+0.25);68 QueIns(tmpm,ode->last_mass);69}70 71U0 PlaceSpring(MyMass *tmpm1,MyMass *tmpm2)72{73 MySpring *tmps=CAlloc(sizeof(MySpring));74 tmps->end1=tmpm1;75 tmps->end2=tmpm2;76 tmps->const=10000;77 tmps->rest_len=100;78 QueIns(tmps,ode->last_spring);79}80 81U0 Init()82{83 ode=ODENew(0,1e-4,ODEF_HAS_MASSES);84 ode->derive=&MyDerivative;85 ode->drag_v2=0.002;86 ode->drag_v3=0.00001;87 ode->acceleration_limit=5e3;88 89 QueIns(ode,Fs->last_ode);90}91 92U0 CleanUp()93{94 QueRem(ode);95 QueDel(&ode->next_mass,TRUE);96 QueDel(&ode->next_spring,TRUE);97 ODEDel(ode);98}99 100U0 MassSpringDemo()101{102 I64 msg_code,arg1,arg2;103 MyMass *tmpm1=NULL,*tmpm2=NULL;104 105 PopUpOk("Left-Click to place mas\n"106 "Right-Click and drag to\n"107 "connect with spring.\n\n"108 "Springs are 100 pixs long.\n");109 SettingsPush; //See SettingsPush110 AutoComplete;111 WinBorder;112 WinMax;113 DocCursor;114 DocClear;115 116 Fs->win_inhibit|=WIG_DBL_CLICK;117 118 MenuPush(119 "File {"120 " Abort(,CH_SHIFT_ESC);"121 " Exit(,CH_ESC);"122 "}"123 "Play {"124 " Restart(,'\n');"125 "}"126 );127 128 Init;129 Fs->draw_it=&DrawIt;130 131 try {132 while (TRUE) {133 msg_code=GetMsg(&arg1,&arg2,134 1<<MSG_MS_L_DOWN|1<<MSG_MS_R_DOWN|1<<MSG_MS_R_UP|1<<MSG_KEY_DOWN);135 switch (msg_code) {136 case MSG_MS_L_DOWN:137 PlaceMass(arg1,arg2);138 break;139 case MSG_MS_R_DOWN:140 tmpm1=MassFind(ode,arg1,arg2);141 tmpm2=NULL;142 break;143 case MSG_MS_R_UP:144 if (tmpm1 && (tmpm2=MassFind(ode,arg1,arg2)) && tmpm1!=tmpm2)145 PlaceSpring(tmpm1,tmpm2);146 tmpm1=tmpm2=NULL;147 break;148 case MSG_KEY_DOWN:149 switch (arg1) {150 case '\n':151 CleanUp;152 Init;153 break;154 case CH_SHIFT_ESC:155 case CH_ESC:156 goto ms_done;157 }158 break;159 }160 }161ms_done: //Don't goto out of try162 GetMsg(,,1<<MSG_KEY_UP);163 } catch164 PutExcept;165 SettingsPop;166 CleanUp;167 MenuPop;168}169 170MassSpringDemo;171 