How can I prevent deformation when rotating about the line-of-sight in OpenGL? - c

I've drawn an ellipse in the XZ plane, and set my perspective slightly up on the Y-axis and back on the Z, looking at the center of ellipse from a 45-degree angle, using gluPerspective() to set my viewing frustrum.
Unrotated, the major axis of the ellipse spans the width of my viewport. When I rotate 90-degrees about my line-of-sight, the major axis of the ellipse now spans the height of my viewport, thus deforming the ellipse (in this case, making it appear less eccentric).
What do I need to do to prevent this deformation (or at least account for it), so rotation about the line-of-sight preserves the perceived major axis of the ellipse (in this case, causing it to go beyond the viewport)?

It looks like you're using 1.0 as the aspect when you call gluPerspective(). You should use width/height. For example, if your viewport is 640x480, you would use 1.33333 as the aspect argument.

According to the OpenGL Spec:
void gluPerspective( GLdouble fovy,
GLdouble aspect,
GLdouble zNear,
GLdouble zFar )
Aspect should be a function of your window width and height. Specifically width divided by height (but watch out for division by zero).
Perhaps you are using 1 as the aspect which is not accurate unless your window is a square.

It looks like the aspect parameter on your gluPerspective call need tweaking. See The Man Page. If your window were physically square, the aspect ratio would be 1 and your problem would go away. However, your window is rectangular, so the viewing frustum needs to be non-square.
Set the aspect ratio to window_width / window_height, and your ellipse should look correct. Note that you'll need to update this whenever the window resizes; if you're using GLUT set a glutReshapeFunc and recalculate the projection matrix in there.

Related

Setting Up a Coordinate System For Perspective Viewing?

I understand the concept behind a frustrum viewing system; it's shaped like a pyramid, and as objects get closer to the center, they get smaller until they're finally clipped off. However, when using a viewing projecting in say, OpenGL (heads up: I don't use deprecated features), you set up your coordinate system like so:
orthoExample(left, right, bottom, top, near, far);
That's all fine, but when it comes to say, perspective, things get a bit strange.
perspectiveExample(field_of_view_y, aspect, near, far);
How do I go about setting up a coordinate system with a function like this?!? It doesn't let me specify a left, right, bottom, top, etc. I know perspective is just a variation of a frustrum projection...
The code found here should clear things up for you.
The Z-axis is taken to be the center of projection. tan(fov_y)*near gives you top (and the negative, bottom). aspect is the ratio of width to height, so multiplying top by aspect gives you right and the negative of that is left.

Stretching polygon by Adorner in wpf

I have a polygon with outline (adorner has four thumb in four corners ).
When I change with or height by thumbs the polygon points doesn't change their values
but the polygon change its Width and height well.
I mean if I have polygon has points ((10,20),(50,160),(300,10))
when I stretch the polygon the points doesn't change
It will never change. As per WPF, you are only scaling (changing width and height of) polygon (UIElement). You might have specified Stretch="Fill", don't use it in this case. Create Adroners and edit points using them visually OR simply just update each point on Width or Height change.

How can I create beveled corners on a border in WPF?

I'm trying to do simple drawing in a subclass of a decorator, similar to what they're doing here...
How can I draw a border with squared corners in wpf?
...except with a single-pixel border thickness instead of the two they're using there. However, no matter what I do, WPF decides it needs to do its 'smoothing' (e.g. instead of rendering a single-pixel line, it renders a two-pixel line with each 'half' about 50% of the opacity.) In other words, it's trying to anti-alias the drawing. I do not want anti-aliased drawing. I want to say if I draw a line from 0,0 to 10,0 that I get a single-pixel-wide line that's exactly 10 pixels long without smoothing.
Now I know WPF does that, but I thought that's specifically why they introduced SnapsToDevicePixels and UseLayoutRounding, both of which I've set to 'True' in the XAML. I'm also making sure that the numbers I'm using are actual integers and not fractional numbers, but still I'm not getting the nice, crisp, one-pixel-wide lines I'm hoping for.
Help!!!
Mark
Aaaaah.... got it! WPF considers a line from 0,0 to 10,0 to literally be on that logical line, not the row of pixels as it is in GDI. To better explain, think of the coordinates in WPF being representative of the lines drawn on a piece of graph paper whereas the pixels are the squares those lines make up (assuming 96 DPI that is. You'd need to adjust accordingly if they are different.)
So... to get the drawing to refer to the pixel locations, we need to shift the drawing from the lines themselves to be the center of the pixels (squares on graph paper) so we shift all drawing by 0.5, 0.5 (again, assuming a DPI of 96)
So if it is a 96 DPI setting, simply adding this in the OnRender method worked like a charm...
drawingContext.PushTransform(new TranslateTransform(.5, .5));
Hope this helps others!
M
Have a look at this article: Draw lines exactly on physical device pixels
UPD
Some valuable quotes from the link:
The reason why the lines appear blurry, is that our points are center
points of the lines not edges. With a pen width of 1 the edges are
drawn excactly between two pixels.
A first approach is to round each point to an integer value (snap to a
logical pixel) an give it an offset of half the pen width. This
ensures, that the edges of the line align with logical pixels.
Fortunately the developers of the milcore (MIL stands for media
integration layer, that's WPFs rendering engine) give us a way to
guide the rendering engine to align a logical coordinate excatly on a
physical device pixels. To achieve this, we need to create a
GuidelineSet
protected override void OnRender(DrawingContext drawingContext)
{
Pen pen = new Pen(Brushes.Black, 1);
Rect rect = new Rect(20,20, 50, 60);
double halfPenWidth = pen.Thickness / 2;
// Create a guidelines set
GuidelineSet guidelines = new GuidelineSet();
guidelines.GuidelinesX.Add(rect.Left + halfPenWidth);
guidelines.GuidelinesX.Add(rect.Right + halfPenWidth);
guidelines.GuidelinesY.Add(rect.Top + halfPenWidth);
guidelines.GuidelinesY.Add(rect.Bottom + halfPenWidth);
drawingContext.PushGuidelineSet(guidelines);
drawingContext.DrawRectangle(null, pen, rect);
drawingContext.Pop();
}

WPF 3D Perspective camera question

I am working on a 3D flip control that can flip horizontally, vertically and can have any size and square or rectangular shape.
While I have it working, I ran into a very odd issue with the perspective camera. When I create a MeshGeometry3D I scale to the proper ratio of the content. If the width > height, all is well. However, if height > width, then the 3d mesh is sized too small.
The only thing that fixed this was (if height > width) change the UpDirection on the perspective camera from 0 1 0 to 1 0 0 and apply a 90 rotate transform. When I do this, everything looks perfect.
Anyone know why this is? Does the perspective camera only take width into account when sizing the mesh?
Thanks!
Try to play with the FieldOfView property. That's the angle at which the scene is "seen" by the camera. In your case multiplying the ratio by height / width without changing the FoV should suffice.

Converting equations of motion to pixels for display on Silverlight canvas

Can anyone point me in the direction of some information to understand this. I have a Canvas that displays an ellipse. I can move the ellipse around using the keyboard but I want to simulate a "jump", so I thought I'd use Newtons equations of motion to move the ellipse up and then down when the user presses the up arrow. All these equations are defined in metres where as the TranslateTransform on the UserControl is in pixels.
Can I get the resolution in SL to convert from metres to pixels?
Not really, no. Silverlight doesn't understand pixels.
There are 96 units in an inch (no matter the dpi of the display). That suggests there are 3779.5 silverlight units in a metre. I'd think about applying a ScaleTransform to any area you're displaying so you can give Silverlight metres and get the right visuals out if that matters to you.

Resources