Browse Source

add file headers and docstring comments
change get_read_x_size() to get_x_size()
rename subdivisons to num_subdivisions
replace pow()
use intersections.empty() and size_t

hecris 6 years ago
parent
commit
9c35e68650

+ 54 - 6
panda/src/collide/collisionHeightfield.I

@@ -1,30 +1,66 @@
+/**
+ * PANDA 3D SOFTWARE
+ * Copyright (c) Carnegie Mellon University.  All rights reserved.
+ *
+ * All use of this software is subject to the terms of the revised BSD
+ * license.  You should have received a copy of this license along
+ * with this source code in a file named "LICENSE."
+ *
+ * @file collisionHeightfield.I
+ * @author hecris
+ * @date 2019-07-01
+ */
+
+/**
+ *
+ */
 INLINE CollisionHeightfield::
 INLINE CollisionHeightfield::
 CollisionHeightfield() {
 CollisionHeightfield() {
 }
 }
 
 
+/**
+ *
+ */
 INLINE CollisionHeightfield::
 INLINE CollisionHeightfield::
 CollisionHeightfield(const CollisionHeightfield &copy) {
 CollisionHeightfield(const CollisionHeightfield &copy) {
 }
 }
 
 
+/**
+ *
+ */
+INLINE CollisionHeightfield::
+~CollisionHeightfield() {
+  delete[] _nodes;
+ }
+
+/**
+ *
+ */
 INLINE void CollisionHeightfield::
 INLINE void CollisionHeightfield::
 flush_level() {
 flush_level() {
   _volume_pcollector.flush_level();
   _volume_pcollector.flush_level();
   _test_pcollector.flush_level();
   _test_pcollector.flush_level();
 }
 }
 
 
+/**
+ *
+ */
 INLINE PNMImage CollisionHeightfield::
 INLINE PNMImage CollisionHeightfield::
 get_heightfield() {
 get_heightfield() {
   return _heightfield;
   return _heightfield;
 }
 }
 
 
