Jump to content
  • Advertisement
Sign in to follow this  
Purebe

Drawing a 3-D grid?

This topic is 2471 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hey, I'm trying to really understand the idea of drawing a grid in 3D space, it seems fairly simple but on my own I'm just not getting it too well. I 've been able to only find a single source on the topic at all and it was just to give some code with no explanation. I can pour over this code if I have to in order to understand this concept but since it seems very important I'd like to understand it through and through and I was wondering if anyone knew of any good reviews of the topic?

Thanks! Here's the code if anyone is interested:

public class Grid
{
private GraphicsDevice device;
private GraphicsDeviceManager graphics;
private ContentManager content;
private Matrix worldMatrix, viewMatrix, projectionMatrix;
private BasicEffect basicEffect;
private VertexBuffer vertexBuffer;

public Grid(GraphicsDevice graphicsDevice, GraphicsDeviceManager graphicsDeviceManager, ContentManager contentManager)
{
device = graphicsDevice;
graphics = graphicsDeviceManager;
content = contentManager;
}

public void LoadContent()
{
float aspectRatio = (float)device.Viewport.Width /
(float)device.Viewport.Height;

float fov = MathHelper.PiOver4 * aspectRatio;

worldMatrix = Matrix.Identity;
viewMatrix = Matrix.CreateLookAt(new Vector3(0.0f, 2.0f, 2.0f), Vector3.Zero, Vector3.Up);
projectionMatrix = Matrix.CreatePerspectiveFieldOfView(fov, aspectRatio, 0.1f, 1000.0f);

basicEffect = new BasicEffect(device);
basicEffect.World = worldMatrix;
basicEffect.View = viewMatrix;
basicEffect.Projection = projectionMatrix;
basicEffect.LightingEnabled = false;

CreateGrid(10, 10, 5, 5, Vector3.Zero);
}

public void UnloadContent()
{
if (vertexBuffer != null)
{
vertexBuffer.Dispose();
vertexBuffer = null;
}

if (basicEffect != null)
{
basicEffect.Dispose();
basicEffect = null;
}
}

public void Update(GameTime gameTime)
{
worldMatrix *= Matrix.CreateRotationY(0.005f) * Matrix.CreateRotationX(0.005f);
}

public void Draw()
{
device.SetVertexBuffer(vertexBuffer);

basicEffect.World = worldMatrix;
basicEffect.CurrentTechnique.Passes[0].Apply();
foreach (EffectPass CurrentPass in basicEffect.CurrentTechnique.Passes)
{
device.DrawPrimitives(PrimitiveType.LineList, 0, vertexBuffer.VertexCount / 2);
}
}

// Algorithm/code thanks to: http://8bitmemories.blogspot.com/2010/01/simple-grid-in-xna.html
public void CreateGrid(int width, int height, int rows, int columns, Vector3 position)
{
List<VertexPositionColor> vertices;

vertices = new List<VertexPositionColor>();
int xDiff = width / columns;
int zDiff = height / rows;
float xBase = position.X - width / 2.0f;
float zBase = position.Z - height / 2.0f;
float yBase = position.Y;

for (int i = 0; i <= rows; ++i)
{
vertices.Add(new VertexPositionColor(new Vector3(xBase + i * xDiff, yBase, zBase), Color.White));
vertices.Add(new VertexPositionColor(new Vector3(xBase + i * xDiff, yBase, zBase + height), Color.White));
}

for (int i = 0; i <= columns; ++i)
{
vertices.Add(new VertexPositionColor(new Vector3(xBase, yBase, zBase + i * zDiff), Color.White));
vertices.Add(new VertexPositionColor(new Vector3(xBase + width, yBase, zBase + i * zDiff), Color.White));
}

vertexBuffer = new VertexBuffer(device, typeof(VertexPositionColor), vertices.Count, BufferUsage.WriteOnly);
vertexBuffer.SetData<VertexPositionColor>(vertices.ToArray());
}
}

Share this post


Link to post
Share on other sites
Advertisement
Well, the CreateGrid function allocates a vertex buffer and fills it with list of vertices representing the endpoints of both "column" and "row" lines.

Since the data is drawn using non-indexed line list topology, the device interprets each 2 consecutive vertices in the buffer as one line. The number of primitives (lines) in the buffer, therefore, is the number of vertices divided by 2.

The rest of the code is basic D3D setup.

Share this post


Link to post
Share on other sites
Ah well I understand the code, it's getting my head around the method it's using to create the grid, and I'd like to be able to extend it into the y direction as well, also to be able to do it with different primitivetypes etc.

I was hoping for a more complete reference to getting all of that geometry "down" or something. I'm not sure of the right words to describe what I mean here, sorry.

This particular bit of code is a beginning and I can probably extend onto the rest of what I want to do from it, but, I imagine there has to be a standardized way of doing these sort of things and I think that's what I'm really looking for. Thanks for the explanation though!

Share this post


Link to post
Share on other sites
The method runs two loops, one to establish lines in "columns" direction, and other to establish lines in "rows" direction. The "column" and "row" lines cross each other.

---

There are also triangle and point primitive types available. Whereas a line requires 2 vertices (like in your code), a triangle requires 3 vertices and point requires 1 vertices. When you call the DrawPrimitives method, you specify which type of primitives to draw - the data comes from the currently bound input streams (vertex buffers) in any case.

When you have an actual mesh in which some (most) vertices are shared by several triangles, you want to use "indexing" for performance and to save bus bandwidth. With indexing, you create a separate index buffer that specifies 3 integer indices to vertex data for each triangle (or 2 indices for line); then you use DrawIndexed* methods so that the device uses the index buffer data in the drawing operation. The indices simply specify, "what vertices in the vertex array are used with this primitive".

Indexed data is also easier to optimize manually (cache optimization, primitive ordering) because the draw order and the actual vertex data are separated by indirection offered by the indices.

Share this post


Link to post
Share on other sites
All that said, though: while you generate the geometry in code here, it is much more common to load the geometry data from mesh files. This way, you can use a shared mesh loader for any type of visual game object, and you can use modeling programs to define the geometry much more intuitively than in code.

Share this post


Link to post
Share on other sites
Yeah I just finished designing my own grid generating code (turned out eerily similar to the code I was referencing....wonder why tongue.png) -- but I understand it now. It's a lot simpler than I thought, I get overwhelmed easily sometimes in math sort of subjects.

To me this seems to be a better way of doing grids than loading a mesh grid if you want to use the grids to "place" objects at the right coordinates (as a "reference" grid). My goal is to design a 3D level editor that is rather intuitive to use, as if you were walking around in say Minecraft and building (except with meshes, cameras, lights, etc, rather than blocks)

Then I'm going to use that as a basis for the games I make in XNA with 3D, and as I go along add more and more functionality to the level editor. I feel like doing grids (generated this way) is more accurate than using meshes, but I'm probably wrong on that. Maybe it's just a preference thing?

Next up: generating grids with triangle's rather than rectangles as the "meat"

Share this post


Link to post
Share on other sites
Both pre-modeled and procedurally generated meshes have valid uses.

For coordinate system grids (and generally, any fixed grid system), procedural tends to be the easier and more practical approach. However, external mesh would be just as precise if the content production chain itself (modeling->export->loading) would be precise.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!