My goal is to be able to create what is called an Occupancy grid, its similar to a tile/grid game, looks like the attached image. This is for a small robot project I am working on. All being done in C/C++.
So I want to be able to:
- Change the resolution, or size of each grid cell. So for example 1x1cm or a 5x5cm, etc.
- Change the color of each cell based on some criteria. Obstacle == black, free == white, etc. Might add user click on cell and it change color. For example if the robot starts in 0x0 the cell is red, then the next instance it moves to 1x1. Now 0x0 should be white color, and 1x1 should be red.
- Add some form of scrolling or following (probably done through MVP camera).
What OpenGL method/approach should I take? I am currently thinking of:
Having a square shader (two triangle vertices and index buffer) with a color attribute. Then have a vertex array object/buffer with all the indicies and colors, but wondering how to handle changing colors during run time.
Having all the real world center or corner coordinates(0x0, 0x1, ...1x1, etc) for each grid and have the shaders draw the individual squares, if possible.
Use a texture/image of NxN and update the texture pixel colors.
I am just not sure what is the best scalable, or performant approach. What if I want to draw a 10000x10000 grid cell (zoom out far for example), or if the color is changing a lot.
The most dynamic aspect of the grid is the fill color. For example I may have a grid of 100x100. At one instance all cells are white, then as the robot moves I change the color of the corresponding cell. Or if it detects an obstacle in a cell change that cell color.
I came up with something that you should use for your project. It is a zoomable grid that can be resized to whatever dimensions you need. It should be relatively fast, lines are batched and quads are instanced. It has basic interaction with left and right click and the scroll wheel click and scroll, but you should be able to adapt this interface to your needs. The API should be fairly easy to use
createCell
,removeCell
, etc...A few things:
This was fun to make and I hope you can make use of it, if you have any questions let me know!
EDIT: yes the
flatten
section was a bit unstructured. That flatten method was originally just to flatten a 2D models vector down to a 1D vector to be sent to the GPU (the internal_model
data). The ternary operations are determining a 2D slice of this list (think a box section within the main grid), which is how the frustum cull occurs. bottomLeft and topRight is used to calculate the bounding box of the camera frustum which gets intersected with the whole grid to get indexes into an (ordered) vector of models and colors that gets sent to the GPU, its abit hacky but it ensures operations that interact with the grid (add, remove, change color,etc...) are O(1). There was a small bug causing some cells to freeze, and it was caused by resetting the cell to uninitialized in the QuadRenderer'sremove()
method omitted it from being sent to the GPU (a performance saving optimization), and it was causing the memory to be offset incorrectly, and causing the rendering to desynchronize. So it could have been solved two ways, remove the check to send only initialized cells to the GPU (slower) or just set squares to white instead (hackier). So I chose to set removed cells to white, which means they still get rendered (even though they are camouflage with the clear color). You might be able to change so white cells don't get rendered either, but it shouldn't be too much lost performance, considering you keep cells uninitialized to start (don't for god sake initialize them to white! :) )The remove() function can be changed to:
Here is the code: