voxel example
This commit is contained in:
parent
7ebca63db3
commit
3e6b6a5847
10 changed files with 1691 additions and 2 deletions
218
tests/demo/screens/voxel_meshing_demo.py
Normal file
218
tests/demo/screens/voxel_meshing_demo.py
Normal file
|
|
@ -0,0 +1,218 @@
|
|||
# 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")
|
||||
Loading…
Add table
Add a link
Reference in a new issue