mapping texture to trapezoid

hi,

I need to mapp a texture to a trapezoid ( with no parallele border). I need a “transformation- warp” mode like in photoshop. I have a 2D quad and I wants to map the texture without the annoying diagonals visible (the two triangle edge). How I can do ? I’ve try with q coordinate but I works only if the bottom and the top are parallel. it get’s me mad!!! I think perhaps I can do calculate the homography between the quad corner of the texture and the corner of the trapezoid… and then load this in the texture matrix … but it don’t works …
what can I do?

I don’t understand. Can’t you assign texture coordinates to the four vertices? What’s the problem?

(The problem described is caused by the linear interpolation of texcoords along triangles.)

However I don’t know what you mean by “transformation- warp”.

It depends on your needs, but you can start tesselating your quadrilateral into a grid, and interpolate yourself either the texcoords or vertices coordinates (maybe both).

Yes I can tesselate … but It seems that I can do directly in opengl with the q coordinate … but I don’t succeed.

Don’t nVidia have a demo that relates directly to this problem? All I can remember was it a trapezoid with a checkered texture - and that’s about all I can remember… I had a quick scan of the nvidia site but couldn’t see it (everything seems harder to find on the nVidia site since they rearranged things…)

I think the demo is called “understanding Q” and the site is Cass’ private site: www.r3.nu

Yes I have test this demo … but it only works if the top and the bottom are parallel …

Some code snippets that might help…

Code that creates a mapping from s and t texture coordinates related to xyz positions…

 gzVoid CMapTweaker::setMappingValues(const gzVec2 &st0 , const gzVec3 &xyz0 , 
							const gzVec2 &st1 , const gzVec3 &xyz1 ,
							const gzVec2 &st2 , const gzVec3 &xyz2 ,
							const gzVec2 &st3 , const gzVec3 &xyz3 )
{
	m_ST=gzMatrix4(	gzVec4(1,st0.v1,st0.v2,st0.v1*st0.v2),
					gzVec4(1,st1.v1,st1.v2,st1.v1*st1.v2),
					gzVec4(1,st2.v1,st2.v2,st2.v1*st2.v2),
					gzVec4(1,st3.v1,st3.v2,st3.v1*st3.v2));

	m_ST.getInvertedMatrix(m_ST_inv);

	m_XYZ=gzMatrix4(gzVec4(xyz0.v1,xyz0.v2,xyz0.v3,1),
					gzVec4(xyz1.v1,xyz1.v2,xyz1.v3,1),
					gzVec4(xyz2.v1,xyz2.v2,xyz2.v3,1),
					gzVec4(xyz3.v1,xyz3.v2,xyz3.v3,1));

	m_A=m_XYZ*m_ST_inv;

	m_bInit = true;

} 

and perhaps the most interesting part… Code that calculates texture coordinates from a generic xyz position or calculates xyz postion out of a texture coordinate

</font><blockquote><font size=“1” face=“Verdana, Arial”>code:</font><hr /><pre style=“font-size:x-small; font-family: monospace;”>

gzVec3 CMapTweaker::getXYZ(const gzVec2 &st)
{
ATLASSERT(m_bInit);
return gzVec3( m_A.v11 + m_A.v12st.v1 + m_A.v13st.v2 + m_A.v14st.v1st.v2,
m_A.v21 + m_A.v22st.v1 + m_A.v23st.v2 + m_A.v24st.v1st.v2,
m_A.v31 + m_A.v32st.v1 + m_A.v33st.v2 + m_A.v34st.v1st.v2 );
}

