Jump to content

  • Log In with Google      Sign In   
  • Create Account


Drawing infinite grid


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
12 replies to this topic

#1 zgintasz   Members   -  Reputation: 152

Like
0Likes
Like

Posted 29 March 2013 - 08:16 AM

I'm making a 2D map editor and I'm trying to make an infinite(pseudo of course) grid. And then later I need to check in which grid's square is the certain point(mouse pointer). The grid shouldn't stick on the screen like a GUI, user should see grid like so(like "scrolling"):
How can I do that?
P.S. I'm using winforms and opentk if it makes any sense.


Sponsor:

#2 GeneralQuery   Crossbones+   -  Reputation: 1263

Like
2Likes
Like

Posted 29 March 2013 - 09:38 AM

Translating the grid by the mouse delta when a mouse button is held would be the simplest solution but what specifically are you having trouble with?



#3 zgintasz   Members   -  Reputation: 152

Like
0Likes
Like

Posted 29 March 2013 - 10:52 AM

any example? I move my camera when mouse is pressed, so if I move a grid too, grid will be kinda "stick", like a game's hud. But I want to make it like in this video but infinite.



#4 GeneralQuery   Crossbones+   -  Reputation: 1263

Like
2Likes
Like

Posted 29 March 2013 - 10:58 AM

I'm not following what your problem is. Do you have the grid already? If so, you say you move the camera, what is the problem? Translating the camera or grid will achieve the same thing albeit in opposite directions. Or is the problem with rendering the grid?


Edited by GeneralQuery, 29 March 2013 - 10:58 AM.


#5 zgintasz   Members   -  Reputation: 152

Like
-1Likes
Like

Posted 29 March 2013 - 11:16 AM

It's hard to explain for me... Can you give me a code for infinite grid like in that video?


Edited by zgintasz, 29 March 2013 - 11:16 AM.


#6 Waterlimon   Crossbones+   -  Reputation: 2381

Like
2Likes
Like

Posted 29 March 2013 - 11:35 AM

Are you asking how to do it using the tools you use (winforms/opentk?), or are you asking how to structure and code it (store unlimited amount of tiles, load them, show the correct ones at correct offset...)?


Waterlimon (imagine this is handwritten please)


#7 zgintasz   Members   -  Reputation: 152

Like
0Likes
Like

Posted 29 March 2013 - 11:39 AM

"structure and code it (store unlimited amount of tiles, load them, show the correct ones at correct offset...)"

yes, exactly.


Edited by zgintasz, 29 March 2013 - 12:01 PM.


#8 Waterlimon   Crossbones+   -  Reputation: 2381

Like
1Likes
Like

Posted 29 March 2013 - 12:18 PM

Well, first of all you want to store the tiles in chunks. (lets say 32*32 tiles per chunk)

 

This way you can render the chunks that are visible, and you can create the chunks as you scroll further. Maybe even save chunks to disk if theres a problem with memory and theyre far away...

 

As you want infinite terrain, you cant really use a huge grid of those chunks (if you can without using up too much memory, its probably simpler that way. Depends how you define "infinite"). You want a tree like container to store them (quadtree or some kind of hash map container...) so you can store lets say the chunk at 3,6 and the one at 64,12553 and leave the left empty.

 

Then you need a camera, to represent where on top of the terrain you are looking at. From the position of the camera and the size of the screen, you can find a rectangle. Find the chunks inside the rectangle (convert the corners to chunk-coordinates, like chunk 1,1 or chunk 4,5, then get all the chunks in that rectangle...), then render them with the appropriate offset from the screen center (difference between the chunk position and camera position)

 

For starters, i would make a single chunk, and a camera, and make the chunk render in the right spot as you move the camera.


Waterlimon (imagine this is handwritten please)


#9 zgintasz   Members   -  Reputation: 152

Like
-1Likes
Like

Posted 30 March 2013 - 07:07 AM

I'm trying to make it almost for a week... If somebody already did it, I would be very thankful if that person would share the code.



#10 rip-off   Moderators   -  Reputation: 7706

Like
2Likes
Like

Posted 30 March 2013 - 08:15 AM

What have you tried?



#11 EVIL_ENT   Members   -  Reputation: 212

