BosonX/src/render.cpp

105 lines
3.0 KiB
C++

#define __BSD_VISIBLE 1
#include <math.h>
#include "render.h"
#include "game.h"
#include "util.h"
#include <azur/gint/render.h>
void camera::set_fov(num fov)
{
this->fov = fov;
float fov_radians = (float)fov * 3.14159 / 180;
float sd = 1 / tanf(fov_radians / 2);
this->_sd = num(sd);
}
void camera_track(struct camera *camera, struct player const *player)
{
camera->pos = player->pos() + player->up() * RENDER_EYE_HEIGHT;
camera->pos.z -= RENDER_CAMERA_BACK_DISTANCE;
camera->platform = player->platform;
if(player->jump_dir && player->jump_t >= TIME_ROTATION / 2)
camera->platform += player->jump_dir;
num angle = player->world_angle();
camera->angle_vector = vec2(num_cos(-angle), num_sin(-angle));
}
vec3 camera_project_point(struct camera *camera, vec3 u)
{
if(u.z < camera->pos.z + camera->near_plane())
return u;
u = vec_rotate_around_z(u - camera->pos, camera->angle_vector);
num f = camera->screen_distance() * (camera->screen_size.y / 2) / u.z;
u.x = u.x * f + camera->screen_size.x / 2;
u.y = -u.y * f + camera->screen_size.y / 2 ;
return u;
}
void camera_project_prect(struct camera *camera, struct prect *p)
{
/* Require the rectangle to be already clipped */
if(p->nl.z < camera->pos.z + camera->near_plane())
return;
vec2 half_screen(camera->screen_size.x / 2, camera->screen_size.y / 2);
p->nl = vec_rotate_around_z(p->nl - camera->pos, camera->angle_vector);
p->nr = vec_rotate_around_z(p->nr - camera->pos, camera->angle_vector);
p->fl = vec_rotate_around_z(p->fl - camera->pos, camera->angle_vector);
p->fr = vec_rotate_around_z(p->fr - camera->pos, camera->angle_vector);
/* We assume nl/nr have the same z, and so do fl/fr */
num f = camera->screen_distance() * half_screen.y;
num near_f = f / p->nl.z;
num far_f = f / p->fl.z;
p->nl.x = p->nl.x * near_f + half_screen.x;
p->nl.y = -p->nl.y * near_f + half_screen.y;
p->nr.x = p->nr.x * near_f + half_screen.x;
p->nr.y = -p->nr.y * near_f + half_screen.y;
p->fl.x = p->fl.x * far_f + half_screen.x;
p->fl.y = -p->fl.y * far_f + half_screen.y;
p->fr.x = p->fr.x * far_f + half_screen.x;
p->fr.y = -p->fr.y * far_f + half_screen.y;
}
int camera_platform_color(struct camera *camera, int platform_id)
{
/* Accounting for the full angle is too precise and results in weird
color jumps at different times across platforms, instead switch at half
movement. */
int dist = platform_id - camera->platform;
if(dist < 0)
dist += PLATFORM_COUNT;
dist = std::min(dist, PLATFORM_COUNT - dist);
int gray = 31 - 2 * dist;
return C_RGB(gray, gray, gray);
}
void render_triangle(vec3 *p1, vec3 *p2, vec3 *p3, int color)
{
azrp_triangle(
(int)p1->x, (int)p1->y,
(int)p2->x, (int)p2->y,
(int)p3->x, (int)p3->y,
color);
}
void render_dots(std::initializer_list<vec3> const &&points)
{
extern image_t img_dot;
for(auto p: points)
azrp_image((int)p.x - 2, (int)p.y - 2, &img_dot);
}