diff --git a/source/defines.h b/source/defines.h index 7e95596..e5f29e5 100644 --- a/source/defines.h +++ b/source/defines.h @@ -100,6 +100,13 @@ 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) +// Configuración de Helix (espiral helicoidal 3D) +constexpr float HELIX_RADIUS_FACTOR = 0.25f; // Radio de la espiral (proporción de altura) +constexpr float HELIX_PITCH_FACTOR = 0.25f; // Separación vertical entre vueltas (proporción de altura) +constexpr float HELIX_NUM_TURNS = 3.0f; // Número de vueltas completas (1-5) +constexpr float HELIX_ROTATION_SPEED_Y = 1.2f; // Velocidad rotación eje Y (rad/s) +constexpr float HELIX_PHASE_SPEED = 0.5f; // Velocidad de animación vertical (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%) diff --git a/source/engine.cpp b/source/engine.cpp index 31a24a0..284fde2 100644 --- a/source/engine.cpp +++ b/source/engine.cpp @@ -25,6 +25,7 @@ #include "external/texture.h" // for Texture #include "shapes/sphere_shape.h" // for SphereShape #include "shapes/cube_shape.h" // for CubeShape +#include "shapes/helix_shape.h" // for HelixShape // Función auxiliar para obtener la ruta del directorio del ejecutable std::string getExecutableDirectory() { @@ -1068,6 +1069,9 @@ void Engine::activateShape(ShapeType type) { case ShapeType::CUBE: active_shape_ = std::make_unique(); break; + case ShapeType::HELIX: + active_shape_ = std::make_unique(); + break; // Futuras figuras se añadirán aquí default: active_shape_ = std::make_unique(); // Fallback diff --git a/source/shapes/helix_shape.cpp b/source/shapes/helix_shape.cpp new file mode 100644 index 0000000..2bc9a80 --- /dev/null +++ b/source/shapes/helix_shape.cpp @@ -0,0 +1,59 @@ +#include "helix_shape.h" +#include "../defines.h" +#include + +void HelixShape::generatePoints(int num_points, float screen_width, float screen_height) { + num_points_ = num_points; + radius_ = screen_height * HELIX_RADIUS_FACTOR; + pitch_ = screen_height * HELIX_PITCH_FACTOR; + total_height_ = pitch_ * HELIX_NUM_TURNS; + // Las posiciones 3D se calculan en getPoint3D() usando ecuaciones paramétricas +} + +void HelixShape::update(float delta_time, float screen_width, float screen_height) { + // Recalcular dimensiones por si cambió resolución (F4) + radius_ = screen_height * HELIX_RADIUS_FACTOR; + pitch_ = screen_height * HELIX_PITCH_FACTOR; + total_height_ = pitch_ * HELIX_NUM_TURNS; + + // Actualizar rotación en eje Y (horizontal) + angle_y_ += HELIX_ROTATION_SPEED_Y * delta_time; + + // Actualizar fase para animación vertical (efecto "subiendo/bajando") + phase_offset_ += HELIX_PHASE_SPEED * delta_time; +} + +void HelixShape::getPoint3D(int index, float& x, float& y, float& z) const { + // Parámetro t: distribuir uniformemente de 0 a (2π * num_turns) + float t = (static_cast(index) / static_cast(num_points_)) * (2.0f * PI * HELIX_NUM_TURNS); + + // Ecuaciones paramétricas de hélice + // x = radius * cos(t) + // y = pitch * (t / 2π) + phase_offset (altura proporcional al ángulo) + // z = radius * sin(t) + float x_base = radius_ * cosf(t); + float y_base = (pitch_ * (t / (2.0f * PI))) + (sinf(phase_offset_) * pitch_ * 0.3f); + float z_base = radius_ * sinf(t); + + // Centrar verticalmente: restar mitad de altura total + y_base -= total_height_ * 0.5f; + + // Aplicar rotación en eje Y (horizontal) + float cos_y = cosf(angle_y_); + float sin_y = sinf(angle_y_); + float x_rot = x_base * cos_y - z_base * sin_y; + float z_rot = x_base * sin_y + z_base * cos_y; + + // Retornar coordenadas finales + x = x_rot; + y = y_base; + z = z_rot; +} + +float HelixShape::getScaleFactor(float screen_height) const { + // Factor de escala para física: proporcional a la dimensión mayor (altura total) + // Altura base = 180px para 3 vueltas con pitch=0.25 en 240px de altura (180 = 240 * 0.25 * 3) + const float BASE_HEIGHT = 180.0f; + float current_height = screen_height * HELIX_PITCH_FACTOR * HELIX_NUM_TURNS; + return current_height / BASE_HEIGHT; +} diff --git a/source/shapes/helix_shape.h b/source/shapes/helix_shape.h new file mode 100644 index 0000000..b82f800 --- /dev/null +++ b/source/shapes/helix_shape.h @@ -0,0 +1,23 @@ +#pragma once + +#include "shape.h" + +// Figura: Espiral helicoidal 3D con distribución uniforme +// Comportamiento: Rotación en eje Y + animación de fase vertical +// Ecuaciones: x = r*cos(t), y = pitch*t + phase, z = r*sin(t) +class HelixShape : public Shape { +private: + float angle_y_ = 0.0f; // Ángulo de rotación en eje Y (rad) + float phase_offset_ = 0.0f; // Offset de fase para animación vertical (rad) + float radius_ = 0.0f; // Radio de la espiral (píxeles) + float pitch_ = 0.0f; // Separación vertical entre vueltas (píxeles) + float total_height_ = 0.0f; // Altura total de la espiral (píxeles) + int num_points_ = 0; // Cantidad de puntos generados + +public: + 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 getPoint3D(int index, float& x, float& y, float& z) const override; + const char* getName() const override { return "HELIX"; } + float getScaleFactor(float screen_height) const override; +};