Like
1Likes
Like

Posted 30 March 2013 - 08:41 AM

You don't have to draw an infinite grid to make it look like one:

 

#include <GL/glfw.h>

int main(){
    int x, y, nx, ny, mx, my, lx, ly;
    int dx = 0;
    int dy = 0;
    int w = 512;
    int h = 512;
    int cell_w = 32;
    int cell_h = 32;

    glfwInit();
    glfwOpenWindow(w, h, 8, 8, 8, 8, 0, 0, GLFW_WINDOW);

    glfwGetMousePos(&lx, &ly);

    while (!glfwGetKey(GLFW_KEY_ESC)){
        glClear(GL_COLOR_BUFFER_BIT);

        /* Make OpenGL cover full window size */
        glfwGetWindowSize(&w, &h);
        glViewport(0, 0, w, h);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho(0, w, h, 0, -1, 1);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();

        /* Handle mouse input */
        glfwGetMousePos(&mx, &my);
        if (glfwGetMouseButton(GLFW_MOUSE_BUTTON_LEFT)){
            /* Offset the grid by the distance the mouse moved */
            dx += mx - lx;
            dy += my - ly;
            /* Use the %-operator to jump back */
            dx %= cell_w;
            dy %= cell_h;

            float r = 10.0f;
            glRectf(mx-r, my-r, mx+r, my+r);
        }
        lx = mx;
        ly = my;

        glTranslatef(dx, dy, 0.0f);

        /* Draw a grid which is a little bigger than the screen */
        nx = w/cell_w + 2;
        ny = h/cell_h + 2;
        glBegin(GL_LINES);
        for (x=0; x<nx; x++){
            glVertex2f(x*cell_w,  -cell_h);
            glVertex2f(x*cell_w, h+cell_h);
        }
        for (y=0; y<ny; y++){
            glVertex2f( -cell_w, y*cell_h);
            glVertex2f(w+cell_w, y*cell_h);
        }
        glEnd();

        glfwSwapBuffers();
    }
    glfwTerminate();
    return 0;
}

This is deprecated OpenGL. With a fragment shader this would be much easier (but much harder to setup).



#12 zgintasz   Members   -  Reputation: 152

Like
0Likes
Like

Posted 31 March 2013 - 03:29 AM

What have you tried?

I knew somebody will ask that question biggrin.png.

After a few hours of thinking I finally almost completed it, there is only one issue left:

http://tinypic.com/player.php?v=6h55wl&s=6

sorry for that terrible quality(I can try to record it again if needed...), but as you can see the grid doesn't follow the screen very well.


I'll be very thankful if someone will help me fixing that problem.

I've just started learning opengl few weeks ago, so I don't know everything very well...

