Hi I am trying to add sets of coordinates to a single line of a List (so x, y as a single list line). I am currently generating the x and y coordinates as I break up an image and display the chunks in a grid. I am hitting a brick wall in being able to add both x and y to the same List line. Here is the code I have so far -
float sf = 1f;
int x = 0;
int y = 0;
int width = tileImage.Width / tileNumber;
int height = tileImage.Height / tileNumber;
int placeXValue = (width / 10);
int placeYValue = (height / 10);
int placeX = placeXValue;
int placeY = placeYValue;
Rectangle tileRect = tileImage.Bounds;
tileRect.Width = width;
tileRect.Height = height;
coordinates = new List<int>();
for (int i = 0; i < tileNumber; i++)
{
for (int j = 0; j < tileNumber; j++)
{
tileRect.X = x;
tileRect.Y = y;
_spriteBatch.Draw(tileImage, new Vector2((x + placeX) * sf, (y + placeY) * sf), tileRect, Color.White, 0, new Vector2(0, 0), sf, SpriteEffects.None, 0);
placeX += placeXValue;
x += width;
coordinates.Add(x,y);
}
x = 0;
y += height;
placeX = placeXValue;
placeY += placeYValue;
}
I found out how to do what I was trying to in the question. The first thing that I did was change my - private List<int> coordinates; - to a tuple list like this - List<Tuple<int, int>> coordinates; - This then allowed me to add my x and y elements to a new list by using the - coordinates.Add(new Tuple<int, int>(x,y)); - tuple functionality. Making this change has allowed me to add my generated coordinate pairs to my list.
Related
I am trying to implement the Cohen-Daubechies-Feauveau-Wavelet 5/3 high pass and low pass.
I am stucking at the moment. My output image is always white because all values become 255 during my calculation. It's really hard to find any examples of this kind of wavelet. Does any one see the bug in my calculation which I am not able to find.
static double[] lowpass = {1/8d, 2/8d, 6/8d, 2/8d, -1/8};
static double[] highpass = {1/2d, 1d, -1/2d };
public static void lowPassFilter(Bitmap img)
{
int index = 0;
double R = 0.0, G = 0.0, B = 0.0;
Bitmap filteredImg = img;
// Iterate over each pixel
for (int x = 0; x < filteredImg.Width; x++)
{
for (int y = 0; y < filteredImg.Height; y++)
{
// Apply filter in x direction
for (int i = 0; i < lowpass.Length; i++)
{
index = Math.Min(Math.Max(x - (lowpass.Length / 2) + i, 0), filteredImg.Width - 1);
R += img.GetPixel(index, y).R * lowpass[i];
G += img.GetPixel(index, y).G * lowpass[i];
B += img.GetPixel(index, y).B * lowpass[i];
}
R = Math.Min(Math.Max(R, 0), 255);
G = Math.Min(Math.Max(G, 0), 255);
B = Math.Min(Math.Max(B, 0), 255);
filteredImg.SetPixel(x, y, Color.FromArgb((int)R, (int)G, (int)B));
}
}
So I'm trying to draw a layered tile based map, as the title says. I have this so far. The tiles i am using are (32, 32). It's currently drawing only 1 type of tile as the whole tile map. When it should be drawing out several different types of tiles to make a map.
for (int layers = 0; layers < map.Layers.Count; layers++) {
for (var i = 0; i < map.Layers[layers].Tiles.Count; i++) {
int gid = map.Layers[layers].Tiles[i].Gid;
if (gid != 0) {
int tileFrame = gid - 1;
int row = tileFrame / (map.Height / tileHeight);
float x = (i % map.Width) * map.TileWidth;
float y = (float)Math.Floor(i / (double)map.Width) * map.TileHeight;
Rectangle tilesetRec = new Rectangle(0, 0, 32, 32);
for (int j = 0; j < tileSets.Count; j++) {
for (int k = 0; k < tileSets[j].Tiles.Count; k++) {
spriteBatch.Draw(tileSets[j].Tiles[k].Image.Texture, new Rectangle((int)x, (int)y, 32, 32), Color.White);
}
}
}
}
}
This is not entirely my code this is someone elses that i have tried to build on apparently it worked for the person for drawing one layer. This is the original code:
for (var i = 0; i < _map.Layers[0].Tiles.Count; i++) {
int gid = _map.Layers[0].Tiles[i].Gid;
// Empty tile, do nothing
if (gid == 0) {
} else {
int tileFrame = gid - 1;
int row = tileFrame / (_tileset.Height / _tileHeight);
float x = (i % _map.Width) * _map.TileWidth;
float y = (float)Math.Floor(i / (double)_map.Width) * _map.TileHeight;
Rectangle tilesetRec = new Rectangle(_tileWidth * tileFrame, _tileHeight * row, 32, 32);
spriteBatch.Draw(_tileset, new Rectangle((int)x, (int)y, 32, 32), tilesetRec, Color.White);
}
}
Your problem is that for each tile position you seem to be drawing all tiles in all tilesets. The variables tileFrame, row and tilesetRec, which were used to render the specific tile in the original code, are not used in your first snippet.
I am creating a game after working through a XNA 4.0 book. It will be 3D, but I am already stuck in creating the terrain...
UPDATE: Everything starting from here is an update...
Terrain Update:
public void Update(Matrix view, Matrix projection)
{
View = view;
Projection = projection;
World = Matrix.CreateTranslation(-Width / 2f, 0, Height / 2f);
}
Terrain Draw:
public void Draw(GraphicsDevice g)
{
effect.CurrentTechnique = effect.Techniques["ColoredNoShading"];
effect.Parameters["xView"].SetValue(View);
effect.Parameters["xProjection"].SetValue(Projection);
effect.Parameters["xWorld"].SetValue(World);
foreach (EffectPass pass in effect.CurrentTechnique.Passes)
{
pass.Apply();
//g.DrawUserIndexedPrimitives(PrimitiveType.TriangleList, vertices, 0, vertices.Length, indices, 0, indices.Length / 3, VertexPositionColorNormal.VertexDeclaration);
g.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, vertices.Length, 0, indices.Length / 3);
}
}
The commented line is working, in the both cases I am able to see the terrain...
The following code is to initialize Vertex and Index Buffer:
private void SetUpVertices(GraphicsDevice g)
{
float currentH;
int currentI;
vertices = new VertexPositionColorNormal[Width * Height];
for (int x = 0; x < Width; x++)
{
for (int y = 0; y < Height; y++)
{
currentH = heightData[x,y];
currentI = x + y * Width;
vertices[currentI].Position = new Vector3(x, currentH , -y);
if (currentH < minH + (maxH - minH) / 3)
vertices[currentI].Color = Color.ForestGreen;
else if (currentH < maxH - (maxH - minH) / 3)
vertices[currentI].Color = Color.LawnGreen;
else
vertices[currentI].Color = Color.White;
}
}
SetUpIndices(g);
}
private void SetUpIndices(GraphicsDevice g)
{
indices = new int[(Width - 1) * (Height - 1) * 6];
int counter = 0;
for (int y = 0; y < Height - 1; y++)
{
for (int x = 0; x < Width - 1; x++)
{
int lowerLeft = x + y * Width;
int lowerRight = (x + 1) + y * Width;
int topLeft = x + (y + 1) * Width;
int topRight = (x + 1) + (y + 1) * Width;
indices[counter++] = topLeft;
indices[counter++] = lowerRight;
indices[counter++] = lowerLeft;
indices[counter++] = topLeft;
indices[counter++] = topRight;
indices[counter++] = lowerRight;
}
}
SetUpNormals(g);
}
private void SetUpNormals(GraphicsDevice g)
{
for (int i = 0; i < vertices.Length; i++)
{
vertices[i].Normal = Vector3.Zero;
}
int[] index = new int[3];
Vector3 s1, s2, n;
for (int i = 0; i < vertices.Length / 3; i++)
{
for (int y = 0; y < 3; y++)
index[y] = indices[i * 3 + y];
s1 = vertices[index[0]].Position - vertices[index[2]].Position;
s2 = vertices[index[0]].Position - vertices[index[1]].Position;
n = Vector3.Cross(s1, s2);
for (int y = 0; y < 3; y++)
{
vertices[index[y]].Normal += n;
vertices[index[y]].Normal.Normalize();
}
}
FillBuffers(g);
}
private void FillBuffers(GraphicsDevice g)
{
VertexBuffer = new VertexBuffer(g, VertexPositionColorNormal.VertexDeclaration, vertices.Length, BufferUsage.WriteOnly);
VertexBuffer.SetData(vertices);
IndexBuffer = new IndexBuffer(g, typeof(int), indices.Length, BufferUsage.WriteOnly);
IndexBuffer.SetData(indices);
g.Indices = IndexBuffer;
g.SetVertexBuffer(VertexBuffer);
}
I don't think, that there is a mistake, because it is working with the other line. Might there be an error with the .fx file I am using. If you think so, I am going to switch to BasicEffects...
(You might notice, that the code is from http://www.riemers.net/eng/Tutorials/XNA/Csharp/series1.php )
Thanks for your help...
Yours,
Florian
(Answer to original revision of the question.)
You're not setting your vertex buffer and index buffer onto the graphics device. These two lines of code (untested) should do what you need:
g.GraphicsDevice.Indices = indexBuffer;
g.GraphicsDevice.SetVertexBuffer(vertexBuffer);
Place them just after you set the parameters on your effect (ef), before the loop.
The vertex buffer provides the vertex declaration that the exception message is asking for.
Edit after question update: In your new version you're setting the vertex and index buffers - but it's in the wrong place. You need to set them onto the graphics device each frame. Your code would only work if nothing changes them after you set them in FillBuffers. But I'm guessing that stuff is being drawn outside your class's Draw method?
If that something else is a SpriteBatch, even it works using vertex buffers and index buffers. So it will reset your settings. (It's worth adding that it also sets render states - in which case you might need to see this article.)
I'm trying to add texture coordinates to each of the vertices so that a grass texture is added to each triangle. The code I have stretches the texture across the entire area which works but doesn't scale up very well. How do I correctly add (0,0), (0,1), (1,1), etc to the vertices?
Currently they're added in the SetUpVertices() method, should they be added in the SetUpIndices() method when the code can distinguish whether it's top left, bottom left, bottom right, etc. Any help would be greatly appreciated. The relevant methods are below and the full Game1.cs code is here http://pastebin.com/REd8QDZA
private void SetUpVertices()
{
vertices = new VertexPositionNormalTexture[terrainWidth * terrainHeight];
for (int x = 0; x < terrainWidth; x++)
{
for (int y = 0; y < terrainHeight; y++)
{
vertices[x + y * terrainWidth].Position = new Vector3(x, -y, heightData[x, y]);
vertices[x + y * terrainWidth].TextureCoordinate.X = x / (terrainWidth - 1.0);
vertices[x + y * terrainWidth].TextureCoordinate.Y = y / (terrainHeight - 1.0);
}
}
}
private void SetUpIndices()
{
indices = new short[(terrainWidth - 1) * (terrainHeight - 1) * 6];
int counter = 0;
for (int y = 0; y < terrainHeight - 1; y++)
{
for (int x = 0; x < terrainWidth - 1; x++)
{
int lowerLeft = x + y * terrainWidth;
int lowerRight = (x + 1) + y * terrainWidth;
int topLeft = x + (y + 1) * terrainWidth;
int topRight = (x + 1) + (y + 1) * terrainWidth;
indices[counter++] = (short)topLeft;
indices[counter++] = (short)lowerRight;
indices[counter++] = (short)lowerLeft;
indices[counter++] = (short)topLeft;
indices[counter++] = (short)topRight;
indices[counter++] = (short)lowerRight;
}
}
}
Just specify
vertices[x + y * terrainWidth].TextureCoordinate.X = x;
vertices[x + y * terrainWidth].TextureCoordinate.Y = y;
By default, texture coordinates greater than 1 will be wrapped and the texture is repeated.
Currently, I have a random terrain generator, which I am sure works properly, however, when I attempt to build a set of VertexPositionColor, it does not render properly. This is what I currently have (overhead view):
My code:
List<VertexPositionColor> w = new List<VertexPositionColor>();
int width = 20;
int height = 20;
float terrainScale = 2.0f;
long seed = (DateTime.Now.Millisecond + DateTime.Now.Second * DateTime.Now.Hour);
ProceduralLayeredMapGenerator plmg = new ProceduralLayeredMapGenerator(seed);
Random rand = new Random((int)seed);
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
Vector3 position = new Vector3();
position.X = x;//(x - width / 2) * terrainScale;
position.Z = y;//(y - height / 2) * terrainScale;
float point = plmg.getPoint(x, y);
Color computedColor = new Color(rand.Next(255), rand.Next(255), rand.Next(255));
position.Y = (point * 2);
w.Add(new VertexPositionColor(position, computedColor));
}
}
colors = w.ToArray();
And then the drawing code:
foreach (EffectPass pass in effect.CurrentTechnique.Passes)
{
pass.Apply();
GraphicsDevice.DrawUserPrimitives(PrimitiveType.TriangleStrip, colors, 0, colors.Length / 3, VertexPositionColor.VertexDeclaration);
}
How can I get it to look something more like this:
If you want to draw a TriangleStrip then you must add the vertices in the order in which they will be used to draw the triangles; right now you're adding vertices top-to-bottom, left-to-right. Also, to render a height map like that you'll need to use multiple TriangleStrips.