3D / voxel unit tests
This commit is contained in:
parent
e12e80e511
commit
71cd2b9b41
22 changed files with 4705 additions and 0 deletions
202
tests/unit/meshlayer_test.py
Normal file
202
tests/unit/meshlayer_test.py
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
# meshlayer_test.py - Unit tests for MeshLayer terrain system
|
||||
# Tests HeightMap to 3D mesh conversion via Viewport3D
|
||||
|
||||
import mcrfpy
|
||||
import sys
|
||||
|
||||
def test_viewport3d_layer_creation():
|
||||
"""Test that layers can be created and managed"""
|
||||
print("Testing Viewport3D layer creation...")
|
||||
|
||||
viewport = mcrfpy.Viewport3D(pos=(0, 0), size=(320, 240))
|
||||
|
||||
# Initial layer count should be 0
|
||||
assert viewport.layer_count() == 0, f"Expected 0 layers, got {viewport.layer_count()}"
|
||||
|
||||
# Add a layer
|
||||
layer_info = viewport.add_layer("test_layer", z_index=5)
|
||||
assert layer_info is not None, "add_layer returned None"
|
||||
assert layer_info["name"] == "test_layer", f"Layer name mismatch: {layer_info['name']}"
|
||||
assert layer_info["z_index"] == 5, f"Z-index mismatch: {layer_info['z_index']}"
|
||||
|
||||
# Layer count should be 1
|
||||
assert viewport.layer_count() == 1, f"Expected 1 layer, got {viewport.layer_count()}"
|
||||
|
||||
# Get the layer
|
||||
retrieved = viewport.get_layer("test_layer")
|
||||
assert retrieved is not None, "get_layer returned None"
|
||||
assert retrieved["name"] == "test_layer"
|
||||
|
||||
# Get non-existent layer
|
||||
missing = viewport.get_layer("nonexistent")
|
||||
assert missing is None, "Expected None for missing layer"
|
||||
|
||||
# Remove the layer
|
||||
removed = viewport.remove_layer("test_layer")
|
||||
assert removed == True, "remove_layer should return True"
|
||||
assert viewport.layer_count() == 0, "Layer count should be 0 after removal"
|
||||
|
||||
# Remove non-existent layer
|
||||
removed_again = viewport.remove_layer("test_layer")
|
||||
assert removed_again == False, "remove_layer should return False for missing layer"
|
||||
|
||||
print(" PASS: Layer creation and management")
|
||||
|
||||
def test_terrain_from_heightmap():
|
||||
"""Test building terrain mesh from HeightMap"""
|
||||
print("Testing terrain mesh from HeightMap...")
|
||||
|
||||
viewport = mcrfpy.Viewport3D(pos=(0, 0), size=(320, 240))
|
||||
|
||||
# Create a small heightmap
|
||||
hm = mcrfpy.HeightMap((10, 10))
|
||||
hm.fill(0.5) # Flat terrain at 0.5 height
|
||||
|
||||
# Build terrain
|
||||
vertex_count = viewport.build_terrain(
|
||||
layer_name="terrain",
|
||||
heightmap=hm,
|
||||
y_scale=2.0,
|
||||
cell_size=1.0
|
||||
)
|
||||
|
||||
# Expected vertices: (10-1) x (10-1) quads x 2 triangles x 3 vertices = 9 * 9 * 6 = 486
|
||||
expected_verts = 9 * 9 * 6
|
||||
assert vertex_count == expected_verts, f"Expected {expected_verts} vertices, got {vertex_count}"
|
||||
|
||||
# Verify layer exists
|
||||
layer = viewport.get_layer("terrain")
|
||||
assert layer is not None, "Terrain layer not found"
|
||||
assert layer["vertex_count"] == expected_verts
|
||||
|
||||
print(f" PASS: Built terrain with {vertex_count} vertices")
|
||||
|
||||
def test_heightmap_terrain_generation():
|
||||
"""Test that HeightMap generation methods work with terrain"""
|
||||
print("Testing HeightMap generation methods...")
|
||||
|
||||
viewport = mcrfpy.Viewport3D(pos=(0, 0), size=(320, 240))
|
||||
|
||||
# Test midpoint displacement
|
||||
hm = mcrfpy.HeightMap((17, 17)) # Power of 2 + 1 for midpoint displacement
|
||||
hm.mid_point_displacement(0.5, seed=123)
|
||||
hm.normalize(0.0, 1.0)
|
||||
|
||||
min_h, max_h = hm.min_max()
|
||||
assert min_h >= 0.0, f"Min height should be >= 0, got {min_h}"
|
||||
assert max_h <= 1.0, f"Max height should be <= 1, got {max_h}"
|
||||
|
||||
vertex_count = viewport.build_terrain("terrain", hm, y_scale=5.0, cell_size=1.0)
|
||||
assert vertex_count > 0, "Should have vertices"
|
||||
|
||||
print(f" PASS: Midpoint displacement terrain with {vertex_count} vertices")
|
||||
|
||||
def test_orbit_camera():
|
||||
"""Test camera orbit helper"""
|
||||
print("Testing camera orbit...")
|
||||
|
||||
viewport = mcrfpy.Viewport3D(pos=(0, 0), size=(320, 240))
|
||||
|
||||
# Test orbit at different angles
|
||||
import math
|
||||
|
||||
viewport.orbit_camera(angle=0, distance=10, height=5)
|
||||
pos = viewport.camera_pos
|
||||
assert abs(pos[0] - 10.0) < 0.01, f"X should be 10 at angle=0, got {pos[0]}"
|
||||
assert abs(pos[1] - 5.0) < 0.01, f"Y (height) should be 5, got {pos[1]}"
|
||||
assert abs(pos[2]) < 0.01, f"Z should be 0 at angle=0, got {pos[2]}"
|
||||
|
||||
viewport.orbit_camera(angle=math.pi/2, distance=10, height=5)
|
||||
pos = viewport.camera_pos
|
||||
assert abs(pos[0]) < 0.01, f"X should be 0 at angle=pi/2, got {pos[0]}"
|
||||
assert abs(pos[2] - 10.0) < 0.01, f"Z should be 10 at angle=pi/2, got {pos[2]}"
|
||||
|
||||
print(" PASS: Camera orbit positioning")
|
||||
|
||||
def test_large_terrain():
|
||||
"""Test larger terrain (performance check)"""
|
||||
print("Testing larger terrain mesh...")
|
||||
|
||||
viewport = mcrfpy.Viewport3D(pos=(0, 0), size=(320, 240))
|
||||
|
||||
# 80x45 is mentioned in the milestone doc
|
||||
hm = mcrfpy.HeightMap((80, 45))
|
||||
hm.mid_point_displacement(0.5, seed=999)
|
||||
hm.normalize(0.0, 1.0)
|
||||
|
||||
vertex_count = viewport.build_terrain("large_terrain", hm, y_scale=4.0, cell_size=1.0)
|
||||
|
||||
# Expected: 79 * 44 * 6 = 20,856 vertices
|
||||
expected = 79 * 44 * 6
|
||||
assert vertex_count == expected, f"Expected {expected} vertices, got {vertex_count}"
|
||||
|
||||
print(f" PASS: Large terrain ({80}x{45} heightmap) with {vertex_count} vertices")
|
||||
|
||||
def test_terrain_color_map():
|
||||
"""Test applying RGB color maps to terrain"""
|
||||
print("Testing terrain color map...")
|
||||
|
||||
viewport = mcrfpy.Viewport3D(pos=(0, 0), size=(320, 240))
|
||||
|
||||
# Create small terrain
|
||||
hm = mcrfpy.HeightMap((10, 10))
|
||||
hm.fill(0.5)
|
||||
viewport.build_terrain("colored_terrain", hm, y_scale=2.0, cell_size=1.0)
|
||||
|
||||
# Create RGB color maps
|
||||
r_map = mcrfpy.HeightMap((10, 10))
|
||||
g_map = mcrfpy.HeightMap((10, 10))
|
||||
b_map = mcrfpy.HeightMap((10, 10))
|
||||
|
||||
# Fill with test colors (red terrain)
|
||||
r_map.fill(1.0)
|
||||
g_map.fill(0.0)
|
||||
b_map.fill(0.0)
|
||||
|
||||
# Apply colors - should not raise
|
||||
viewport.apply_terrain_colors("colored_terrain", r_map, g_map, b_map)
|
||||
|
||||
# Test with mismatched dimensions (should fail silently or raise)
|
||||
wrong_size = mcrfpy.HeightMap((5, 5))
|
||||
wrong_size.fill(0.5)
|
||||
# This should not crash, just do nothing due to dimension mismatch
|
||||
viewport.apply_terrain_colors("colored_terrain", wrong_size, wrong_size, wrong_size)
|
||||
|
||||
# Test with non-existent layer
|
||||
try:
|
||||
viewport.apply_terrain_colors("nonexistent", r_map, g_map, b_map)
|
||||
assert False, "Should have raised ValueError for non-existent layer"
|
||||
except ValueError:
|
||||
pass # Expected
|
||||
|
||||
print(" PASS: Terrain color map application")
|
||||
|
||||
def run_all_tests():
|
||||
"""Run all unit tests"""
|
||||
print("=" * 60)
|
||||
print("MeshLayer Unit Tests")
|
||||
print("=" * 60)
|
||||
|
||||
try:
|
||||
test_viewport3d_layer_creation()
|
||||
test_terrain_from_heightmap()
|
||||
test_heightmap_terrain_generation()
|
||||
test_orbit_camera()
|
||||
test_large_terrain()
|
||||
test_terrain_color_map()
|
||||
|
||||
print("=" * 60)
|
||||
print("ALL TESTS PASSED")
|
||||
print("=" * 60)
|
||||
sys.exit(0)
|
||||
except AssertionError as e:
|
||||
print(f"FAIL: {e}")
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"ERROR: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
sys.exit(1)
|
||||
|
||||
# Run tests
|
||||
run_all_tests()
|
||||
Loading…
Add table
Add a link
Reference in a new issue