Hacer RotoBall totalmente escalable con resolución de pantalla
Problema: - Radio fijo de 80px funcionaba bien en 320x240 - En F4 fullscreen (1920x1080), radio de 360px era correcto visualmente - PERO las fuerzas físicas (spring_k, damping) seguían siendo para 80px - Resultado: pelotas nunca llegaban a pegarse en resoluciones altas Solución: 1. Radio proporcional a altura de pantalla (ROTOBALL_RADIUS_FACTOR = 0.333) 2. Escalar TODAS las constantes de física proporcionalmente al radio 3. Fórmula: scale = sphere_radius / BASE_RADIUS (80px) Cambios técnicos: - defines.h: ROTOBALL_RADIUS → ROTOBALL_RADIUS_FACTOR (0.333) - engine.cpp: Calcular radius dinámicamente en generate/update - ball.h: applyRotoBallForce() ahora recibe sphere_radius - ball.cpp: Escalar spring_k, damping_base, damping_near, near_threshold, max_force Resultado: - 320x240: Radio 80px, scale=1.0 (idéntico a antes) - 640x480: Radio 160px, scale=2.0 (fuerzas 2x) - 1920x1080: Radio 360px, scale=4.5 (fuerzas 4.5x) Comportamiento físico IDÉNTICO en todas las resoluciones ✅ 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -980,6 +980,9 @@ void Engine::generateRotoBallSphere() {
|
||||
int num_points = static_cast<int>(balls_.size());
|
||||
if (num_points == 0) return;
|
||||
|
||||
// Calcular radio dinámico proporcional a la altura de pantalla
|
||||
float radius = current_screen_height_ * ROTOBALL_RADIUS_FACTOR;
|
||||
|
||||
// Constante Golden Ratio para Fibonacci sphere
|
||||
const float golden_ratio = (1.0f + sqrtf(5.0f)) / 2.0f;
|
||||
const float angle_increment = PI * 2.0f * golden_ratio;
|
||||
@@ -991,9 +994,9 @@ void Engine::generateRotoBallSphere() {
|
||||
float theta = angle_increment * static_cast<float>(i); // Longitud
|
||||
|
||||
// Convertir coordenadas esféricas a cartesianas
|
||||
float x = cosf(theta) * sinf(phi) * ROTOBALL_RADIUS;
|
||||
float y = sinf(theta) * sinf(phi) * ROTOBALL_RADIUS;
|
||||
float z = cosf(phi) * ROTOBALL_RADIUS;
|
||||
float x = cosf(theta) * sinf(phi) * radius;
|
||||
float y = sinf(theta) * sinf(phi) * radius;
|
||||
float z = cosf(phi) * radius;
|
||||
|
||||
// Guardar posición 3D en la pelota
|
||||
balls_[i]->setRotoBallPosition3D(x, y, z);
|
||||
@@ -1004,7 +1007,7 @@ void Engine::generateRotoBallSphere() {
|
||||
balls_[i]->setRotoBallTarget2D(center_x + x, center_y + y);
|
||||
|
||||
// Calcular brillo inicial según profundidad Z
|
||||
float z_normalized = (z + ROTOBALL_RADIUS) / (2.0f * ROTOBALL_RADIUS);
|
||||
float z_normalized = (z + radius) / (2.0f * radius);
|
||||
balls_[i]->setDepthBrightness(z_normalized);
|
||||
}
|
||||
}
|
||||
@@ -1013,6 +1016,9 @@ void Engine::generateRotoBallSphere() {
|
||||
void Engine::updateRotoBall() {
|
||||
if (current_mode_ != SimulationMode::ROTOBALL) return;
|
||||
|
||||
// Calcular radio dinámico proporcional a la altura de pantalla
|
||||
float radius = current_screen_height_ * ROTOBALL_RADIUS_FACTOR;
|
||||
|
||||
// Actualizar ángulos de rotación de la esfera
|
||||
rotoball_.angle_y += ROTOBALL_ROTATION_SPEED_Y * delta_time_;
|
||||
rotoball_.angle_x += ROTOBALL_ROTATION_SPEED_X * delta_time_;
|
||||
@@ -1032,9 +1038,9 @@ void Engine::updateRotoBall() {
|
||||
float phi = acosf(1.0f - 2.0f * t);
|
||||
float theta = angle_increment * static_cast<float>(i);
|
||||
|
||||
float x = cosf(theta) * sinf(phi) * ROTOBALL_RADIUS;
|
||||
float y = sinf(theta) * sinf(phi) * ROTOBALL_RADIUS;
|
||||
float z = cosf(phi) * ROTOBALL_RADIUS;
|
||||
float x = cosf(theta) * sinf(phi) * radius;
|
||||
float y = sinf(theta) * sinf(phi) * radius;
|
||||
float z = cosf(phi) * radius;
|
||||
|
||||
// Aplicar rotación en eje Y
|
||||
float cos_y = cosf(rotoball_.angle_y);
|
||||
@@ -1053,10 +1059,10 @@ void Engine::updateRotoBall() {
|
||||
float target_y = center_y + y_rot;
|
||||
|
||||
// Aplicar fuerza de atracción física hacia el punto rotado
|
||||
balls_[i]->applyRotoBallForce(target_x, target_y, delta_time_);
|
||||
balls_[i]->applyRotoBallForce(target_x, target_y, radius, delta_time_);
|
||||
|
||||
// Calcular brillo según profundidad Z para renderizado
|
||||
float z_normalized = (z_final + ROTOBALL_RADIUS) / (2.0f * ROTOBALL_RADIUS);
|
||||
float z_normalized = (z_final + radius) / (2.0f * radius);
|
||||
z_normalized = std::max(0.0f, std::min(1.0f, z_normalized));
|
||||
balls_[i]->setDepthBrightness(z_normalized);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user