Archived

This topic is now archived and is closed to further replies.

Texture coord question

This topic is 5536 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I''ve asked this question time and time again, but never actually gotten my problem fixed. The problem is as such: I''m making a 3D world editor, similar to those of UnrealEd or WorldCraft. Thus far, I create quads, which are square and have a texture on them. Then when you click on the quad, it highlites the verticies, and allows them to be dragged in any direction. When I drag, the texture drags too, as if clamped to each corner of the quad, which is undesireable. I would like the textures to behave as they do in the two editors above. On other words, to not stretch, but to repeat. How do I get it to repeat?

Share this post


Link to post
Share on other sites
Call glTexParameteri(). One of the arguments allows you to set to GL_REPEAT instead of GL_CLAMP. I don''t know how you are setting your texture coords, but you may need to look into this as well.

Share this post


Link to post
Share on other sites

I would guess (can''t be certain without looking at your code, of course) that you''re assinging tex coords to each vertex .. probably like:

glTexCoord2f(0.0,0.0);
glVertex3fv(vertex1);
glTexCoord2f(1.0,0.0);
glVertex3fv(vertex1);
...

?

If so, the problem is that the glTexCoord2f calls are keeping the ''corners'' of the texture at the corners of the quad.

What you need to do is scale the s and t floats passed to glTexCoord2f as the quad increases in size (if they are > 1, the texture will repeat).

You''ll need to set
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
in your initialisation, too.

btw: E&OE .. I''m pretty new to OGL myself

Share this post


Link to post
Share on other sites
I had this exact problem. My editor was nearing completion, and I couldn't get it to generate texture coords like q3radiant, UnrealEd, and Hammer. I searched fruitlessly, and even posted here, but to no avail. I finally sat down and solved the problem logically (I can do some math). Here's how to do it:

  • Work out the normal for the new quad.

  • Create a reference normal (I use (0, 1, 0). This works for all normals other than (0, -1, 0) and (0, 1, 0) but I catch them and change the reference to something like (0, 0, -1)).

  • Get the cross product of the two normals, and normalize it. This gives you the s coord normal.

  • Get the cross product of the triangle's normal and the s coord normal, and normalize it. This gives you the t coord normal.

  • The s texture coord for a vertex is:

    s = (Vertex.x * sCoord(1)) + (Vertex.y * sCoord(2)) + (Vertex.z * sCoord(3))

  • The t texture coord for a vertex is:

    t = (Vertex.x * tCoord(1)) + (Vertex.y * tCoord(2)) + (Vertex.z * tCoord(3))

This works absolutely perfectly every time in my editor, and as an added bonus, by using (0, 1, 0), all the textures on the sides of boxes, walls, etc. are the right way up...

PS. If you want a look at my editor, follow the link below to DarkVertex. Only the picture with the black background (the stairs) uses the above method, I haven't had time to create new screenshots. The others use a less reliable (and much more complex) method...

EDIT: Mulligan, if you want the source code for this (it's in VB, but that's easy to read), email me...


Movie Quote of the Week:

"You've been eating retard sandwiches again."
- Birdman, Beautiful Girls.
Try http://uk.geocities.com/mentalmantle. Seriously. It's brilliant.
And I just completely redesigned it so it looks even better.
DarkVertex Beta 0.8 available soon!


[edited by - iNsAn1tY on October 18, 2002 6:49:09 PM]

Share this post


Link to post
Share on other sites
quote:
Original post by simbobx

I would guess (can''t be certain without looking at your code, of course) that you''re assinging tex coords to each vertex .. probably like:

glTexCoord2f(0.0,0.0);
glVertex3fv(vertex1);
glTexCoord2f(1.0,0.0);
glVertex3fv(vertex1);
...


If so, the problem is that the glTexCoord2f calls are keeping the ''corners'' of the texture at the corners of the quad.



Yes, this is my problem, and that is how it works right now.
quote:

What you need to do is scale the s and t floats passed to glTexCoord2f as the quad increases in size (if they are > 1, the texture will repeat).



This is mainly what confused me last time. What are s and t? Just a letter the OpenGL programmers choose?

So i just keep everything the way i have, but add the code you told me to add? right?

Share this post


Link to post
Share on other sites
Basically, s and t are the x and y axis of the texture. Except that OpenGL programmers don't call them "texture x and y coords", they just call them s and t coords. Makes life easier, no-one gets confused.

Scaling the s and t coords as the quad changes size won't work, especially if you rotate the quad. It works fine in the x = 0, y = 0 and z = 0 planes, but doesn't in any other. The problem is basically this.

