#include "solid.h"

void render_facet(struct solid_obj *obj_ptr,
    struct facet *facet_ptr)
/*  renders (shades) and displays a facet */
{
    struct vertex *vertex_ptr;
    int x_first, y_first; /* screen coords for 1st
        vertex of facet */
    int vertex_ref_index;
    float screen_x, screen_y; /* screen coords */
    float x_normal, y_normal, z_normal; /* surface
        normal vector */
    float x_total, y_total, x_ave, y_ave;
        /* coords to compute seed point for fill */
    float light_vect_x, light_vect_y, light_vect_z;
        /* unit vector from light source to first
        vertex of facet */
    struct vector normal; /* unit vector normal to
        facet */
    float unit; /* mult. factor to get unit vector */
    float illum_x, illum_y, illum_z; /* illumination */
    int illum;
    char fill_pat[12][8] = {
        {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
            /*   0% */
        {0x0, 0x20, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0},
            /*   3% */
        {0x20, 0x0, 0x2, 0x0, 0x80, 0x0, 0x8, 0x0},
            /*   6% */
        {0x20, 0x2, 0x80, 0x8, 0x20, 0x2, 0x80, 0x8},
            /*  12% */
        {0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44,
            0x11}, /*  25% */
        {0xaa, 0x44, 0xaa, 0x11, 0xaa, 0x44, 0xaa,
            0x11}, /*  37% */
        {0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55,
            0xaa}, /*  50% */
        {0x55, 0xbb, 0x55, 0xec, 0x55, 0xbb, 0x55,
            0xec}, /*  62% */
        {0xbb, 0xec, 0xbb, 0xec, 0xbb, 0xec, 0xbb,
            0xec}, /*  75% */
        {0xdf, 0xfd, 0x7f, 0xf7, 0xdf, 0xfd, 0x7f,
            0xf7}, /*  87% */
        {0xff, 0xdf, 0xff, 0xff, 0xff, 0xed, 0xff,
            0xff}, /*  93% */
        {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
            0xff}}; /* 100% */
    unsigned line_pat[12] = {0x0000, 0x0000, 0x0100,
        0x1010, 0x4444, 0x8a8a, 0xaaaa, 0xdada, 0xdddd,
        0xdfdf, 0xefef, 0xffff};

    setcolor(WHITE); /* draw white border */
    setlinestyle(SOLID_LINE, NULL, NORM_WIDTH);
    draw_polygon(obj_ptr, facet_ptr);

    /* seed point for fill */
    x_total = y_total = 0.0;
    for (vertex_ref_index = 0; vertex_ref_index <
        facet_ptr->vertex_count; ++vertex_ref_index) {
        vertex_ptr = obj_ptr->vertex_first +
            facet_ptr->vertex_index[vertex_ref_index];
        x_total += proj_d * vertex_ptr->coord[0] /
            proj_z;
        y_total += proj_d * vertex_ptr->coord[1] /
            proj_z;
    }
    x_ave = x_total / facet_ptr->vertex_count;
    y_ave = y_total / facet_ptr->vertex_count;

    /* unit vector from 1st vertex to light source */
    light_vect_x = light_x;
    light_vect_y = light_y;
    light_vect_z = light_z;
    unit = 1.0 / sqrt(light_vect_x * light_vect_x +
        light_vect_y * light_vect_y + light_vect_z *
        light_vect_z);
    light_vect_x *= unit;
    light_vect_y *= unit;
    light_vect_z *= unit;

    /* unit vector normal to facet */
    normal = normal_vector(obj_ptr, facet_ptr);
    unit = 1.0 / sqrt(normal.x * normal.x + normal.y *
        normal.y + normal.z * normal.z);
    normal.x *= unit;
    normal.y *= unit;
    normal.z *= unit;

    /* illumination and shading */
    illum_x = light_vect_x * normal.x;
    illum_y = light_vect_y * normal.y;
    illum_z = light_vect_z * normal.z;
    illum = 1 + (int)((((illum_x < 0.0) ? 0.0 :
        illum_x) + ((illum_y < 0.0) ? 0.0 : illum_y) +
        ((illum_z < 0.0) ? 0.0 : illum_z)) * 11.0 -
        0.5);
    setfillpattern(&fill_pat[illum][0],
        obj_ptr->color); /* fill polygon */
    floodfill((int)(((x_ave - screen_x_min) /
        (screen_x_max - screen_x_min)) * maxx),
        (int)(((y_ave - screen_y_min) /
        (screen_y_max - screen_y_min)) * maxy), WHITE);
    setcolor(color_bkgd); /* redraw border in
        background color */
    draw_polygon(obj_ptr, facet_ptr);
    setcolor(obj_ptr->color); /* overlay border with
        pattern */
    setlinestyle(USERBIT_LINE, line_pat[illum],
        NORM_WIDTH);
    draw_polygon(obj_ptr, facet_ptr);
    return;
}
