From 8898ad9b25fca6afe2374d293a981db02a83d7e9 Mon Sep 17 00:00:00 2001 From: "FWoltermann@gmail.com" Date: Thu, 31 May 2012 14:46:27 +0000 Subject: Committing the documentation to svn to have it accessible online --- Doc/doxygen/html/_physical_8cpp_source.html | 892 ++++++++++++++++++++++++++++ 1 file changed, 892 insertions(+) create mode 100644 Doc/doxygen/html/_physical_8cpp_source.html (limited to 'Doc/doxygen/html/_physical_8cpp_source.html') diff --git a/Doc/doxygen/html/_physical_8cpp_source.html b/Doc/doxygen/html/_physical_8cpp_source.html new file mode 100644 index 0000000..5044777 --- /dev/null +++ b/Doc/doxygen/html/_physical_8cpp_source.html @@ -0,0 +1,892 @@ + + + + + +Starshatter_Open: D:/SRC/StarshatterSVN/nGenEx/Physical.cpp Source File + + + + + + + + + + + + + +
+
+ + + + + + +
+
Starshatter_Open +
+
Open source Starshatter engine
+
+
+ + + + + +
+
+ +
+
+
+ +
+ + + + +
+ +
+ +
+
+
Physical.cpp
+
+
+Go to the documentation of this file.
1 /* Project nGenEx
+
2  Destroyer Studios LLC
+
3  Copyright © 1997-2004. All Rights Reserved.
+
4 
+
5  SUBSYSTEM: nGenEx.lib
+
6  FILE: Physical.cpp
+
7  AUTHOR: John DiCamillo
+
8 
+
9 
+
10  OVERVIEW
+
11  ========
+
12  Abstract Physical Object
+
13 */
+
14 
+
15 #include "MemDebug.h"
+
16 #include "Physical.h"
+
17 #include "Graphic.h"
+
18 #include "Light.h"
+
19 #include "Director.h"
+
20 
+
21 // +--------------------------------------------------------------------+
+
22 
+
23 int Physical::id_key = 1;
+
24 double Physical::sub_frame = 1.0 / 60.0;
+
25 
+
26 static const double GRAV = 6.673e-11;
+
27 
+
28 // +--------------------------------------------------------------------+
+
29 
+ +
31 : id(id_key++), obj_type(0), rep(0), light(0),
+
32 thrust(0.0f), drag(0.0f), lat_thrust(false),
+
33 trans_x(0.0f), trans_y(0.0f), trans_z(0.0f), straight(false),
+
34 roll(0.0f), pitch(0.0f), yaw(0.0f), dr(0.0f), dp(0.0f), dy(0.0f),
+
35 dr_acc(0.0f), dp_acc(0.0f), dy_acc(0.0f),
+
36 dr_drg(0.0f), dp_drg(0.0f), dy_drg(0.0f),
+
37 flight_path_yaw(0.0f), flight_path_pitch(0.0f), primary_mass(0),
+
38 roll_rate(1.0f), pitch_rate(1.0f), yaw_rate(1.0f), shake(0.0f),
+
39 radius(0.0f), mass(1.0f), integrity(1.0f), life(-1), dir(0),
+
40 g_accel(0.0f), Do(0.0f), CL(0.0f), CD(0.0f), alpha(0.0f), stall(0.0f)
+
41 {
+
42  strcpy_s(name, "unknown object");
+
43 }
+
44 
+
45 // +--------------------------------------------------------------------+
+
46 
+
47 Physical::Physical(const char* n, int t)
+
48 : id(id_key++), obj_type(t), rep(0), light(0),
+
49 thrust(0.0f), drag(0.0f), lat_thrust(false),
+
50 trans_x(0.0f), trans_y(0.0f), trans_z(0.0f), straight(false),
+
51 roll(0.0f), pitch(0.0f), yaw(0.0f), dr(0.0f), dp(0.0f), dy(0.0f),
+
52 dr_acc(0.0f), dp_acc(0.0f), dy_acc(0.0f),
+
53 dr_drg(0.0f), dp_drg(0.0f), dy_drg(0.0f),
+
54 flight_path_yaw(0.0f), flight_path_pitch(0.0f), primary_mass(0),
+
55 roll_rate(1.0f), pitch_rate(1.0f), yaw_rate(1.0f), shake(0.0f),
+
56 radius(0.0f), mass(1.0f), integrity(1.0f), life(-1), dir(0),
+
57 g_accel(0.0f), Do(0.0f), CL(0.0f), CD(0.0f), alpha(0.0f), stall(0.0f)
+
58 {
+
59  strncpy_s(name, n, NAMELEN-1);
+
60  name[NAMELEN-1] = 0;
+
61 }
+
62 
+
63 // +--------------------------------------------------------------------+
+
64 
+ +
66 {
+
67  // inform graphic rep and light that we are leaving:
+ + +
70 
+
71  // we own the director
+
72  delete dir;
+
73  dir = 0;
+
74 }
+
75 
+
76 // +--------------------------------------------------------------------+
+
77 
+
78 inline double random() { return rand()-16384; }
+
79 
+
80 void
+ +
82 {
+
83  Point orig_velocity = Velocity();
+ +
85 
+
86  // if this object is under direction,
+
87  // but doesn't need subframe accuracy,
+
88  // update the control parameters:
+
89  if (dir && !dir->Subframe())
+
90  dir->ExecFrame(s);
+
91 
+
92  // decrement life before destroying the frame time:
+
93  if (life > 0)
+
94  life -= s;
+
95 
+
96  // integrate equations
+
97  // using slices no larger
+
98  // than sub_frame:
+
99 
+
100  double seconds = s;
+
101 
+
102  while (s > 0.0) {
+
103  if (s > sub_frame)
+
104  seconds = sub_frame;
+
105  else
+
106  seconds = s;
+
107 
+
108  // if the director needs subframe accuracy, run it now:
+
109  if (dir && dir->Subframe())
+
110  dir->ExecFrame(seconds);
+
111 
+
112  if (!straight)
+
113  AngularFrame(seconds);
+
114 
+
115  // LINEAR MOVEMENT ----------------------------
+
116  Point pos = cam.Pos();
+
117 
+
118  // if the object is thrusting,
+
119  // accelerate along the camera normal:
+
120  if (thrust) {
+
121  Point thrustvec = cam.vpn();
+
122  thrustvec *= ((thrust/mass) * seconds);
+
123  velocity += thrustvec;
+
124  }
+
125 
+
126  LinearFrame(seconds);
+
127 
+
128  // move the position by the (time-frame scaled) velocity:
+
129  pos += velocity * seconds;
+
130  cam.MoveTo(pos);
+
131 
+
132  s -= seconds;
+
133  }
+
134 
+
135  alpha = 0.0f;
+
136 
+
137  // now update the graphic rep and light sources:
+
138  if (rep) {
+
139  rep->MoveTo(cam.Pos());
+ +
141  }
+
142 
+
143  if (light) {
+
144  light->MoveTo(cam.Pos());
+
145  }
+
146 
+
147  if (!straight)
+
148  CalcFlightPath();
+
149 
+
150  accel = (Velocity() - orig_velocity) * (1/seconds);
+
151  if (!_finite(accel.x) || !_finite(accel.y) || !_finite(accel.z))
+
152  accel = Point();
+
153 }
+
154 
+
155 // +--------------------------------------------------------------------+
+
156 
+
157 void
+ +
159 {
+ +
161 
+
162  // if this object is under direction,
+
163  // but doesn't need subframe accuracy,
+
164  // update the control parameters:
+
165  if (dir && !dir->Subframe())
+
166  dir->ExecFrame(s);
+
167 
+
168  // decrement life before destroying the frame time:
+
169  if (life > 0)
+
170  life -= s;
+
171 
+
172  // integrate equations
+
173  // using slices no larger
+
174  // than sub_frame:
+
175 
+
176  double seconds = s;
+
177 
+
178  while (s > 0.0) {
+
179  if (s > sub_frame)
+
180  seconds = sub_frame;
+
181  else
+
182  seconds = s;
+
183 
+
184  // if the director needs subframe accuracy, run it now:
+
185  if (dir && dir->Subframe())
+
186  dir->ExecFrame(seconds);
+
187 
+
188  AngularFrame(seconds);
+
189 
+
190  // LINEAR MOVEMENT ----------------------------
+
191  Point pos = cam.Pos();
+
192 
+
193  // if the object is thrusting,
+
194  // accelerate along the camera normal:
+
195  if (thrust) {
+
196  Point thrustvec = cam.vpn();
+
197  thrustvec *= ((thrust/mass) * seconds);
+
198  velocity += thrustvec;
+
199  }
+
200 
+
201  // AERODYNAMICS ------------------------------
+
202 
+
203  if (lat_thrust)
+
204  LinearFrame(seconds);
+
205 
+
206  // if no thrusters, do constant gravity:
+
207  else if (g_accel > 0)
+
208  velocity += Point(0, -g_accel, 0) * seconds;
+
209 
+
210  // compute alpha, rho, drag, and lift:
+
211 
+
212  Point vfp = velocity;
+
213  double v = vfp.Normalize();
+
214  double v_2 = 0;
+
215  double rho = GetDensity();
+
216  double lift = 0;
+
217 
+
218  if (v > 150) {
+
219  v_2 = (v-150) * (v-150);
+
220 
+
221  Point vfp1 = vfp - cam.vrt() * (vfp * cam.vrt());
+
222  vfp1.Normalize();
+
223 
+
224  double cos_alpha = vfp1 * cam.vpn();
+
225 
+
226  if (cos_alpha >= 1) {
+
227  alpha = 0.0f;
+
228  }
+
229  else {
+
230  alpha = (float) acos(cos_alpha);
+
231  }
+
232 
+
233  // if flight path is above nose, alpha is negative:
+
234  if (vfp1 * cam.vup() > 0)
+
235  alpha = -alpha;
+
236 
+
237  if (alpha <= stall) {
+
238  lift = CL * alpha * rho * v_2;
+
239  }
+
240  else {
+
241  lift = CL * (2*stall - alpha) * rho * v_2;
+
242  }
+
243 
+
244  // add lift to velocity:
+
245  if (_finite(lift))
+
246  velocity += cam.vup() * lift * seconds;
+
247  else
+
248  lift = 0;
+
249 
+
250  // if drag applies, decellerate:
+
251  double alpha_2 = alpha*alpha;
+
252  double drag_eff = (drag + (CD * alpha_2)) * rho * v_2;
+
253 
+
254  Point vn = velocity;
+
255  vn.Normalize();
+
256 
+
257  velocity += vn * -drag_eff * seconds;
+
258  }
+
259  else {
+
260  velocity *= exp(-drag * seconds);
+
261  }
+
262 
+
263  // move the position by the (time-frame scaled) velocity:
+
264  pos += velocity * seconds;
+
265  cam.MoveTo(pos);
+
266 
+
267  s -= seconds;
+
268  }
+
269 
+
270  // now update the graphic rep and light sources:
+
271  if (rep) {
+
272  rep->MoveTo(cam.Pos());
+ +
274  }
+
275 
+
276  if (light) {
+
277  light->MoveTo(cam.Pos());
+
278  }
+
279 }
+
280 
+
281 double
+ +
283 {
+
284  double alt = cam.Pos().y;
+
285  double rho = 0.75 * Do * (250e3-alt)/250e3;
+
286 
+
287  return rho;
+
288 }
+
289 
+
290 // +--------------------------------------------------------------------+
+
291 
+
292 void
+ +
294 {
+
295  // if this object is under direction,
+
296  // but doesn't need subframe accuracy,
+
297  // update the control parameters:
+
298  if (dir && !dir->Subframe())
+
299  dir->ExecFrame(s);
+
300 
+
301  // decrement life before destroying the frame time:
+
302  if (life > 0)
+
303  life -= s;
+
304 
+
305  // integrate equations
+
306  // using slices no larger
+
307  // than sub_frame:
+
308 
+
309  double seconds = s;
+
310 
+
311  while (s > 0.0) {
+
312  if (s > sub_frame)
+
313  seconds = sub_frame;
+
314  else
+
315  seconds = s;
+
316 
+
317  // if the director needs subframe accuracy, run it now:
+
318  if (dir && dir->Subframe())
+
319  dir->ExecFrame(seconds);
+
320 
+
321  if (!straight)
+
322  AngularFrame(seconds);
+
323 
+
324  Point pos = cam.Pos();
+
325 
+
326  // ARCADE FLIGHT MODEL:
+
327  // arcade_velocity vector is always in line with heading
+
328 
+
329  double speed = arcade_velocity.Normalize();
+
330  double bleed = arcade_velocity * cam.vpn();
+
331 
+
332  speed *= pow(bleed, 30);
+
333  arcade_velocity = cam.vpn() * speed;
+
334 
+
335  if (thrust) {
+
336  Point thrustvec = cam.vpn();
+
337  thrustvec *= ((thrust/mass) * seconds);
+
338  arcade_velocity += thrustvec;
+
339  }
+
340 
+
341  if (drag)
+
342  arcade_velocity *= exp(-drag * seconds);
+
343 
+
344  LinearFrame(seconds);
+
345 
+
346  // move the position by the (time-frame scaled) velocity:
+
347  pos += arcade_velocity * seconds +
+
348  velocity * seconds;
+
349 
+
350  cam.MoveTo(pos);
+
351 
+
352  s -= seconds;
+
353  }
+
354 
+
355  alpha = 0.0f;
+
356 
+
357  // now update the graphic rep and light sources:
+
358  if (rep) {
+
359  rep->MoveTo(cam.Pos());
+ +
361  }
+
362 
+
363  if (light) {
+
364  light->MoveTo(cam.Pos());
+
365  }
+
366 }
+
367 
+
368 // +--------------------------------------------------------------------+
+
369 
+
370 void
+
371 Physical::AngularFrame(double seconds)
+
372 {
+
373  if (!straight) {
+
374  dr += (float) (dr_acc * seconds);
+
375  dy += (float) (dy_acc * seconds);
+
376  dp += (float) (dp_acc * seconds);
+
377 
+
378  dr *= (float) exp(-dr_drg * seconds);
+
379  dy *= (float) exp(-dy_drg * seconds);
+
380  dp *= (float) exp(-dp_drg * seconds);
+
381 
+
382  roll = (float) (dr * seconds);
+
383  pitch = (float) (dp * seconds);
+
384  yaw = (float) (dy * seconds);
+
385 
+
386  if (shake > 0.01) {
+
387  vibration = Point(random(), random(), random());
+ +
389  vibration *= (float) (shake * seconds);
+
390 
+
391  shake *= (float) exp(-1.5 * seconds);
+
392  }
+
393  else {
+
394  vibration.x = vibration.y = vibration.z = 0.0f;
+
395  shake = 0.0f;
+
396  }
+
397 
+
398  cam.Aim(roll, pitch, yaw);
+
399  }
+
400 }
+
401 
+
402 // +--------------------------------------------------------------------+
+
403 
+
404 void
+
405 Physical::LinearFrame(double seconds)
+
406 {
+
407  // deal with lateral thrusters:
+
408 
+
409  if (trans_x) { // side-to-side
+
410  Point transvec = cam.vrt();
+
411  transvec *= ((trans_x/mass) * seconds);
+
412 
+
413  velocity += transvec;
+
414  }
+
415 
+
416  if (trans_y) { // fore-and-aft
+
417  Point transvec = cam.vpn();
+
418  transvec *= ((trans_y/mass) * seconds);
+
419 
+
420  velocity += transvec;
+
421  }
+
422 
+
423  if (trans_z) { // up-and-down
+
424  Point transvec = cam.vup();
+
425  transvec *= ((trans_z/mass) * seconds);
+
426 
+
427  velocity += transvec;
+
428  }
+
429 
+
430  // if gravity applies, attract:
+
431  if (primary_mass > 0) {
+
432  Point g = primary_loc - cam.Pos();
+
433  double r = g.Normalize();
+
434 
+
435  g *= GRAV * primary_mass / (r*r);
+
436 
+
437  velocity += g * seconds;
+
438  }
+
439 
+
440  // constant gravity:
+
441  else if (g_accel > 0)
+
442  velocity += Point(0, -g_accel, 0) * seconds;
+
443 
+
444  // if drag applies, decellerate:
+
445  if (drag)
+
446  velocity *= exp(-drag * seconds);
+
447 }
+
448 
+
449 // +--------------------------------------------------------------------+
+
450 
+
451 void
+ +
453 {
+
454  flight_path_yaw = 0.0f;
+
455  flight_path_pitch = 0.0f;
+
456 
+
457  // transform flight path into camera frame:
+
458  Point flight_path = velocity;
+
459  if (flight_path.Normalize() < 1)
+
460  return;
+
461 
+
462  Point tmp = flight_path;
+
463  flight_path.x = tmp * cam.vrt();
+
464  flight_path.y = tmp * cam.vup();
+
465  flight_path.z = tmp * cam.vpn();
+
466 
+
467  if (flight_path.z < 0.1)
+
468  return;
+
469 
+
470  // first, compute azimuth:
+
471  flight_path_yaw = (float) atan(flight_path.x / flight_path.z);
+
472  if (flight_path.z < 0) flight_path_yaw -= (float) PI;
+
473  if (flight_path_yaw < -PI) flight_path_yaw += (float) (2*PI);
+
474 
+
475  // then, rotate path into azimuth frame to compute elevation:
+
476  Camera yaw_cam;
+
477  yaw_cam.Clone(cam);
+
478  yaw_cam.Yaw(flight_path_yaw);
+
479 
+
480  flight_path.x = tmp * yaw_cam.vrt();
+
481  flight_path.y = tmp * yaw_cam.vup();
+
482  flight_path.z = tmp * yaw_cam.vpn();
+
483 
+
484  flight_path_pitch = (float) atan(flight_path.y / flight_path.z);
+
485 }
+
486 
+
487 // +--------------------------------------------------------------------+
+
488 
+
489 void
+
490 Physical::MoveTo(const Point& new_loc)
+
491 {
+
492  cam.MoveTo(new_loc);
+
493 }
+
494 
+
495 void
+ +
497 {
+
498  Point new_loc = cam.Pos() - ref;
+
499  cam.MoveTo(new_loc);
+
500 }
+
501 
+
502 void
+ +
504 {
+
505  velocity += force/mass;
+
506 }
+
507 
+
508 void
+ +
510 {
+
511  dr += (float) (torque.x/mass);
+
512  dp += (float) (torque.y/mass);
+
513  dy += (float) (torque.z/mass);
+
514 }
+
515 
+
516 void
+ +
518 {
+
519  thrust = (float) t;
+
520 }
+
521 
+
522 void
+ +
524 {
+
525  trans_x = (float) t;
+
526 }
+
527 
+
528 void
+ +
530 {
+
531  trans_y = (float) t;
+
532 }
+
533 
+
534 void
+ +
536 {
+
537  trans_z = (float) t;
+
538 }
+
539 
+
540 // +--------------------------------------------------------------------+
+
541 
+
542 void
+
543 Physical::SetHeading(double r, double p, double y)
+
544 {
+
545  roll = (float) r;
+
546  pitch = (float) p;
+
547  yaw = (float) y;
+
548 
+
549  cam.Aim(roll, pitch, yaw);
+
550 }
+
551 
+
552 void
+ +
554 {
+
555  cam.LookAt(dst);
+
556 }
+
557 
+
558 void
+ +
560 {
+
561  cam.Clone(c);
+
562 }
+
563 
+
564 void
+
565 Physical::SetAbsoluteOrientation(double r, double p, double y)
+
566 {
+
567  roll = (float) r;
+
568  pitch = (float) p;
+
569  yaw = (float) y;
+
570 
+
571  Camera work(Location().x, Location().y, Location().z);
+
572  work.Aim(r,p,y);
+
573  cam.Clone(work);
+
574 }
+
575 
+
576 void
+ +
578 {
+
579  if (r > 1) r = 1;
+
580  else if (r < -1) r = -1;
+
581 
+
582  dr_acc = (float) r * roll_rate;
+
583 }
+
584 
+
585 void
+ +
587 {
+
588  if (p > 1) p = 1;
+
589  else if (p < -1) p = -1;
+
590 
+
591  dp_acc = (float) p * pitch_rate;
+
592 }
+
593 
+
594 void
+ +
596 {
+
597  if (y > 1) y = 1;
+
598  else if (y < -1) y = -1;
+
599 
+
600  dy_acc = (float) y * yaw_rate;
+
601 }
+
602 
+
603 void
+
604 Physical::SetAngularRates(double r, double p, double y)
+
605 {
+
606  roll_rate = (float) r;
+
607  pitch_rate = (float) p;
+
608  yaw_rate = (float) y;
+
609 }
+
610 
+
611 void
+
612 Physical::GetAngularRates(double& r, double& p, double& y)
+
613 {
+
614  r = roll_rate;
+
615  p = pitch_rate;
+
616  y = yaw_rate;
+
617 }
+
618 
+
619 void
+
620 Physical::SetAngularDrag(double r, double p, double y)
+
621 {
+
622  dr_drg = (float) r;
+
623  dp_drg = (float) p;
+
624  dy_drg = (float) y;
+
625 }
+
626 
+
627 void
+
628 Physical::GetAngularDrag(double& r, double& p, double& y)
+
629 {
+
630  r = dr_drg;
+
631  p = dp_drg;
+
632  y = dy_drg;
+
633 }
+
634 
+
635 void
+
636 Physical::GetAngularThrust(double& r, double& p, double& y)
+
637 {
+
638  r = 0;
+
639  p = 0;
+
640  y = 0;
+
641 
+
642  if (dr_acc > 0.05 * roll_rate) r = 1;
+
643  else if (dr_acc < -0.05 * roll_rate) r = -1;
+
644  else if (dr > 0.01 * roll_rate) r = -1;
+
645  else if (dr < -0.01 * roll_rate) r = 1;
+
646 
+
647  if (dy_acc > 0.05 * yaw_rate) y = 1;
+
648  else if (dy_acc < -0.05 * yaw_rate) y = -1;
+
649  else if (dy > 0.01 * yaw_rate) y = -1;
+
650  else if (dy < -0.01 * yaw_rate) y = 1;
+
651 
+
652  if (dp_acc > 0.05 * pitch_rate) p = 1;
+
653  else if (dp_acc < -0.05 * pitch_rate) p = -1;
+
654  else if (dp > 0.01 * pitch_rate) p = -1;
+
655  else if (dp < -0.01 * pitch_rate) p = 1;
+
656 }
+
657 
+
658 
+
659 void
+
660 Physical::SetPrimary(const Point& l, double m)
+
661 {
+
662  primary_loc = l;
+
663  primary_mass = m;
+
664 }
+
665 
+
666 void
+ +
668 {
+
669  if (g >= 0)
+
670  g_accel = (float) g;
+
671 }
+
672 
+
673 void
+ +
675 {
+
676  if (d >= 0)
+
677  Do = (float) d;
+
678 }
+
679 
+
680 // +--------------------------------------------------------------------+
+
681 
+
682 void
+
683 Physical::InflictDamage(double damage, int /*type*/)
+
684 {
+
685  integrity -= (float) damage;
+
686 
+
687  if (integrity < 1.0f)
+
688  integrity = 0.0f;
+
689 }
+
690 
+
691 // +--------------------------------------------------------------------+
+
692 
+
693 int
+ +
695 {
+
696  // representation collision test (will do bounding spheres first):
+
697  if (rep && o.rep)
+
698  return rep->CollidesWith(*o.rep);
+
699 
+
700  Point delta_loc = Location() - o.Location();
+
701 
+
702  // bounding spheres test:
+
703  if (delta_loc.length() > radius + o.radius)
+
704  return 0;
+
705 
+
706  // assume collision:
+
707  return 1;
+
708 }
+
709 
+
710 
+
711 // +--------------------------------------------------------------------+
+
712 
+
713 void
+ +
715 {
+
716  double mass_sum = a.mass + b.mass;
+
717  double mass_delta = a.mass - b.mass;
+
718 
+
719  Point vel_a = (Point(b.velocity) * (2 * b.mass) + Point(a.velocity) * mass_delta) * (1/mass_sum);
+
720  Point vel_b = (Point(a.velocity) * (2 * a.mass) - Point(b.velocity) * mass_delta) * (1/mass_sum);
+
721 
+
722  a.velocity = vel_a;
+
723  b.velocity = vel_b;
+
724 }
+
725 
+
726 // +--------------------------------------------------------------------+
+
727 
+
728 void
+ +
730 {
+
731  double mass_sum = a.mass + b.mass;
+
732 
+
733  Point vel_a = (Point(a.velocity) * a.mass + Point(b.velocity) * b.mass) * (1/mass_sum);
+
734 
+
735  a.velocity = vel_a;
+
736  b.velocity = vel_a;
+
737 }
+
738 
+
739 // +--------------------------------------------------------------------+
+
740 
+
741 void
+ +
743 {
+
744  double mass_sum = a.mass + b.mass;
+
745  double mass_delta = a.mass - b.mass;
+
746 
+
747  Point avel = a.Velocity();
+
748  Point bvel = b.Velocity();
+
749  Point dv = avel - bvel;
+
750 
+
751  // low delta-v: stick
+
752  if (dv.length() < 20) {
+
753  if (a.mass > b.mass) {
+
754  b.velocity = a.velocity;
+
755  }
+
756 
+
757  else {
+
758  a.velocity = b.velocity;
+
759  }
+
760  }
+
761 
+
762  // high delta-v: bounce
+
763  else {
+
764  Point Ve_a = (bvel * (2 * b.mass) + avel * mass_delta) * (1/mass_sum) * 0.65;
+
765  Point Ve_b = (avel * (2 * a.mass) - bvel * mass_delta) * (1/mass_sum) * 0.65;
+
766  Point Vi_ab = (avel * a.mass + bvel * b.mass) * (1/mass_sum) * 0.35;
+
767 
+
768  a.arcade_velocity = Point();
+
769  b.arcade_velocity = Point();
+
770 
+
771  a.velocity = Ve_a + Vi_ab;
+
772  b.velocity = Ve_b + Vi_ab;
+
773  }
+
774 }
+
775 
+
+
+ + + + -- cgit v1.1