Files
orni-attack/source/core/rendering/shape_renderer.cpp
T
JailDesigner fa7da4ca58 Fase 7b+c: swap atomico a SDL3 GPU (Vulkan/Metal, sin SDL_Renderer)
El runtime de rendering pasa a SDL3 GPU. SDL_Renderer eliminado por
completo del proyecto: SDLManager posee un GpuFrameRenderer y todo
el resto del codigo habla con un Rendering::Renderer* opaco (alias
del GpuFrameRenderer).

Cambios principales:

- core/rendering/render_context.hpp: alias central
  `using Rendering::Renderer = GPU::GpuFrameRenderer;` — punto unico
  de indireccion entre el juego y el backend de dibujo.

- core/rendering/sdl_manager.hpp/cpp: deja de tener SDL_Renderer*;
  contiene un Rendering::Renderer gpu_renderer_. iniciar() ahora hace
  GpuDevice::init + pipeline; clear() llama beginFrame; present()
  llama endFrame. Letterbox se aplica via setViewport tras cada
  begin del render pass. toggleVSync() usa
  SDL_SetGPUSwapchainParameters.

- core/rendering/line_renderer.hpp/cpp: la firma cambia a
  `linea(Renderer*, x1,y1,x2,y2, brightness, thickness)`. La
  implementacion deja de usar SDL_RenderLine: empuja la linea como
  quad extrudido al batch del GpuFrameRenderer. Se anade un grosor
  global configurable via setLineThickness (default 1.5 px). Ya no
  se aplica transform_x/y porque el shader hace logical->NDC y el
  viewport hace el letterbox.

- gpu_frame_renderer: anade setViewport (aplicable mid-frame),
  setVSync (PRESENTMODE_VSYNC/IMMEDIATE) y applyViewport interno
  que re-aplica el viewport tras reabrir el render pass en flushBatch.

- Sed sweep masivo en 19 archivos: SDL_Renderer* -> Rendering::Renderer*
  en headers y .cpp de entities, effects, graphics y title. Los
  archivos solo propagan el puntero — solo line_renderer consume sus
  metodos. SDL_Renderer queda eliminado del proyecto.

Smoke test xvfb: backend Vulkan detectado, binario arranca, carga
todos los shapes/audio/title, TitleScene inicializa, termina limpio
con "Adeu!". stderr vacio. Validacion visual pendiente en hardware
real (xvfb VMware sin 3D no muestra el swapchain Vulkan).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 14:12:34 +02:00

121 lines
4.6 KiB
C++

// shape_renderer.cpp - Implementació del renderizado de formes
// © 2025 Port a C++20 con SDL3
#include "core/rendering/shape_renderer.hpp"
#include <cmath>
#include "core/defaults.hpp"
#include "core/rendering/line_renderer.hpp"
namespace Rendering {
// Helper: aplicar rotación 3D a un point 2D (assumeix Z=0)
static Vec2 apply_3d_rotation(float x, float y, const Rotation3D& rot) {
float z = 0.0F; // Todos los points 2D comencen a Z=0
// Pitch (rotación 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ón eix Y): guiñada izquierda/derecha
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ón 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)
// Naves quieren hacia el point de fuga (320, 240) a "infinit" (Z → +∞)
// Z més grande = més lluny = més pequeño a pantalla
constexpr float perspective_factor = 500.0F;
float scale_factor = perspective_factor / (perspective_factor + z2);
return {.x = x3 * scale_factor, .y = y3 * scale_factor};
}
// Helper: transformar un point con rotación, scale i traslación
static Vec2 transform_point(const Vec2& point, const Vec2& shape_centre, const Vec2& position, float angle, float scale, const Rotation3D* rotation_3d) {
// 1. Centrar el point respecte al centro de la shape
float centered_x = point.x - shape_centre.x;
float centered_y = point.y - shape_centre.y;
// 2. Aplicar rotación 3D (si es proporciona)
if ((rotation_3d != nullptr) && rotation_3d->has_rotation()) {
Vec2 rotated_3d = apply_3d_rotation(centered_x, centered_y, *rotation_3d);
centered_x = rotated_3d.x;
centered_y = rotated_3d.y;
}
// 3. Aplicar scale al point (después de rotación 3D)
float scaled_x = centered_x * scale;
float scaled_y = centered_y * scale;
// 4. Aplicar rotación 2D (Z-axis, tradicional)
// IMPORTANT: En el sistema original, angle=0 apunta AMUNT (no derecha)
// Per això usem (angle - PI/2) per compensar
// Pero aquí angle ya ve en el sistema correcte del juego
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 traslación a posición mundial
return {.x = rotated_x + position.x, .y = rotated_y + position.y};
}
void render_shape(Rendering::Renderer* renderer,
const std::shared_ptr<Graphics::Shape>& shape,
const Vec2& position,
float angle,
float scale,
float progress,
float brightness,
const Rotation3D* rotation_3d) {
// Verificar que la shape es vàlida
if (!shape || !shape->isValid()) {
return;
}
// Si progress < 1.0, no draw (tot o res)
if (progress < 1.0F) {
return;
}
// Obtenir el centro de la shape para transformacions
const Vec2& shape_centre = shape->getCenter();
// Iterar sobre todas las primitives
for (const auto& primitive : shape->get_primitives()) {
if (primitive.type == Graphics::PrimitiveType::POLYLINE) {
// POLYLINE: connectar points consecutius
for (size_t i = 0; i < primitive.points.size() - 1; i++) {
Vec2 p1 = transform_point(primitive.points[i], shape_centre, position, angle, scale, rotation_3d);
Vec2 p2 = transform_point(primitive.points[i + 1], shape_centre, position, angle, scale, rotation_3d);
linea(renderer, static_cast<int>(p1.x), static_cast<int>(p1.y),
static_cast<int>(p2.x), static_cast<int>(p2.y), brightness);
}
} else { // PrimitiveType::LINE
// LINE: exactament 2 points
if (primitive.points.size() >= 2) {
Vec2 p1 = transform_point(primitive.points[0], shape_centre, position, angle, scale, rotation_3d);
Vec2 p2 = transform_point(primitive.points[1], shape_centre, position, angle, scale, rotation_3d);
linea(renderer, static_cast<int>(p1.x), static_cast<int>(p1.y),
static_cast<int>(p2.x), static_cast<int>(p2.y), brightness);
}
}
}
}
} // namespace Rendering