OpenGL/SharpGL Faces Misbehaving - c#

I am currently writing an OpenGL application using the SharpGL library and I am trying to simply create a 3x3x3 set of cubes arranged in a symmetric grid.
I am currently seeing some strange behaviour exhibited in the following picture:
This has me completely stumped as I can see no reason why the code is missing out the last 3 blocks. The method in charge of creating the cube looks like this:
private void CreateCube2(OpenGL gl, int cubeSize)
{
gl.PushMatrix();
const float spacing = 2.5f;
for (int z = 0; z < cubeSize; z++)
{
for (int y = 0; y < cubeSize; y++)
{
for (int x = 0; x < cubeSize; x++)
{
var cube = new Cube();
ColourCube(cube, cubeSize, x, y, z);
cube.Render(gl, RenderMode.Render);
gl.Translate(spacing, 0, 0);
}
gl.Translate(-spacing * cubeSize, spacing, 0);
}
gl.Translate(0, -spacing * cubeSize, spacing);
}
gl.PopMatrix();
}
where the definition of ColourCube is as follows:
private bool m_blackCubeMiddle = true;
private void ColourCube(Cube cube, int size, int x, int y, int z)
{
cube.Faces[0].Material = (!m_blackCubeMiddle || y == 0) ? WhiteMaterial : BlackMaterial; // Bottom
cube.Faces[1].Material = (!m_blackCubeMiddle || y == size - 1) ? YellowMaterial : BlackMaterial; // Top
cube.Faces[2].Material = (!m_blackCubeMiddle || x == size - 1) ? GreenMaterial : BlackMaterial; // Right
cube.Faces[3].Material = (!m_blackCubeMiddle || x == 0) ? BlueMaterial : BlackMaterial; // Left
cube.Faces[4].Material = (!m_blackCubeMiddle || z == 0) ? OrangeMaterial : BlackMaterial; // Front
cube.Faces[5].Material = (!m_blackCubeMiddle || z == size - 1) ? RedMaterial : BlackMaterial; // Back
}
The entire project can be downloaded from here.

The strange behaviour is caused by a bug in SharpGL 'Polygon.Render' method. It is not caused by your own code. When you call Triangulate on the cube, it already shows 27 cubes on screen in the correct positions. But even then, SharpGL incorrectly renders one of the cubes.
Having looked at the source code for ShapGL's Cube & Polygon classes I'ld suggest to write your own cube class. The implementation of the Cube class, that you are using now, is absolutely horible from several standpoints (GL_POLYGON (deprecated), immediate mode vertex submission (deprecated))

Related

How can I make a hole at a specific place using script (unity)

I am working on making a hole in the terrain in real-time with a mouse click. I found this script which allows the user to raise terrain at a circle shape with a mouse click and I tried to add the code to generate a hole to it like so :
void PaintCircle(Vector3 point )
{
int x ;
int z;
int heightX;
int heightZ;
float heightY;
Vector2 calc ;
var b = new bool[heightmapWidth-1, heightmapHeight-1];
for (z = -circleRadius; z <= circleRadius; z++)
{
for (x = -circleRadius; x <= circleRadius; x++)
{
// for a circle, calcualate a relative Vector2
calc = new Vector2(x, z);
// check if the magnitude is within the circle radius
if (calc.magnitude <= circleRadius)
{
// is within circle, paint height
heightX = (int)(point.x + x);
heightZ = (int)(point.z + z);
// check if heightX and Z is within the heightmapData array size
if (heightX >= 0 && heightX < heightmapWidth && heightZ >= 0 && heightZ < heightmapHeight)
{
// read current height
heightY = heightmapData[heightZ, heightX]; // note that in heightmapData, X and Z are reversed
// add paintWeight to the current height
heightY -= paintWeight;
// reach the bottom terrain.terrainData.GetHeight((int)heightmapPos.x, (int)heightmapPos.z)
// update heightmapData array
heightmapData[heightZ, heightX] = heightY;
b[heightZ, heightX] = (heightX < 20 && heightX > 80 && heightZ < 20 && heightZ > 80);
}
}
}
}
terrain.terrainData.SetHoles(0, 0, b);
// apply new heights to terrainData
terrainData.SetHeights(0, 0, heightmapData);
}
I added the raise terrain and the hole together because I need them to work together. Unfortunately, this did not work all of the terrains disappeared so I tried to invert the area where the hole should be like this :
b[heightZ, heightX] = !(heightX < 20 && heightX > 80 && heightZ < 20 && heightZ > 80);
but it gave me what I want in reverse, the area where the hole should remain and all the other terrain disappeared so I thought that the problem could be in this line
var b = new bool[heightmapWidth-1, heightmapHeight-1];
so I changed it to this :
bool[,] b = terrainData.GetHoles(0, 0, heightmapWidth, heightmapHeight);
but it gave me this error :
ArgumentException: Trying to access out-of-bounds terrain holes information.
UnityEngine.TerrainData.GetHoles (System.Int32 xBase, System.Int32 yBase, System.Int32 width, System.Int32 height)
I am out of ideas so I am hoping if someone can tell me what is the problem and how can I fix it
the solution was this :
bool[,] b = terrainData.GetHoles(0, 0, heightmapWidth-1, heightmapHeight-1);

