// <ZZ> This file has all the stuff for displaying the screen...  3D card does everything...


#define ZNEAR 0.625f                     // The near frustum plane
#define MIN_CAMERA_DISTANCE 1.0

float initial_camera_matrix[16];        // A matrix to speed up/simplify 3D drawing routines
float rotate_camera_matrix[16];         // A matrix to speed up/simplify 3D drawing routines

unsigned short camera_rotation_xy[2] = {16384,  32768};      // The current camera rotation...
float camera_distance = 300.0f;         // The last distance of the camera from the players
float camera_xyz[3];                    // The camera location
float camera_fore_xyz[3];               // The forward vector of the camera
float camera_side_xyz[3];               // The side vector of the camera
float camera_up_xyz[3];                 // The side up of the camera
float target_xyz[6] = {-250.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};                    // The location of the camera's target point (look at)


// Stuff for doing multitexturing...
unsigned char display_multitexture = FALSE;  // Do we support multitexture?
PFNGLACTIVETEXTUREARBPROC       glActiveTextureARB       = NULL;
PFNGLMULTITEXCOORD2FARBPROC     glMultiTexCoord2fARB     = NULL;
PFNGLCLIENTACTIVETEXTUREARBPROC glClientActiveTextureARB = NULL;


//-----------------------------------------------------------------------------------------------
// <ZZ> Some macros to do simple stuff...
#define display_clear_zbuffer()         { glClear(GL_DEPTH_BUFFER_BIT); }
#define display_clear_buffers()         { glClearColor(0.0, 0.0, 0.0, 1.0);  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); }

#define display_swap()                  { SDL_GL_SwapBuffers(); }
#define display_zbuffer_on()            { glEnable(GL_DEPTH_TEST);  glDepthMask(TRUE);  glDepthFunc(GL_LEQUAL); }
#define display_zbuffer_shadow()        { glEnable(GL_DEPTH_TEST);  glDepthMask(FALSE); glDepthFunc(GL_GEQUAL); }
#define display_zbuffer_off()           { glDisable(GL_DEPTH_TEST); glDepthMask(FALSE); }
#define display_zbuffer_write_on()      { glDepthMask(TRUE); }
#define display_zbuffer_write_off()     { glDepthMask(FALSE); }
#define display_cull_on()               { glEnable(GL_CULL_FACE); glFrontFace(GL_CW); }
#define display_cull_reversed()         { glEnable(GL_CULL_FACE); glFrontFace(GL_CCW); }
#define display_cull_off()              { glDisable(GL_CULL_FACE); }
#define display_shade_on()              { glShadeModel(GL_SMOOTH); }
#define display_shade_off()             { glShadeModel(GL_FLAT); }
#define display_blend_trans()           { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); }
#define display_blend_double()          { glEnable(GL_BLEND); glBlendFunc(GL_DST_COLOR, GL_ONE); }
#define display_blend_light()           { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE); }
#define display_blend_off()             { glDisable(GL_BLEND); }
#define display_depth_scene()           { glDepthRange(0.0f, 1.0f); }
#define display_texture_on()            { glEnable(GL_TEXTURE_2D); }
#define display_texture_off()           { glDisable(GL_TEXTURE_2D); }

#define display_paperdoll_on()          { glEnable(GL_ALPHA_TEST); }
#define display_paperdoll_func(ALPHA)   { glAlphaFunc(GL_GREATER, ALPHA*0.00390625f); }
#define display_paperdoll_off()         { glDisable(GL_ALPHA_TEST); }

#define display_pick_texture(X)         { glBindTexture(GL_TEXTURE_2D, X); }
#define display_multi_zero()            { glActiveTextureARB(GL_TEXTURE0_ARB); }
#define display_multi_one()             { glActiveTextureARB(GL_TEXTURE1_ARB); }
#define display_multi_two()             { glActiveTextureARB(GL_TEXTURE2_ARB); }
#define display_multi_zero_xy(X, Y)     { glMultiTexCoord2fARB(GL_TEXTURE0_ARB, X, Y); }
#define display_multi_one_xy(X, Y)      { glMultiTexCoord2fARB(GL_TEXTURE1_ARB, X, Y); }
#define display_multi_two_xy(X, Y)      { glMultiTexCoord2fARB(GL_TEXTURE2_ARB, X, Y); }

