Implementar figura ATOM (núcleo + órbitas) - Tecla I - TODAS LAS FIGURAS COMPLETADAS
- Nueva clase AtomShape con núcleo central + 3 órbitas - Núcleo: esfera pequeña con distribución Fibonacci - Órbitas: planos inclinados con electrones animados - Rotación global + rotación orbital independiente - Modelo atómico clásico de Bohr - Compatible con física spring-damper y z-sorting ✅ TODAS LAS 8 FIGURAS 3D IMPLEMENTADAS: Q-Sphere, W-WaveGrid, E-Helix, R-Torus, T-Cube, Y-Cylinder, U-Icosahedron, I-Atom 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -132,6 +132,13 @@ constexpr float ICOSAHEDRON_ROTATION_SPEED_X = 0.4f; // Velocidad rotación eje
|
|||||||
constexpr float ICOSAHEDRON_ROTATION_SPEED_Y = 0.7f; // Velocidad rotación eje Y (rad/s)
|
constexpr float ICOSAHEDRON_ROTATION_SPEED_Y = 0.7f; // Velocidad rotación eje Y (rad/s)
|
||||||
constexpr float ICOSAHEDRON_ROTATION_SPEED_Z = 0.2f; // Velocidad rotación eje Z (rad/s)
|
constexpr float ICOSAHEDRON_ROTATION_SPEED_Z = 0.2f; // Velocidad rotación eje Z (rad/s)
|
||||||
|
|
||||||
|
// Configuración de Atom (núcleo con órbitas electrónicas)
|
||||||
|
constexpr float ATOM_NUCLEUS_RADIUS_FACTOR = 0.08f; // Radio del núcleo central
|
||||||
|
constexpr float ATOM_ORBIT_RADIUS_FACTOR = 0.30f; // Radio de las órbitas
|
||||||
|
constexpr float ATOM_NUM_ORBITS = 3; // Número de órbitas
|
||||||
|
constexpr float ATOM_ORBIT_ROTATION_SPEED = 2.0f; // Velocidad de electrones (rad/s)
|
||||||
|
constexpr float ATOM_ROTATION_SPEED_Y = 0.5f; // Velocidad rotación global (rad/s)
|
||||||
|
|
||||||
// Control manual de escala de figuras 3D (Numpad +/-)
|
// Control manual de escala de figuras 3D (Numpad +/-)
|
||||||
constexpr float SHAPE_SCALE_MIN = 0.3f; // Escala mínima (30%)
|
constexpr float SHAPE_SCALE_MIN = 0.3f; // Escala mínima (30%)
|
||||||
constexpr float SHAPE_SCALE_MAX = 3.0f; // Escala máxima (300%)
|
constexpr float SHAPE_SCALE_MAX = 3.0f; // Escala máxima (300%)
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
#include "shapes/torus_shape.h" // for TorusShape
|
#include "shapes/torus_shape.h" // for TorusShape
|
||||||
#include "shapes/cylinder_shape.h" // for CylinderShape
|
#include "shapes/cylinder_shape.h" // for CylinderShape
|
||||||
#include "shapes/icosahedron_shape.h" // for IcosahedronShape
|
#include "shapes/icosahedron_shape.h" // for IcosahedronShape
|
||||||
|
#include "shapes/atom_shape.h" // for AtomShape
|
||||||
|
|
||||||
// Función auxiliar para obtener la ruta del directorio del ejecutable
|
// Función auxiliar para obtener la ruta del directorio del ejecutable
|
||||||
std::string getExecutableDirectory() {
|
std::string getExecutableDirectory() {
|
||||||
@@ -1088,7 +1089,9 @@ void Engine::activateShape(ShapeType type) {
|
|||||||
case ShapeType::ICOSAHEDRON:
|
case ShapeType::ICOSAHEDRON:
|
||||||
active_shape_ = std::make_unique<IcosahedronShape>();
|
active_shape_ = std::make_unique<IcosahedronShape>();
|
||||||
break;
|
break;
|
||||||
// Futuras figuras se añadirán aquí
|
case ShapeType::ATOM:
|
||||||
|
active_shape_ = std::make_unique<AtomShape>();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
active_shape_ = std::make_unique<SphereShape>(); // Fallback
|
active_shape_ = std::make_unique<SphereShape>(); // Fallback
|
||||||
break;
|
break;
|
||||||
|
|||||||
96
source/shapes/atom_shape.cpp
Normal file
96
source/shapes/atom_shape.cpp
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
#include "atom_shape.h"
|
||||||
|
#include "../defines.h"
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
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<int>(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<float>(index) / static_cast<float>(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<float>(point_in_orbit) / static_cast<float>(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<float>(orbit_index) / static_cast<float>(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;
|
||||||
|
}
|
||||||
22
source/shapes/atom_shape.h
Normal file
22
source/shapes/atom_shape.h
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "shape.h"
|
||||||
|
|
||||||
|
// Figura: Átomo con núcleo central y órbitas electrónicas
|
||||||
|
// Comportamiento: Núcleo estático + electrones orbitando en planos inclinados
|
||||||
|
// Efecto: Modelo atómico clásico Bohr
|
||||||
|
class AtomShape : public Shape {
|
||||||
|
private:
|
||||||
|
float angle_y_ = 0.0f; // Ángulo de rotación global en eje Y (rad)
|
||||||
|
float orbit_phase_ = 0.0f; // Fase de rotación de electrones (rad)
|
||||||
|
float nucleus_radius_ = 0.0f; // Radio del núcleo central (píxeles)
|
||||||
|
float orbit_radius_ = 0.0f; // Radio de las órbitas (píxeles)
|
||||||
|
int num_points_ = 0; // Cantidad total de puntos
|
||||||
|
|
||||||
|
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 "ATOM"; }
|
||||||
|
float getScaleFactor(float screen_height) const override;
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user