Texture coord question

Started by
10 comments, last by Mulligan 21 years, 6 months ago
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?
Advertisement
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.
Hi!

Im also working on a similiar project.. are you using MFC or win32app?

Bye

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
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]
My opinion is a recombination and regurgitation of the opinions of those around me. I bring nothing new to the table, and as such, can be safely ignored.[ Useful things - Firefox | GLee | Boost | DevIL ]
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?
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]
My opinion is a recombination and regurgitation of the opinions of those around me. I bring nothing new to the table, and as such, can be safely ignored.[ Useful things - Firefox | GLee | Boost | DevIL ]
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]
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]
My opinion is a recombination and regurgitation of the opinions of those around me. I bring nothing new to the table, and as such, can be safely ignored.[ Useful things - Firefox | GLee | Boost | DevIL ]
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]

This topic is closed to new replies.

Advertisement