#define display_start_strip()           { glBegin(GL_TRIANGLE_STRIP); }
#define display_start_fan()             { glBegin(GL_TRIANGLE_FAN); }
#define display_start_points()          { glBegin(GL_POINTS); }
#define display_start_line()            { glBegin(GL_LINES); }
#define display_start_line_strip()      { glBegin(GL_LINE_STRIP); }
#define display_start_line_loop()       { glBegin(GL_LINE_LOOP); }
#define display_color(PTR)              { glColor3ubv(PTR); }
#define display_color_alpha(PTR)        { glColor4ubv(PTR); }
#define display_color_float(PTR)        { glColor3fv(PTR); }
#define display_texpos(PTR)             { glTexCoord2fv(PTR); } 
#define display_texpos_xy(X, Y)         { glTexCoord2f(X, Y); }

#define display_vertex(PTR)             { glVertex3fv(PTR); }
#define display_vertex_xy(X, Y)         { glVertex2f(X, Y); }
#define display_vertex_xyz(X, Y, Z)     { glVertex3f(X, Y, Z); }
#define display_point(PTR)              { glVertex2fv(PTR); }
#define display_end()                   { glEnd(); }

//------------------------------------------------------------------------------------
float letter_width[64] = 
{
  0.7f, 0.6f, 0.7f, 0.7f, 0.7f, 0.7f, 0.7f, 0.7f,
  0.7f, 0.65f, 0.9f, 0.7f, 0.8f, 0.8f, 0.7f, 0.7f,
  0.8f, 0.7f, 0.4f, 0.5f, 0.8f, 0.7f, 0.9f, 0.8f,
  0.8f, 0.7f, 0.9f, 0.8f, 0.6f, 0.7f, 0.7f, 0.8f,
  0.9f, 0.8f, 0.7f, 0.8f, 0.6f, 0.6f, 0.6f, 0.6f
};
float display_letter(unsigned char letter, float x, float y, float scale)
{
    float tx, ty;
    int temp;

    temp = 63;
    if(letter >= '0' && letter <= '9')
    {
        temp = letter - '0';
    }
    else if(letter >= 'A' && letter <= 'Z')
    {
        temp = letter - 'A' + 10;
    }
    else if(letter >= 'a' && letter <= 'z')
    {
        temp = letter - 'a' + 10;
    }
    else if(letter == '.')
    {
        temp = 36;
    }
    else if(letter == '_')
    {
        temp = 37;
    }
    else if(letter == '~')
    {
        temp = 38;
    }
    else if(letter == '-')
    {
        temp = 39;
    }
    if(temp <= 39)
    {
        tx = (temp & 7) * 0.125f;
        ty = (temp >> 3) * 0.125f;
        display_start_fan();
            display_texpos_xy(tx+0.000f, ty+0.000f);  display_vertex_xy(x+0.0f, y+0.0f);
            display_texpos_xy(tx+0.125f, ty+0.000f);  display_vertex_xy(x+scale, y+0.0f);
            display_texpos_xy(tx+0.125f, ty+0.125f);  display_vertex_xy(x+scale, y+scale);
            display_texpos_xy(tx+0.000f, ty+0.125f);  display_vertex_xy(x, y+scale);
        display_end();
        x = x+scale*letter_width[temp];
    }
    else
    {
        x = x+scale*0.5f;
    }
    return x;
}

//------------------------------------------------------------------------------------
void display_string(unsigned char* text, float x, float y, float scale, unsigned short max_length)
{
    unsigned short i;
    i = 0;
    display_pick_texture(font_texture);
    while(text[i] != 0 && i < max_length)
    {
        x = display_letter(text[i], x, y, scale);
        i++;
    }    
}

//-----------------------------------------------------------------------------------------------
void display_marker(unsigned char* color, float x, float y, float z, float scale)
{
    display_color(color);
    display_start_line();
        display_vertex_xyz(x-scale, y, z);
        display_vertex_xyz(x+scale, y, z);

        display_vertex_xyz(x, y-scale, z);
        display_vertex_xyz(x, y+scale, z);

        display_vertex_xyz(x, y, z-scale);
        display_vertex_xyz(x, y, z+scale);
    display_end();
}

