    void render(BITMAP *buffer, ZBUFFER *z)
    {
        set_zbuffer(z);
        for (unsigned int c = 0; c < rotated_count; c++)
        {
            V3D_f vtx[4] = {rotated[c].vtx[0], rotated[c].vtx[1], rotated[c].vtx[2], rotated[c].vtx[3]};
/*
            for (int v = 0; v < 4; v++)
            {
                persp_project_f(
                        rotated[c].vtx[v].x, rotated[c].vtx[v].y, rotated[c].vtx[v].z,
                        &vtx[v].x, &vtx[v].y);
            }
*/
            quad3d_f(buffer, POLYTYPE_GCOL, NULL, &vtx[0], &vtx[1], &vtx[2], &vtx[3]);
        }
    }


/*

        if(key[KEY_W])
        {
            position.x++;
        }
        if(key[KEY_S])
        {
            position.x--;
        }
        if(key[KEY_A])
        {
            position.z++;
        }
        if(key[KEY_D])
        {
            position.z--;
        }

        if(key[KEY_Q])
        {
            position.y++;
        }
        if(key[KEY_E])
        {
            position.y--;
        }
*/


inline void move(float pan, float pitch, distance, float *out_x, float *out_y, float *out_z)
{
    float horizontal = distance * cos(pitch * M_PI / 180);
    float vertical = distance * sin(pitch * M_PI / 180);
    *out_x = sin(pan * M_PI / 180) * horizontal;
    *out_y = vertical;
    *out_z = cos(pan * M_PI / 180) * horizontal;
}

/*

    return;

    QUAT q;
    get_rotation_quat(&q, pan / 360 * 256, pitch / 360 * 256, 0);
    apply_quat(&q, x, y, z, out_x, out_y, out_z);

    return;

    float tx = z * sin(pan / 180 * M_PI) + x * cos(pan / 180 * M_PI);
    float ty = y;
    float tZ = z * cos(pan / 180 * M_PI) - x * sin(pan / 180 * M_PI);


    *out_x = tx;
    *out_y = ty;
    *out_z = tx;

    return;

    MATRIX_f m;
//    get_transformation_matrix_f(&m, 1, pitch * 256 / 360, pan * 256 / 360, 0, 0, 0, 0);

    get_transformation_matrix_f(&m, 1, pitch * 256 / 360, pan * 256 / 360, 0, 0, 0, 0);

//    get_transformation_matrix_f(&m, 1, pitch, pan, 0, 0, 0, 0);
    apply_matrix_f(&m, x, y, z, out_x, out_y, out_z);
*/


        for(int c = 0; c < 360; c += 10)
        {
            float a = (float)c / 180 * M_PI;
            float b = (float)(c + 10) / 180 * M_PI;

            float d = ((float)c / 360) * wide;
            float e = ((float)(c + 10) / 360) * wide;

            glColor3ub(255, 64 + sin(a) * 64, 128);

            glTexCoord2f(tex_s / 256, d / 256);
            glVertex3f(r * sin(a), r * cos(a), start);

            glTexCoord2f(tex_e / 256, d / 256);
            glVertex3f(r * sin(a), r * cos(a), end);

            glColor3ub(255, 64 + sin(b) * 64, 128);

            glTexCoord2f(tex_e / 256, e / 256);
            glVertex3f( r * sin(b), r * cos(b), end);

            glTexCoord2f(tex_s / 256, e / 256);
            glVertex3f( r * sin(b), r * cos(b), start);
        }


/*
        int xc = (int)(x / x_scale);
        int zc = (int)(z / z_scale);

        if ((xc < 0) || (xc >= width) || (zc < 0) || (zc >= height))
        {
            return 0;
        }

        return y_scale * data[cell(xc, zc)];
*/

//        textprintf_ex(screen, font, 0, 30, makecol(255, 255, 255), -1, "cell(x, y) = (%d, %d)", (int)pig.position.x / 100, (int)pig.position.z / -100);
//        textprintf_ex(screen, font, 0, 40, makecol(255, 255, 255), -1, "data: %d", 2 * map.data[map.cell((int)pig.position.x / 100, (int)pig.position.z / -100)]);

//        textprintf_ex(screen, font, 0, 50, makecol(255, 255, 255), -1, "data: %d", map.y_scale * map.data[map.cell((int)position.x / -map.x_scale, (int)position.z / map.z_scale)]);
//        textprintf_ex(screen, font, 0, 60, makecol(255, 255, 255), -1, "data: %f", map.height_of_ground(pig.position.x, -pig.position.z));

//        textprintf_ex(screen, font, 0, 30, makecol(255, 255, 255), -1, "PIG(x, y, z) = (%.1f, %.1f, %.1f)", pig.position.x, pig.position.y, pig.position.z);

                if (h2 > position.y)
                {
                    position.x = old_position.x;
                    if (position.y > old_position.y)
                    {
                            position.y = old_position.y;
                    }
                }

//                if (projected_height > old_player_height)
//                {
//                    position.x = old_position.x;
//                }



                /*
                if (key[KEY_R])
                {
                    allegro_message("h1: %f h2: %f\ny: %f oy: %f", h1, h2, (int)position.y, (int)old_position.y);
                }
                */

            if ((position.x - old_position.x) > 0)
                x_projected_height = m->height_of_ground((int)old_position.x + 100, -(int)old_position.z);
            else
                x_projected_height = m->height_of_ground((int)old_position.x - 100, -(int)old_position.z);

            if (x_projected_height > old_player_height)
            {
                position.x = old_position.x;
//                allegro_message("current: %f\nold: %f\nprojected: %f\ny: %f", current_player_height, old_player_height, x_projected_height,
//                                                position.y);
            }
            if (x_projected_height > position.y)
            {
//                allegro_message("current: %f\nold: %f\nprojected: %f\ny: %f", current_player_height, old_player_height, x_projected_height,
//                                                    position.y);
//                position.x = old_position.x;
            }


/*
            // the projected cell height > current cell
            if (x_projected_height > position.y)
            {

                if (parkour_up <= 0)
                    parkour_up = 30;
            }
*/
        }
/*
        else if (velocity.y < 0)
        {
            parkour_up = -1;
        }
        else
        {
            parkour_up = 0;
        }
*/


//        float current_player_height = m->height_of_ground((int)position.x, -(int)position.z);
//        float old_player_height = m->height_of_ground((int)old_position.x, -(int)old_position.z);


        if (parkour_up > 0)
        {
            if (parkour_up_direction == -1)
                pan = -90;
            if (parkour_up_direction == 1)
                pan = 90;
            if (parkour_up_direction == -2)
                pan = 0;
            if (parkour_up_direction == 2)
                pan = 180;
        }
/*
            if (offset_x > 0)
              pan_draw = 90;
            else
              pan_draw = -90;
*/


                    float wall_angle = (offset_x < 0) ? 270 : 90;
                    if (fabs(wall_angle - angle) > 40)
                    {
//                        allegro_message("%f", fabs(wall_angle - angle));
                        if ((wall_angle - angle) > 0)
                            parkour_along_direction = 1;
                        else
                            parkour_along_direction = -1;

                        // setup a flight sideways
                        parkour_flight = 100;
                        if (parkour_along_direction > 0)
                            parkour_flight_pan = 0;
                        else
                            parkour_flight_pan = 180;
                        velocity.y = -1;
                    }
                    else
                    {
                        parkour_up = 30;
                        pitch_draw = -90;
                        parkour_up_direction = 1 * ((offset_x < 0) ? 1 : -1);
                        parkour_position = position;
                        parkour_flight = 0;
                    }
