Browse Source

physics: Add support for distance-based falloff (#1731)

omn14 8 months ago
parent
commit
33e6ed8907

+ 16 - 1
direct/src/tkpanels/ParticlePanel.py

@@ -2872,6 +2872,12 @@ class ParticlePanel(AppShell):
             if type == 'FT_ONE_OVER_R_CUBED':
             if type == 'FT_ONE_OVER_R_CUBED':
                 #f.setFalloffType(LinearDistanceForce.FTONEOVERRCUBED)
                 #f.setFalloffType(LinearDistanceForce.FTONEOVERRCUBED)
                 f.setFalloffType(2)
                 f.setFalloffType(2)
+            if type == 'FT_ONE_OVER_R_OVER_DISTANCE':
+                f.setFalloffType(3)
+            if type == 'FT_ONE_OVER_R_OVER_DISTANCE_SQUARED':
+                f.setFalloffType(4)
+            if type == 'FT_ONE_OVER_R_OVER_DISTANCE_CUBED':
+                f.setFalloffType(5)
 
 
         def setForceCenter(vec, f = force):
         def setForceCenter(vec, f = force):
             f.setForceCenter(Point3(vec[0], vec[1], vec[2]))
             f.setForceCenter(Point3(vec[0], vec[1], vec[2]))
@@ -2886,7 +2892,10 @@ class ParticlePanel(AppShell):
             'Set force falloff type',
             'Set force falloff type',
             ('FT_ONE_OVER_R',
             ('FT_ONE_OVER_R',
              'FT_ONE_OVER_R_SQUARED',
              'FT_ONE_OVER_R_SQUARED',
-             'FT_ONE_OVER_R_CUBED'),
+             'FT_ONE_OVER_R_CUBED',
+             'FT_ONE_OVER_R_OVER_DISTANCE',
+             'FT_ONE_OVER_R_OVER_DISTANCE_SQUARED',
+             'FT_ONE_OVER_R_OVER_DISTANCE_CUBED'),
             command = setFalloffType)
             command = setFalloffType)
         self.getWidget(pageName, forceName + ' Falloff').configure(
         self.getWidget(pageName, forceName + ' Falloff').configure(
             label_width = 16)
             label_width = 16)
@@ -2897,6 +2906,12 @@ class ParticlePanel(AppShell):
             var.set('FT_ONE_OVER_R_SQUARED')
             var.set('FT_ONE_OVER_R_SQUARED')
         elif falloff == LinearDistanceForce.FTONEOVERRCUBED:
         elif falloff == LinearDistanceForce.FTONEOVERRCUBED:
             var.set('FT_ONE_OVER_R_CUBED')
             var.set('FT_ONE_OVER_R_CUBED')
+        elif falloff == LinearDistanceForce.FTONEOVERROVERDISTANCE:
+            var.set('FT_ONE_OVER_R_OVER_DISTANCE')
+        elif falloff == LinearDistanceForce.FTONEOVERROVERDISTANCESQUARED:
+            var.set('FT_ONE_OVER_R_OVER_DISTANCE_SQUARED')
+        elif falloff == LinearDistanceForce.FTONEOVERROVERDISTANCECUBED:
+            var.set('FT_ONE_OVER_R_OVER_DISTANCE_CUBED')
         vec = force.getForceCenter()
         vec = force.getForceCenter()
         self.createVector3Entry(frame, pageName, forceName + ' Center',
         self.createVector3Entry(frame, pageName, forceName + ' Center',
                                 'Set center of force',
                                 'Set center of force',

+ 4 - 1
panda/src/physics/linearDistanceForce.h

@@ -26,7 +26,10 @@ PUBLISHED:
   enum FalloffType {
   enum FalloffType {
     FT_ONE_OVER_R,
     FT_ONE_OVER_R,
     FT_ONE_OVER_R_SQUARED,
     FT_ONE_OVER_R_SQUARED,
-    FT_ONE_OVER_R_CUBED
+    FT_ONE_OVER_R_CUBED,
+    FT_ONE_OVER_R_OVER_DISTANCE,
+    FT_ONE_OVER_R_OVER_DISTANCE_SQUARED,
+    FT_ONE_OVER_R_OVER_DISTANCE_CUBED
   };
   };
 
 
   INLINE void set_radius(PN_stdfloat r);
   INLINE void set_radius(PN_stdfloat r);

+ 19 - 1
panda/src/physics/linearSinkForce.cxx

@@ -61,7 +61,25 @@ make_copy() {
  */
  */
 LVector3 LinearSinkForce::
 LVector3 LinearSinkForce::
 get_child_vector(const PhysicsObject *po) {
 get_child_vector(const PhysicsObject *po) {
-  return (get_force_center() - po->get_position()) * get_scalar_term();
+  LVector3 distance_vector = get_force_center() - po->get_position();
+  PN_stdfloat distance_squared = distance_vector.length_squared();
+
+  if (distance_squared == 0) {
+    return distance_vector;
+  }
+
+  PN_stdfloat scalar = get_scalar_term();
+
+  switch (get_falloff_type()) {
+  case FT_ONE_OVER_R_OVER_DISTANCE:
+    return (distance_vector / sqrt(distance_squared)) * scalar;
+  case FT_ONE_OVER_R_OVER_DISTANCE_SQUARED:
+    return (distance_vector / distance_squared) * scalar;
+  case FT_ONE_OVER_R_OVER_DISTANCE_CUBED:
+    return (distance_vector / (distance_squared * sqrt(distance_squared))) * scalar;
+  default:
+    return distance_vector * scalar;
+  }
 }
 }
 
 
 /**
 /**

+ 19 - 1
panda/src/physics/linearSourceForce.cxx

@@ -61,7 +61,25 @@ make_copy() {
  */
  */
 LVector3 LinearSourceForce::
 LVector3 LinearSourceForce::
 get_child_vector(const PhysicsObject *po) {
 get_child_vector(const PhysicsObject *po) {
-  return (po->get_position() - get_force_center()) * get_scalar_term();
+  LVector3 distance_vector = po->get_position() - get_force_center();
+  PN_stdfloat distance_squared = distance_vector.length_squared();
+
+  if (distance_squared == 0) {
+    return distance_vector;
+  }
+
+  PN_stdfloat scalar = get_scalar_term();
+
+  switch (get_falloff_type()) {
+  case FT_ONE_OVER_R_OVER_DISTANCE:
+    return (distance_vector / sqrt(distance_squared)) * scalar;
+  case FT_ONE_OVER_R_OVER_DISTANCE_SQUARED:
+    return (distance_vector / distance_squared) * scalar;
+  case FT_ONE_OVER_R_OVER_DISTANCE_CUBED:
+    return (distance_vector / (distance_squared * sqrt(distance_squared))) * scalar;
+  default:
+    return distance_vector * scalar;
+  }
 }
 }
 
 
 /**
 /**