//-----------------------------------------------------------------------------------------------
void display_solid_marker(unsigned char* color, float x, float y, float z, float scale)
{
    display_color(color);  
    display_start_fan();
        display_vertex_xyz(x, y, z-scale);
        display_vertex_xyz(x, y-scale, z);
        display_vertex_xyz(x+scale, y, z);
        display_vertex_xyz(x, y+scale, z);
        display_vertex_xyz(x-scale, y, z);
        display_vertex_xyz(x, y-scale, z);
    display_end();

    display_start_fan();
        display_vertex_xyz(x, y, z+scale);
        display_vertex_xyz(x, y-scale, z);
        display_vertex_xyz(x-scale, y, z);
        display_vertex_xyz(x, y+scale, z);
        display_vertex_xyz(x+scale, y, z);
        display_vertex_xyz(x, y-scale, z);
    display_end();
}

//-----------------------------------------------------------------------------------------------
unsigned char temp_texture_data[512*512*4];  // Temporary memory for loading textures onto the card
unsigned int display_load_texture_file_rgba(unsigned char* filename)
{
    // <ZZ> This function loads a 4 channel tga/bmp file from disk as a texture, and returns the texture
    //      number that it was loaded as...  May fail, but it'll still return a texture number...
    //      Makes some assumptions about the TGA...
    FILE* read_file;
    unsigned char idsize;
    unsigned char* data;
    unsigned char red;
    unsigned char green;
    unsigned char blue;
    unsigned char alpha;
    unsigned int texture_number;
    unsigned short size_x;
    unsigned short size_y;
    unsigned char bits;
    unsigned int headersize;
    int x;
    int y;
    unsigned int i;
    unsigned char tga;
    unsigned int offset;
    unsigned char compression;



    // Open the file
    log_message("Trying to load texture %s", filename);
    texture_number = 0;
    read_file = fopen(filename, "rb");
    if(read_file)
    {
        log_message("Found file...");

        // Read the first two bytes of the header...
        idsize = fgetc(read_file);
        tga = fgetc(read_file);


        // Is it a bitmap file?
        if(idsize == 'B' && tga == 'M')
        {
            // Yup...
            idsize = 0;
            tga = FALSE;
        }
        else
        {
            tga = TRUE;
        }




        if(tga)
        {
            // Read the header...
            repeat(i, 10)
            {
                fgetc(read_file);
            }
            size_x = fgetc(read_file);
            size_x |= fgetc(read_file)<<8;
            size_y = fgetc(read_file);
            size_y |= fgetc(read_file)<<8;
            bits = fgetc(read_file);
            fgetc(read_file);


            // Burn through the ID field of the header...
            repeat(i, idsize)
            {
                fgetc(read_file);
            }
        }
        else
        {
            // Bitmap...
            repeat(i, 8)
            {
                fgetc(read_file);
            }


            // Read the offset
            offset = fgetc(read_file);
            offset |= fgetc(read_file)<<8;
            offset |= fgetc(read_file)<<16;
            offset |= fgetc(read_file)<<24;


            // Headersize
            headersize = fgetc(read_file);
            headersize |= fgetc(read_file)<<8;
            headersize |= fgetc(read_file)<<16;
            headersize |= fgetc(read_file)<<24;
            if(headersize != 40 && headersize != 108 && headersize != 124)
            {
                log_message("ERROR:  Unrecognized header format in bitmap file");
                return 0;
            }


            // Size X
            size_x = fgetc(read_file);
            size_x |= fgetc(read_file)<<8;
            fgetc(read_file);
            fgetc(read_file);


            // Size Y
            size_y = fgetc(read_file);
            size_y |= fgetc(read_file)<<8;
            fgetc(read_file);
            fgetc(read_file);


            // Skip
            fgetc(read_file);
            fgetc(read_file);


            // Bits per pixel
            bits = (char) fgetc(read_file);
            fgetc(read_file);


            // Compression method
            compression = (char) fgetc(read_file);
            fgetc(read_file);
            if(compression != 0)
            {
                log_message("ERROR:  Compressed bitmap files are not supported");
                return 0;
            }


            // Skip until we reach our offset...
            offset-=32;
            repeat(i, offset)
            {
                fgetc(read_file);
            }
        }


        // Do a filesize check...
        log_message("File is %d by %d, with %d bits per pixel", size_x, size_y, bits);
        if((bits != 24 && bits != 32) || size_x > 512 || size_y > 512)
        {
            // Error...
            log_message("ERROR:  File had trouble...  Bits == %d, X == %d, Y == %d", bits, size_x, size_y);
            log_message("INFO:   Only 24 and 32 bit textures are supported");
            log_message("INFO:   Textures cannot be larger than 512 x 512 pixels");
            return 0;
        }


        // Start writing the data to a temporary location
        data = temp_texture_data;
        repeat(y, size_y)
        {
            repeat(x, size_x)
            {
                blue = (char) fgetc(read_file);
                green = (char) fgetc(read_file);
                red = (char) fgetc(read_file);
                if(bits == 32)
                {
                    alpha = (char) fgetc(read_file);
                }

                *data = red;  data++;
                *data = green;  data++;
                *data = blue;  data++;
                if(bits == 32)
                {
                    *data = alpha;  data++;
                }
            }
        }
        fclose(read_file);
    }


    // Now load the texture onto the graphics card...  We do have a graphics card, right?
    glGenTextures(1, &texture_number);
    glBindTexture(GL_TEXTURE_2D, texture_number);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    if(bits == 24)
    {
        glTexImage2D(GL_TEXTURE_2D, 0, 3, size_x, size_y, 0, GL_RGB, GL_UNSIGNED_BYTE, temp_texture_data);
    }
    else
    {
        glTexImage2D(GL_TEXTURE_2D, 0, 4, size_x, size_y, 0, GL_RGBA, GL_UNSIGNED_BYTE, temp_texture_data);
    }
	return texture_number;
}

