#include "atom_shape.h" #include "../defines.h" #include void AtomShape::generatePoints(int num_points, float screen_width, float screen_height) { num_points_ = num_points; nucleus_radius_ = screen_height * ATOM_NUCLEUS_RADIUS_FACTOR; orbit_radius_ = screen_height * ATOM_ORBIT_RADIUS_FACTOR; // Las posiciones se calculan en getPoint3D() } void AtomShape::update(float delta_time, float screen_width, float screen_height) { // Recalcular dimensiones por si cambió resolución (F4) nucleus_radius_ = screen_height * ATOM_NUCLEUS_RADIUS_FACTOR; orbit_radius_ = screen_height * ATOM_ORBIT_RADIUS_FACTOR; // Actualizar rotación global del átomo angle_y_ += ATOM_ROTATION_SPEED_Y * delta_time; // Actualizar fase de rotación de electrones en órbitas orbit_phase_ += ATOM_ORBIT_ROTATION_SPEED * delta_time; } void AtomShape::getPoint3D(int index, float& x, float& y, float& z) const { int num_orbits = static_cast(ATOM_NUM_ORBITS); // Calcular cuántos puntos para núcleo vs órbitas int nucleus_points = (num_points_ < 10) ? 1 : (num_points_ / 10); // 10% para núcleo if (nucleus_points < 1) nucleus_points = 1; // Si estamos en el núcleo if (index < nucleus_points) { // Distribuir puntos en esfera pequeña (núcleo) float t = static_cast(index) / static_cast(nucleus_points); float phi = acosf(1.0f - 2.0f * t); float theta = PI * 2.0f * t * 3.61803398875f; // Golden ratio float x_nuc = nucleus_radius_ * cosf(theta) * sinf(phi); float y_nuc = nucleus_radius_ * sinf(theta) * sinf(phi); float z_nuc = nucleus_radius_ * cosf(phi); // Aplicar rotación global float cos_y = cosf(angle_y_); float sin_y = sinf(angle_y_); x = x_nuc * cos_y - z_nuc * sin_y; y = y_nuc; z = x_nuc * sin_y + z_nuc * cos_y; return; } // Puntos restantes: distribuir en órbitas int orbit_points = num_points_ - nucleus_points; int points_per_orbit = orbit_points / num_orbits; if (points_per_orbit < 1) points_per_orbit = 1; int orbit_index = (index - nucleus_points) / points_per_orbit; if (orbit_index >= num_orbits) orbit_index = num_orbits - 1; int point_in_orbit = (index - nucleus_points) % points_per_orbit; // Ángulo del electrón en su órbita float electron_angle = (static_cast(point_in_orbit) / static_cast(points_per_orbit)) * 2.0f * PI; electron_angle += orbit_phase_; // Añadir rotación animada // Inclinación del plano orbital (cada órbita en ángulo diferente) float orbit_tilt = (static_cast(orbit_index) / static_cast(num_orbits)) * PI; // Posición del electrón en su órbita (plano XY local) float x_local = orbit_radius_ * cosf(electron_angle); float y_local = orbit_radius_ * sinf(electron_angle); float z_local = 0.0f; // Inclinar el plano orbital (rotación en eje X local) float cos_tilt = cosf(orbit_tilt); float sin_tilt = sinf(orbit_tilt); float y_tilted = y_local * cos_tilt - z_local * sin_tilt; float z_tilted = y_local * sin_tilt + z_local * cos_tilt; // Aplicar rotación global del átomo (eje Y) float cos_y = cosf(angle_y_); float sin_y = sinf(angle_y_); float x_rot = x_local * cos_y - z_tilted * sin_y; float z_rot = x_local * sin_y + z_tilted * cos_y; x = x_rot; y = y_tilted; z = z_rot; } float AtomShape::getScaleFactor(float screen_height) const { // Factor de escala para física: proporcional al radio de órbita // Radio órbita base = 72px (0.30 * 240px en resolución 320x240) const float BASE_RADIUS = 72.0f; float current_radius = screen_height * ATOM_ORBIT_RADIUS_FACTOR; return current_radius / BASE_RADIUS; }