Sign in to follow this  
zarfius

Calculating UV coordinates from vertices and normal

Recommended Posts

Hi I have a bit of math question regarding calculating UV coordinates for repeating textures in level geometry. Say I have a quad representing the wall in a room. I want the texture to be repeated depending on the length and height of the wall, and similarly for the floor and roof. So say the vertices and uv coordinates of my wall quad look something like this: x,y,z u,v 0,0,0 0,0 5,0,0 5,0 5,2,0 5,2 0,2,0 0,2 (in this case the normal is on the z coordinate) And similarly for a floor quad I might have something like this x,y,z u,v 0,0,0 0,0 5,0,0 5,0 5,0,5 5,5 0,0,5 0,5 (in this case the normal is on the y coordinate) Is there a formula to use the normal of the quad to determine the uv coordinates in a similar fashion to the examples above? I hope that makes some sense. Thanks

Share this post


Link to post
Share on other sites
No, the formula is to compute the length and height of you wall. All you need it the length of 3D vectors

U = VectorLength(wallPointBottom1 - WallPointBottom2);
V = VectorLength(WallPointTop2 - WallPointBottom2);

Share this post


Link to post
Share on other sites
Thanks

Although, the problem with that solution is that it doesn't take into account the offset when 2 walls are sitting next to each other as shown.

In other words, if the left wall has u = 5.5 then the wall on the right should start it's u = 5.5 (or 0.5) to compensate.

For a vertical wall this happens to be the same value as the x coordinate on either wall, but depending on the normal it could be the y or z coordinate.

Share this post


Link to post
Share on other sites
I had this when doing my lightmapper. (long story)

The fix I came up with was simply to check the normal and it's sign and basically find out which "box" face I was mapping by picking the biggest abs of each component and then checking the sign.

When that was done, I used the actual worldspace positions x/y/z for the UV, picking the other two values based on what box face I was on iyswim.

You could further modify it for walls that are vertical but angled, by making a matrix out of the normal and three endpoints as suggested above, then using the x/y components out of that. This breaks up the matching though

Share this post


Link to post
Share on other sites
The thing is, there seems to be a pattern with what I'm trying to achieve but I just can't seem to get the math right. For example, these are the results I'm expecting to see:

Normal U V
(1,0,0) y z
(0,1,0) x z
(0,0,1) x y

The UV coordinates should be the same as 2 of the 3 x, y or z values of the vertex. The 2 values to extract seem to be the ones that are set to zero in the normal.

This doesn't take into account a normal pointing in a non-axis direction like (0.5, 0, 0.5) but I get the feeling there might be a way to calculate the UV coordinates for something like that anyway once I work out the rest.

Perhaps I'm going about it the wrong way and I should be using the direction of the vectors that go along the edges of the quad.

Perhaps my quest is impossible and I should just write some code to handle the 6 axis aligned normals and forget about the rest.

Share this post


Link to post
Share on other sites
This will probably be a repeat of what's already been said, but I'll go ahead and throw it out there...

As I understand it, the goal is to texture map the surfaces so that the alignment is logical and so that the transitions are seamless from surface to surface (that is, there are no discontinuities like the one in your example image).

To do this, you can think of all surfaces that share a given normal as being projected onto a plane with that normal (I think this was suggested earlier in the thread). You then build a coordinate frame for each of these planes, transform the vertices of each surface that you want to texture map into the local space of this frame, and then compute the texture coordinates from the resulting x, y coordinates.

Whenever you get to a new surface you want to texture map, you should be able to construct the basis for the plane onto which the surface projects in such a way that it will always come out the same for every surface that lies on that plane. For this I would use the standard billboarding technique of crossing the normal with the 'optimal' cardinal axis, and then crossing again to yield the complete basis (ask if you need more details on this).

A potential problem with this method is that a surface may start 'in the middle' of a texture, which may not be what you want. In that case you could instead build the basis from that particular surface (using the normal, a corner, and an edge), but then you're back to the problem of aligning textures across connected, coplanar faces. Also, aligning the texture properly to an edge of one surface might knock it out of alignment with another edge; in these cases there would be no one 'right' solution, so it would be difficult to automate the alignment in this case.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this