UV mapping a quad
by James Ford · in Technical Issues · 07/10/2008 (10:44 am) · 7 replies
I have an arbitrary quad... That is, it is a trapezoid not a quadrilateral. Eg. Some are getting narrower from bottom to top, some are getting wider, and some could be staying the same width. I want the corners of the quad to correspond to these texture UVs...
If it helps to visualize the problem or isolate it to a particular field, what I am actually doing here is texture mapping a square decal to a stretched/nonsquare shape.
Note that the change in width is NOT because of a perspective projection, its because it is just changing in width. Any perspective projection will be applied automatically after all of this.
So far I am getting decent results using bilinear interpolation. But sometimes the texture along the center of the quad appears to be "wavy". eg... if there was a line down the center of the quad, it might appear like this...
So the questions...
1. Could this waviness be a by-product of bilinear interpolation or does that sound like an error elsewhere?
2. I have not heard of bilinear interpolation being used for this purpose before, so, is there something else more appropriate?
0,1 ---------- 1,1 | | | | | | 0,0 ---------- 1,0
If it helps to visualize the problem or isolate it to a particular field, what I am actually doing here is texture mapping a square decal to a stretched/nonsquare shape.
Note that the change in width is NOT because of a perspective projection, its because it is just changing in width. Any perspective projection will be applied automatically after all of this.
So far I am getting decent results using bilinear interpolation. But sometimes the texture along the center of the quad appears to be "wavy". eg... if there was a line down the center of the quad, it might appear like this...
0,1 --------- 1,1 | \ | | / | | \ | 0,0 --------- 1,0
So the questions...
1. Could this waviness be a by-product of bilinear interpolation or does that sound like an error elsewhere?
2. I have not heard of bilinear interpolation being used for this purpose before, so, is there something else more appropriate?
About the author
http://jamesdev.info
#2
So here I have the verts represented by o(s) scattered throughout the quad, and I need to calculate their UVs relative to the known corner UVs.
Note: This quad is not necessarily planar, but this flat projection of the texture is the best we can do. The "wavy" problem can occur on completely flat terrain.
07/10/2008 (1:11 pm)
Ok actually I left out some of the complexity. There are really a lot more verts than those corner four because this is a decal that is applied to the terrain, we are capturing and clipping the terrain polys. So to build my vertex buffer I have to calculate textCoords for each of those verts. That is the reason for using bilinear interpolation.X------------X | o | | o | | o | X------------X
So here I have the verts represented by o(s) scattered throughout the quad, and I need to calculate their UVs relative to the known corner UVs.
Note: This quad is not necessarily planar, but this flat projection of the texture is the best we can do. The "wavy" problem can occur on completely flat terrain.
#3
hm,
since opposite edges of the quad are not parallel,
i'm not sure that bilinear interpolation will work.
hm.
just taking a stab here, but i would maybe try something like this:
07/10/2008 (1:45 pm)
Ah i gotcha.hm,
since opposite edges of the quad are not parallel,
i'm not sure that bilinear interpolation will work.
hm.
just taking a stab here, but i would maybe try something like this:
let's call the top edge of the quad T, the right R, the bottom B, and the left L. P is the point in question. * project P onto T, R, B, and L. * let Ut be the U-value at the projected point on T. * let Ub be the U-value at the projected point on B. * let Vl be the V-value at the projected point on L. * let Vr be the V-value at the projected point on R. * let PT be the distance from P to T. * let PR be the distance from P to R. * let PB be the distance from P to B. * let PL be the distance from P to L. then * Up = [Ut * (PT / (PT + PB)] + [Ub * (PB / (PT + PB)]. * Vp = [Vr * (PR / (PR + PL)] + [Vl * (PR / (PR + PL)]. (this of course can be optimized, but i think this is the clearest expression)
#4
But how do you do the projection in the first place? I guess to do a projection on the top/bottom edges I need a projection vector - the direction to do the projection. If the left/right edges were parallel then it would make since to use that direction for the projection, but we do not necessarily have any parallel edges.
If the left/right edge direction vectors differ, then we would want to project onto the top/bottom edges using the left edge vector when P is at distance zero from that edge, and use the right edge vector when P is at distance zero from that edge. And interpolate between the two in the area between.
But how do we know the distance from the left/right edges? Well we have to do a projection onto them, which requires we have already done the projection on the top/bottom ....
07/10/2008 (3:20 pm)
That makes sense... As you reach a distance of 1 from one of the opposing edges, the P(s) U/V value becomes the U/V of that edge.But how do you do the projection in the first place? I guess to do a projection on the top/bottom edges I need a projection vector - the direction to do the projection. If the left/right edges were parallel then it would make since to use that direction for the projection, but we do not necessarily have any parallel edges.
If the left/right edge direction vectors differ, then we would want to project onto the top/bottom edges using the left edge vector when P is at distance zero from that edge, and use the right edge vector when P is at distance zero from that edge. And interpolate between the two in the area between.
But how do we know the distance from the left/right edges? Well we have to do a projection onto them, which requires we have already done the projection on the top/bottom ....
#5
i should have been more clear. these are all perpendicular projections.
07/10/2008 (3:52 pm)
> But how do you do the projection in the first place?i should have been more clear. these are all perpendicular projections.
if a line has two points A and B, to project point P perpendicularly onto it: AB = vector from A to B ABn = AB normalized AP = vector from A to P Q = the perpendicular projection of P onto AB = A + (ABn * (ABn DOT AP)) fwiw, Q is also the point on AB which is closest to P.
#6
07/10/2008 (4:07 pm)
While we're at it, if ABn DOT AP is < 0 or > 1, then the perpendicular projection of the point does not lie between A & B, which will happen sometimes in the above algorithm, but which should be fine.
#7
www.garagegames.com/community/forums/viewthread/124881
03/15/2011 (10:29 am)
Bug in T3D: related?www.garagegames.com/community/forums/viewthread/124881
Associate Orion Elenzil
Real Life Plus
can you post some images ?
typically, if you've got an arbitrary (but planar!) quadrilateral
with the regular unit texture coords at the corners (00 10 11 01),
it should render nice and smoothly stretched.