Mejoras animaciones 3D: tumbling en cilindro + pivoteo en wave grid
- **CylinderShape**: Añadido sistema de tumbling ocasional - Volteretas de 90° en eje X cada 3-5 segundos - Interpolación suave con ease-in-out (1.5s) - Rotación Y continua + tumbling X ocasional = más dinámico - **WaveGridShape**: Reemplazada rotación por pivoteo sutil - Eliminada rotación completa en eje Y - Pivoteo en esquinas (oscilación lenta 0.3/0.5 rad/s) - Grid paralelo a pantalla con efecto "sábana ondeando" - Ondas sinusoidales + pivoteo = movimiento más orgánico 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,11 +1,15 @@
|
|||||||
#include "cylinder_shape.h"
|
#include "cylinder_shape.h"
|
||||||
#include "../defines.h"
|
#include "../defines.h"
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <cstdlib> // Para rand()
|
||||||
|
|
||||||
void CylinderShape::generatePoints(int num_points, float screen_width, float screen_height) {
|
void CylinderShape::generatePoints(int num_points, float screen_width, float screen_height) {
|
||||||
num_points_ = num_points;
|
num_points_ = num_points;
|
||||||
radius_ = screen_height * CYLINDER_RADIUS_FACTOR;
|
radius_ = screen_height * CYLINDER_RADIUS_FACTOR;
|
||||||
height_ = screen_height * CYLINDER_HEIGHT_FACTOR;
|
height_ = screen_height * CYLINDER_HEIGHT_FACTOR;
|
||||||
|
|
||||||
|
// Inicializar timer de tumbling con valor aleatorio (3-5 segundos)
|
||||||
|
tumble_timer_ = 3.0f + (rand() % 2000) / 1000.0f;
|
||||||
// Las posiciones 3D se calculan en getPoint3D() usando ecuaciones paramétricas del cilindro
|
// Las posiciones 3D se calculan en getPoint3D() usando ecuaciones paramétricas del cilindro
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -14,8 +18,39 @@ void CylinderShape::update(float delta_time, float screen_width, float screen_he
|
|||||||
radius_ = screen_height * CYLINDER_RADIUS_FACTOR;
|
radius_ = screen_height * CYLINDER_RADIUS_FACTOR;
|
||||||
height_ = screen_height * CYLINDER_HEIGHT_FACTOR;
|
height_ = screen_height * CYLINDER_HEIGHT_FACTOR;
|
||||||
|
|
||||||
// Actualizar ángulo de rotación en eje Y
|
// Actualizar ángulo de rotación en eje Y (siempre activo)
|
||||||
angle_y_ += CYLINDER_ROTATION_SPEED_Y * delta_time;
|
angle_y_ += CYLINDER_ROTATION_SPEED_Y * delta_time;
|
||||||
|
|
||||||
|
// Sistema de tumbling ocasional
|
||||||
|
if (is_tumbling_) {
|
||||||
|
// Estamos en tumble: animar angle_x hacia el objetivo
|
||||||
|
tumble_duration_ += delta_time;
|
||||||
|
float tumble_progress = tumble_duration_ / 1.5f; // 1.5 segundos de duración
|
||||||
|
|
||||||
|
if (tumble_progress >= 1.0f) {
|
||||||
|
// Tumble completado
|
||||||
|
angle_x_ = tumble_target_;
|
||||||
|
is_tumbling_ = false;
|
||||||
|
tumble_timer_ = 3.0f + (rand() % 2000) / 1000.0f; // Nuevo timer (3-5s)
|
||||||
|
} else {
|
||||||
|
// Interpolación suave con ease-in-out
|
||||||
|
float t = tumble_progress;
|
||||||
|
float ease = t < 0.5f
|
||||||
|
? 2.0f * t * t
|
||||||
|
: 1.0f - (-2.0f * t + 2.0f) * (-2.0f * t + 2.0f) / 2.0f;
|
||||||
|
angle_x_ = ease * tumble_target_;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// No estamos en tumble: contar tiempo
|
||||||
|
tumble_timer_ -= delta_time;
|
||||||
|
if (tumble_timer_ <= 0.0f) {
|
||||||
|
// Iniciar nuevo tumble
|
||||||
|
is_tumbling_ = true;
|
||||||
|
tumble_duration_ = 0.0f;
|
||||||
|
// Objetivo: PI/2 radianes (90°) o -PI/2
|
||||||
|
tumble_target_ = angle_x_ + ((rand() % 2) == 0 ? PI * 0.5f : -PI * 0.5f);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CylinderShape::getPoint3D(int index, float& x, float& y, float& z) const {
|
void CylinderShape::getPoint3D(int index, float& x, float& y, float& z) const {
|
||||||
@@ -56,15 +91,21 @@ void CylinderShape::getPoint3D(int index, float& x, float& y, float& z) const {
|
|||||||
float y_base = (height_ * 0.5f) * v; // Centrar verticalmente
|
float y_base = (height_ * 0.5f) * v; // Centrar verticalmente
|
||||||
float z_base = radius_ * sinf(u);
|
float z_base = radius_ * sinf(u);
|
||||||
|
|
||||||
// Aplicar rotación en eje Y
|
// Aplicar rotación en eje Y (principal, siempre activa)
|
||||||
float cos_y = cosf(angle_y_);
|
float cos_y = cosf(angle_y_);
|
||||||
float sin_y = sinf(angle_y_);
|
float sin_y = sinf(angle_y_);
|
||||||
float x_rot = x_base * cos_y - z_base * sin_y;
|
float x_rot_y = x_base * cos_y - z_base * sin_y;
|
||||||
float z_rot = x_base * sin_y + z_base * cos_y;
|
float z_rot_y = x_base * sin_y + z_base * cos_y;
|
||||||
|
|
||||||
// Retornar coordenadas finales rotadas
|
// Aplicar rotación en eje X (tumbling ocasional)
|
||||||
x = x_rot;
|
float cos_x = cosf(angle_x_);
|
||||||
y = y_base;
|
float sin_x = sinf(angle_x_);
|
||||||
|
float y_rot = y_base * cos_x - z_rot_y * sin_x;
|
||||||
|
float z_rot = y_base * sin_x + z_rot_y * cos_x;
|
||||||
|
|
||||||
|
// Retornar coordenadas finales con ambas rotaciones
|
||||||
|
x = x_rot_y;
|
||||||
|
y = y_rot;
|
||||||
z = z_rot;
|
z = z_rot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,15 +3,22 @@
|
|||||||
#include "shape.h"
|
#include "shape.h"
|
||||||
|
|
||||||
// Figura: Cilindro 3D rotante
|
// Figura: Cilindro 3D rotante
|
||||||
// Comportamiento: Superficie cilíndrica con rotación en eje Y
|
// Comportamiento: Superficie cilíndrica con rotación en eje Y + tumbling ocasional en X/Z
|
||||||
// Ecuaciones: x = r*cos(u), y = v, z = r*sin(u)
|
// Ecuaciones: x = r*cos(u), y = v, z = r*sin(u)
|
||||||
class CylinderShape : public Shape {
|
class CylinderShape : public Shape {
|
||||||
private:
|
private:
|
||||||
float angle_y_ = 0.0f; // Ángulo de rotación en eje Y (rad)
|
float angle_y_ = 0.0f; // Ángulo de rotación en eje Y (rad)
|
||||||
|
float angle_x_ = 0.0f; // Ángulo de rotación en eje X (tumbling ocasional)
|
||||||
float radius_ = 0.0f; // Radio del cilindro (píxeles)
|
float radius_ = 0.0f; // Radio del cilindro (píxeles)
|
||||||
float height_ = 0.0f; // Altura del cilindro (píxeles)
|
float height_ = 0.0f; // Altura del cilindro (píxeles)
|
||||||
int num_points_ = 0; // Cantidad de puntos generados
|
int num_points_ = 0; // Cantidad de puntos generados
|
||||||
|
|
||||||
|
// Sistema de tumbling ocasional
|
||||||
|
float tumble_timer_ = 0.0f; // Temporizador para próximo tumble
|
||||||
|
float tumble_duration_ = 0.0f; // Duración del tumble actual
|
||||||
|
bool is_tumbling_ = false; // ¿Estamos en modo tumble?
|
||||||
|
float tumble_target_ = 0.0f; // Ángulo objetivo del tumble
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void generatePoints(int num_points, float screen_width, float screen_height) override;
|
void generatePoints(int num_points, float screen_width, float screen_height) override;
|
||||||
void update(float delta_time, float screen_width, float screen_height) override;
|
void update(float delta_time, float screen_width, float screen_height) override;
|
||||||
|
|||||||
@@ -34,8 +34,10 @@ void WaveGridShape::update(float delta_time, float screen_width, float screen_he
|
|||||||
grid_size_ = screen_height * WAVE_GRID_SIZE_FACTOR;
|
grid_size_ = screen_height * WAVE_GRID_SIZE_FACTOR;
|
||||||
amplitude_ = screen_height * WAVE_GRID_AMPLITUDE;
|
amplitude_ = screen_height * WAVE_GRID_AMPLITUDE;
|
||||||
|
|
||||||
// Actualizar rotación en eje Y (horizontal)
|
// Pivoteo sutil en ejes X e Y (esquinas adelante/atrás, izq/der)
|
||||||
angle_y_ += WAVE_GRID_ROTATION_SPEED_Y * delta_time;
|
// Usamos velocidades lentas para movimiento sutil y orgánico
|
||||||
|
tilt_x_ += 0.3f * delta_time; // Pivoteo vertical (esquinas arriba/abajo)
|
||||||
|
tilt_y_ += 0.5f * delta_time; // Pivoteo horizontal (esquinas izq/der)
|
||||||
|
|
||||||
// Actualizar fase de las ondas (animación)
|
// Actualizar fase de las ondas (animación)
|
||||||
phase_ += WAVE_GRID_PHASE_SPEED * delta_time;
|
phase_ += WAVE_GRID_PHASE_SPEED * delta_time;
|
||||||
@@ -70,18 +72,22 @@ void WaveGridShape::getPoint3D(int index, float& x, float& y, float& z) const {
|
|||||||
// z = amplitude * sin(frequency * x + phase) * cos(frequency * y + phase)
|
// z = amplitude * sin(frequency * x + phase) * cos(frequency * y + phase)
|
||||||
float kx = WAVE_GRID_FREQUENCY * PI; // Frecuencia en X
|
float kx = WAVE_GRID_FREQUENCY * PI; // Frecuencia en X
|
||||||
float ky = WAVE_GRID_FREQUENCY * PI; // Frecuencia en Y
|
float ky = WAVE_GRID_FREQUENCY * PI; // Frecuencia en Y
|
||||||
float z_base = amplitude_ * sinf(kx * u + phase_) * cosf(ky * v + phase_);
|
float z_wave = amplitude_ * sinf(kx * u + phase_) * cosf(ky * v + phase_);
|
||||||
|
|
||||||
// Aplicar rotación en eje Y (horizontal)
|
// Añadir pivoteo sutil: esquinas se mueven adelante/atrás según posición
|
||||||
float cos_y = cosf(angle_y_);
|
// tilt_x oscila esquinas arriba/abajo, tilt_y oscila esquinas izq/der
|
||||||
float sin_y = sinf(angle_y_);
|
float tilt_amount_x = sinf(tilt_x_) * 0.15f; // Máximo 15% del grid_size
|
||||||
float x_rot = x_base * cos_y - z_base * sin_y;
|
float tilt_amount_y = sinf(tilt_y_) * 0.1f; // Máximo 10% del grid_size
|
||||||
float z_rot = x_base * sin_y + z_base * cos_y;
|
|
||||||
|
|
||||||
// Retornar coordenadas finales
|
float z_tilt = (u * tilt_amount_y + v * tilt_amount_x) * grid_size_;
|
||||||
x = x_rot;
|
|
||||||
|
// Z final = ondas + pivoteo
|
||||||
|
float z_final = z_wave + z_tilt;
|
||||||
|
|
||||||
|
// Retornar coordenadas (grid paralelo a pantalla, sin rotación global)
|
||||||
|
x = x_base;
|
||||||
y = y_base;
|
y = y_base;
|
||||||
z = z_rot;
|
z = z_final;
|
||||||
}
|
}
|
||||||
|
|
||||||
float WaveGridShape::getScaleFactor(float screen_height) const {
|
float WaveGridShape::getScaleFactor(float screen_height) const {
|
||||||
|
|||||||
@@ -3,11 +3,12 @@
|
|||||||
#include "shape.h"
|
#include "shape.h"
|
||||||
|
|
||||||
// Figura: Malla ondeante 3D (Wave Grid)
|
// Figura: Malla ondeante 3D (Wave Grid)
|
||||||
// Comportamiento: Grid 2D con ondas sinusoidales en Z + rotación
|
// Comportamiento: Grid 2D paralelo a pantalla con ondas + pivoteo sutil en esquinas
|
||||||
// Ecuaciones: z = A * sin(kx*x + phase) * cos(ky*y + phase)
|
// Ecuaciones: z = A * sin(kx*x + phase) * cos(ky*y + phase) + pivoteo
|
||||||
class WaveGridShape : public Shape {
|
class WaveGridShape : public Shape {
|
||||||
private:
|
private:
|
||||||
float angle_y_ = 0.0f; // Ángulo de rotación en eje Y (rad)
|
float tilt_x_ = 0.0f; // Ángulo de pivoteo en eje X (esquinas adelante/atrás)
|
||||||
|
float tilt_y_ = 0.0f; // Ángulo de pivoteo en eje Y (esquinas izq/der)
|
||||||
float phase_ = 0.0f; // Fase de animación de ondas (rad)
|
float phase_ = 0.0f; // Fase de animación de ondas (rad)
|
||||||
float grid_size_ = 0.0f; // Tamaño del grid (píxeles)
|
float grid_size_ = 0.0f; // Tamaño del grid (píxeles)
|
||||||
float amplitude_ = 0.0f; // Amplitud de las ondas (píxeles)
|
float amplitude_ = 0.0f; // Amplitud de las ondas (píxeles)
|
||||||
|
|||||||
Reference in New Issue
Block a user