If you scale your texture coords in the x and y directions, then the texture will only look right if you look at it down the z axis. From any other angle, the texture will appear skewed. What you're loooking for is the plane that the quad resides in, and once you have that, you can figure out the texture coordinates that will map the texture correctly.

There is no quick fix to this problem. Changing a few OpenGL state variables or scaling in arbitrary axes will do nothing. You have to use the method I described above, or something very similar. By using the above methods, you get the s and t normals of the plane in which the quad resides, and therefore, you can mathematically evaluate the correct texture coords.

To illustrate my point, think of this: the s and t normals of a quad which resides in the plane z = 0, and has a normal of (0, 0, 1) are (1, 0, 0) and (0, 1, 0).

EDIT: I'm sorry if this isn't written too well. I'm trying to make my points clearly, but this is quite a complex subject. I'm going to write an article on it, and post it on here. It's actually quite simple to understand with a few images...


Movie Quote of the Week:

"You've been eating retard sandwiches again."
- Birdman, Beautiful Girls.
Try http://uk.geocities.com/mentalmantle. Seriously. It's brilliant.
And I just completely redesigned it so it looks even better.
DarkVertex Beta 0.8 available soon!


[edited by - iNsAn1tY on October 18, 2002 7:55:22 PM]

Share this post


Link to post
Share on other sites
Thats the most helpful bit of information I've gotten yet! At least now I'm thinking down the right track, thanks! It may be asking a lot, but would you be willing to post some sample code of how you did it? It doesn't matter is its commented or totally out of context, I'd just like to see one working solution.


[edited by - Mulligan on October 19, 2002 12:54:45 PM]

Share this post


Link to post
Share on other sites
Here's some source code. Like I said, it's in VB (and might not look right as the source box is formatted for C), but it shouldn't be too difficult to read. This is the actual texture coord generator from DarkVertex. It runs through an object's BSP tree (I use convex hulls; easier for CSG) and creates texture coords for every splitter (the splitters are just triangles). The s and t normals (sCoord and tCoord) are created, then normalized, then scaled so that the texture is a decent size on the triangles, and finally applied to create texture coords. Enjoy


  
' Takes an object, and creates texture
' coords for all triangles it contains...
Public Sub CreateTexCoordsFromObject(u As DV_OBJECT)

Dim sCoord(1 To 3) As GLfloat, tCoord(1 To 3) As GLfloat
Dim Reference(1 To 3) As GLfloat, x As Integer, y As Integer

' Check if texture coords are actually
' required. Errors happen if you don't...
If u.Obj_Texture = 0 Then Exit Sub

' Run through every BSP node of this object...
For x = 1 To u.Obj_BSPTree.BSP_NumberOfNodes Step 1

' Continue if this node isn't a leaf...
If Not u.Obj_BSPTree.BSP_Nodes(x).BSP_IsLeaf Then

With u.Obj_BSPTree.BSP_Nodes(x).BSP_Splitter

' Create this triangle's reference point...
If (.Tri_Normal(1) = 0 And .Tri_Normal(2) = 1 And .Tri_Normal(3) = 0) Or _
(.Tri_Normal(1) = 0 And .Tri_Normal(2) = -1 And .Tri_Normal(3) = 0) Then

Reference(1) = 1

Else

Reference(2) = -1

End If

' The sCoord is the cross-product of the
' object's normal and the reference point.
' Normalize sCoord when it's returned...
GetCrossProduct .Tri_Normal, Reference, sCoord
Normalize sCoord, sCoord

' The tCoord is the cross-product of the
' object's normal, and the sCoord...
' Normalize tCoord when it's returned...
GetCrossProduct .Tri_Normal, sCoord, tCoord
Normalize tCoord, tCoord

' Multiply sCoord and tCoord by the sizes
' of this object's texture divided by 40...
For y = 1 To 3 Step 1

sCoord(y) = sCoord(y) / (Sys_Textures.Tex_Textures(u.Obj_Texture).Tex_Width / 40)
tCoord(y) = tCoord(y) / (Sys_Textures.Tex_Textures(u.Obj_Texture).Tex_Height / 40)

Next y

' Using the new sCoords and tCoords just
' obtained, create the texture coords...
For y = 1 To 3 Step 1

.Tri_TexCoords(y, 1) = (.Tri_Vertices(y, 1) * sCoord(1)) + _
(.Tri_Vertices(y, 2) * sCoord(2)) + _
(.Tri_Vertices(y, 3) * sCoord(3))

.Tri_TexCoords(y, 2) = (.Tri_Vertices(y, 1) * tCoord(1)) + _
(.Tri_Vertices(y, 2) * tCoord(2)) + _
(.Tri_Vertices(y, 3) * tCoord(3))

Next y

End With

End If

Next x

End Sub



Movie Quote of the Week:

