Browse Source

Update project overview and version in Copilot instructions; enhance clarity and detail

master
Matteo Benedetto 2 months ago
parent
commit
ef5715c901
  1. 342
      .github/copilot-instructions.md
  2. 8
      src/app.py

342
.github/copilot-instructions.md

@ -18,9 +18,9 @@
## Project Overview ## Project Overview
**GLTerrain** is an isometric terrain generator using OpenGL, Pygame, and Perlin noise. It creates procedurally generated 3D terrains with RollerCoaster Tycoon-style isometric view, biome-based coloring, and real-time camera controls. **GLTerrain** is an isometric terrain generator using OpenGL, Pygame, and Perlin noise. It creates procedurally generated 3D terrains with RollerCoaster Tycoon-style isometric view, biome-based coloring, procedural pixelated textures, and real-time camera controls.
**Version**: 1.0.0 **Version**: 1.1.0
**Language**: Python 3.13+ **Language**: Python 3.13+
**Graphics**: OpenGL with Pygame **Graphics**: OpenGL with Pygame
@ -28,303 +28,153 @@
**IMPORTANT**: This project uses a Python virtual environment located at `./venv`. **IMPORTANT**: This project uses a Python virtual environment located at `./venv`.
### Before Running Any Python Script:
1. **Always activate the virtual environment**:
```bash
source venv/bin/activate && python <script_name.py>
```
2. **For installing packages**:
```bash
source venv/bin/activate && pip install -r requirements.txt
```
### Standard Command Pattern: ### Standard Command Pattern:
```bash ```bash
cd /home/enne2/Sviluppo/shader && source venv/bin/activate && python main.py cd /home/enne2/Sviluppo/shader && source venv/bin/activate && python main.py
``` ```
### DO NOT: **DO NOT** run Python scripts without activating the virtual environment.
- Run Python scripts without activating the virtual environment
- Install packages globally
- Modify code without testing with activated venv
## Project Architecture ## Project Architecture
### Directory Structure: ### Directory Structure:
``` ```
shader/ shader/
├── main.py # Entry point (uses modular architecture) ├── main.py # Entry point
├── isometric_terrain.py # Legacy monolithic version (preserved) ├── isometric_terrain.py # Legacy version (preserved)
├── requirements.txt # Python dependencies ├── requirements.txt
├── config/ ├── config/
│ └── settings.py # All configuration (TERRAIN, CAMERA, RENDERING, BIOMES) │ └── settings.py # All configuration
├── src/ ├── src/
│ ├── app.py # Main application coordinator │ ├── app.py # Main application
│ ├── camera/ │ ├── camera/camera.py # Camera controls
│ │ └── camera.py # Camera positioning and controls │ ├── terrain/generator.py # Perlin noise terrain
│ ├── terrain/ │ └── rendering/terrain_renderer.py # OpenGL + textures
│ │ └── generator.py # Perlin noise terrain generation
│ └── rendering/
│ └── terrain_renderer.py # OpenGL mesh rendering
└── docs/ # Italian documentation (8 chapters) └── docs/ # Italian documentation (8 chapters)
├── README.md # Index with navigation
├── 01-introduzione.md
├── 02-concetti-base.md
├── 03-opengl.md
├── 04-perlin-noise.md
├── 05-implementazione.md
├── 06-rendering.md
├── 07-camera.md
└── 08-personalizzazione.md
``` ```
### Dependencies: ### Dependencies:
- **pygame** >= 2.5.0: Window management and event handling - pygame >= 2.5.0, PyOpenGL >= 3.1.7, numpy >= 1.24.0, noise
- **PyOpenGL** >= 3.1.7: OpenGL bindings for 3D rendering
- **PyOpenGL-accelerate** >= 3.1.7: Performance optimization
- **numpy** >= 1.24.0: Array operations for heightmaps
- **noise**: Perlin noise generation (installed with pygame)
## Key Configuration Files
### config/settings.py
**CRITICAL**: All project parameters are centralized here. Never hardcode values in source files.
#### Main Sections:
1. **TERRAIN** - Grid and generation parameters:
```python
grid_size: 20 # 20×20 tiles
tile_width: 30 # 30px width
tile_height: 30 # 30px height
perlin_scale: 8.0 # Noise frequency (≈ grid_size / 2.5)
height_multiplier: 80.0 # Vertical scale
perlin_octaves: 4 # Detail levels
perlin_persistence: 0.6 # Detail influence
perlin_lacunarity: 2.5 # Detail density
```
2. **CAMERA** - View parameters:
```python
distance: 800 # Camera distance from center
height: 450 # Camera height (Y axis)
fov: 45 # Field of view (degrees)
zoom_speed: 10.0 # UP/DOWN key speed
height_speed: 10.0 # LEFT/RIGHT key speed
```
3. **RENDERING** - Visual settings:
```python
line_width: 5.0 # Tile border thickness
line_color: (0,0,0) # Border color (RGB)
light_position: (1,1,1,0) # Directional light
```
4. **BIOME_COLORS** - Biome RGB colors:
```python
water, sand, grass_low, grass_mid, grass_high, rock, snow
```
5. **BIOME_THRESHOLDS** - Height thresholds for biome assignment:
```python
water: -10, sand: 0, grass_low: 10, grass_mid: 25,
grass_high: 40, rock: 55, snow: 70
```
## Architecture Principles ## Key Configuration (config/settings.py)
### Separation of Concerns: **CRITICAL**: All parameters centralized here. Never hardcode values.
- **TerrainGenerator**: Only generates heightmaps (Perlin noise)
- **TerrainRenderer**: Only renders geometry (OpenGL calls)
- **Camera**: Only handles view transformations and input
- **IsometricTerrainApp**: Orchestrates all components
### Data Flow: **TERRAIN**: `grid_size: 20`, `tile_width: 30`, `perlin_scale: 8.0`, `height_multiplier: 80.0`
``` **CAMERA**: `distance: 800`, `height: 450`, `zoom_speed: 10.0`
User Input → Camera → App.update() **RENDERING**: `line_width: 5.0`, `side_face_color: (0.55, 0.45, 0.35)`
App → TerrainGenerator.generate() → heightmap array
App → TerrainRenderer.render(heightmap) → OpenGL drawing
```
### Key Design Patterns: **Texture settings (v1.1.0)**:
1. **Configuration Object**: All settings in one module - `texture_enabled: True`
2. **Single Responsibility**: Each class has one clear purpose - `texture_detail_scale: 8.0` (noise sampling)
3. **Dependency Injection**: Pass dependencies via __init__ - `texture_variation: 0.25` (color variation 0-1)
4. **Stateless Rendering**: Renderer doesn't store heightmap - `texture_spots_threshold: 0.6` (dark spots)
## Important Implementation Details **BIOME_COLORS**: water, sand, grass_low, grass_mid, grass_high, rock, snow
**BIOME_THRESHOLDS**: Heights for biome transitions
### Perlin Noise Parameters
**Rule of Thumb**: `perlin_scale ≈ grid_size / 2.5`
- Grid 10×10 → scale = 4.0 ## Architecture Principles
- Grid 20×20 → scale = 8.0 (current)
- Grid 30×30 → scale = 12.0
**Why?** Ensures terrain features span multiple tiles for natural appearance.
### Isometric View Mathematics ### Separation of Concerns:
- **TerrainGenerator**: Heightmaps with random seeds
- **TerrainRenderer**: Geometry + procedural textures (OpenGL)
- **Camera**: View transformations and input
- **IsometricTerrainApp**: Orchestrates components
Camera positioned at **45° horizontal and vertical**: ### Texture System (v1.1.0):
```python ```
camera_position = (distance, height, distance) # X = Z for 45° Per-Tile Generation:
look_at = (0, 0, 0) # Center of terrain 1. get_texture_for_tile(color, grid_i, grid_j)
up_vector = (0, 1, 0) # Y is up 2. generate_procedural_texture() → 16×16 pixels
3. 3-layer Perlin noise: detail + pattern + spots
4. glTexImage2D() → OpenGL texture
5. Cache with key: (grid_i, grid_j, color, seed)
6. UV mapping with glTexCoord2f()
``` ```
### Tile Rendering ## Important Implementation Details
Each tile is a **quad** with 4 vertices: ### Perlin Noise Scale
``` **Rule**: `perlin_scale ≈ grid_size / 2.5`
Top face: 4 vertices at (x, height, z) corners Grid 20×20 → scale = 8.0 (current)
Side faces: Only drawn if neighbor is lower
```
### Biome Assignment ### Tile Rendering (v1.1.0)
**Top face**:
- 16×16 texture per tile (GL_NEAREST = pixelated)
- GL_LIGHTING disabled (pure colors)
- Unique texture: (grid_i, grid_j, biome, seed)
```python **Side faces**:
if height < threshold['water']: - Uniform brown with shading (0.7 right, 0.8 back)
color = BIOME_COLORS['water'] - GL_LIGHTING enabled
elif height < threshold['sand']:
color = BIOME_COLORS['sand']
# ... etc
```
## Common Modification Patterns ### Random Seeds (v1.1.0)
**Heightmap**: `random_base = random.randint(0, 10000)` in `generate()`
**Textures**: New `texture_seed` in `set_heightmap()` + cache clear
**Result**: R key regenerates both completely
### Changing Grid Size: ## Common Modifications
1. Update `TERRAIN['grid_size']` in settings.py
2. Adjust `TERRAIN['perlin_scale']` (new_size / 2.5)
3. Consider adjusting `CAMERA['distance']` for larger grids
### Adding New Biome: ### Grid Size:
1. Add color to `BIOME_COLORS` 1. Update `TERRAIN['grid_size']`
2. Add threshold to `BIOME_THRESHOLDS` 2. Adjust `perlin_scale` (new_size / 2.5)
3. Update `get_color_for_height()` in terrain_renderer.py 3. Adjust `CAMERA['distance']` if needed
4. Ensure thresholds are in ascending order
### Modifying Camera Behavior: ### Textures:
1. Edit Camera class in `src/camera/camera.py` - `texture_variation`: 0.0-1.0 (more/less change)
2. All movement logic in `handle_input(keys)` - `texture_detail_scale`: Lower = larger patterns
3. Projection setup in `setup_projection(aspect_ratio)` - `texture_spots_threshold`: Lower = more spots
4. View setup in `setup_modelview()` - `texture_size=16`: Change in `generate_procedural_texture()`
- GL_LINEAR for smooth (non-pixelated)
### Performance Optimization: ### Performance:
- Reduce `grid_size` (20 15) - Reduce `grid_size` (20→15) = fewer textures
- Reduce `perlin_octaves` (4 3) - Reduce `perlin_octaves` (4→3)
- Disable `enable_smoothing` - Texture size (16×16 → 8×8)
- Reduce `far_clip` (5000 → 3000) - `texture_enabled: False` disables textures
## Testing Guidelines ## Testing
### Always Test After Changes:
```bash ```bash
source venv/bin/activate && python main.py source venv/bin/activate && python main.py
``` ```
### Test Controls: **Controls**: UP/DOWN (zoom), LEFT/RIGHT (height), R (regenerate terrain+textures), ESC (exit)
- **UP/DOWN**: Zoom (should be smooth)
- **LEFT/RIGHT**: Height (should move camera up/down)
- **R**: Regenerate terrain (should create new random terrain)
- **ESC**: Exit
### Visual Validation:
- Check tile borders are visible (line_width > 3.0)
- Verify biome colors match settings
- Ensure no Z-fighting (flickering surfaces)
- Confirm terrain has variety (not flat)
## Documentation **Visual checks**:
- Tile borders visible (line_width > 3.0)
- Textures pixelated and unique per tile
- Dark spots and color variations
- Side faces uniform brown with shading
### Italian Documentation (docs/): ## Debugging
Complete 8-chapter guide explaining:
1. Project overview and results
2. 3D graphics and isometric concepts
3. OpenGL technology
4. Perlin noise algorithm
5. Code architecture
6. Rendering system
7. Camera system
8. Customization guide
**Target Audience**: Non-technical users, no OpenGL knowledge assumed **Common Issues**:
1. Flat terrain: Increase `height_multiplier` or reduce `perlin_scale`
**Update Rule**: When changing features, update relevant documentation chapter. 2. Invisible borders: Increase `line_width`
3. Textures not visible: Check `texture_enabled: True` + GL_LIGHTING disabled for tops
4. Textures not pixelated: Verify GL_NEAREST filtering
5. All tiles same: Check cache key includes `texture_seed`
## Git Workflow ## Git Workflow
### Repository: **Remote**: `ssh://git@git.enne2.net:222/enne2/GLTerrain.git`
- Remote: `ssh://git@git.enne2.net:222/enne2/GLTerrain.git` **Branch**: `master`
- Branch: `master`
### Version Tagging:
```bash ```bash
git tag -a v1.x.x -m "Description" git tag -a v1.x.x -m "Description"
git push origin master --tags git push origin master --tags
``` ```
### .gitignore Includes: ## Documentation
- venv/, __pycache__/, *.pyc
- .vscode/, .idea/ Italian docs in `docs/` (8 chapters). Update relevant chapter when changing features.
- *.png, *.jpg (generated screenshots)
- *_backup_*.py ## Contact
## Debugging Tips **Author**: Matteo Benedetto
### Common Issues:
1. **Flat Terrain**: Increase `height_multiplier` or reduce `perlin_scale`
2. **Too Chaotic**: Reduce `height_multiplier` or increase `perlin_scale`
3. **Invisible Borders**: Increase `line_width` (5.0 → 8.0)
4. **Camera Issues**: Check `distance` and `height` values match tile scale
5. **Performance**: Reduce `grid_size` or `perlin_octaves`
### OpenGL Debugging:
- Enable depth testing: `glEnable(GL_DEPTH_TEST)` (already enabled)
- Check matrix mode: `glMatrixMode(GL_MODELVIEW)` before drawing
- Verify vertex order: Counter-clockwise for front faces
## Future Enhancement Ideas
### Easy Additions:
- Export heightmap to PNG (PIL/Pillow)
- Save/load terrain seeds
- Multiple camera presets
- Minimap in corner
- FPS counter
### Medium Complexity:
- Smooth camera transitions (lerp)
- Camera rotation (Q/E keys)
- Day/night cycle (lighting animation)
- Biome gradients (blend colors)
- Water animation (vertex shader)
### Advanced Features:
- Texture mapping (replace flat colors)
- Normal mapping (surface detail)
- Shadow mapping
- LOD system (level of detail)
- Terrain editing tools
## Code Style Guidelines
- **Imports**: Standard library → Third party → Local modules
- **Naming**: snake_case for functions/variables, PascalCase for classes
- **Constants**: UPPER_CASE in settings.py
- **Docstrings**: Include for all public methods
- **Comments**: Explain "why", not "what"
- **Line Length**: Max 100 characters
- **Type Hints**: Use where it improves clarity
## Contact & Maintenance
**Author**: enne2
**Project**: GLTerrain (Isometric Terrain Generator) **Project**: GLTerrain (Isometric Terrain Generator)
**License**: (Add license info if applicable)
**Last Updated**: October 2025 **Last Updated**: October 2025
#**Important**: These instructions must be under 200 lines to ensure clarity and conciseness.

