Implementar control manual de escala para figuras 3D + actualizar README
NUEVAS CARACTERÍSTICAS: - Control de escala dinámico con Numpad +/-/* (30%-300%) - Protección automática contra clipping según resolución - Texto informativo muestra porcentaje de escala - Fix: Redondeo correcto en display de escala (79% → 80%) CAMBIOS EN README: - Actualizar tabla de controles (C→F, T→B, añadir Q/W/E/R/T/Y/U/I) - Documentar sistema polimórfico de figuras 3D - Añadir sección "Controles de Figuras 3D" con Numpad +/-/* - Actualizar debug display (8 líneas ahora) - Expandir sección "Modo RotoBall" → "Sistema de Figuras 3D" - Documentar Esfera y Cubo implementados - Listar 6 figuras futuras (Wave/Helix/Torus/Cylinder/Icosahedron/Atom) - Actualizar estructura del proyecto (añadir source/shapes/) - Añadir parámetros de escala manual a sección técnica IMPLEMENTACIÓN TÉCNICA: - defines.h: Constantes SHAPE_SCALE_MIN/MAX/STEP/DEFAULT - engine.h: Variable shape_scale_factor_, método clampShapeScale() - engine.cpp: Handlers Numpad +/-/*, multiplicar scale_factor en updateShape() - clampShapeScale(): Límite dinámico según tamaño de pantalla (90% máximo) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
131
README.md
131
README.md
@@ -43,19 +43,34 @@ El nombre refleja su proposito: **ViBe** (vibe-coding experimental) + **Physics*
|
||||
| `KP_3` | **Tema NEON (colores vibrantes)** |
|
||||
| `KP_4` | **Tema BOSQUE (verdes naturales)** |
|
||||
| `KP_5` | **Tema RGB (fondo blanco, colores matematicos)** |
|
||||
| `T` | **Ciclar entre todos los temas** |
|
||||
| `B` | **Ciclar entre todos los temas** |
|
||||
|
||||
### Controles de Simulacion
|
||||
| Tecla | Accion |
|
||||
|-------|--------|
|
||||
| `1-8` | Cambiar numero de pelotas (1, 10, 100, 500, 1K, 10K, 50K, 100K) |
|
||||
| `ESPACIO` | Impulsar todas las pelotas hacia arriba |
|
||||
| `↑` | **Gravedad hacia ARRIBA** |
|
||||
| `↓` | **Gravedad hacia ABAJO** |
|
||||
| `←` | **Gravedad hacia IZQUIERDA** |
|
||||
| `→` | **Gravedad hacia DERECHA** |
|
||||
| `G` | **Alternar gravedad ON/OFF (mantiene direccion)** |
|
||||
| `C` | **🎯 MODO ROTOBALL - Alternar esfera 3D rotante (demoscene effect)** |
|
||||
| `↑` | **Gravedad hacia ARRIBA (sale de figura con gravedad)** |
|
||||
| `↓` | **Gravedad hacia ABAJO (sale de figura con gravedad)** |
|
||||
| `←` | **Gravedad hacia IZQUIERDA (sale de figura con gravedad)** |
|
||||
| `→` | **Gravedad hacia DERECHA (sale de figura con gravedad)** |
|
||||
| `G` | **Alternar gravedad ON/OFF / Sale de figura SIN gravedad** |
|
||||
|
||||
### Controles de Figuras 3D
|
||||
| Tecla | Accion |
|
||||
|-------|--------|
|
||||
| `F` | **Toggle entre modo FISICA ↔ última FIGURA 3D** |
|
||||
| `Q` | **Activar figura ESFERA (Fibonacci Sphere)** |
|
||||
| `W` | **Activar figura WAVE GRID (pendiente)** |
|
||||
| `E` | **Activar figura HELIX (pendiente)** |
|
||||
| `R` | **Activar figura TORUS (pendiente)** |
|
||||
| `T` | **Activar figura CUBO (rotación triple XYZ)** |
|
||||
| `Y` | **Activar figura CYLINDER (pendiente)** |
|
||||
| `U` | **Activar figura ICOSAHEDRON (pendiente)** |
|
||||
| `I` | **Activar figura ATOM (pendiente)** |
|
||||
| `KP_+` | **Aumentar escala de figura (+10%)** |
|
||||
| `KP_-` | **Reducir escala de figura (-10%)** |
|
||||
| `KP_*` | **Reset escala de figura a 100%** |
|
||||
|
||||
## 📊 Informacion en Pantalla
|
||||
|
||||
@@ -68,9 +83,10 @@ Cuando se activa el debug display con la tecla `H`:
|
||||
|
||||
- **Esquina superior izquierda**: Estado V-Sync (VSYNC ON/OFF) en **cian**
|
||||
- **Esquina superior derecha**: Contador FPS en tiempo real en **amarillo**
|
||||
- **Lineas 3-5**: Valores fisica primera pelota (GRAV, VY, FLOOR) en **magenta**
|
||||
- **Linea 6**: Tema activo (THEME SUNSET/OCEAN/NEON/FOREST/RGB) en **amarillo claro**
|
||||
- **Linea 7**: Modo de simulación (MODE PHYSICS/ROTOBALL) en **verde claro**
|
||||
- **Lineas 3-5**: Valores fisica primera pelota (GRAV, VY, SURFACE, LOSS) en **magenta**
|
||||
- **Linea 6**: Dirección de gravedad actual (GRAVITY UP/DOWN/LEFT/RIGHT) en **amarillo**
|
||||
- **Linea 7**: Tema activo (THEME SUNSET/OCEAN/NEON/FOREST/RGB) en **amarillo claro**
|
||||
- **Linea 8**: Modo de simulación (MODE PHYSICS/SPHERE/CUBE/etc.) en **verde claro**
|
||||
|
||||
## 🎨 Sistema de Temas de Colores
|
||||
|
||||
@@ -89,7 +105,7 @@ Cuando se activa el debug display con la tecla `H`:
|
||||
### Controles de Temas
|
||||
|
||||
- **Seleccion directa**: Usa `KP_1`, `KP_2`, `KP_3`, `KP_4` o `KP_5` para cambiar inmediatamente al tema deseado
|
||||
- **Ciclado secuencial**: Presiona `T` para avanzar al siguiente tema en orden
|
||||
- **Ciclado secuencial**: Presiona `B` para avanzar al siguiente tema en orden
|
||||
- **Indicador visual**: El nombre del tema aparece temporalmente en el centro de la pantalla con colores tematicos
|
||||
- **Regeneracion automatica**: Las pelotas adoptan automaticamente la nueva paleta de colores al cambiar tema
|
||||
|
||||
@@ -100,42 +116,84 @@ Cuando se activa el debug display con la tecla `H`:
|
||||
- **Rendimiento optimizado**: El cambio de tema solo regenera los colores, manteniendo la fisica
|
||||
- **Compatibilidad completa**: Funciona con todos los escenarios (1 a 100,000 pelotas)
|
||||
|
||||
## 🎯 Modo RotoBall - Esfera 3D Rotante
|
||||
## 🎯 Sistema de Figuras 3D - Efectos Demoscene
|
||||
|
||||
**Modo RotoBall** es un efecto demoscene que convierte las pelotas en una esfera 3D rotante proyectada en 2D.
|
||||
**ViBe3 Physics** incluye un sistema polimórfico de figuras 3D que convierte las pelotas en formas geométricas rotantes proyectadas en 2D.
|
||||
|
||||
### Características del Modo RotoBall
|
||||
### Figuras Implementadas
|
||||
|
||||
- **Algoritmo Fibonacci Sphere**: Distribución uniforme de puntos en la superficie de una esfera 3D
|
||||
- **Rotación dual**: Rotación simultánea en ejes X e Y para efecto visual dinámico
|
||||
- **Profundidad Z simulada**: Color modulado según profundidad (puntos lejanos más oscuros, cercanos más brillantes)
|
||||
- **Transición suave**: Interpolación de 1.5 segundos desde física normal a esfera 3D
|
||||
#### 🌐 ESFERA (Tecla Q)
|
||||
- **Algoritmo**: Fibonacci Sphere - distribución uniforme de puntos
|
||||
- **Rotación**: Dual (ejes X e Y)
|
||||
- **Efecto**: Esfera rotante clásica estilo demoscene
|
||||
|
||||
#### 🎲 CUBO (Tecla T)
|
||||
- **Distribución inteligente**:
|
||||
- 1-8 pelotas: Solo vértices (8 puntos)
|
||||
- 9-26 pelotas: Vértices + centros de caras + aristas (26 puntos)
|
||||
- 27+ pelotas: Grid volumétrico 3D uniforme
|
||||
- **Rotación**: Triple (ejes X, Y y Z simultáneos)
|
||||
- **Efecto**: Cubo Rubik rotante
|
||||
|
||||
#### 🔮 Figuras Futuras (Pendientes)
|
||||
- **W - WAVE GRID**: Malla ondeante 3D
|
||||
- **E - HELIX**: Espiral helicoidal
|
||||
- **R - TORUS**: Donut/toroide
|
||||
- **Y - CYLINDER**: Cilindro rotante
|
||||
- **U - ICOSAHEDRON**: Poliedro D20
|
||||
- **I - ATOM**: Núcleo con órbitas electrónicas
|
||||
|
||||
### Características Técnicas
|
||||
|
||||
- **Física de atracción**: Sistema spring-damper (Hooke's Law) para transición suave
|
||||
- **Profundidad Z simulada**: Color modulado según distancia (oscuro=fondo, brillante=frente)
|
||||
- **Z-sorting**: Painter's Algorithm para oclusión correcta
|
||||
- **Escala dinámica**: Control manual con Numpad +/- (30% - 300%)
|
||||
- **Protección de clipping**: Escala limitada automáticamente según resolución
|
||||
- **Sin sprites adicionales**: Usa `SDL_SetTextureColorMod` para simular profundidad
|
||||
|
||||
### Parámetros Técnicos (ajustables en defines.h)
|
||||
### Parámetros Físicos (defines.h)
|
||||
|
||||
```cpp
|
||||
ROTOBALL_RADIUS = 80.0f; // Radio de la esfera (píxeles)
|
||||
ROTOBALL_ROTATION_SPEED_Y = 1.5f; // Velocidad rotación eje Y (rad/s)
|
||||
ROTOBALL_ROTATION_SPEED_X = 0.8f; // Velocidad rotación eje X (rad/s)
|
||||
ROTOBALL_TRANSITION_TIME = 1.5f; // Tiempo de transición (segundos)
|
||||
ROTOBALL_MIN_BRIGHTNESS = 50; // Brillo mínimo fondo (0-255)
|
||||
ROTOBALL_MAX_BRIGHTNESS = 255; // Brillo máximo frente (0-255)
|
||||
// Física compartida entre todas las figuras
|
||||
ROTOBALL_SPRING_K = 300.0f; // Rigidez del resorte (N/m)
|
||||
ROTOBALL_DAMPING_BASE = 35.0f; // Amortiguación crítica
|
||||
ROTOBALL_DAMPING_NEAR = 80.0f; // Absorción cerca del punto
|
||||
|
||||
// Esfera
|
||||
ROTOBALL_RADIUS_FACTOR = 0.333f; // 33% de altura de pantalla
|
||||
ROTOBALL_ROTATION_SPEED_Y = 1.5f; // rad/s (eje Y)
|
||||
ROTOBALL_ROTATION_SPEED_X = 0.8f; // rad/s (eje X)
|
||||
|
||||
// Cubo
|
||||
CUBE_SIZE_FACTOR = 0.25f; // 25% de altura de pantalla
|
||||
CUBE_ROTATION_SPEED_X = 0.5f; // rad/s
|
||||
CUBE_ROTATION_SPEED_Y = 0.7f; // rad/s
|
||||
CUBE_ROTATION_SPEED_Z = 0.3f; // rad/s
|
||||
|
||||
// Control manual de escala
|
||||
SHAPE_SCALE_MIN = 0.3f; // Mínimo 30%
|
||||
SHAPE_SCALE_MAX = 3.0f; // Máximo 300%
|
||||
SHAPE_SCALE_STEP = 0.1f; // Incremento 10%
|
||||
```
|
||||
|
||||
### Cómo Funciona
|
||||
|
||||
1. **Generación**: Fibonacci sphere distribuye puntos uniformemente en esfera 3D
|
||||
1. **Generación**: Algoritmo específico distribuye puntos en forma 3D
|
||||
2. **Rotación**: Matrices de rotación 3D aplicadas en tiempo real
|
||||
3. **Proyección**: Coordenadas 3D proyectadas a 2D (ortográfica)
|
||||
4. **Profundidad**: Componente Z normalizada controla brillo del color
|
||||
5. **Renderizado**: Batch rendering con color modulado por profundidad
|
||||
3. **Escala**: Factor manual multiplicado a coordenadas y física
|
||||
4. **Proyección**: Coordenadas 3D → 2D (ortográfica)
|
||||
5. **Z-sorting**: Ordenar pelotas por profundidad (fondo primero)
|
||||
6. **Profundidad**: Componente Z controla brillo del color
|
||||
7. **Renderizado**: Batch rendering con color modulado
|
||||
|
||||
### Activación
|
||||
### Uso
|
||||
|
||||
- **Tecla C**: Alternar entre modo física y modo RotoBall
|
||||
- **Compatible**: Funciona con cualquier número de pelotas (1-100,000)
|
||||
- **Temas**: Mantiene la paleta de colores del tema activo
|
||||
- **Activación**: Presiona Q/W/E/R/T/Y/U/I para figura específica, o F para toggle
|
||||
- **Escala**: Usa Numpad +/- para ajustar tamaño, * para reset
|
||||
- **Salir**: G (sin gravedad), cursores (con gravedad), F (toggle), o 1-8 (cambiar escenario)
|
||||
- **Compatible**: Funciona con 1-100,000 pelotas
|
||||
- **Temas**: Mantiene paleta de colores activa
|
||||
|
||||
## 🏗️ Estructura del Proyecto
|
||||
|
||||
@@ -143,8 +201,13 @@ ROTOBALL_MAX_BRIGHTNESS = 255; // Brillo máximo frente (0-255)
|
||||
vibe3_physics/
|
||||
├── source/
|
||||
│ ├── main.cpp # Bucle principal y logica del juego
|
||||
│ ├── ball.h/cpp # Clase Ball - logica de las pelotas
|
||||
│ ├── engine.h/cpp # Motor principal con loop y rendering
|
||||
│ ├── ball.h/cpp # Clase Ball - fisica de pelotas
|
||||
│ ├── defines.h # Constantes y configuracion
|
||||
│ ├── shapes/ # Sistema polimorfico de figuras 3D
|
||||
│ │ ├── shape.h # Interfaz abstracta Shape
|
||||
│ │ ├── sphere_shape.h/cpp # Fibonacci Sphere
|
||||
│ │ └── cube_shape.h/cpp # Cubo rotante triple
|
||||
│ └── external/ # Utilidades y bibliotecas externas
|
||||
│ ├── sprite.h/cpp # Clase Sprite - renderizado de texturas
|
||||
│ ├── texture.h/cpp # Clase Texture - gestion de imagenes
|
||||
|
||||
@@ -100,4 +100,10 @@ constexpr float CUBE_ROTATION_SPEED_X = 0.5f; // Velocidad rotación eje X
|
||||
constexpr float CUBE_ROTATION_SPEED_Y = 0.7f; // Velocidad rotación eje Y (rad/s)
|
||||
constexpr float CUBE_ROTATION_SPEED_Z = 0.3f; // Velocidad rotación eje Z (rad/s)
|
||||
|
||||
// Control manual de escala de figuras 3D (Numpad +/-)
|
||||
constexpr float SHAPE_SCALE_MIN = 0.3f; // Escala mínima (30%)
|
||||
constexpr float SHAPE_SCALE_MAX = 3.0f; // Escala máxima (300%)
|
||||
constexpr float SHAPE_SCALE_STEP = 0.1f; // Incremento por pulsación
|
||||
constexpr float SHAPE_SCALE_DEFAULT = 1.0f; // Escala por defecto (100%)
|
||||
|
||||
constexpr float PI = 3.14159265358979323846f; // Constante PI
|
||||
@@ -310,6 +310,42 @@ void Engine::handleEvents() {
|
||||
initBalls(scenario_);
|
||||
break;
|
||||
|
||||
// Control de escala de figura (solo en modo SHAPE)
|
||||
case SDLK_KP_PLUS:
|
||||
if (current_mode_ == SimulationMode::SHAPE) {
|
||||
shape_scale_factor_ += SHAPE_SCALE_STEP;
|
||||
clampShapeScale();
|
||||
text_ = "SCALE " + std::to_string(static_cast<int>(shape_scale_factor_ * 100.0f + 0.5f)) + "%";
|
||||
int text_width = static_cast<int>(text_.length() * 8);
|
||||
text_pos_ = (current_screen_width_ - text_width) / 2;
|
||||
text_init_time_ = SDL_GetTicks();
|
||||
show_text_ = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case SDLK_KP_MINUS:
|
||||
if (current_mode_ == SimulationMode::SHAPE) {
|
||||
shape_scale_factor_ -= SHAPE_SCALE_STEP;
|
||||
clampShapeScale();
|
||||
text_ = "SCALE " + std::to_string(static_cast<int>(shape_scale_factor_ * 100.0f + 0.5f)) + "%";
|
||||
int text_width = static_cast<int>(text_.length() * 8);
|
||||
text_pos_ = (current_screen_width_ - text_width) / 2;
|
||||
text_init_time_ = SDL_GetTicks();
|
||||
show_text_ = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case SDLK_KP_MULTIPLY:
|
||||
if (current_mode_ == SimulationMode::SHAPE) {
|
||||
shape_scale_factor_ = SHAPE_SCALE_DEFAULT;
|
||||
text_ = "SCALE RESET (100%)";
|
||||
int text_width = static_cast<int>(text_.length() * 8);
|
||||
text_pos_ = (current_screen_width_ - text_width) / 2;
|
||||
text_init_time_ = SDL_GetTicks();
|
||||
show_text_ = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case SDLK_1:
|
||||
scenario_ = 0;
|
||||
initBalls(scenario_);
|
||||
@@ -1052,8 +1088,8 @@ void Engine::updateShape() {
|
||||
// Actualizar animación de la figura
|
||||
active_shape_->update(delta_time_, static_cast<float>(current_screen_width_), static_cast<float>(current_screen_height_));
|
||||
|
||||
// Obtener factor de escala para física
|
||||
float scale_factor = active_shape_->getScaleFactor(static_cast<float>(current_screen_height_));
|
||||
// Obtener factor de escala para física (base de figura + escala manual)
|
||||
float scale_factor = active_shape_->getScaleFactor(static_cast<float>(current_screen_height_)) * shape_scale_factor_;
|
||||
|
||||
// Centro de la pantalla
|
||||
float center_x = current_screen_width_ / 2.0f;
|
||||
@@ -1065,6 +1101,11 @@ void Engine::updateShape() {
|
||||
float x_3d, y_3d, z_3d;
|
||||
active_shape_->getPoint3D(static_cast<int>(i), x_3d, y_3d, z_3d);
|
||||
|
||||
// Aplicar escala manual a las coordenadas 3D
|
||||
x_3d *= shape_scale_factor_;
|
||||
y_3d *= shape_scale_factor_;
|
||||
z_3d *= shape_scale_factor_;
|
||||
|
||||
// Proyección 2D ortográfica (punto objetivo móvil)
|
||||
float target_x = center_x + x_3d;
|
||||
float target_y = center_y + y_3d;
|
||||
@@ -1081,3 +1122,17 @@ void Engine::updateShape() {
|
||||
balls_[i]->setDepthBrightness(z_normalized);
|
||||
}
|
||||
}
|
||||
|
||||
// Limitar escala de figura para evitar que se salga de pantalla
|
||||
void Engine::clampShapeScale() {
|
||||
// Calcular tamaño máximo permitido según resolución actual
|
||||
// La figura más grande (esfera/cubo) usa ~33% de altura por defecto
|
||||
// Permitir hasta que la figura ocupe 90% de la dimensión más pequeña
|
||||
float max_dimension = std::min(current_screen_width_, current_screen_height_);
|
||||
float base_size_factor = 0.333f; // ROTOBALL_RADIUS_FACTOR o similar
|
||||
float max_scale_for_screen = (max_dimension * 0.9f) / (max_dimension * base_size_factor);
|
||||
|
||||
// Limitar entre SHAPE_SCALE_MIN y el mínimo de (SHAPE_SCALE_MAX, max_scale_for_screen)
|
||||
float max_allowed = std::min(SHAPE_SCALE_MAX, max_scale_for_screen);
|
||||
shape_scale_factor_ = std::max(SHAPE_SCALE_MIN, std::min(max_allowed, shape_scale_factor_));
|
||||
}
|
||||
@@ -86,6 +86,7 @@ private:
|
||||
ShapeType current_shape_type_ = ShapeType::SPHERE; // Tipo de figura actual
|
||||
ShapeType last_shape_type_ = ShapeType::SPHERE; // Última figura para toggle F
|
||||
std::unique_ptr<Shape> active_shape_; // Puntero polimórfico a figura activa
|
||||
float shape_scale_factor_ = 1.0f; // Factor de escala manual (Numpad +/-)
|
||||
|
||||
// Batch rendering
|
||||
std::vector<SDL_Vertex> batch_vertices_;
|
||||
@@ -129,4 +130,5 @@ private:
|
||||
void activateShape(ShapeType type); // Activar figura específica (teclas Q/W/E/R/Y/U/I)
|
||||
void updateShape(); // Actualizar figura activa
|
||||
void generateShape(); // Generar puntos de figura activa
|
||||
void clampShapeScale(); // Limitar escala para evitar clipping
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user