"You've been eating retard sandwiches again."
- Birdman, Beautiful Girls.
Try http://uk.geocities.com/mentalmantle. Seriously. It's brilliant.
And I just completely redesigned it so it looks even better.
DarkVertex Beta 0.8 available soon!


[edited by - iNsAn1tY on October 19, 2002 2:58:25 PM]

Share this post


Link to post
Share on other sites
Sweet jesus! It works! This is truly a good day! Finally!!!
Thanks iNsAn1tY.
My final code looks like this:

void CFace::CreateTexCoordsFromObject()
{
D3DXVECTOR3 vS( 0, 0, 0 ), vT( 0, 0, 0 ), vRef( 0, 0, 0 );

if( ( m_vNormal.x == 0 && m_vNormal.y == 1 && m_vNormal.z == 0 ) ||
( m_vNormal.x == 0 && m_vNormal.y == -1 && m_vNormal.z == 0 ) )
vRef.x = 1;
else
vRef.y = -1;

Normalize( GetCrossProduct( m_vNormal, vRef ) );
Normalize( GetCrossProduct( m_vNormal, vS ) );

for( int y = 0; y < 4; y++ )
{
m_Verts[y].m_fU = ( m_Verts[y].m_vPos.x * vS.x ) +
( m_Verts[y].m_vPos.y * vS.y ) +
( m_Verts[y].m_vPos.z * vS.z );

m_Verts[y].m_fV = ( m_Verts[y].m_vPos.x * vT.x ) +
( m_Verts[y].m_vPos.y * vT.y ) +
( m_Verts[y].m_vPos.z * vT.z );
}
}


[edited by - Mulligan on October 21, 2002 6:45:54 PM]

Share this post


Link to post
Share on other sites
Well, the number 40 I chose after some experimentation, choosing values (I think I started out at 10), and seeing what effect it had on the scale of the texture. If you scale the texture too little, you get artifacts when you''re up close to it, and if you scale it too much you can''t see the detail of the texture. 40 seemed to be just right. I think it scales down a 64x64 texture to be about 32x32 or 16x16 on the polygon. It''s a good trade off when considering the above scaling problem.

Tri_TexCoords() are the texture coords of the three vertices of that triangle. The declaration is this:

Tri_TexCoords(1 To 3, 1 To 2) As GLfloat

Basically, there are three (the "1 To 3" bit) pairs (the "1 To 2" bit) of texture coords, one for each vertex in the triangle. It''s a two-dimensional array. In C it would be:

GLfloat Tri_TexCoords[3][2];

The for loop runs through the three vertices of the triangle, multiplies every x, y, z element of the vertex by the x, y, z elements of sCoord and tCoord and then adds together the products of those multiplications to get the s texture coord and t texture coord respectively.

I hope this is explained well enough here for you to understand it, like I said before, it''s kinda difficult without pictures. I''ll try to do it in C:


  
for(int y=0;y<3;y++)
{

// Get the s texture coord...

TextureCoord[y][0] = (sCoord[0] * Vertex[y][0]) +
(sCoord[1] * Vertex[y][1]) +
(sCoord[2] * Vertex[y][2]);

// Get the t texture coord...

TextureCoord[y][1] = (tCoord[0] * Vertex[y][0]) +
(tCoord[1] * Vertex[y][1]) +
(tCoord[2] * Vertex[y][2]);

}

I had to think about that! I''ve been using VB to develop my map editor for some time now, and VB''s syntax is nothing compared to C. Anyway, that''s it. Do you have a website with some pictures of your map editor on it? I''d be interested to see how you''re doing it...


Movie Quote of the Week:

"Mr. Madison, what you have just said is one of the most insanely
idiotic things I have ever heard. At no point in your rambling,
incoherent response were you even close to anything that could
be considered a rational thought. Everyone in this room is now
dumber for having listened to it. I award you no points, and may
God have mercy on your soul."
- The Principal, Billy Madison.
Try http://uk.geocities.com/mentalmantle. Seriously. It''s brilliant.
And I just completely redesigned it so it looks even better.
DarkVertex Beta 0.8 available soon!

Share this post


Link to post
Share on other sites
You figured it out, cool


Movie Quote of the Week:

"Mr. Madison, what you have just said is one of the most insanely
idiotic things I have ever heard. At no point in your rambling,
incoherent response were you even close to anything that could
be considered a rational thought. Everyone in this room is now
dumber for having listened to it. I award you no points, and may
God have mercy on your soul."
- The Principal, Billy Madison.
Try http://uk.geocities.com/mentalmantle. Seriously. It''s brilliant.
And I just completely redesigned it so it looks even better.
DarkVertex Beta 0.8 available soon!

Share this post


Link to post
Share on other sites