#include "cube_shape.h" #include "../defines.h" #include void CubeShape::generatePoints(int num_points, float screen_width, float screen_height) { num_points_ = num_points; size_ = screen_height * CUBE_SIZE_FACTOR; // Limpiar vectores anteriores base_x_.clear(); base_y_.clear(); base_z_.clear(); // Seleccionar estrategia según cantidad de pelotas if (num_points <= 8) { generateVertices(); } else if (num_points <= 26) { generateVerticesAndCenters(); } else { generateVolumetricGrid(); } // Si sobran posiciones, repetir en espiral (distribución uniforme) while (static_cast(base_x_.size()) < num_points) { base_x_.push_back(base_x_[base_x_.size() % base_x_.size()]); base_y_.push_back(base_y_[base_y_.size() % base_y_.size()]); base_z_.push_back(base_z_[base_z_.size() % base_z_.size()]); } } void CubeShape::update(float delta_time, float screen_width, float screen_height) { // Recalcular tamaño por si cambió resolución (F4) size_ = screen_height * CUBE_SIZE_FACTOR; // Actualizar ángulos de rotación en los 3 ejes (efecto Rubik) angle_x_ += CUBE_ROTATION_SPEED_X * delta_time; angle_y_ += CUBE_ROTATION_SPEED_Y * delta_time; angle_z_ += CUBE_ROTATION_SPEED_Z * delta_time; } void CubeShape::getPoint3D(int index, float& x, float& y, float& z) const { if (index >= static_cast(base_x_.size())) { x = y = z = 0.0f; return; } // Obtener posición base float x_base = base_x_[index]; float y_base = base_y_[index]; float z_base = base_z_[index]; // Aplicar rotación en eje Z float cos_z = cosf(angle_z_); float sin_z = sinf(angle_z_); float x_rot_z = x_base * cos_z - y_base * sin_z; float y_rot_z = x_base * sin_z + y_base * cos_z; float z_rot_z = z_base; // Aplicar rotación en eje Y float cos_y = cosf(angle_y_); float sin_y = sinf(angle_y_); float x_rot_y = x_rot_z * cos_y + z_rot_z * sin_y; float y_rot_y = y_rot_z; float z_rot_y = -x_rot_z * sin_y + z_rot_z * cos_y; // Aplicar rotación en eje X float cos_x = cosf(angle_x_); float sin_x = sinf(angle_x_); float x_final = x_rot_y; float y_final = y_rot_y * cos_x - z_rot_y * sin_x; float z_final = y_rot_y * sin_x + z_rot_y * cos_x; // Retornar coordenadas finales rotadas x = x_final; y = y_final; z = z_final; } float CubeShape::getScaleFactor(float screen_height) const { // Factor de escala para física: proporcional al tamaño del cubo // Tamaño base = 60px (resolución 320x240, factor 0.25) const float BASE_SIZE = 60.0f; float current_size = screen_height * CUBE_SIZE_FACTOR; return current_size / BASE_SIZE; } // Métodos auxiliares privados void CubeShape::generateVertices() { // 8 vértices del cubo: todas las combinaciones de (±size, ±size, ±size) for (int x_sign : {-1, 1}) { for (int y_sign : {-1, 1}) { for (int z_sign : {-1, 1}) { base_x_.push_back(x_sign * size_); base_y_.push_back(y_sign * size_); base_z_.push_back(z_sign * size_); } } } } void CubeShape::generateVerticesAndCenters() { // 1. Añadir 8 vértices generateVertices(); // 2. Añadir 6 centros de caras // Caras: X=±size (Y,Z varían), Y=±size (X,Z varían), Z=±size (X,Y varían) base_x_.push_back(size_); base_y_.push_back(0); base_z_.push_back(0); // +X base_x_.push_back(-size_); base_y_.push_back(0); base_z_.push_back(0); // -X base_x_.push_back(0); base_y_.push_back(size_); base_z_.push_back(0); // +Y base_x_.push_back(0); base_y_.push_back(-size_);base_z_.push_back(0); // -Y base_x_.push_back(0); base_y_.push_back(0); base_z_.push_back(size_); // +Z base_x_.push_back(0); base_y_.push_back(0); base_z_.push_back(-size_); // -Z // 3. Añadir 12 centros de aristas // Aristas paralelas a X (4), Y (4), Z (4) // Paralelas a X (Y y Z en vértices, X=0) for (int y_sign : {-1, 1}) { for (int z_sign : {-1, 1}) { base_x_.push_back(0); base_y_.push_back(y_sign * size_); base_z_.push_back(z_sign * size_); } } // Paralelas a Y (X y Z en vértices, Y=0) for (int x_sign : {-1, 1}) { for (int z_sign : {-1, 1}) { base_x_.push_back(x_sign * size_); base_y_.push_back(0); base_z_.push_back(z_sign * size_); } } // Paralelas a Z (X y Y en vértices, Z=0) for (int x_sign : {-1, 1}) { for (int y_sign : {-1, 1}) { base_x_.push_back(x_sign * size_); base_y_.push_back(y_sign * size_); base_z_.push_back(0); } } } void CubeShape::generateVolumetricGrid() { // Calcular dimensión del grid cúbico: N³ ≈ num_points int grid_dim = static_cast(ceilf(cbrtf(static_cast(num_points_)))); if (grid_dim < 3) grid_dim = 3; // Mínimo grid 3x3x3 float step = (2.0f * size_) / (grid_dim - 1); // Espacio entre puntos for (int ix = 0; ix < grid_dim; ix++) { for (int iy = 0; iy < grid_dim; iy++) { for (int iz = 0; iz < grid_dim; iz++) { float x = -size_ + ix * step; float y = -size_ + iy * step; float z = -size_ + iz * step; base_x_.push_back(x); base_y_.push_back(y); base_z_.push_back(z); // Si ya tenemos suficientes puntos, salir if (static_cast(base_x_.size()) >= num_points_) { return; } } } } }