Problem with duty cycle (rectangular wave) with drawline C#

I need to draw a rectangular wave using drawline, depending on the duty cycle, the frequency, and the amplitude (using trackbars). Everything is working fine, except for the duty cycle.
Here is the formula for my wave, which is basically a square wave :
double y = Math.Sign(Math.Sin(x / 180 * Math.PI)) * amplitude.Value;
I'm using a pictureBox in order to draw it (every integers are only here for a better display on the pictureBox):
private void P_ZoneDeTrace_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
Pen myPen = new Pen(Color.Green);
double x1 = 10;
double y1 = 0;
for (double x = 1; x < pictureBox1.Width*10; x++)
{
double y = Math.Sign(Math.Sin(x / 180 * Math.PI)) * amplitude.Value;
g.DrawLine(myPen, (float)x1, (float)y1 + 120, (float)(x / fréquence.Value) + 10, (float)y + 120);
x1 = x / fréquence.Value + 10;
y1 = y;
}}
I have now a regular square wave. Now I need to transform it into a rectangular wave, using the duty cyle, which is a trackbar, going from 0 to 10. If it's equal to 0, the wave is always at -1, and if it's equal to 10, the wave is always at 1.
In my else I tried to manage the wave when the duty cycle is between 1 and 9 :
close to 1, every pattern has to stay longer at -1
close to 9, every pattern has to stay longer at 1
Here is the code, right under the y formula, to do that :
int i = 0;
int val = 0;
if (rapport.Value == 0)
{
if (y < 0)
{
y = y * -1;
}
}
if (rapport.Value == 10)
{
if (y > 0)
{
y = y * -1;
}
}
else
{
if (y>0 && i < rapport.Value *18 && val==0)
{
y = y * -1;
i++;
}
if (y > 0 && i == (rapport.Value * 18))
{
val = 1;
}
if (y < 0 && val == 1)
{
i = 0;
val = 0;
}
}
I multiply "y" by -1 to go from -1 to 1 and conversely. "rapport" is the duty cycle, and it's multiplied by 18 in order to be proportional with my wave.
"val" help me to modify other patterns than the first one (if I don't use "val", only the first one is modified)
The problem is that only the first pattern is working well, as described before. For other patterns, the wave is staying to long at 1 when duty cycle is close to 1 (and conversely if it's close to 9).
Here is the full signal :
The first pattern, which is right :
Other patterns, wrong, and that should be the same as the first one :
Every patterns should be the same as the first one, and as you can see, it's not working. They are moving using the trackbar, but not enough, the most beeing as the picture above).
If you could help me to resolve this problem, every pattenrs having to behave as the 1st one ? thanks in advance.

Flood fill missing a tile or two

edit: It works now, I moved the getting X and Y into a seperate function, and it seemed to have fixed it (I'm not sure exactly what was wrong, sorry)
I've been making a Tile Editor using WPF and C#, and I seem to have come across a rather odd problem.
When I first run the fill algorithm on a blank canvas, it fills up all tiles except one (usually around (2,7)). Depending on where I start, it jumps around slightly in that area.
What really confuses me is if I flood fill that same area, it will fix the missing tile.
I tried the recursive flood fill as well as the one using a Queue. Here's the code for the Recursion one:
private void FloodFill(Tile node, int targetID, int replaceID) {
if (targetID == replaceID) return;
if (node.TileID != targetID) return;
node.TileID = replaceID;
SetImageAtCoord(node.X, node.Y);
if (node.Y + 1 != Map.Height) FloodFill(Map.TileInformation[node.X, node.Y + 1], targetID, replaceID);
if (node.Y - 1 != -1) FloodFill(Map.TileInformation[node.X, node.Y - 1], targetID, replaceID);
if (node.X - 1 != -1) FloodFill(Map.TileInformation[node.X - 1, node.Y], targetID, replaceID);
if (node.X + 1 != Map.Width) FloodFill(Map.TileInformation[node.X + 1, node.Y], targetID, replaceID);
}
Now since I also tried a different method and got the same problem, I thought it might be in the SetImageAtCoord():
private void SetImageAtCoord(int x, int y) {
IEnumerable<Rectangle> rectangles = MapViewer.Children.OfType<Rectangle>();
Map.TileInformation[x, y].TileID = CurrentTile;
foreach (Rectangle rect in rectangles) {
int X = (int)Canvas.GetLeft(rect) / 32;
int Y = (int)Canvas.GetTop(rect) / 32;
if (X == x && Y == y) {
rect.Fill = CurrentImage;
}
}
}
My only guess is that it either misses it on the pass (yet somehow make it every other time), or it has something to do with the placement of the rectangle on the Canvas.
edit:
Here is the code for selecting what CurrentImage (and CurrentTile are):
private void Sprite_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) {
Rectangle curr = (Rectangle)e.OriginalSource;
CurrentImage = (ImageBrush)curr.Fill;
int x = (int)Canvas.GetLeft(curr) / 32;
int y = (int)Canvas.GetTop(curr) / 32;
CurrentTile = y * Map.SpriteSheet.GetLength(0) + x;
}
and the code that calls FloodFill
if (CurrentContol == MapEditControl.Fill) {
Rectangle ClickedRectangle = (Rectangle)e.OriginalSource;
ClickedRectangle.Fill = CurrentImage;
int x = (int)Canvas.GetLeft(ClickedRectangle) / 32;
int y = (int)Canvas.GetTop(ClickedRectangle) / 32;
int oldTile = Map.TileInformation[x, y].TileID;
FloodFill(Map.TileInformation[x, y], oldTile, CurrentTile);
}
Map.TileInformation is actually only really used to store the ID for exporting to JSON, and the actual rectangles aren't bound to that in anyway (probably should have)

Tilemap Index out of bounds collision

I created my tile map and my player with movement.
I'm now trying to create the collision and I feel i'm on the right track.
Here is how I've created the map.
List<Texture2D> tileTextures = new List<Texture2D>();
int tileWidth = 60;
int tileHeight = 60;
public int[,] Map = new int[,]
{
{2,2,2,2,2,2,2,2,2,2},
{2,2,2,2,1,2,2,2,2,2},
{2,2,2,2,2,2,2,2,2,2},
{2,2,2,2,2,2,2,2,2,2},
};
public void Draw(SpriteBatch spriteBatch)
{
int tileMapWidth = Map.GetLength(1);
int tileMapHeight = Map.GetLength(0);
for (int x = 0; x < tileMapWidth; x++)
{
for (int y = 0; y < tileMapHeight; y++)
{
int textureIndex = Map[y, x];
Texture2D texture = tileTextures[textureIndex];
spriteBatch.Draw(
texture,
source = new Rectangle(x *myTile.Width,
y * myTile.Height,
tileWidth,
tileHeight),
Color.White);
}
}
}
I am checking the 2d array coords with this condition and checking to see if a specific tile is there, where I can then set my previous location if it is true.
I'm currently testing on 1 tile atm.
public void Update(GameTime gameTime)
{
prevPosition = position;
input(gameTime);
if(tiles.Map[(int)playerPosition.X/60,(int)playerPosition.Y/60] == 1)
{
position = prevPosition;
}
}
However my player position keeps going out of the index bounds of the 2D array and I believe I need to scale it down so that it stops this, I've tried dividing the play coords by the width of the tiles but that hasn't worked.
If anyone can help me with the correct scaling I would be very appreciative.
This will happen if your player's position is like -x,y or x,-y or maybe -x,-y. Yor approach might be better if you'd make a fuction like this one
public bool CollidesWithWall(int x, int y)
{
if(x < 0 || x > *matrix width* - 1) return false;
if(y < 0 || y > *matrix height* -1) return false;
if (Map[x,y] == 1) return true;
return false;
}
and use it insead of the line tiles.Map[(int)playerPosition.X/60,(int)playerPosition.Y/60]
Or, if you need the type of tile returned
public int CollidesWithWall(int x, int y)
{
if(x < 0 || x > *matrix width* - 1) return -1;
if(y < 0 || y > *matrix height* -1) return -1;
return Map[x,y];
}
By doing it this way, you'll know if you stumbled upon a health potion (just set it's ID to like 3) or a wall (with ID of 1 or something, that's tottaly up to you) and if it is 0, it's empty space (or maybe -1). Notice that the "-1" part is totaly up to you. Just write down a list of id's that youll have and which items they present.
Other suggestions
Try if(tiles.Map[(int)(playerPosition.X/60f),(int)(playerPosition.Y/60f)] == 1)

XNA - 2D collision failure without any obvious pattern

Alright, so I am pretty new to XNA programming and I am trying to code a platformer. I have implemented pixel-perfect collision but it seems to fail for no apparent reason sometimes (I couldn't figure out a pattern) and the hero sprite goes through platforms.
static bool IntersectsPixel(Rectangle rect1, Color[] data1, Rectangle rect2, Color[] data2)
{
int top = Math.Max (rect1.Top, rect2.Top);
int bottom = Math.Min(rect1.Bottom, rect2.Bottom);
int left = Math.Max (rect1.Left,rect2.Left);
int right = Math.Min(rect1.Right,rect2.Right);
//Top
for(int y = top; y<bottom;y++)
for (int x = left; x < right; x++)
{
Color color1 = data1[x-rect1.Left + (y-rect1.Top) * rect1.Width];
Color color2 = data2[x - rect2.Left + (y - rect2.Top) * rect2.Width];
if (color1.A != 0 && color2.A != 0)
return true;
}
return false;
}
And here's the Update Method
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
foreach(Platform platform in platformList)
{
Rectangle check = new Rectangle(hero.GetRectangle().X - 300, hero.GetRectangle().Y - 300, 600, 600);
if(check.Intersects(platform.rectangle))
if (IntersectsPixel(hero.GetRectangle(), hero.textureData, platform.rectangle, platform.platformTextureData))
{
int direction = CheckDirection(platform,hero);
if (hero.hasJumped == true && direction == 3 && hero.velocity.Y <= 0 )
{
hero.velocity.Y = 0f;
hero.SetPosition(new Vector2((float)hero.GetPosition().X, (float)platform.rectangle.Bottom));
break;
}
else
if (direction == 4 && hero.velocity.X >= 0)
{
hero.velocity.X = 1;
hero.SetPosition(new Vector2((float)platform.rectangle.Left - (float)hero.GetRectangle().Width, (float)hero.GetPosition().Y));
break;
}
else
if (direction == 2 && hero.velocity.X <= 0)
{
hero.velocity.X = -1;
hero.SetPosition(new Vector2((float)platform.rectangle.Right - 1, (float)hero.GetPosition().Y));
break;
}
else
if (direction == 1 && hero.velocity.Y >= 0)
{
hero.velocity.Y = 0;
hero.hasJumped = false;
hero.SetPosition(new Vector2((float)hero.GetRectangle().X, (float)platform.rectangle.Y - (float)hero.GetRectangle().Height + 1));
hero.SetRectangle(new Rectangle((int)hero.GetPosition().X, (int)hero.GetPosition().Y, (int)hero.GetSize().X, (int)hero.GetSize().Y));
break;
}
}
}
hero.Update(gameTime);
camera.Update(gameTime, hero, screenBounds);
base.Update(gameTime);
}
And here's the direction check:
private int CheckDirection(Platform platform,Hero hero)
{
int distance = Math.Abs(platform.rectangle.Top - hero.GetRectangle().Bottom);
int direction = 1; //Top
if (distance > Math.Abs(platform.rectangle.Right - hero.GetRectangle().Left))
{
distance = Math.Abs(platform.rectangle.Right - hero.GetRectangle().Left);
direction = 2;
}
if (distance > Math.Abs(platform.rectangle.Bottom - hero.GetRectangle().Top))
{
distance = Math.Abs(platform.rectangle.Bottom - hero.GetRectangle().Top);
direction = 3;
}
if (distance > Math.Abs(platform.rectangle.Left - hero.GetRectangle().Right))
{
direction = 4;
distance = Math.Abs(platform.rectangle.Left - hero.GetRectangle().Right);
}
return direction;
}
Those are all my functions related to collision detection. If you happen to have any ideea of what might cause this, please let me know.
Thank you very much !
One thing I see that might be a possible reason is that right in the beginning where you build a box around both objects:
int top = Math.Max (rect1.Top, rect2.Top);
int bottom = Math.Min(rect1.Bottom, rect2.Bottom);
int left = Math.Max (rect1.Left,rect2.Left);
int right = Math.Min(rect1.Right,rect2.Right);
Unless you flipped it, typically XNA's Y grows positive as you go down (not up). This means you would actually want to take the Max of Bottom, and the Min of Top, since Top will always be less than Bottom. It looks like you already knew that though by the look of this line:
for(int y = top; y<bottom;y++)
I'll keep looking (it's difficult to test without the actual project). Another recommendation I'd give you is to do some debug drawing. Draw where the intersection functions thinks that pixels are touching or not touching.
Because of lag, Your character could be moving more than the blocks height per frame, so the collision may think it is in between blocks, and cause it to fly through.
https://gamedev.stackexchange.com/questions/30458/platformer-starter-kit-collision-issues
Check that out, It solved the problem for me.
Either slowing down movement, or clamping the change in position to the size of a block should solve this.

Categories