//------------------------------------------------------------------------------------
void display_unload_texture(unsigned int texture)
{
    // <ZZ> This function unloads a given texture...
    glDeleteTextures(1, &texture);
}

//-----------------------------------------------------------------------------------------------
unsigned char display_setup()
{
    // <ZZ> This function initializes the display via SDL and GL.
    int rgb_size[3];
    unsigned char color_depth;
    unsigned char z_depth;


    // Let's get started...
    if(SDL_Init(SDL_INIT_VIDEO) < 0)
    {
        log_message("ERROR:  Couldn't turn on SDL...  That's bad");
        return FALSE;
    }
    log_message("Trying to turn on the display");


    // Figure out all of the display settings...
    color_depth = 16;
    z_depth = 16;
    rgb_size[0] = 5;
    rgb_size[1] = 5;
    rgb_size[2] = 5;
    SDL_GL_SetAttribute(SDL_GL_RED_SIZE, rgb_size[0]);
    SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, rgb_size[1]);
    SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, rgb_size[2]);
    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, z_depth);
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, TRUE);


    if(SDL_SetVideoMode(screen_x, screen_y, color_depth, SDL_OPENGL) == NULL)
    {
        log_message("ERROR:  SDL couldn't turn on GL...");
        return FALSE;
    }


    // Set the window manager title bar
    SDL_WM_SetCaption(APPLICATION_NAME, APPLICATION_NAME);


    // Hide the mouse cursor
//    SDL_ShowCursor(0);


    // Clear the buffers
    display_clear_buffers();
    display_swap();


    // Make sure the graphics library doesn't try to do its own lighting...
    glDisable(GL_LIGHTING);


    // Setup our camera's field of view...
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glFrustum(-0.4, 0.4, -0.3, 0.3, ZNEAR, MAX_TERRAIN_DISTANCE);


    // Setup the texture matrix...
    glMatrixMode(GL_TEXTURE);
    glLoadIdentity();


    // Setup our initial camera matrix
    // This fixes rotation so it makes sense...  x,y checkerboard...  z height off ground
    // It also scoots the camera back a tad, so the near clipping plane is where it should be...
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glGetFloatv(GL_MODELVIEW_MATRIX, rotate_camera_matrix);
    glTranslatef(0.0, 0.0, -(ZNEAR+1));
    glRotatef(90.0, 1.0, 0.0, 0.0);
    glRotatef(180.0, 0.0, 1.0, 0.0);
    glScalef(-1.0, 1.0, 1.0);
    glGetFloatv(GL_MODELVIEW_MATRIX, initial_camera_matrix);



    // Remember to quit...
    atexit(SDL_Quit);
    return TRUE;
}

//-----------------------------------------------------------------------------------------------
void display_camera_position()
{
    // <ZZ> This function generates the camera's xyz position, based on its rotation...
    float angle_xy[2];

    angle_xy[X] = camera_rotation_xy[X]*2*PI/65536.0f;
    angle_xy[Y] = camera_rotation_xy[Y]*2*PI/65536.0f;
    camera_xyz[X] = (float) sin(angle_xy[X]);
    camera_xyz[Y] = (float) cos(angle_xy[X]);

    camera_xyz[Z] = (float) cos(angle_xy[Y]);
    camera_xyz[X] *= camera_xyz[Z];
    camera_xyz[Y] *= camera_xyz[Z];
    camera_xyz[Z] = (float) sin(angle_xy[Y]);

    camera_xyz[X] *= camera_distance;
    camera_xyz[Y] *= camera_distance;
    camera_xyz[Z] *= camera_distance;

    camera_xyz[X] += target_xyz[X];
    camera_xyz[Y] += target_xyz[Y];
    camera_xyz[Z] += target_xyz[Z];
}

