#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <stddef.h>
#include <graphics.h>

typedef short BOOL;
typedef int INDEX;
#define TRUE  1
#define FALSE 0
#define PI 3.14159
#define MAX_LINE_LEN 255
#define YAW rotate[0]
#define ROLL rotate[1]
#define PITCH rotate[2]
enum LINESTYLE {LINE_NOSHOW, LINE_BROKEN, LINE_SOLID};

/* object types */
#define MAX_TYPES  4 /* number of types defined */
#define CUBE_OBJ   0
#define SPHERE_OBJ 1
#define CYLIND_OBJ 2
#define CONE_OBJ   3

/* error messages */
#define ERR_MEMORY  1 /* insufficient memory */
#define ERR_OBJTYPE 2 /* invalid solid object type */
#define ERR_DRIVER  3 /* requires ega/vga graphics */

#define ADV_FACET_PTR(n) (struct facet *)((char *) \
    facet_ptr + sizeof(struct facet) + n * \
    sizeof(INDEX))

/* descriptor definitions */
struct obj_defn { /* definition of a solid object */
    int vertex_count;
    struct vertex *vertex_first; /* pointer to first
        vertex descriptor */
    int facet_count;
    struct facet *facet_first; /* ptr to 1st facet */
};
struct solid_obj { /* instance of a solid object */
    int obj_type;
    struct vertex *vertex_first; /* pointer to first
        vertex descriptor */
    int color;
    float scale; /* scaling factor */
    float xlate[3]; /* translation */
    float rotate[3]; /* yaw, roll, pitch (rotation) in
        radians */
    struct solid_obj *obj_next; /* pointer to next
        object */
    BOOL visible[]; /* 1 if facet is visible, 0 if
        hidden */
};
struct facet { /* facet descriptor */
    int vertex_count; /* number of vertices for this
        facet */
    INDEX vertex_index[]; /* indices of vertices for
        this facet */
};
struct vertex { /* vertex descriptors */
    float coord[3]; /* x, y, z coordinates */
};

struct vector {
    float x, y, z; /* x, y, z components */
};

/* function prototypes */
void define_solid(int);
struct solid_obj *make_object(int);
void transform_object(struct solid_obj *);
void make_vertex(float, float, float, int);
void display_facet(struct solid_obj *, struct facet *,
    int, int);
void render_facet(struct solid_obj *, struct facet *);
void draw_polygon(struct solid_obj *, struct facet *);
struct vector normal_vector(struct solid_obj *,
    struct facet *);
void show_scene();
void quit(int, char [], int);

/* global variables */
extern struct obj_defn *defn_ptr[MAX_TYPES];
    /* pointers to object definitions */
extern struct solid_obj *obj_first; /* pointer to first
    object in scene */
extern int sweeps; /* number of sweeps to construct
    sphere; must be even */
extern int facets; /* number of facets per sweep */
extern float proj_z; /* distance between viewer and
    model */
extern float proj_d; /* distance between viewer and
    picture plane */
extern BOOL init_screen; /* indicates whether screen is
    initialized */
extern int maxx, maxy; /* maximum x and y screen
    coordinates */
extern float border; /* fraction of graphics screen to
    use as a border when maximizing image size */
extern float screen_x_min, screen_x_max, screen_y_min,
    screen_y_max; /* minimum and maximum coordinates
    used to maximize image size */
extern int color_bkgd, color_visible, color_hidden;
    /* color selections for background, visible lines,
    hidden lines */
extern enum LINESTYLE disp_hidden; /* how to display
    hidden lines: don't display, broken line, solid
    line */
extern float light_x, light_y, light_z; /* light source
    coordinates */
extern int render_opt; /* rendering option */
