perspective correction of texture coordinates in 3d - math

I'm writing a software renderer which is currently working well, but I'm trying to get perspective correction of texture coordinates and that doesn't seem to be correct. I am using all the same matrix math as opengl for my renderer. To rasterise a triangle I do the following:
transform the vertices using the modelview and projection matrixes, and transform into clip coordinates.
for each pixel in each triangle, calculate barycentric coordinates to interpolate properties (color, texture coordinates, normals etc.)
to correct for perspective I use perspective correct interpolation:
(w is depth coordinate of vertex, c is texture coordinate of vertex, b is the barycentric weight of a vertex)
1/w = b0*(1/w0) + b1*(1/w1) + b2*(1/w2)
c/w = b0*(c0/w0) + b1*(c1/w1) + b2*(c2/w2)
c = (c/w)/(1/w)
This should correct for perspective, and it helps a little, but there is still an obvious perspective problem. Am I missing something here, perhaps some rounding issues (I'm using floats for all math)?
See in this image the error in the texture coordinates evident along the diagonal, this is the result having done the division by depth coordinates.
Also, this is usually done for texture coordinates... is it necessary for other properties (e.g. normals etc.) as well?

I cracked the code on this issue recently. You can use a homography if you plan on modifying the texture in memory prior to assigning it to the surface. That's computationally expensive and adds an additional dependency to your program. There's a nice hack that'll fix the problem for you.
OpenGL automatically applies perspective correction to the texture you are rendering. All you need to do is multiply your texture coordinates (UV - 0.0f-1.0f) by the Z component (world space depth of an XYZ position vector) of each corner of the plane and it'll "throw off" OpenGL's perspective correction.
I asked and solved this problem recently. Give this link a shot:
texture mapping a trapezoid with a square texture in OpenGL
The paper I read that fixed this issue is called, "Navigating Static Environments Using Image-Space Simplification and Morphing" - page 9 appendix A.
Hope this helps!
ct

The only correct transformation from UV coordinates to a 3D plane is an homographic transformation.
http://en.wikipedia.org/wiki/Homography
You must have it at some point in your computations.
To find it yourself, you can write the projection of any pixel of the texture (the same as for the vertex) and invert them to get texture coordinates from screen coordinates.
It will come in the form of an homographic transform.

Yeah, that looks like your traditional broken-perspective dent. Your algorithm looks right though, so I'm really not sure what could be wrong. I would check that you're actually using the newly calculated value later on when you render it? This really looks like you went to the trouble of calculating the perspective-correct value, and then used the basic non-corrected value for rendering.

You need to inform OpenGL that you need perspective correction on pixels with
glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST)
What you are observing is the typical distortion of linear texture mapping. On hardware that is not capable of per-pixel perspective correction (like for example the PS1) the standard solution is just subdividing in smaller polygons to make the defect less noticeable.

Related

Getting scan lines of arbitrary 2d triangle

How would one go about retrieving scan lines for all the lines in a 2D triangle?
I'm attempting to implement the most basic feature of a 2D software renderer, that of texture mapping triangles. I've done this more times than i can count using OpenGL, but i find myself limping when trying to do it myself.
I see a number of articles saying that in order to fill a triangle (whose three vertices each have texture coordinates clamped to [0, 1]), i need to linearly interpolate between the three points. What? I thought interpolation was between two n-dimensional values.
NOTE; This is not for 3D, it's strictly 2D, all the triangles are arbitrary (not axis-aligned in any way). I just need to fill the screen with their textures the way OpenGL would. I cannot use OpenGL as a solution.
An excellent answer and description can be found here: http://sol.gfxile.net/tri/index.html
You can use the Bresenham algorithm to draw/find the sides.
One way to handle it is to interpolate in two steps if you use scanline algorithm. First you interpolate the value on the edges of the triangle and when you start drawing the scanline you interpolate between the start and end value of that scanline.
Since you are working in 2d you can also use a matrix transformation to obtain the screen coordinate to texture coordinate. Yesterday I answered a similar question here. The technique is called change of basis in mathematics.

Method for finding normals to a voxel surface

I was working on a method to approximate the normal to a surface of a 3d voxel image.
The method suggested in this article (only algorithm I found via Google) seems to work. The suggested method from the paper is to find the direction the surface varies the most in, choose 2 points on the tangent plane using some procedure, and then take the cross product. Some Pascal code by the article author code, commented in Portuguese, implements this method.
However, using the gradient of f (use each partial derivative as a component of the vector) as the normal seems to work pretty well; I tested this along several circles on a voxellated sphere and I got results that look correct in most spots (there are a few outliers that are off by about 30 degrees). This is very different from the method used in the paper, but it still works. What I don't understand is why the gradient of f = 1/dist calculated along the surface of an object should produce the normal.
Why does this procedure work? Is it just the fact that the sphere test was too much of a special case? Could you suggest a simpler method, or explain any of these methods?
Using the gradient of the volume as a normal for lighting is a standard technique in volume rendering.
If you interpret the value of a voxel as the opacity, the gradient will give you the direction of the greatest change in the opacity, which is similar to a surface normal.

Detect Shapes in an array of points