8
src/app.py

@ -55,7 +55,7 @@ class IsometricTerrainApp:
glEnable(GL_BLEND) glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
# Setup lighting (sunset lighting) # Setup lighting
glEnable(GL_LIGHTING) glEnable(GL_LIGHTING)
glEnable(GL_LIGHT0) glEnable(GL_LIGHT0)
glEnable(GL_COLOR_MATERIAL) glEnable(GL_COLOR_MATERIAL)
@ -64,12 +64,6 @@ class IsometricTerrainApp:
glLightfv(GL_LIGHT0, GL_POSITION, self.config.RENDERING['light_position']) glLightfv(GL_LIGHT0, GL_POSITION, self.config.RENDERING['light_position'])
glLightfv(GL_LIGHT0, GL_AMBIENT, self.config.RENDERING['light_ambient']) glLightfv(GL_LIGHT0, GL_AMBIENT, self.config.RENDERING['light_ambient'])
glLightfv(GL_LIGHT0, GL_DIFFUSE, self.config.RENDERING['light_diffuse']) glLightfv(GL_LIGHT0, GL_DIFFUSE, self.config.RENDERING['light_diffuse'])
# Add specular component for sunset highlights
if 'light_specular' in self.config.RENDERING:
glLightfv(GL_LIGHT0, GL_SPECULAR, self.config.RENDERING['light_specular'])
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, [0.3, 0.3, 0.3, 1.0])
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 10.0)
def handle_events(self): def handle_events(self):
"""Handle pygame events""" """Handle pygame events"""

Loading…
Cancel
Save