//-----------------------------------------------------------------------------------------------
void display_arbitrary_camera(float* center_xyz, float* front_xyz, float* up_xyz)
{
    // <ZZ> This function builds the camera matrix from a center point, a forward looking
    //      vector, and an upwards looking vector...
    float distance, x, y, z;
    float side_xyz[3];


    // Front
    glLoadMatrixf(initial_camera_matrix);
    x = -front_xyz[X];
    y = -front_xyz[Y];
    z = -front_xyz[Z];
    distance = (float) sqrt(x*x + y*y + z*z);
    if(distance < 0.0001) { distance = 0.0001f; }
    rotate_camera_matrix[1] = x/distance;
    rotate_camera_matrix[5] = y/distance;
    rotate_camera_matrix[9] = z/distance;


    // Up
    x = up_xyz[X];
    y = up_xyz[Y];
    z = up_xyz[Z];
    distance = (float) sqrt(x*x + y*y + z*z);
    if(distance < 0.0001) { distance = 0.0001f; }
    rotate_camera_matrix[2] = x/distance;
    rotate_camera_matrix[6] = y/distance;
    rotate_camera_matrix[10] = z/distance;



    // Remember where the camera is lookin'
    camera_fore_xyz[X] = -rotate_camera_matrix[1];
    camera_fore_xyz[Y] = -rotate_camera_matrix[5];
    camera_fore_xyz[Z] = -rotate_camera_matrix[9];
    camera_up_xyz[X] = rotate_camera_matrix[2];
    camera_up_xyz[Y] = rotate_camera_matrix[6];
    camera_up_xyz[Z] = rotate_camera_matrix[10];


    // Up
    cross_product(camera_fore_xyz, camera_up_xyz, side_xyz);
    rotate_camera_matrix[0] = -side_xyz[X];
    rotate_camera_matrix[4] = -side_xyz[Y];
    rotate_camera_matrix[8] = -side_xyz[Z];
    glMultMatrixf(rotate_camera_matrix);
    glTranslatef(-center_xyz[X], -center_xyz[Y], -center_xyz[Z]);


    camera_side_xyz[X] = rotate_camera_matrix[0];
    camera_side_xyz[Y] = rotate_camera_matrix[4];
    camera_side_xyz[Z] = rotate_camera_matrix[8];


    camera_xyz[X] = center_xyz[X];
    camera_xyz[Y] = center_xyz[Y];
    camera_xyz[Z] = center_xyz[Z];
}

//------------------------------------------------------------------------------------
void display_look_at(float* lilcam_xyz, float* liltarg_xyz)
{
    float distance, x, y, z;


    // Front
    glLoadMatrixf(initial_camera_matrix);
    x = lilcam_xyz[X]-liltarg_xyz[X];
    y = lilcam_xyz[Y]-liltarg_xyz[Y];
    z = lilcam_xyz[Z]-liltarg_xyz[Z];
    distance = (float) sqrt(x*x + y*y + z*z);
    if(distance < 0.0001) distance = 0.0001f;
    rotate_camera_matrix[1] = x/distance;
    rotate_camera_matrix[5] = y/distance;
    rotate_camera_matrix[9] = z/distance;

    // Side
    x = rotate_camera_matrix[1];
    y = rotate_camera_matrix[5];
    distance = (float) sqrt(x*x + y*y);
    if(distance < 0.0001) {  y = 1.0f;  distance = 1.0f; }
    rotate_camera_matrix[0] = y/distance;
    rotate_camera_matrix[4] = -x/distance;
    rotate_camera_matrix[8] = 0;

    // Up
    rotate_camera_matrix[2] = rotate_camera_matrix[4]*rotate_camera_matrix[9];
    rotate_camera_matrix[6] = -rotate_camera_matrix[0]*rotate_camera_matrix[9];
    rotate_camera_matrix[10] = rotate_camera_matrix[0]*rotate_camera_matrix[5]-rotate_camera_matrix[4]*rotate_camera_matrix[1];
    glMultMatrixf(rotate_camera_matrix);
    glTranslatef(-lilcam_xyz[X], -lilcam_xyz[Y], -lilcam_xyz[Z]);


    // Remember where the camera is lookin'
    camera_fore_xyz[X] = -rotate_camera_matrix[1];
    camera_fore_xyz[Y] = -rotate_camera_matrix[5];
    camera_fore_xyz[Z] = -rotate_camera_matrix[9];
    camera_side_xyz[X] = rotate_camera_matrix[0];
    camera_side_xyz[Y] = rotate_camera_matrix[4];
    camera_side_xyz[Z] = rotate_camera_matrix[8];
    camera_up_xyz[X] = rotate_camera_matrix[2];
    camera_up_xyz[Y] = rotate_camera_matrix[6];
    camera_up_xyz[Z] = rotate_camera_matrix[10];
}

