test_into_heightfield.py 3.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. import pytest
  2. from collisions import *
  3. from panda3d.core import PNMImage
  4. def test_sphere_into_heightfield():
  5. # Setup PNMImage
  6. img = PNMImage(512, 512, 1)
  7. img.set_gray_val(1, 1, 255)
  8. # Make CollisionHeightfield
  9. max_height = 10
  10. num_subdivisions = 1
  11. heightfield = CollisionHeightfield(img, max_height, num_subdivisions)
  12. # The coordinate (1, 1) on our heightfield image
  13. # maps to the coordinate (1, 510, Z) in 3D space
  14. sphere = CollisionSphere((1, 510, 11), 1)
  15. entry, np_from, np_into = make_collision(sphere, heightfield)
  16. assert entry.get_surface_point(np_from) == (1, 510, 10)
  17. assert entry.get_surface_normal(np_from) == (0, 0, 1)
  18. # Set the sphere higher so it is not colliding anymore
  19. sphere.set_center((1, 510, 11.1))
  20. entry = make_collision(sphere, heightfield)[0]
  21. assert entry is None
  22. # Set the max_height to re-collide with the sphere
  23. max_height = 10.1
  24. heightfield.set_max_height(max_height)
  25. entry, np_from, np_into = make_collision(sphere, heightfield)
  26. assert entry.get_surface_point(np_from) == (1, 510, 10.1)
  27. #with pytest.raises(AssertionError) as err:
  28. # assert heightfield.set_num_subdivisions(-1) == err
  29. # assert heightfield.set_num_subdivisions(11) == err
  30. # Use a greater number of subdivisions, should still work
  31. num_subdivisions = 10
  32. heightfield.set_num_subdivisions(num_subdivisions)
  33. entry, np_from, np_into = make_collision(sphere, heightfield)
  34. assert entry.get_surface_point(np_from) == (1, 510, 10.1)
  35. # Using 10 subdivisions is overkill for such a small heightfield,
  36. # CollisionHeightfield should've automatically decreased it
  37. assert heightfield.get_num_subdivisions() < num_subdivisions
  38. # Zero subdivisions should work too
  39. num_subdivisions = 0
  40. heightfield.set_num_subdivisions(num_subdivisions)
  41. entry, np_from, np_into = make_collision(sphere, heightfield)
  42. assert entry.get_surface_point(np_from) == (1, 510, 10.1)
  43. # Modify the heightfield, no longer colliding
  44. img.set_gray_val(1, 1, 254)
  45. heightfield.set_heightfield(img)
  46. entry = make_collision(sphere, heightfield)[0]
  47. assert entry is None
  48. def test_ray_into_heightfield():
  49. # Setup heightfield
  50. img = PNMImage(127, 127, 1)
  51. img.fill_val(0)
  52. max_height = 10
  53. num_subdivisions = 1
  54. heightfield = CollisionHeightfield(img, max_height, num_subdivisions)
  55. # Make ray
  56. ray = CollisionRay((100, 100, 100), (-1, -1, -1))
  57. entry = make_collision(ray, heightfield)[0]
  58. assert entry is not None
  59. # Ray with only a z component in its direction
  60. ray.set_direction((0, 0, -5))
  61. entry, np_from, np_into = make_collision(ray, heightfield)
  62. assert entry.get_surface_point(np_from) == (100, 100, 0)
  63. # Set coordinate (54, 38) on heightfield to gray value of 255
  64. # Note that coordinate (54, 38) on the heightfield
  65. # maps to (54, 88, Z) in 3D space
  66. img.set_gray_val(54, 38, 255)
  67. heightfield.set_heightfield(img)
  68. ray.set_origin((54, 88, 10))
  69. entry, np_from, np_into = make_collision(ray, heightfield)
  70. assert entry.get_surface_point(np_from) == (54, 88, 10)
  71. def test_box_into_heightfield():
  72. # Try using a large non-square heightfield image
  73. img = PNMImage(5023, 5130, 1)
  74. img.set_gray_val(1, 1, 255)
  75. # Make CollisionHeightfield
  76. max_height = 10
  77. num_subdivisions = 5
  78. heightfield = CollisionHeightfield(img, max_height, num_subdivisions)
  79. # Make box
  80. box = CollisionBox((1, 5128, 10), 1, 1, 1)
  81. entry = make_collision(box, heightfield)
  82. assert entry is not None