+/**
+ *
+ */
 INLINE void CollisionHeightfield::
 INLINE void CollisionHeightfield::
 set_heightfield(PNMImage heightfield) {
 set_heightfield(PNMImage heightfield) {
-  int r = _heightfield.get_read_x_size();
-  int c = _heightfield.get_read_y_size();
+  int r = _heightfield.get_x_size();
+  int c = _heightfield.get_y_size();
   _heightfield = heightfield;
   _heightfield = heightfield;
 
 
-  if (_heightfield.get_read_x_size() == r &&
-      _heightfield.get_read_y_size() == c) {
+  if (_heightfield.get_x_size() == r &&
+      _heightfield.get_y_size() == c) {
     fill_quadtree_heights();
     fill_quadtree_heights();
   } else {
   } else {
     fill_quadtree_areas();
     fill_quadtree_areas();
@@ -32,22 +68,34 @@ set_heightfield(PNMImage heightfield) {
   }
   }
 }
 }
 
 
+/**
+ *
+ */
 INLINE PN_stdfloat CollisionHeightfield::
 INLINE PN_stdfloat CollisionHeightfield::
 get_max_height() {
 get_max_height() {
   return _max_height;
   return _max_height;
 }
 }
 
 
+/**
+ *
+ */
 INLINE void CollisionHeightfield::
 INLINE void CollisionHeightfield::
 set_max_height(PN_stdfloat max_height) {
 set_max_height(PN_stdfloat max_height) {
   _max_height = max_height;
   _max_height = max_height;
   fill_quadtree_heights();
   fill_quadtree_heights();
 }
 }
 
 
+/**
+ *
+ */
 INLINE int CollisionHeightfield::
 INLINE int CollisionHeightfield::
-get_subdivisions() {
-  return _subdivisions;
+get_num_subdivisions() {
+  return _num_subdivisions;
 }
 }
 
 
+/**
+ *
+ */
 INLINE PN_stdfloat CollisionHeightfield::
 INLINE PN_stdfloat CollisionHeightfield::
 get_height(int x, int y) const {
 get_height(int x, int y) const {
   return _heightfield.get_gray(x, y) * _max_height;
   return _heightfield.get_gray(x, y) * _max_height;

+ 34 - 33
panda/src/collide/collisionHeightfield.cxx

@@ -6,7 +6,7 @@
  * license.  You should have received a copy of this license along
  * license.  You should have received a copy of this license along
  * with this source code in a file named "LICENSE."
  * with this source code in a file named "LICENSE."
  *
  *
- * @file CollisionHeightfield.cxx
+ * @file collisionHeightfield.cxx
  * @author hecris
  * @author hecris
  * @date 2019-07-01
  * @date 2019-07-01
  */
  */
@@ -30,17 +30,23 @@ using std::queue;
 using std::vector;
 using std::vector;
 using std::sort;
 using std::sort;
 
 
+PStatCollector CollisionHeightfield::_volume_pcollector(
+      "Collision Volumes:CollisionHeightfield");
+PStatCollector CollisionHeightfield::_test_pcollector(
+      "Collision Tests:CollisionHeightfield");
+TypeHandle CollisionHeightfield::_type_handle;
+
 /**
 /**
  *
  *
  */
  */
 CollisionHeightfield::
 CollisionHeightfield::
 CollisionHeightfield(PNMImage heightfield,
 CollisionHeightfield(PNMImage heightfield,
-                     PN_stdfloat max_height, int subdivisions) {
+                     PN_stdfloat max_height, int num_subdivisions) {
   _heightfield = heightfield;
   _heightfield = heightfield;
   _max_height = max_height;
   _max_height = max_height;
   _nodes_count = 0;
   _nodes_count = 0;
 
 
-  set_subdivisions(subdivisions);
+  set_num_subdivisions(num_subdivisions);
 }
 }
 
 
 /**
 /**
@@ -53,30 +59,30 @@ CollisionHeightfield(PNMImage heightfield,
  * automatically be decremented.
  * automatically be decremented.
  */
  */
 void CollisionHeightfield::
 void CollisionHeightfield::
-set_subdivisions(int subdivisions) {
+set_num_subdivisions(int num_subdivisions) {
   // The number of subdivisions should not be negative
   // The number of subdivisions should not be negative
-  nassertv(subdivisions >= 0 && subdivisions <= 10);
+  nassertv(num_subdivisions >= 0 && num_subdivisions <= 10);
   // Determine the number of quadtree nodes needed
   // Determine the number of quadtree nodes needed
   // for the corresponding number of subdivisions.
   // for the corresponding number of subdivisions.
   int nodes_count = 0;
   int nodes_count = 0;
-  for (int i = 0; i <= subdivisions; i++) {
-    nodes_count += pow(4, i);
+  for (int i = 0; i <= num_subdivisions; i++) {
+    nodes_count += 1 << (i * 2);
   }
   }
   if (nodes_count == _nodes_count) {
   if (nodes_count == _nodes_count) {
     // No changes to quadtree to be done
     // No changes to quadtree to be done
     return;
     return;
   }
   }
   // Calculate the index of the first quad tree leaf node
   // Calculate the index of the first quad tree leaf node
-  int leaf_first_index = nodes_count - pow(4, subdivisions);
+  int leaf_first_index = nodes_count - pow(4, num_subdivisions);
   // Calculate the area of a leaf node in the quadtree
   // Calculate the area of a leaf node in the quadtree
-  PN_stdfloat heightfield_area = _heightfield.get_read_x_size() *
-                                 _heightfield.get_read_y_size();
+  PN_stdfloat heightfield_area = _heightfield.get_x_size() *
+                                 _heightfield.get_y_size();
   nassertv(heightfield_area > 0);
   nassertv(heightfield_area > 0);
   PN_stdfloat num_leafs = nodes_count - leaf_first_index;
   PN_stdfloat num_leafs = nodes_count - leaf_first_index;
   // If the area is too small (less than 1), then we
   // If the area is too small (less than 1), then we
   // retry by decrementing the number of subdivisions.
   // retry by decrementing the number of subdivisions.
   if (heightfield_area / num_leafs < 1) {
   if (heightfield_area / num_leafs < 1) {
-    set_subdivisions(subdivisions - 1);
+    set_num_subdivisions(num_subdivisions - 1);
     return;
     return;
   }
   }
   if (nodes_count < _nodes_count) {
   if (nodes_count < _nodes_count) {
@@ -97,7 +103,7 @@ set_subdivisions(int subdivisions) {
     fill_quadtree_areas();
     fill_quadtree_areas();
     fill_quadtree_heights();
     fill_quadtree_heights();
   }
   }
-  _subdivisions = subdivisions;
+  _num_subdivisions = num_subdivisions;
 }
 }
 
 
 /**
 /**
@@ -105,12 +111,12 @@ set_subdivisions(int subdivisions) {
  */
  */
 void CollisionHeightfield::
 void CollisionHeightfield::
 fill_quadtree_areas() {
 fill_quadtree_areas() {
-  nassertv(_heightfield.get_read_x_size() > 0 &&
-           _heightfield.get_read_y_size() > 0);
+  nassertv(_heightfield.get_x_size() > 0 &&
+           _heightfield.get_y_size() > 0);
 
 
   _nodes[0].area.min = {0, 0};
   _nodes[0].area.min = {0, 0};
-  _nodes[0].area.max = {(float)_heightfield.get_read_x_size(),
-                        (float)_heightfield.get_read_y_size()};
+  _nodes[0].area.max = {(float)_heightfield.get_x_size(),
+                        (float)_heightfield.get_y_size()};
   _nodes[0].index = 0;
   _nodes[0].index = 0;
   QuadTreeNode parent;
   QuadTreeNode parent;
   for (int i = 1; i < _nodes_count; i += 4) {
   for (int i = 1; i < _nodes_count; i += 4) {
@@ -156,7 +162,7 @@ fill_quadtree_heights() {
       for (int x = node.area.min[0]; x < node.area.max[0]; x++) {
       for (int x = node.area.min[0]; x < node.area.max[0]; x++) {
         for (int y = node.area.min[1]; y < node.area.max[1]; y++) {
         for (int y = node.area.min[1]; y < node.area.max[1]; y++) {
           PN_stdfloat value = _heightfield.get_gray(x,
           PN_stdfloat value = _heightfield.get_gray(x,
-            _heightfield.get_read_y_size() - 1 - y) * _max_height;
+            _heightfield.get_y_size() - 1 - y) * _max_height;
 
 
           height_min = min(value, height_min);
           height_min = min(value, height_min);
           height_max = max(value, height_max);
           height_max = max(value, height_max);
@@ -192,7 +198,7 @@ test_intersection_from_ray(const CollisionEntry &entry) const {
   vector<QuadTreeIntersection> intersections;
   vector<QuadTreeIntersection> intersections;
   intersections = find_intersections(line_intersects_box, params);
   intersections = find_intersections(line_intersects_box, params);
 
 
-  if (intersections.size() == 0) {
+  if (intersections.empty()) {
     return nullptr;
     return nullptr;
   }
   }
   // Sort intersections by their t1 values so we can return
   // Sort intersections by their t1 values so we can return
@@ -200,7 +206,7 @@ test_intersection_from_ray(const CollisionEntry &entry) const {
   sort(intersections.begin(), intersections.end());
   sort(intersections.begin(), intersections.end());
 
 
   double t1, t2;
   double t1, t2;
-  for (unsigned i = 0; i < intersections.size(); i++) {
+  for (size_t i = 0; i < intersections.size(); i++) {
     t1 = intersections[i].tmin;
     t1 = intersections[i].tmin;
     t2 = intersections[i].tmax;
     t2 = intersections[i].tmax;
 
 
@@ -282,7 +288,9 @@ test_intersection_from_sphere(const CollisionEntry &entry) const {
   vector<QuadTreeIntersection> intersections;
   vector<QuadTreeIntersection> intersections;
   intersections= find_intersections(sphere_intersects_box, params);
   intersections= find_intersections(sphere_intersects_box, params);
 
 
-  if (intersections.size() == 0) return nullptr;
+  if (intersections.empty()) {
+    return nullptr;
+  }
 
 
   LPoint3 point;
   LPoint3 point;
   LPoint3 closest_point;
   LPoint3 closest_point;
@@ -292,7 +300,7 @@ test_intersection_from_sphere(const CollisionEntry &entry) const {
   bool intersected = false;
   bool intersected = false;
   #define in_box(x, y, node) (x >= node.area.min[0] && y >= node.area.min[1] \
   #define in_box(x, y, node) (x >= node.area.min[0] && y >= node.area.min[1] \
                            && x <= node.area.max[0] && y <= node.area.max[1])
                            && x <= node.area.max[0] && y <= node.area.max[1])
-  for (unsigned i = 0; i < intersections.size(); i++) {
+  for (size_t i = 0; i < intersections.size(); i++) {
     QuadTreeNode node = _nodes[intersections[i].node_index];
     QuadTreeNode node = _nodes[intersections[i].node_index];
     // Iterate through the circle's area and find triangle intersections,
     // Iterate through the circle's area and find triangle intersections,
     // find the one closest to the center of the sphere.
     // find the one closest to the center of the sphere.
@@ -355,13 +363,13 @@ test_intersection_from_box(const CollisionEntry &entry) const {
   vector<QuadTreeIntersection> intersections;
   vector<QuadTreeIntersection> intersections;
   intersections = find_intersections(box_intersects_box, params);
   intersections = find_intersections(box_intersects_box, params);
 
 
-  if (intersections.size() == 0) {
+  if (intersections.empty()) {
     return nullptr;
     return nullptr;
   }
   }
 
 
   bool intersected = false;
   bool intersected = false;
   Triangle intersected_tri;
   Triangle intersected_tri;
-  for (unsigned i = 0; i < intersections.size(); i++) {
+  for (size_t i = 0; i < intersections.size(); i++) {
     QuadTreeNode node = _nodes[intersections[i].node_index];
     QuadTreeNode node = _nodes[intersections[i].node_index];
     // Find the overlapping rectangle between the two boxes and
     // Find the overlapping rectangle between the two boxes and
     // test the heightfield elements in that area.
     // test the heightfield elements in that area.
@@ -453,14 +461,13 @@ line_intersects_triangle(double &t, const LPoint3 &from,
                          const LPoint3 &delta,
                          const LPoint3 &delta,
                          const Triangle &triangle) {
                          const Triangle &triangle) {
   // Implementation of Möller-Trumbore algorithm
   // Implementation of Möller-Trumbore algorithm
-  const PN_stdfloat EPSILON = 1.0e-7;
   PN_stdfloat a,f,u,v;
   PN_stdfloat a,f,u,v;
   LVector3 edge1, edge2, h, s, q;
   LVector3 edge1, edge2, h, s, q;
   edge1 = triangle.p2 - triangle.p1;
   edge1 = triangle.p2 - triangle.p1;
   edge2 = triangle.p3 - triangle.p1;
   edge2 = triangle.p3 - triangle.p1;
   h = delta.cross(edge2);
   h = delta.cross(edge2);
   a = dot(edge1, h);
   a = dot(edge1, h);
-  if (a > -EPSILON && a < EPSILON) {
+  if (IS_NEARLY_ZERO(a)) {
     // line parallel to triangle
     // line parallel to triangle
     return false;
     return false;
   }
   }
@@ -676,8 +683,8 @@ find_intersections(BoxIntersection intersects_box, IntersectionParams params) co
  */
  */
 vector<CollisionHeightfield::Triangle> CollisionHeightfield::
 vector<CollisionHeightfield::Triangle> CollisionHeightfield::
 get_triangles(int x, int y) const {
 get_triangles(int x, int y) const {
-  int rows = _heightfield.get_read_x_size();
-  int cols = _heightfield.get_read_y_size();
+  int rows = _heightfield.get_x_size();
+  int cols = _heightfield.get_y_size();
   vector<Triangle> triangles;
   vector<Triangle> triangles;
   if (x < 0 || y < 0 || x >= rows || y >= cols)
   if (x < 0 || y < 0 || x >= rows || y >= cols)
     return triangles;
     return triangles;
@@ -765,9 +772,3 @@ void CollisionHeightfield::
 register_with_read_factory() {
 register_with_read_factory() {
   BamReader::get_factory()->register_factory(get_class_type(), make_CollisionHeightfield);
   BamReader::get_factory()->register_factory(get_class_type(), make_CollisionHeightfield);
 }
 }
-
-PStatCollector CollisionHeightfield::_volume_pcollector(
-      "Collision Volumes:CollisionHeightfield");
-PStatCollector CollisionHeightfield::_test_pcollector(
-      "Collision Tests:CollisionHeightfield");
-TypeHandle CollisionHeightfield::_type_handle;

+ 18 - 5
panda/src/collide/collisionHeightfield.h

@@ -1,3 +1,16 @@
+/**
+ * PANDA 3D SOFTWARE
+ * Copyright (c) Carnegie Mellon University.  All rights reserved.
+ *
+ * All use of this software is subject to the terms of the revised BSD
+ * license.  You should have received a copy of this license along
+ * with this source code in a file named "LICENSE."
+ *
+ * @file collisionHeightfield.h
+ * @author hecris
+ * @date 2019-07-01
+ */
+
 #ifndef COLLISIONHEIGHTFIELD_H
 #ifndef COLLISIONHEIGHTFIELD_H
 #define COLLISIONHEIGHTFIELD_H
 #define COLLISIONHEIGHTFIELD_H
 
 
@@ -15,8 +28,7 @@
 class EXPCL_PANDA_COLLIDE CollisionHeightfield : public CollisionSolid {
 class EXPCL_PANDA_COLLIDE CollisionHeightfield : public CollisionSolid {
 PUBLISHED:
 PUBLISHED:
   CollisionHeightfield(PNMImage heightfield,
   CollisionHeightfield(PNMImage heightfield,
-                       PN_stdfloat max_height, int subdivisions);
-  ~CollisionHeightfield() { delete[] _nodes; }
+                       PN_stdfloat max_height, int num_subdivisions);
   virtual LPoint3 get_collision_origin() const;
   virtual LPoint3 get_collision_origin() const;
 
 
   INLINE PNMImage get_heightfield();
   INLINE PNMImage get_heightfield();
@@ -25,8 +37,8 @@ PUBLISHED:
   INLINE PN_stdfloat get_max_height();
   INLINE PN_stdfloat get_max_height();
   INLINE void set_max_height(PN_stdfloat max_height);
   INLINE void set_max_height(PN_stdfloat max_height);
 
 
-  INLINE int get_subdivisions();
-  void set_subdivisions(int subdivisions);
+  INLINE int get_num_subdivisions();
+  void set_num_subdivisions(int num_subdivisions);
 
 
   INLINE PN_stdfloat get_height(int x, int y) const;
   INLINE PN_stdfloat get_height(int x, int y) const;
 
 
@@ -75,7 +87,7 @@ protected:
 private:
 private:
   PNMImage _heightfield;
   PNMImage _heightfield;
   PN_stdfloat _max_height;
   PN_stdfloat _max_height;
-  int _subdivisions;
+  int _num_subdivisions;
   QuadTreeNode *_nodes;
   QuadTreeNode *_nodes;
   int _nodes_count;
   int _nodes_count;
   int _leaf_first_index;
   int _leaf_first_index;
@@ -128,6 +140,7 @@ public:
   virtual PStatCollector &get_test_pcollector();
   virtual PStatCollector &get_test_pcollector();
 
 
   INLINE static void flush_level();
   INLINE static void flush_level();
+  INLINE ~CollisionHeightfield();
 
 
 protected:
 protected:
   virtual PT(BoundingVolume) compute_internal_bounds() const;
   virtual PT(BoundingVolume) compute_internal_bounds() const;

+ 14 - 14
tests/collide/test_into_heightfield.py

@@ -8,8 +8,8 @@ def test_sphere_into_heightfield():
     img.set_gray_val(1, 1, 255)
     img.set_gray_val(1, 1, 255)
     # Make CollisionHeightfield
     # Make CollisionHeightfield
     max_height = 10
     max_height = 10
-    subdivisions = 1
-    heightfield = CollisionHeightfield(img, max_height, subdivisions)
+    num_subdivisions = 1
+    heightfield = CollisionHeightfield(img, max_height, num_subdivisions)
     # The coordinate (1, 1) on our heightfield image
     # The coordinate (1, 1) on our heightfield image
     # maps to the coordinate (1, 510, Z) in 3D space
     # maps to the coordinate (1, 510, Z) in 3D space
     sphere = CollisionSphere((1, 510, 11), 1)
     sphere = CollisionSphere((1, 510, 11), 1)
@@ -27,20 +27,20 @@ def test_sphere_into_heightfield():
     assert entry.get_surface_point(np_from) == (1, 510, 10.1)
     assert entry.get_surface_point(np_from) == (1, 510, 10.1)
 
 
     with pytest.raises(AssertionError) as err:
     with pytest.raises(AssertionError) as err:
-        assert heightfield.set_subdivisions(-1) == err
-        assert heightfield.set_subdivisions(11) == err
+        assert heightfield.set_num_subdivisions(-1) == err
+        assert heightfield.set_num_subdivisions(11) == err
 
 
     # Use a greater number of subdivisions, should still work
     # Use a greater number of subdivisions, should still work
-    subdivisions = 10
-    heightfield.set_subdivisions(subdivisions)
+    num_subdivisions = 10
+    heightfield.set_num_subdivisions(num_subdivisions)
     entry, np_from, np_into = make_collision(sphere, heightfield)
     entry, np_from, np_into = make_collision(sphere, heightfield)
     assert entry.get_surface_point(np_from) == (1, 510, 10.1)
     assert entry.get_surface_point(np_from) == (1, 510, 10.1)
     # Using 10 subdivisions is overkill for such a small heightfield,
     # Using 10 subdivisions is overkill for such a small heightfield,
     # CollisionHeightfield should've automatically decreased it
     # CollisionHeightfield should've automatically decreased it
-    assert heightfield.get_subdivisions() < subdivisions
-    # Zero subdivisions work too
-    subdivisions = 0
-    heightfield.set_subdivisions(subdivisions)
+    assert heightfield.get_num_subdivisions() < num_subdivisions
+    # Zero subdivisions should work too
+    num_subdivisions = 0
+    heightfield.set_num_subdivisions(num_subdivisions)
     entry, np_from, np_into = make_collision(sphere, heightfield)
     entry, np_from, np_into = make_collision(sphere, heightfield)
     assert entry.get_surface_point(np_from) == (1, 510, 10.1)
     assert entry.get_surface_point(np_from) == (1, 510, 10.1)
     # Modify the heightfield, no longer colliding
     # Modify the heightfield, no longer colliding
@@ -55,8 +55,8 @@ def test_ray_into_heightfield():
     img = PNMImage(127, 127, 1)
     img = PNMImage(127, 127, 1)
     img.fill_val(0)
     img.fill_val(0)
     max_height = 10
     max_height = 10
-    subdivisions = 1
-    heightfield = CollisionHeightfield(img, max_height, subdivisions)
+    num_subdivisions = 1
+    heightfield = CollisionHeightfield(img, max_height, num_subdivisions)
     # Make ray
     # Make ray
     ray = CollisionRay((100, 100, 100), (-1, -1, -1))
     ray = CollisionRay((100, 100, 100), (-1, -1, -1))
     entry = make_collision(ray, heightfield)[0]
     entry = make_collision(ray, heightfield)[0]
@@ -84,8 +84,8 @@ def test_box_into_heightfield():
     img.set_gray_val(1, 1, 255)
     img.set_gray_val(1, 1, 255)
     # Make CollisionHeightfield
     # Make CollisionHeightfield
     max_height = 10
     max_height = 10
-    subdivisions = 5
-    heightfield = CollisionHeightfield(img, max_height, subdivisions)
+    num_subdivisions = 5
+    heightfield = CollisionHeightfield(img, max_height, num_subdivisions)
     # Make box
     # Make box
     box = CollisionBox((1, 5128, 10), 1, 1, 1)
     box = CollisionBox((1, 5128, 10), 1, 1, 1)
     entry = make_collision(box, heightfield)
     entry = make_collision(box, heightfield)