//-----------------------------------------------------------------------------------------------
unsigned char display_setup_multitexture()
{
    // This function sets us up for using the OpenGL multitexture extensions...
    unsigned char* extensions;
    int num_textures;

    log_message("Attempting to setup multitexturing...");
    display_multitexture = FALSE;
	extensions = (unsigned char*) glGetString(GL_EXTENSIONS);
    glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &num_textures);
    log_message("OpenGL says it can handle up to %d textures", num_textures);


	if(strstr(extensions, "GL_ARB_multitexture"))
	{
		glActiveTextureARB = (PFNGLCLIENTACTIVETEXTUREARBPROC)wglGetProcAddress("glActiveTextureARB");
		glMultiTexCoord2fARB = (PFNGLMULTITEXCOORD2FARBPROC)wglGetProcAddress("glMultiTexCoord2fARB");
		if(glActiveTextureARB && glMultiTexCoord2fARB)
		{
            // Looks like multitexturing was setup correctly...
            log_message("Multitexturing enabled");
            display_multitexture = TRUE;
            return TRUE;
		}
        else
        {
            log_message("Had trouble locating the procedures");
            return FALSE;
        }
	}
    log_message("GL_ARB_multitexture was not found ");
    return FALSE;
}

//------------------------------------------------------------------------------------
void display_window_mode()
{
    // <ZZ> This function sets up the camera so we can display a window overlay...
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glScalef(1.0, -1.0, 1.0);
    glTranslatef(-0.8f, -0.6f, -1.25f);
    glScalef(0.004f, 0.004f, 1.0);
}

//-----------------------------------------------------------------------------------------------
void display_sphere(unsigned char* color, float x, float y, float z, float scale, int idiv, int jdiv)
{
    int i, j;
    float iangle, jangle, iangle_add, jangle_add;
    float point_xyz[3];
    float front_xy[2];
    float sine, cosine;
    float temp;


    display_color(color);


    iangle_add = 2.0f * PI / idiv;
    jangle_add = PI / (jdiv-1);
    iangle = 0.0f;
    repeat(i, idiv)
    {
        front_xy[X] = (float) sin(iangle);
        front_xy[Y] = (float) cos(iangle);
        display_start_line_strip();
        jangle = 0.0f;
            repeat(j, jdiv)
            {
                sine = (float) sin(jangle);
                cosine = (float) cos(jangle);
                point_xyz[X] = x + front_xy[X] * sine * scale;
                point_xyz[Y] = y + front_xy[Y] * sine * scale;
                point_xyz[Z] = z - cosine * scale;
                display_vertex(point_xyz);
                jangle+=jangle_add;
            }
        display_end();
        iangle+=iangle_add;
    }




    idiv = (idiv>>1)+2;
    jdiv = (jdiv<<1);
    iangle_add = PI / (idiv-1);
    jangle_add = 2.0f * PI / (jdiv-1);
    iangle = 0.0f;
    iangle = iangle_add;
    idiv-=2;
    repeat(i, idiv)
    {
        temp = ((float) sin(iangle))*scale;
        point_xyz[Z] = z - ((float) cos(iangle)) * scale;

        jangle = 0.0f;
        display_start_line_strip();
            repeat(j, jdiv)
            {
                sine = (float) sin(jangle);
                cosine = (float) cos(jangle);
                point_xyz[X] = x + sine * temp;
                point_xyz[Y] = y + cosine * temp;
                display_vertex(point_xyz);
                jangle+=jangle_add;
            }
        display_end();
        iangle+=iangle_add;
    }
}

//------------------------------------------------------------------------------------
