How can I draw a horizontal box at the bottom of my viewport in OpenGL? This is drawing it at the top. What's wrong?
var H = window height;
var len = 20;
gl.Vertex3d(0, H - len, 0); //top left
gl.Vertex3d(Width, H - len, 0); //top right
gl.Vertex3d(Width, H + len, 0); //bottom left
gl.Vertex3d(0, H + len, 0); //bottom right
OpenGL's default coordinate space has Y pointing upward. You can change that, or you can change your vertices, depending on what you're going to do and what you're used to. In the case you've posted, where it's just a single quad, you can probably just change the vertices and do something like this:
gl.Vertex3d(0, len, 0); //top left
gl.Vertex3d(Width, len, 0); //top right
gl.Vertex3d(Width, -len, 0); //bottom left
gl.Vertex3d(0, -len, 0); //bottom right
If you're drawing a lot of other stuff, you can set the current transform matrix as you need to before drawing (and possibly restore it afterwards), by doing something along the lines of:
gl.matrixMode(GL_PROJECTION);
gl.ortho(left, right, top, bottom, near, far); // Note reversal of top and bottom
Related
I'm drawing coordinate axes in picturebox
void draw_cor()
{
int w = pictureBox1.ClientSize.Width / 2;
int h = pictureBox1.ClientSize.Height / 2;
Refresh();
Graphics e = pictureBox1.CreateGraphics();
e.TranslateTransform(w, h);
DrawXAxis(new Point(-w, 0), new Point(w, 0), e);
DrawYAxis(new Point(0, h), new Point(0, -h), e);
DrawZAxis(new Point(-pictureBox1.ClientSize.Width , pictureBox1.ClientSize.Height), new Point(pictureBox1.ClientSize.Width, -pictureBox1.ClientSize.Height ), e);
}
markup and text for the x axis as an example
private void DrawXAxis(Point start, Point end, Graphics g)
{
for (int i = Step; i < end.X; i += Step)
{
g.DrawLine(Pens.Black, i, -5, i, 5);
DrawText(new Point(i, 5), (i / Step).ToString(), g, false);
}
for (int i = -Step; i > start.X; i -= Step)
{
g.DrawLine(Pens.Black, i, -5, i, 5);
DrawText(new Point(i, 5), (i / Step).ToString(), g, false);
}
g.DrawLine(Pens.Black, start, end);
g.DrawString("X", new Font(Font.FontFamily, 10, FontStyle.Bold), Brushes.Black, new Point(end.X - 15, end.Y));
}
private void DrawText(Point point, string text, Graphics g, bool isYAxis)
{
var f = new Font(Font.FontFamily, 6);
var size = g.MeasureString(text, f);
var pt = isYAxis
? new PointF(point.X + 1, point.Y - size.Height / 2)
: new PointF(point.X - size.Width / 2, point.Y + 1);
var rect = new RectangleF(pt, size);
g.DrawString(text, f, Brushes.Black, rect);
}
can someone explain how to make a method for marking the z axis?
I understand that the shift should be diagonal in both x and y, but nothing worked out for me and no markup appears on the screen.(so far I have managed to draw only a straight line diagonally )
upd:
private void DrawZAxis(Point start, Point end, Graphics g)
{
for (int i = -Step, j=Step ; i > start.X; i -= Step,j += Step)
{
g.DrawLine(Pens.Black, new Point(i-5, j), new Point(i+5, j));
DrawText(new Point(i, j), (i / -Step).ToString(), g, false);
}
...
}
I seem to have succeeded, but I ran into such a problem:
that is, the markup is not always on the coordinate axis. How to avoid this? It is necessary that the numbers are always on the axis (I suppose I should calculate the coefficient when the window is scaled, but only where to add it or by what to multiply?)
You are dealing with 3D data, so you should use 3D tools to transform your axes, and your data for that matter.
So you need to define a projection from 3D space to 2D space. This is usually done by defining a projection matrix. There are multiple projections to chose from, it looks like your projection is Oblique, but orthographic and perspective projections are also common. The System.Numerics.Vectors library has classes for Matrix4x4, vector2/3/4, with methods to create your projection and transform your vectors.
After transforming a vector you can simply keep the x/y values and discard the z-value to get your image coordinates. Note that if using a perspective transform you need a vector4 and divide the x/y/z elements by W.
Armed with these tools it should be a fairly simple thing to generate start/end points for each axis, and create tick-marks in 3D, before projecting everything to 2D for drawing.
Another option would be to just do everything in Wpf3D to start with, this will likely make some functionality like rotating the camera simpler.
I'm trying to draw one ellipse at 0,0 and it's working but on the other side at pictureBox1.Width it's not drawing anything :
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.FillEllipse(Brushes.Purple, 0, 0, 5, 5);
e.Graphics.FillEllipse(Brushes.Purple, pictureBox1.Width, 0, 5, 5);
}
The result is one ellipse filled on the left side at 0,0 but on the right side nothing.
There should be small purple point also near the right yellow one.
And then to draw filled ellipse on all the 4 corners on the pictureBox1.
The result is one ellipse filled on the left side at 0,0 but on the right side nothing. There should be small purple point also near the right yellow one.
This is because it's off the screen a bit, you'll need to adjust the X coordinate.
e.Graphics.FillEllipse(Brushes.Purple, pictureBox1.Width - 5, 0, 5, 5);
If you'd like all four corners:
int circleSize = 5;
e.Graphics.FillEllipse(Brushes.Purple, 0, 0, circleSize, circleSize); //top left
e.Graphics.FillEllipse(Brushes.Purple, pictureBox1.Width - circleSize, 0, circleSize, circleSize); //top right
e.Graphics.FillEllipse(Brushes.Purple, pictureBox1.Width - circleSize, pictureBox1.Height - circleSize, circleSize, circleSize); //bottom right
e.Graphics.FillEllipse(Brushes.Purple, 0, pictureBox1.Height - circleSize, circleSize, circleSize); //bottom left
I'm trying to make a rendering library for monogame and I'm currently working on drawing 2D polygons. However, The positions don't make any sense. Somehow, drawing them at (0, 0, 0), (100. 0, 0), (0, 100, 0), and (100, 100, 0) doesn't reach the top-left coordinate (0, 0). How do I fix this?
My Code:
BasicEffect basicEffect = new BasicEffect(GraphicsDevice);
VertexPositionColor[] vert = new VertexPositionColor[4];
vert[0].Position = new Vector3(0, 0, 0);
vert[1].Position = new Vector3(100, 0, 0);
vert[2].Position = new Vector3(0, 100, 0);
vert[3].Position = new Vector3(100, 100, 0);
short[] ind = new short[6];
ind[0] = 0;
ind[1] = 2;
ind[2] = 1;
ind[3] = 1;
ind[4] = 2;
ind[5] = 3;
foreach (EffectPass effectPass in basicEffect.CurrentTechnique.Passes)
{
effectPass.Apply();
GraphicsDevice.DrawUserIndexedPrimitives<VertexPositionColor>(
PrimitiveType.TriangleList, vert, 0, vert.Length, ind, 0, ind.Length / 3);
}
RESULT: https://imgur.com/GkyqmlY
MonoGame uses a different origin for 2D and 3D coordinate systems. In 2D, (0, 0) is top-left corner, and Y increases toward the bottom of the screen. In 3D, (0,0,0) is the center of the screen, and the coordinate grid works very much like it does in mathematics - think 4 quadrants in math, if you "flatten" the z-axis.
You're drawing in Quadrant I. If you want the drawing to be based on top-left corner, you need to translate your vertices by -1/2 your viewport width and +1/2 your viewport height.
Unfortunately the picture box during resize jumps into the lower corner.
I read that I need to set something up with Docker and Anchor but I have no idea how.
Your Location (x, y) refers to the upper-left corner of the control. When you resize the PictureBox, only the lower-right corner will move unless you also change the location.
Are you changing the size in code? If so, you can use a helper method to do this. The image needs to shift left by half of the change in width if it is getting bigger, and needs to shift right by half of the change of width if it is getting smaller (same logic applies to height):
private void ChangePictureBoxSize(int newWidth, int newHeight)
{
// these will be negative if picturebox is getting bigger
int changeInWidth = pictureBox1.Width - newWidth;
int changeInHeight = pictureBox1.Height - newHeight;
// will shift left and up if picturebox is getting bigger
int newX = pictureBox1.Location.X + (changeInWidth / 2);
int newY = pictureBox1.Location.Y + (changeInHeight / 2);
pictureBox1.Location = new Point(newX, newY);
pictureBox1.Size = new Size(newWidth, newHeight);
}
I've got question,
I have rounded rectangle. It's only rounded on right side, and straight on left. I want to make that in other way - left rounded, right straight.
What should I change?
int ArcWidth = 10 * 2;
int ArcHeight = 10 * 2;
int ArcX1 = Rect.Left;
int ArcX2 = Rect.Right -(ArcWidth + 1);
int ArcY1 = Rect.Top;
int ArcY2 = Rect.Bottom -(ArcHeight + 1);
path.AddArc(ArcX1, ArcY1, 1, 1, 180, 90); // Top Left
path.AddArc(ArcX2, ArcY1, ArcWidth, ArcHeight, 270, 90); //Top Right
path.AddArc(ArcX2, ArcY2, ArcWidth, ArcHeight, 360, 90); //Bottom Right
path.AddArc(ArcX1, ArcY2, 1, ArcHeight, 90, 90); //Bottom Left
Switch the sides that are rounded. Looks like you have all of your sides laid out. Switch all your numbers.
I found solution here:
http://tech.pro/tutorial/656/csharp-creating-rounded-rectangles-using-a-graphics-path
The way is to draw a Line, not Arc... (yes I know that was obvious)