2019-09-07 21:23:46 +02:00
|
|
|
#include <fxengine/face.h>
|
2019-09-12 19:48:53 +02:00
|
|
|
#include <fxengine/texture.h>
|
2019-09-07 21:23:46 +02:00
|
|
|
#include <fxengine/point.h>
|
2019-09-07 19:57:20 +02:00
|
|
|
#include <render/zbuffer.h>
|
2019-09-01 10:13:17 +02:00
|
|
|
|
2019-09-02 09:38:25 +02:00
|
|
|
#ifdef USE_LIBPROF
|
2019-09-01 10:13:17 +02:00
|
|
|
#include <libprof.h>
|
2019-09-02 09:38:25 +02:00
|
|
|
#endif
|
2019-09-01 10:13:17 +02:00
|
|
|
|
|
|
|
#include <gint/display.h>
|
|
|
|
#include <gint/clock.h>
|
|
|
|
|
2019-09-02 11:41:37 +02:00
|
|
|
#ifdef USE_LIBPROF
|
|
|
|
static uint32_t frame_interval_min=1000000;
|
|
|
|
static uint32_t frame_interval_max=1;
|
|
|
|
#endif
|
2019-09-01 10:13:17 +02:00
|
|
|
|
2019-09-12 19:48:53 +02:00
|
|
|
void fe_render_update(const uint32_t libprof_channel)
|
2019-09-01 10:13:17 +02:00
|
|
|
{
|
|
|
|
//dupdate();
|
2019-09-01 14:58:27 +02:00
|
|
|
#ifdef USE_LIBPROF
|
2019-09-01 10:13:17 +02:00
|
|
|
// gestion du temps avec libprof
|
|
|
|
if (prof_elapsed)
|
|
|
|
{
|
2019-09-01 12:28:31 +02:00
|
|
|
prof_leave(libprof_channel);
|
|
|
|
uint32_t frame_interval = prof_time(libprof_channel);
|
2019-09-01 10:13:17 +02:00
|
|
|
//sleep_us(0, MINIMUM_FRAME_DELAY-frame_interval);
|
|
|
|
if (frame_interval<frame_interval_min)
|
|
|
|
frame_interval_min = frame_interval;
|
|
|
|
if (frame_interval>frame_interval_max)
|
|
|
|
frame_interval_max = frame_interval;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
prof_init(libprof_channel+1, 0);
|
|
|
|
}
|
|
|
|
//dupdate();
|
2019-09-01 12:28:31 +02:00
|
|
|
prof_clear(libprof_channel);
|
|
|
|
prof_enter(libprof_channel);
|
2019-09-01 14:58:27 +02:00
|
|
|
#endif
|
2019-09-07 21:56:35 +02:00
|
|
|
fe_zbuffer_clear();
|
2019-09-01 10:13:17 +02:00
|
|
|
|
2019-09-07 21:56:35 +02:00
|
|
|
///fe_set(dh, dv, roulis, camera);
|
2019-09-01 10:13:17 +02:00
|
|
|
|
2019-09-01 12:28:31 +02:00
|
|
|
//dclear(C_WHITE);
|
2019-09-01 10:13:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Orientation of the face
|
|
|
|
*
|
|
|
|
* @param face The face
|
|
|
|
*
|
|
|
|
* @return if it is true the it is clockwised else it isn't clockwised
|
|
|
|
*/
|
2019-09-07 21:56:35 +02:00
|
|
|
static bool is_colckwised(fe_triangle const * face)
|
2019-09-01 10:13:17 +02:00
|
|
|
{
|
|
|
|
int32_t area = 0;
|
|
|
|
|
|
|
|
area += face->s1->x * face->s2->y;
|
|
|
|
area -= face->s2->x * face->s1->y;
|
|
|
|
|
|
|
|
area += face->s2->x * face->s3->y;
|
|
|
|
area -= face->s3->x * face->s2->y;
|
|
|
|
|
|
|
|
area += face->s3->x * face->s1->y;
|
|
|
|
area -= face->s1->x * face->s3->y;
|
|
|
|
|
|
|
|
return (area < 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// gestion locale des arètes
|
|
|
|
typedef struct line line;
|
|
|
|
struct line
|
|
|
|
{
|
|
|
|
int32_t x,y,z;
|
|
|
|
int32_t dx,dy,dz;
|
|
|
|
int32_t no_line; // si les deux points sont confondus (se comporte comme un bool)
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Sets up a line with 2 points
|
|
|
|
*
|
|
|
|
* @param l The line
|
|
|
|
* @param s1 The s 1
|
|
|
|
* @param s2 The s 2
|
|
|
|
*/
|
2019-09-07 21:56:35 +02:00
|
|
|
static void line_set(line* l,fe_integer_position const * s1, fe_integer_position const * s2)
|
2019-09-01 10:13:17 +02:00
|
|
|
{
|
|
|
|
l->x = s1->x;
|
|
|
|
l->y = s1->y;
|
|
|
|
l->z = s1->z;
|
|
|
|
l->dx = s2->x - s1->x;
|
|
|
|
l->dy = s2->y - s1->y;
|
|
|
|
l->dz = s2->z - s1->z;
|
|
|
|
l->no_line = (l->dx==0 && l->dy==0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int32_t max(int32_t x, int32_t y)
|
|
|
|
{
|
|
|
|
return (x>y ? x : y);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int32_t min(int32_t x, int32_t y)
|
|
|
|
{
|
|
|
|
return (x<y ? x : y);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int32_t abs(int32_t x)
|
|
|
|
{
|
|
|
|
return(x<0 ? -x : x);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief get the corresponding x from the y coordinate
|
|
|
|
*
|
|
|
|
* @param[in] y the y coordinate
|
|
|
|
* @param l the line
|
|
|
|
* @param x address where x is written
|
|
|
|
*
|
|
|
|
* @return if given point coordinate belongs to the l
|
|
|
|
*/
|
|
|
|
static bool line_get_x(int32_t y, line const * l, int32_t * x)
|
|
|
|
{
|
|
|
|
y -= l->y;
|
|
|
|
if (y < 0 && l->dy > 0)
|
|
|
|
return false;
|
|
|
|
if (y > 0 && l->dy < 0)
|
|
|
|
return false;
|
|
|
|
if (abs(y) > abs(l->dy))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (l->dy != 0)
|
|
|
|
*x = l->x + (y * l->dx) / l->dy;
|
|
|
|
else if (y==0)
|
|
|
|
*x = l->x + l->dx;
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-09-07 21:56:35 +02:00
|
|
|
void fe_display_triangle(const fe_triangle * face)
|
2019-09-01 10:13:17 +02:00
|
|
|
{
|
|
|
|
// backface culling
|
|
|
|
if (is_colckwised(face) != face->clockwised)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// incomplete clipping
|
2019-09-01 12:28:31 +02:00
|
|
|
if (face->s1->x < 0 && face->s2->x < 0 && face->s3->x < 0)
|
2019-09-01 10:13:17 +02:00
|
|
|
return;
|
2019-09-07 21:56:35 +02:00
|
|
|
if (face->s1->x >= fe_width && face->s2->x >= fe_width && face->s3->x >= fe_width)
|
2019-09-01 10:13:17 +02:00
|
|
|
return;
|
2019-09-01 12:28:31 +02:00
|
|
|
if (face->s1->y < 0 && face->s2->y < 0 && face->s3->y < 0)
|
2019-09-01 10:13:17 +02:00
|
|
|
return;
|
2019-09-07 21:56:35 +02:00
|
|
|
if (face->s1->y >= fe_height && face->s2->y >= fe_height && face->s3->y >= fe_height)
|
2019-09-01 10:13:17 +02:00
|
|
|
return;
|
2019-09-01 12:28:31 +02:00
|
|
|
if (face->s1->z <= 0 && face->s2->z <= 0 && face->s3->z <= 0)
|
2019-09-01 10:13:17 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
line cotes[3];
|
|
|
|
line_set(&cotes[0], face->s1, face->s2);
|
|
|
|
line_set(&cotes[1], face->s1, face->s3);
|
|
|
|
line_set(&cotes[2], face->s2, face->s3);
|
|
|
|
|
|
|
|
if (cotes[0].no_line || cotes[1].no_line || cotes[2].no_line)
|
|
|
|
return;
|
|
|
|
|
|
|
|
const int32_t ymin = max(min(face->s1->y, min(face->s2->y, face->s3->y)), 0);
|
|
|
|
const int32_t ymax = min(max(face->s1->y, max(face->s2->y, face->s3->y)), 63);
|
|
|
|
|
|
|
|
const int32_t xAB = face->s2->x - face->s1->x, yAB = face->s2->y - face->s1->y, zAB=face->s2->z-face->s1->z;
|
|
|
|
const int32_t xAC = face->s3->x - face->s1->x, yAC = face->s3->y - face->s1->y, zAC=face->s3->z-face->s1->z;
|
|
|
|
const int32_t diviseur_commun = (xAB * yAC - yAB * xAC);
|
|
|
|
|
|
|
|
const int32_t fact_1= (32768 * yAC) / diviseur_commun, fact_2 = (32768 * xAC) / diviseur_commun;
|
|
|
|
const int32_t fact_3= (32768 * xAB) / diviseur_commun, fact_4 = (32768 * yAB) / diviseur_commun;
|
|
|
|
|
|
|
|
for (int32_t y = ymin; y <= ymax; y++)
|
|
|
|
{
|
|
|
|
// xmin and xmax determination
|
|
|
|
int32_t tx1,tx2;
|
|
|
|
|
|
|
|
for (int t=0;t<3;t++)
|
|
|
|
{
|
|
|
|
if (line_get_x(y,&cotes[t],&tx1))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
for (int32_t t=0;t<3;t++)
|
|
|
|
{
|
2019-09-01 12:28:31 +02:00
|
|
|
if (line_get_x(y,&cotes[t],&tx2) && tx1!=tx2)
|
2019-09-01 10:13:17 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
const int32_t txmin=max(min(tx1,tx2),0), txmax=min(max(tx1,tx2),127);
|
|
|
|
|
|
|
|
for (int32_t x=txmin; x<=txmax; x++)
|
|
|
|
{
|
2019-09-01 13:23:26 +02:00
|
|
|
int32_t vx, vy, z;
|
|
|
|
|
|
|
|
const int32_t xcalc = x - face->s1->x, ycalc = y - face->s1->y;
|
2019-09-01 10:13:17 +02:00
|
|
|
// calcul de vx, vy
|
2019-09-01 13:23:26 +02:00
|
|
|
vx = (xcalc*fact_1 - ycalc*fact_2);
|
|
|
|
vy = (ycalc*fact_3 - xcalc*fact_4);
|
|
|
|
z = face->s1->z + (vx * zAB + vy * zAC)/32768;
|
|
|
|
|
|
|
|
|
|
|
|
int32_t vx2= ( vx*face->texture->size_px_x/face->s2->z ) / ((32768-vx)/face->s1->z + vx/face->s2->z);
|
|
|
|
int32_t vy2= ( vy*face->texture->size_px_y/face->s3->z ) / ((32768-vy)/face->s1->z + vy/face->s3->z);
|
2019-09-01 12:28:31 +02:00
|
|
|
/* Perspective correction
|
2019-09-01 10:13:17 +02:00
|
|
|
vx /= (double) face->s2->z / ((1 - vx) / face->s1->z + vx / (double) face->s2->z);
|
|
|
|
vy /= (double) face->s3->z / ((1 - vy) / face->s1->z + vy / (double) face->s3->z);
|
2019-09-01 12:28:31 +02:00
|
|
|
*/
|
2019-09-01 10:13:17 +02:00
|
|
|
// Affichage du point
|
2019-09-12 19:48:53 +02:00
|
|
|
const uint8_t color = fe_texture_get_pixel_r(face->texture, vx2, vy2);
|
2019-09-01 10:13:17 +02:00
|
|
|
|
2019-09-01 12:28:31 +02:00
|
|
|
if (color >> 1)
|
|
|
|
{
|
|
|
|
//dpixel(x,y, C_BLACK);
|
2019-09-07 21:56:35 +02:00
|
|
|
if (fe_zbuffer_set_px(x,y,z))
|
2019-09-01 10:13:17 +02:00
|
|
|
dpixel(x, y, 3 * (color % 2)); // 3* means cast to black and white, and vx,and vy casted between 0 and 7
|
2019-09-01 12:28:31 +02:00
|
|
|
}
|
2019-09-01 10:13:17 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|