76786203a0
- Agregar paréntesis explícitos en operaciones matemáticas para claridad
- Ejemplos: '1.0F - a * b' → '1.0F - (a * b)'
- 291 correcciones aplicadas automáticamente con clang-tidy
- Check 2/N completado
🤖 Generated with Claude Code
120 lines
4.6 KiB
C++
120 lines
4.6 KiB
C++
// shape_renderer.cpp - Implementació del renderitzat de formes
|
|
// © 2025 Port a C++20 amb SDL3
|
|
|
|
#include "core/rendering/shape_renderer.hpp"
|
|
|
|
#include <cmath>
|
|
|
|
#include "core/defaults.hpp"
|
|
#include "core/rendering/line_renderer.hpp"
|
|
|
|
namespace Rendering {
|
|
|
|
// Helper: aplicar rotació 3D a un punt 2D (assumeix Z=0)
|
|
static Punt apply_3d_rotation(float x, float y, const Rotation3D& rot) {
|
|
float z = 0.0F; // Tots els punts 2D comencen a Z=0
|
|
|
|
// Pitch (rotació eix X): cabeceo arriba/baix
|
|
float cos_pitch = std::cos(rot.pitch);
|
|
float sin_pitch = std::sin(rot.pitch);
|
|
float y1 = (y * cos_pitch) - (z * sin_pitch);
|
|
float z1 = (y * sin_pitch) + (z * cos_pitch);
|
|
|
|
// Yaw (rotació eix Y): guiñada esquerra/dreta
|
|
float cos_yaw = std::cos(rot.yaw);
|
|
float sin_yaw = std::sin(rot.yaw);
|
|
float x2 = (x * cos_yaw) + (z1 * sin_yaw);
|
|
float z2 = (-x * sin_yaw) + (z1 * cos_yaw);
|
|
|
|
// Roll (rotació eix Z): alabeo lateral
|
|
float cos_roll = std::cos(rot.roll);
|
|
float sin_roll = std::sin(rot.roll);
|
|
float x3 = (x2 * cos_roll) - (y1 * sin_roll);
|
|
float y3 = (x2 * sin_roll) + (y1 * cos_roll);
|
|
|
|
// Proyecció perspectiva (Z-divide simple)
|
|
// Naus volen cap al punt de fuga (320, 240) a "infinit" (Z → +∞)
|
|
// Z més gran = més lluny = més petit a pantalla
|
|
constexpr float perspective_factor = 500.0F;
|
|
float scale_factor = perspective_factor / (perspective_factor + z2);
|
|
|
|
return {x3 * scale_factor, y3 * scale_factor};
|
|
}
|
|
|
|
// Helper: transformar un punt amb rotació, escala i trasllació
|
|
static Punt transform_point(const Punt& point, const Punt& shape_centre, const Punt& posicio, float angle, float escala, const Rotation3D* rotation_3d) {
|
|
// 1. Centrar el punt respecte al centre de la forma
|
|
float centered_x = point.x - shape_centre.x;
|
|
float centered_y = point.y - shape_centre.y;
|
|
|
|
// 2. Aplicar rotació 3D (si es proporciona)
|
|
if (rotation_3d && rotation_3d->has_rotation()) {
|
|
Punt rotated_3d = apply_3d_rotation(centered_x, centered_y, *rotation_3d);
|
|
centered_x = rotated_3d.x;
|
|
centered_y = rotated_3d.y;
|
|
}
|
|
|
|
// 3. Aplicar escala al punt (després de rotació 3D)
|
|
float scaled_x = centered_x * escala;
|
|
float scaled_y = centered_y * escala;
|
|
|
|
// 4. Aplicar rotació 2D (Z-axis, tradicional)
|
|
// IMPORTANT: En el sistema original, angle=0 apunta AMUNT (no dreta)
|
|
// Per això usem (angle - PI/2) per compensar
|
|
// Però aquí angle ja ve en el sistema correcte del joc
|
|
float cos_a = std::cos(angle);
|
|
float sin_a = std::sin(angle);
|
|
|
|
float rotated_x = (scaled_x * cos_a) - (scaled_y * sin_a);
|
|
float rotated_y = (scaled_x * sin_a) + (scaled_y * cos_a);
|
|
|
|
// 5. Aplicar trasllació a posició mundial
|
|
return {rotated_x + posicio.x, rotated_y + posicio.y};
|
|
}
|
|
|
|
void render_shape(SDL_Renderer* renderer,
|
|
const std::shared_ptr<Graphics::Shape>& shape,
|
|
const Punt& posicio,
|
|
float angle,
|
|
float escala,
|
|
bool dibuixar,
|
|
float progress,
|
|
float brightness,
|
|
const Rotation3D* rotation_3d) {
|
|
// Verificar que la forma és vàlida
|
|
if (!shape || !shape->es_valida()) {
|
|
return;
|
|
}
|
|
|
|
// Si progress < 1.0, no dibuixar (tot o res)
|
|
if (progress < 1.0F) {
|
|
return;
|
|
}
|
|
|
|
// Obtenir el centre de la forma per a transformacions
|
|
const Punt& shape_centre = shape->get_centre();
|
|
|
|
// Iterar sobre totes les primitives
|
|
for (const auto& primitive : shape->get_primitives()) {
|
|
if (primitive.type == Graphics::PrimitiveType::POLYLINE) {
|
|
// POLYLINE: connectar punts consecutius
|
|
for (size_t i = 0; i < primitive.points.size() - 1; i++) {
|
|
Punt p1 = transform_point(primitive.points[i], shape_centre, posicio, angle, escala, rotation_3d);
|
|
Punt p2 = transform_point(primitive.points[i + 1], shape_centre, posicio, angle, escala, rotation_3d);
|
|
|
|
linea(renderer, static_cast<int>(p1.x), static_cast<int>(p1.y), static_cast<int>(p2.x), static_cast<int>(p2.y), dibuixar, brightness);
|
|
}
|
|
} else { // PrimitiveType::LINE
|
|
// LINE: exactament 2 punts
|
|
if (primitive.points.size() >= 2) {
|
|
Punt p1 = transform_point(primitive.points[0], shape_centre, posicio, angle, escala, rotation_3d);
|
|
Punt p2 = transform_point(primitive.points[1], shape_centre, posicio, angle, escala, rotation_3d);
|
|
|
|
linea(renderer, static_cast<int>(p1.x), static_cast<int>(p1.y), static_cast<int>(p2.x), static_cast<int>(p2.y), dibuixar, brightness);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
} // namespace Rendering
|