I have an array of points. I want to know if this array of point represents a circle, a square or a triangle.
Where should i begin? (i use C#)
Thanks
Jon
Depending on your problem, a good approach for this problem may be to use the Hough transform and all its derived algorithm
It consists in a transformation of the image space to an other space where the coordinate represents the objects parameters (angle and initial point for a line, coordinates of the center and radius for a circle)
The algorithm transforms each point of your array of points in points in the other space. Then you have to search in the new space if some points are prevailing. From these points, you will get the parameters of your object.
Of course, you need to do it once to recognize the lines (so you will know how many lines are in your bitmap and where they are) and to it to recognize the circles (it is not exactly the same algorithm)
You may have a look to this lecture (for Hough Circle Transform), but you could easily find the algorithm for line
EDIT: you can also have a look to these answers
Shape recognition algorithm(s)
Detecting an object on the image based on geometrical form
imagine it is each of these one-by-one and try to fit each of these shapes on the data.. for a square, you could find the four extreme points, and try charting out a square that goes through all of them..
Once you have got a shape in place.. you could measure the distance between each of the points and the part of the shape that is nearest to it.. then square these distances and add them up.. the shape which has the smallest sum-of-squares is probably your best bet
Use the Hough Transform.
I'm going to take a wild stab and say if you have 3 points the shape represents a triangle, 4 points is some kind of quadrilateral, any more than that is a circle.
Perhaps there's more information to your problem you could provide.

Find X/Y/Z rotation angles from one position to another

I am using a 3D engine called Electro which is programmed using Lua. It's not a very good 3D engine, but I don't have any choice in the matter.
Anyway, I'm trying to take a flat quadrilateral and transform it to be in a specific location and orientation. I know exactly where it is supposed to go (i.e. I know the exact vertices where the corners should end up), but I'm hitting a snag in getting it rotated to the right place.
Electro does not allow you to apply transformation matrices. Instead, you must transform models by using built-in scale, position (that is, translate), and rotation functions. The rotation function takes an object and 3 angles (in degrees):
E.set_entity_rotation(entity, xangle, yangle, zangle)
The documentation does not speficy this, but after looking through Electro's source, I'm reasonably certain that the rotation is applied in order of X rotation -> Y rotation -> Z rotation.
My question is this: If my starting object is a flat quadrilateral lying on the X-Z plane centered at the origin, and the destination position is in a different location and orientation where the destination vertices are known, how could I use Electro's rotation function to rotate it into the correct orientation before I move it to the correct place?
I've been racking my brain for two days trying to figure this out, looking at math that I don't understand dealing with Euler angles and such, but I'm still lost. Can anyone help me out?
Can you tell us more about the problem? It sounds odd phrased in this way. What else do you know about the final orientation you have to hit? Is it completely arbitrary or user-specified or can you use more knowledge to help solve the problem? Is there any other Electro API you could use to help?
If you really must solve this general problem, then too bad, it's hard, and underspecified. Here's some guy's code that may work, from euclideanspace.com.
First do the translation to bring one corner of the quadrilateral to the point you'd like it to be, then apply the three rotational transformations in succession:
If you know where the quad is, and you know exactly where it needs to go, and you're certain that there are no distortions of the quad to fit it into the place where it needs to go, then you should be able to figure out the angles using the vector scalar product.
If you have two vectors, the angle between them can be calculated by taking the dot product.

Math programming help for a gimble-based painting machine

I'm an artist involved with building various sorts of computer controlled machines. I've started prototyping a gimble-based XY painting machine and have realized that the maths needed are out of my reach. I'm a decent enough programmer but not strong in math- esp. 3D math.
To get a sense of what I'm needing to do, it might be helpful to look at the rig:
Early prototype:
http://roypardi.com/gimble/gimbleSmall.MOV (small video)
http://roypardi.com/gimble/gimbleLarge.mov (larger video)
The two inner rings represent the X/Y axes and are controlled by stepper motors. I want to be able to use both raster images and vector data (gcode). So I need to be able to address a point in 2D space on the paper/from my data and have the gimble figure out what orientation it needs to be at in order to get there (i.e. how much to step each motor).
I've been searching out 2D > 3D projection, Euler angles, etc. but I'm out of my depth. Any pointers, pushes in the right direction, or code snippets would be most welcome. I can make sense of most programming languages.
Very nice machine you have made, I hope this works for you I believe it is correct.
The way I see it, is to get one angle is simple, but the other is slightly harder to visualise as we have tilted the axis which it turns upon.
I'm going to avoid using tan, as when programming this could result in a division by 0, which could be frustrating. Also Z is going to be the height of the origin above the paper.
YAxis = arcsin( X / sqrt(X² + Z²))
XAxis = arcsin( Y / sqrt(Y² + X² + Z²))
or we could use
XAxis = arcsin(Y / sqrt(Y² + Z²))
YAxis = arcsin( X / sqrt(X² + Y² + Z²))
Also, I'd very much like to see a video of this plotting, if it works.
Edit:
After thinking about it i believe only one solution will work it depends on which axis is affected by the other. Is the YAxis in the Middle or the Xaxis?
I think it's a problem of simple http://en.wikipedia.org/wiki/Trigonometry
Let's say that the distance from the centre of your rings to the nearest point on the paper (which I'll call point 'O' for 'Origin') is distance X.
Take another point P directly north of O, whose distance from O is Y.
To paint this point, you need the angle alpha such that tan(alpha)=Y/X, i.e. you can calculate alpha using the formula "arctan(Y/X)" [arctan is sometimes also known as atan]. Arctan is a trignometric function, which I think you'll probably find defined in the API of a general purpose math library.
The above is the simplest case.
The only other case that I can think of is when the point P isn't due north. Instead of being due north, let's say that its distance is Y1 to the north, and Y2 to the east. The solution is two angles (one angle for each of two rings), one of which is "arctan(Y1/X)" and the other of which is "arctan(Y2/X)".
Perhaps I misunderstand, but I don't believe a gimbal will do what you want. A gimbal can point in any 3D direction, but it cannot move to arbitrary points in 3D space. If the plane of the paper intersects the volume swept by the pen held in the gimbal, the pen might be able to draw a circle, but nothing more. Even drawing a circle is not a sure thing, since in this case the paper would also intersect the volume swept by the gimbal rings; trying to orient the pen would make a ring hit the paper.
I think what you want is a plotter, not a gimbal.

Resources