gzVec2 CMapTweaker::getST(const gzVec3 &xyz)
{
ATLASSERT(m_bInit);

gzFloat a=m_A.v14*m_A.v23-m_A.v13*m_A.v24;

gzFloat b=-m_A.v11*m_A.v24+m_A.v12*m_A.v23-m_A.v13*m_A.v22+m_A.v14*m_A.v21-m_A.v14*xyz.v2+m_A.v24*xyz.v1;

gzFloat c=-m_A.v11*m_A.v22+m_A.v12*m_A.v21-m_A.v12*xyz.v2+xyz.v1*m_A.v22;

gzDouble s,t;

if(a==0)
	t=-c/b;
else
{
	t=0.5*(-b+sqrt(b*b-4*a*c))/a;

	if((t&lt;-10)

thanks … but it seems that there is not the end of your source … I think I could implement a shader.

Opps. Sorry !

</font><blockquote><font size=“1” face=“Verdana, Arial”>code:</font><hr /><pre style=“font-size:x-small; font-family: monospace;”>

gzVec2 CMapTweaker::getST(const gzVec3 &xyz)
{
ATLASSERT(m_bInit);

gzFloat a=m_A.v14*m_A.v23-m_A.v13*m_A.v24;

gzFloat b=-m_A.v11*m_A.v24+m_A.v12*m_A.v23-m_A.v13*m_A.v22+m_A.v14*m_A.v21-m_A.v14*xyz.v2+m_A.v24*xyz.v1;

gzFloat c=-m_A.v11*m_A.v22+m_A.v12*m_A.v21-m_A.v12*xyz.v2+xyz.v1*m_A.v22;

gzDouble s,t;

if(a==0)
	t=-c/b;
else
{
	t=0.5*(-b+sqrt(b*b-4*a*c))/a;

	if((t&lt;-10)

How strange. In the preview it looks ok but then it is cut away ???

</font><blockquote><font size=“1” face=“Verdana, Arial”>code:</font><hr /><pre style=“font-size:x-small; font-family: monospace;”>
gzVec2 CMapTweaker::getST(const gzVec3 &xyz)
{
ATLASSERT(m_bInit);

gzFloat a=m_A.v14*m_A.v23-m_A.v13*m_A.v24;

gzFloat b=-m_A.v11*m_A.v24+m_A.v12*m_A.v23-m_A.v13*m_A.v22+m_A.v14*m_A.v21-m_A.v14*xyz.v2+m_A.v24*xyz.v1;

gzFloat c=-m_A.v11*m_A.v22+m_A.v12*m_A.v21-m_A.v12*xyz.v2+xyz.v1*m_A.v22;

gzDouble s,t;

if(a==0)
	t=-c/b;
else
{
	t=0.5*(-b+sqrt(b*b-4*a*c))/a;

	if((t&lt;-10)

I give up. Send me an email to gzimo3d_support(at)sts.saab.se so i can email you the source… It basically allows you to do a planar projection of a texture to any form of polygon…

Hi,
your e-mail is invalid for me … i can send you an email … here’s my email ykohn(at)etc-pigi.com

to be more exact, I need to do the same effect you can see in gimp or photoshop : transformation -> perspective …
I need to map a complete rectangular texture in a trapezoid

The problem with doing this with texture generation is that your texture coordinates are still only on the edges, to acheive tapered texture mapping you have to tesselate your polygon. Its easy to visualize why this is, if you map a quad in 3dstudio and see that the triangle line that divides the quad is directly center, and if you map a tesselated trapezoid you’ll see the line across the center is actually curved. This might be possible in some kind of pixel program, but your still better off just tesselating the polygon. If you want I can email you a picture of what im talking about.

here is what I want :
http://yannickkohn.free.fr

You should be able to archieve what you want (mapping from arbitrary trapezoid A to arbitrary trapezoid B) using a general 4x4 texture matrix which is projective. So much for the theory.

As for the actual implementation, I’m afraid I can’t help. I can only give the advice to take out pen and paper (or Maple/Mathematica for that matter) and do the maths yourself.

Maybe you can think of the problem like this: Try to find a perspective camera that displays your source rectangle as your destination trapezoid with texture coordinates unmodified. Then try to find a texture matrix that does the same transform with the texture coordinates.

Good luck :smiley:

Search for:

Paul Heckbert’s Master Thesis: Fundamentals of Texture Mapping and Image Warping, paragraph 2.2.3

or (better explained):

Jim Blinn’s Corner: Notation, Notation, Notation, chapter 13 (Inferring Transforms, 1999)

Originally posted by kohn:
Yes I have test this demo … but it only works if the top and the bottom are parallel …
I tried this and it works

define this at the top

float bottom=0.7;

and for the display function

void display()
{
	glClear(GL_COLOR_BUFFER_BIT);
	glPushMatrix();

	mouse.apply_transform();

	if(use_q)
	{
		
		float tx=scale_texcoord*top;
		float ty=scale_texcoord*bottom;
		float txy=scale_texcoord*top*bottom;

		glBegin(GL_QUADS);
		
		glTexCoord4f(0.0, 0.0, 0.0, 1.0);
		glVertex3f(-1.0, -1.0, 0.0);
		
		glTexCoord4f(0.0, tx, 0.0, tx);
		glVertex3f(-top, 1.0, 0.0);
		
		glTexCoord4f(txy,  txy, 0, txy);
		glVertex3f(top, bottom, 0.0);
		
		glTexCoord4f(ty, 0.0, 0.0, ty);
		glVertex3f(1.0, -bottom, 0.0);
		
		glEnd();
	}
	else
	{
		
		glBegin(GL_QUADS);
		
		glTexCoord2f(0.0, 0.0);
		glVertex3f(-1.0, -1.0, 0.0);
		
		glTexCoord2f(0.0, 1.0);
		glVertex3f(-top, 1.0, 0.0);
		
		glTexCoord2f(1.0, 1.0);
		glVertex3f(top, bottom, 0.0);
		
		glTexCoord2f(1.0, 0.0);
		glVertex3f(1.0, -bottom, 0.0);
		
		glEnd();
	}

	glPopMatrix();
	glutSwapBuffers();
}