Here is my code(grid class, code is a probably a mess right now, I will tidy it after fixing that problem):

 

    public class grid
    {
        private MainWindow mainWindow;
        
        public float viewWidth;
        public float viewHeight;
        public Point cameraPos;

        public Rectangle glview;
        public int WidthItems { get; set; }
        public int HeightItems { get; set; }
        public Rectangle[] squares;
        private int totalSquares;
        private int squareSize = 75;

        public grid(MainWindow window, int widthitems, int heightitems, int ViewWidth, int ViewHeight)
        {
            mainWindow = window;
            cameraPos = new Point(0, 0);
            viewWidth = ViewWidth;
            viewHeight = ViewHeight;
            WidthItems = (int)(viewHeight / squareSize);
            HeightItems = (int)(viewWidth / squareSize);
            totalSquares = WidthItems * HeightItems;
            squares = new Rectangle[totalSquares];
        }
        public Point CalculateViewCenterPos()
        {
            return mainWindow.convertScreenToWorldCoords((0 + glview.Width) / 2, (0 + glview.Height) / 2);
        }
        float tempOffsetX = 0f, tempOffsetY = 0f;
        float offsetX = 0f, offsetY = 0f;
        public void CameraMoved(float x, float y)
        {
            tempOffsetX += x;
            if (tempOffsetX > squareSize)
            {
                offsetX -= squareSize;
                tempOffsetX = 0;
            }
            else if (tempOffsetX < -squareSize)
            {
                offsetX += squareSize;
                tempOffsetX = 0;
            }
            tempOffsetY += y;
            if (tempOffsetY > squareSize)
            {
                offsetY -= squareSize;
                tempOffsetY = 0;
            }
            else if (tempOffsetY < -squareSize)
            {
                offsetY += squareSize;
                tempOffsetY = 0;
            }
        }
        public void calculateCoords()
        {
            Point topleft = mainWindow.convertScreenToWorldCoords(0, 0);
            mainWindow.testclickX = topleft.X;
            mainWindow.testclickY = topleft.Y;

            int startPosX = topleft.X - squareSize * 2;
            int startPosY = topleft.Y + squareSize;
            int id = 0;
            for (int i = 0; i < WidthItems; i++)
            {
                for (int j = 0; j < HeightItems; j++)
                {
                    squares[id].X = startPosX;
                    squares[id].Y = startPosY;
                    startPosX += squareSize;
                    id++;
                }
                startPosX = topleft.X - squareSize * 2;
                startPosY -= squareSize;
            }
        }
        public void draw()
        {
            for (int i = 0; i < totalSquares; i++)
            {
                GL.Color3(Color.Green);
                GL.PushMatrix();
                GL.Begin(BeginMode.Lines);
                GL.Vertex3(squares[i].X + offsetX, squares[i].Y + offsetY, -2);
                GL.Vertex3(squares[i].X + offsetX, squares[i].Y + squareSize + offsetY, -2);

                GL.Vertex3(squares[i].X + offsetX, squares[i].Y + offsetY, -2);
                GL.Vertex3(squares[i].X + squareSize + offsetX, squares[i].Y + offsetY, -2);

                GL.Vertex3(squares[i].X + squareSize + offsetX, squares[i].Y + squareSize + offsetY, -2);
                GL.Vertex3(squares[i].X + offsetX, squares[i].Y + squareSize + offsetY, -2);

                GL.Vertex3(squares[i].X + squareSize + offsetX, squares[i].Y + squareSize + offsetY, -2);
                GL.Vertex3(squares[i].X + squareSize + offsetX, squares[i].Y + offsetY, -2);
                GL.End();
                GL.PopMatrix();
            }
        }
    }

and MainWindow class:

 

                // ...
                grid maingrid;
                // ...
                maingrid.draw();
                // ...
                glviewRatio = (ClientRectangle.Width / zoom) / (ClientRectangle.Height / zoom) * 5;
                // ...
                maingrid = new grid(this, 50, 50, ClientRectangle.Width * 5 / zoom, ClientRectangle.Height * 5 / zoom);
                maingrid.glview = new Rectangle(glview.Location.X, glview.Location.Y, glview.Size.Width, glview.Size.Height);
                maingrid.calculateCoords();
                // ...
                // (every frame when mouse button is clicked)
                float x = (MousePosition.X - started_mouse_pos.X) * glviewRatio / zoom;
                float y = -(MousePosition.Y - started_mouse_pos.Y) * glviewRatio / zoom;
                maingrid.CameraMoved(x, y);
                started_mouse_pos.X = MousePosition.X;
                started_mouse_pos.Y = MousePosition.Y;

Edited by zgintasz, 31 March 2013 - 08:17 AM.


#13 zgintasz   Members   -  Reputation: 152

Like
0Likes
Like

Posted 01 April 2013 - 10:23 AM

Finally, found the solution myself smile.png. Just changed CameraMoved function:

        public static void CameraMoved(float x, float y)
        {
            tempOffsetX += x;
            tempOffsetY += y;
            while (tempOffsetX >= squareSize)
            {
                offsetX -= squareSize;
                tempOffsetX -= squareSize;
            }
            while (tempOffsetX <= -squareSize)
            {
                offsetX += squareSize;
                tempOffsetX += squareSize;
            }
            while (tempOffsetY >= squareSize)
            {
                offsetY -= squareSize;
                tempOffsetY -= squareSize;
            }
            while (tempOffsetY <= -squareSize)
            {
                offsetY += squareSize;
                tempOffsetY += squareSize;
            }
        }

Edited by zgintasz, 01 April 2013 - 10:30 AM.





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS