# voxel_meshing_demo.py - Visual demo of VoxelGrid mesh rendering # Shows voxel building rendered in Viewport3D with PS1 effects import mcrfpy import sys import math # Create demo scene scene = mcrfpy.Scene("voxel_meshing_demo") # Dark background frame bg = mcrfpy.Frame(pos=(0, 0), size=(1024, 768), fill_color=mcrfpy.Color(15, 15, 25)) scene.children.append(bg) # Title title = mcrfpy.Caption(text="VoxelGrid Meshing Demo - Face-Culled 3D Voxels", pos=(20, 10)) title.fill_color = mcrfpy.Color(255, 255, 255) scene.children.append(title) # Create the 3D viewport viewport = mcrfpy.Viewport3D( pos=(50, 60), size=(600, 500), render_resolution=(320, 240), # PS1 resolution fov=60.0, camera_pos=(20.0, 15.0, 20.0), camera_target=(4.0, 2.0, 4.0), bg_color=mcrfpy.Color(50, 70, 100) # Sky color ) scene.children.append(viewport) # Create voxel grid for building print("Creating voxel building...") voxels = mcrfpy.VoxelGrid(size=(12, 8, 12), cell_size=1.0) # Define materials STONE = voxels.add_material("stone", color=mcrfpy.Color(128, 128, 128)) BRICK = voxels.add_material("brick", color=mcrfpy.Color(165, 82, 42)) WOOD = voxels.add_material("wood", color=mcrfpy.Color(139, 90, 43)) GLASS = voxels.add_material("glass", color=mcrfpy.Color(180, 220, 255, 180), transparent=True) GRASS = voxels.add_material("grass", color=mcrfpy.Color(60, 150, 60)) print(f"Defined {voxels.material_count} materials") # Build a simple house structure # Ground/foundation voxels.fill_box((0, 0, 0), (11, 0, 11), GRASS) # Floor voxels.fill_box((1, 1, 1), (10, 1, 10), STONE) # Walls # Front wall (Z=1) voxels.fill_box((1, 2, 1), (10, 5, 1), BRICK) # Back wall (Z=10) voxels.fill_box((1, 2, 10), (10, 5, 10), BRICK) # Left wall (X=1) voxels.fill_box((1, 2, 1), (1, 5, 10), BRICK) # Right wall (X=10) voxels.fill_box((10, 2, 1), (10, 5, 10), BRICK) # Door opening (front wall) voxels.fill_box((4, 2, 1), (6, 4, 1), 0) # Clear door opening # Windows # Front windows (beside door) voxels.fill_box((2, 3, 1), (3, 4, 1), GLASS) voxels.fill_box((8, 3, 1), (9, 4, 1), GLASS) # Side windows voxels.fill_box((1, 3, 4), (1, 4, 5), GLASS) voxels.fill_box((1, 3, 7), (1, 4, 8), GLASS) voxels.fill_box((10, 3, 4), (10, 4, 5), GLASS) voxels.fill_box((10, 3, 7), (10, 4, 8), GLASS) # Ceiling voxels.fill_box((1, 6, 1), (10, 6, 10), WOOD) # Simple roof (peaked) voxels.fill_box((0, 7, 0), (11, 7, 11), WOOD) voxels.fill_box((1, 8, 1), (10, 8, 10), WOOD) voxels.fill_box((2, 9, 2), (9, 9, 9), WOOD) voxels.fill_box((3, 10, 3), (8, 10, 8), WOOD) voxels.fill_box((4, 11, 4), (7, 11, 7), WOOD) # Build the mesh voxels.rebuild_mesh() print(f"Built voxel house:") print(f" Non-air voxels: {voxels.count_non_air()}") print(f" Vertices: {voxels.vertex_count}") print(f" Faces: {voxels.vertex_count // 6}") # Position the building voxels.offset = (0.0, 0.0, 0.0) voxels.rotation = 0.0 # Add to viewport viewport.add_voxel_layer(voxels, z_index=0) print(f"Added voxel layer to viewport (count: {viewport.voxel_layer_count()})") # Create info panel info_frame = mcrfpy.Frame(pos=(680, 60), size=(300, 250), fill_color=mcrfpy.Color(40, 40, 60, 200)) scene.children.append(info_frame) info_title = mcrfpy.Caption(text="Building Stats", pos=(690, 70)) info_title.fill_color = mcrfpy.Color(255, 255, 100) scene.children.append(info_title) stats_text = f"""Grid: {voxels.width}x{voxels.height}x{voxels.depth} Total voxels: {voxels.width * voxels.height * voxels.depth} Non-air: {voxels.count_non_air()} Materials: {voxels.material_count} Vertices: {voxels.vertex_count} Faces: {voxels.vertex_count // 6} Without culling would be: {voxels.count_non_air() * 36} vertices ({100 - (voxels.vertex_count / (voxels.count_non_air() * 36) * 100):.0f}% reduction)""" stats = mcrfpy.Caption(text=stats_text, pos=(690, 100)) stats.fill_color = mcrfpy.Color(200, 200, 200) scene.children.append(stats) # Controls info controls_frame = mcrfpy.Frame(pos=(680, 330), size=(300, 180), fill_color=mcrfpy.Color(40, 40, 60, 200)) scene.children.append(controls_frame) controls_title = mcrfpy.Caption(text="Controls", pos=(690, 340)) controls_title.fill_color = mcrfpy.Color(255, 255, 100) scene.children.append(controls_title) controls_text = """R - Toggle rotation 1-5 - Change camera angle SPACE - Reset camera ESC - Exit demo""" controls = mcrfpy.Caption(text=controls_text, pos=(690, 370)) controls.fill_color = mcrfpy.Color(200, 200, 200) scene.children.append(controls) # Animation state rotation_enabled = False current_angle = 0.0 camera_angles = [ (20.0, 15.0, 20.0), # Default - diagonal view (0.0, 15.0, 25.0), # Front view (25.0, 15.0, 0.0), # Side view (5.5, 25.0, 5.5), # Top-down view (5.5, 3.0, 20.0), # Low angle ] current_camera = 0 def rotate_building(timer, runtime): """Timer callback for building rotation""" global current_angle, rotation_enabled if rotation_enabled: current_angle += 1.0 if current_angle >= 360.0: current_angle = 0.0 voxels.rotation = current_angle # Set up rotation timer timer = mcrfpy.Timer("rotate", rotate_building, 33) # ~30 FPS def handle_key(key, action): """Keyboard handler""" global rotation_enabled, current_camera if action != mcrfpy.InputState.PRESSED: return if key == mcrfpy.Key.R: rotation_enabled = not rotation_enabled print(f"Rotation: {'ON' if rotation_enabled else 'OFF'}") elif key == mcrfpy.Key.NUM_1: current_camera = 0 viewport.camera_pos = camera_angles[0] print("Camera: Default diagonal") elif key == mcrfpy.Key.NUM_2: current_camera = 1 viewport.camera_pos = camera_angles[1] print("Camera: Front view") elif key == mcrfpy.Key.NUM_3: current_camera = 2 viewport.camera_pos = camera_angles[2] print("Camera: Side view") elif key == mcrfpy.Key.NUM_4: current_camera = 3 viewport.camera_pos = camera_angles[3] print("Camera: Top-down view") elif key == mcrfpy.Key.NUM_5: current_camera = 4 viewport.camera_pos = camera_angles[4] print("Camera: Low angle") elif key == mcrfpy.Key.SPACE: current_camera = 0 voxels.rotation = 0.0 viewport.camera_pos = camera_angles[0] print("Camera: Reset") elif key == mcrfpy.Key.ESCAPE: print("Exiting demo...") sys.exit(0) scene.on_key = handle_key # Activate the scene mcrfpy.current_scene = scene print("Voxel Meshing Demo ready! Press R to toggle rotation.") # Main entry point for --exec mode if __name__ == "__main__": # Demo is set up, print summary print("\n=== Voxel Meshing Demo Summary ===") print(f"Grid size: {voxels.width}x{voxels.height}x{voxels.depth}") print(f"Non-air voxels: {voxels.count_non_air()}") print(f"Generated vertices: {voxels.vertex_count}") print(f"Rendered faces: {voxels.vertex_count // 6}") print("===================================\n")