// Parameters: grid units
  void reshape(pair<int,int> size) {
    int w = MIN(MAX(size.first, MIN_GRID_X), MAX_GRID_X);
    int h = MIN(MAX(size.second, MIN_GRID_Y), MAX_GRID_Y);
#ifdef DEBUG
    cout << "Resizing grid to " << w << "x" << h << endl;
#endif
    gps_allocate(w, h);
    reshape_gl();
  }
Esempio n. 2
0
void renderer_cool::draw(int vertex_count)
{
    static bool initial_resize = false;
    if (!initial_resize)
    {
        if (enabler->fullscreen)
            resize(size_x, size_y);
        else
            resize((size_x/init->font.small_font_dispx)*init->font.small_font_dispx, (size_y/init->font.small_font_dispy)*init->font.small_font_dispy);
            //resize(gps->dimx*init->font.small_font_dispx, gps->dimy*init->font.small_font_dispy);

        reshape_gl();
        initial_resize = true;
    }

    static df::viewscreen *prevws = NULL;
    df::viewscreen *ws = Gui::getCurViewscreen();
    is_main_scr = df::viewscreen_dwarfmodest::_identity.is_direct_instance(ws) || df::viewscreen_dungeonmodest::_identity.is_direct_instance(ws);
    if (ws != prevws)
    {
        gps->force_full_display_count = 1;
        prevws = ws;
        /*if (is_main_scr)
        {
            for (int x = 1; x < gps->dimx-gmenu_w-1; x++)
            {
                for (int y = 1; y < gps->dimy-1; y++)
                {
                    const int tile1 = x * gps->dimy + y;
                    for (int i = 0; i < 6; i++)
                        *(fg + tile * 4 * i + 3) = 0;
                }
            }
        }*/
    }    

    display_new(is_main_scr);

#ifdef WIN32
    // We can't do this in plugin_init() because OpenGL context isn't initialized by that time
    static bool glew_init = false;
    if (!glew_init)
    {
        GLenum err = glewInit();
        if (err != GLEW_OK)
            *out2 << glewGetErrorString(err);
        glew_init = true;
    }
#endif

    static int old_dimx, old_dimy, old_winx, old_winy;
    if (domapshot)
    {
        if (domapshot == 10)
        {
            old_dimx = gps->dimx;
            old_dimy = gps->dimy;
            old_winx = *df::global::window_x;
            old_winy = *df::global::window_y;

            grid_resize(world->map.x_count + 36, world->map.y_count + 2);
            *df::global::window_x = 0;
            *df::global::window_y = 0;
            gps->force_full_display_count = 1;
        }
        domapshot--;
    }

    GLuint framebuffer, renderbuffer;
    GLenum status;
    if (domapshot == 5)
    {
        // Set the width and height appropriately for your image
        GLuint imageWidth = gps->dimx * dispx,
               imageHeight = gps->dimy * dispy;
        //Set up a FBO with one renderbuffer attachment
        glGenFramebuffers(1, &framebuffer);
        glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
        glGenRenderbuffers(1, &renderbuffer);
        glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
        glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, imageWidth, imageHeight);
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
                                  GL_RENDERBUFFER, renderbuffer);
        glViewport(0, 0, gps->dimx * dispx, gps->dimy * dispy);

        /*glMatrixMode(GL_PROJECTION);
        glLoadIdentity();

        glOrtho(0,gps->dimx,gps->dimy,0,-1,1);*/
    }

    if (is_main_scr)
    {
        bool skip = false;
        if (df::viewscreen_dungeonmodest::_identity.is_direct_instance(ws))
        {
            int m = df::global::ui_advmode->menu;
            bool tmode = advmode_needs_map(m);
            skip = !tmode;
        }

        if (!skip)
        {
            /////
            glViewport(goff_x, goff_y_gl, gdimx * gdispx, gdimy * gdispy);

            glMatrixMode(GL_PROJECTION);
            glLoadIdentity();
            glOrtho(0, gdimx, gdimy, 0, -1, 1);
            //glTranslatef(1,-1,0);

            //glScissor(off_x+(float)size_x/gps->dimx, off_y+(float)size_y/gps->dimy, gsize_x, gsize_y);
            //glEnable(GL_SCISSOR_TEST);
            //glClearColor(1,0,0,1);
            //glClear(GL_COLOR_BUFFER_BIT);

            if (multi_rendered && fogdensity > 0)
            {
                glEnable(GL_FOG);
                glFogfv(GL_FOG_COLOR, fogcolor);
                glFogf(GL_FOG_DENSITY, fogdensity);
                glFogi(GL_FOG_COORD_SRC, GL_FOG_COORD);
                glEnableClientState(GL_FOG_COORD_ARRAY);
                glFogCoordPointer(GL_FLOAT, 0, fogcoord);
            }

            glVertexPointer(2, GL_FLOAT, 0, gvertexes);

            // Render background colors
            glDisable(GL_TEXTURE_2D);
            glDisableClientState(GL_TEXTURE_COORD_ARRAY);
            glDisable(GL_BLEND);
            glColorPointer(4, GL_FLOAT, 0, gbg);
            glDrawArrays(GL_TRIANGLES, 0, gdimx * gdimy * 6);

            // Render foreground
            glEnable(GL_TEXTURE_2D);
            glEnableClientState(GL_TEXTURE_COORD_ARRAY);
            glEnable(GL_BLEND);
            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
            glTexCoordPointer(2, GL_FLOAT, 0, gtex);
            glColorPointer(4, GL_FLOAT, 0, gfg);
            glDrawArrays(GL_TRIANGLES, 0, gdimx * gdimy * 6);

            if (multi_rendered)
            {
                glDisableClientState(GL_FOG_COORD_ARRAY);
                glDisable(GL_FOG);
            }

            // Prepare and render shadows
            if (multi_rendered)
            {
                int elemcnt = 0;
                //TODO: don't do this if view not moved and tiles with shadows not changed
                {
                    gl_texpos *txt = (gl_texpos *) enabler->textures.gl_texpos;
                    int x1 = std::min(gdimx, world->map.x_count-gwindow_x);                
                    int y1 = std::min(gdimy, world->map.y_count-gwindow_y);

                    for (int tile = 0; tile < gdimx * gdimy; tile++)
                    {
                        int xx = tile / gdimy;
                        int yy = tile % gdimy;

                        int d = depth[tile];
                        if (d && d != 0x7f) //TODO: no need for the second check in fort mode
                        {
                            GLfloat *tex = shadowtex + elemcnt * 2;

                            bool top = false, left = false, btm = false, right = false;
                            if (xx > 0 && (depth[((xx - 1)*gdimy + yy)]) < d)
                            {
                                memcpy(shadowvert + elemcnt * 2, gvertexes + tile * 6 * 2, 6 * 2 * sizeof(float));
                                SETTEX(shadow_texpos[0]);
                                elemcnt += 6;
                                left = true;
                            }
                            if (yy < y1 - 1 && (depth[((xx)*gdimy + yy + 1)]) < d)
                            {
                                memcpy(shadowvert + elemcnt * 2, gvertexes + tile * 6 * 2, 6 * 2 * sizeof(float));
                                SETTEX(shadow_texpos[1]);
                                elemcnt += 6;
                                btm = true;
                            }
                            if (yy > 0 && (depth[((xx)*gdimy + yy - 1)]) < d)
                            {
                                memcpy(shadowvert + elemcnt * 2, gvertexes + tile * 6 * 2, 6 * 2 * sizeof(float));
                                SETTEX(shadow_texpos[2]);
                                elemcnt += 6;
                                top = true;
                            }
                            if (xx < x1-1 && (depth[((xx + 1)*gdimy + yy)]) < d)
                            {
                                memcpy(shadowvert + elemcnt * 2, gvertexes + tile * 6 * 2, 6 * 2 * sizeof(float));
                                SETTEX(shadow_texpos[3]);
                                elemcnt += 6;
                                right = true;
                            }

                            if (!right && !btm && xx < x1 - 1 && yy < y1 - 1 && (depth[((xx + 1)*gdimy + yy + 1)]) < d)
                            {
                                memcpy(shadowvert + elemcnt * 2, gvertexes + tile * 6 * 2, 6 * 2 * sizeof(float));
                                SETTEX(shadow_texpos[4]);
                                elemcnt += 6;
                            }
                            if (!left && !btm && xx > 0 && yy < y1 - 1 && (depth[((xx - 1)*gdimy + yy + 1)]) < d)
                            {
                                memcpy(shadowvert + elemcnt * 2, gvertexes + tile * 6 * 2, 6 * 2 * sizeof(float));
                                SETTEX(shadow_texpos[5]);
                                elemcnt += 6;
                            }
                            if (!left && !top && xx > 0 && yy > 0 && (depth[((xx - 1)*gdimy + yy - 1)]) < d)
                            {
                                memcpy(shadowvert + elemcnt * 2, gvertexes + tile * 6 * 2, 6 * 2 * sizeof(float));
                                SETTEX(shadow_texpos[6]);
                                elemcnt += 6;
                            }
                            if (!top && !right && xx < x1 - 1 && yy > 0 && (depth[((xx + 1)*gdimy + yy - 1)]) < d)
                            {
                                memcpy(shadowvert + elemcnt * 2, gvertexes + tile * 6 * 2, 6 * 2 * sizeof(float));
                                SETTEX(shadow_texpos[7]);
                                elemcnt += 6;
                            }
                        }
                    }
                }

                if (elemcnt)
                {
                    glDisableClientState(GL_COLOR_ARRAY);
                    glColor4fv(shadowcolor);
                    glEnable(GL_BLEND);
                    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
                    //glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA);
                    glTexCoordPointer(2, GL_FLOAT, 0, shadowtex);
                    glVertexPointer(2, GL_FLOAT, 0, shadowvert);
                    glDrawArrays(GL_TRIANGLES, 0, elemcnt);
                    glEnableClientState(GL_COLOR_ARRAY);
                }
            }

            glDisable(GL_SCISSOR_TEST);

            glViewport(off_x, off_y, size_x, size_y);
            glMatrixMode(GL_PROJECTION);
            glLoadIdentity();
            glOrtho(0, tdimx, tdimy, 0, -1, 1);            
        }
    }
    {
        glVertexPointer(2, GL_FLOAT, 0, vertexes);

        // Render background colors
        glDisable(GL_TEXTURE_2D);
        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
        glEnable(GL_BLEND);
        glColorPointer(4, GL_FLOAT, 0, bg);
        glDrawArrays(GL_TRIANGLES, 0, tdimx*tdimy*6);

        // Render foreground
        glEnable(GL_TEXTURE_2D);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        glTexCoordPointer(2, GL_FLOAT, 0, tex);
        glColorPointer(4, GL_FLOAT, 0, fg);
        glDrawArrays(GL_TRIANGLES, 0, tdimx*tdimy*6);
    }


    if (domapshot == 1)
    {
        int w = world->map.x_count * dispx;
        int h = world->map.y_count * dispy;

        unsigned char *data = (unsigned char *) malloc(w * h * 3);

        glPixelStorei(GL_PACK_ALIGNMENT, 1);
        glPixelStorei(GL_PACK_ROW_LENGTH, 0);
        glReadPixels(dispx, dispy, w, h, GL_BGR, GL_UNSIGNED_BYTE, data);


#pragma pack(push,1)
        typedef struct _TgaHeader
        {
            unsigned char IDLength;        /* 00h  Size of Image ID field */
            unsigned char ColorMapType;    /* 01h  Color map type */
            unsigned char ImageType;       /* 02h  Image type code */
            unsigned short CMapStart;       /* 03h  Color map origin */
            unsigned short CMapLength;      /* 05h  Color map length */
            unsigned char CMapDepth;       /* 07h  Depth of color map entries */
            unsigned short XOffset;         /* 08h  X origin of image */
            unsigned short YOffset;         /* 0Ah  Y origin of image */
            unsigned short Width;           /* 0Ch  Width of image */
            unsigned short Height;          /* 0Eh  Height of image */
            unsigned char PixelDepth;      /* 10h  Image pixel size */
            unsigned char ImageDescriptor; /* 11h  Image descriptor byte */
        } TGAHEAD;
#pragma pop

        TGAHEAD hdr;
        memset(&hdr, 0, sizeof(hdr));
        hdr.ImageType = 2;
        hdr.Width = w;
        hdr.Height = h;
        hdr.PixelDepth = 24;


        *out2 << w << " " << h << std::endl;
        std::ofstream img("mapshot.tga", std::ofstream::binary);
        img.write((const char *)&hdr, sizeof(hdr));
        /*        for (int j = 0; j<w*h*3; j++)
                {
                    unsigned char c = data[j+0];
                    data[0] = data[j+2];
                    data[j+2] = c;
                }*/
        img.write((const char *)data, w * h * 3);

        glBindFramebuffer(GL_FRAMEBUFFER, 0);
        // Delete the renderbuffer attachment
        glDeleteRenderbuffers(1, &renderbuffer);

        grid_resize(old_dimx, old_dimy);
        *df::global::window_x = old_winx;
        *df::global::window_y = old_winy;
        gps->force_full_display_count = 1;
        domapshot = 0;
    }
}