Subdividing a quadrangle's uv coordinates?

Started by
1 comment, last by Spa8nky 12 years, 8 months ago
I would like to subdivide my quadrangle so that it can be divided into n number of quadrangles along the u and along the v texture coordinates.

Each quadrangle is orientated in 3 dimensions (x, y, z).


2 subdivisions example:


----------- -------------
| | | | |
| | => |----- |----- |
| | | | |
----------- ------------


The scaling of each new quadrangle subdivision is simple enough:

Original Quadrangle Size / Number Subdivisions

The problem I am encountering is how to offset each one of the quadrangle subdivisions so they patch together to recreate the original texture seamlessly.

This might also appear simple but I am working in 3D and I need to take all dimensions into account:



for (int x = 0; x < numSubDivisions; ++x)
{
for (int y = 0; y < numSubDivisions; ++y)
{
for (int z = 0; z < numSubDivisions; ++z)
{


as I am subdividing quadrangle faces on a cube.

So far I have tried determining the offset based on the rotation of the quadrangle but that doesn't offset the textures correctly:



Vector3 uvOffset = new Vector3();
uvOffset.X = x * subDivSize;
uvOffset.Y = y * subDivSize;
uvOffset.Z = z * subDivSize;

tile.Faces[0].UVScaleOffset(scale, scale, Math.Abs(Vector3.Dot(uvOffset, tile.Faces[0].Rotation.Right)), Math.Abs(Vector3.Dot(uvOffset, tile.Faces[0].Rotation.Up)));
tile.Faces[1].UVScaleOffset(scale, scale, Math.Abs(Vector3.Dot(uvOffset, tile.Faces[1].Rotation.Right)), Math.Abs(Vector3.Dot(uvOffset, tile.Faces[1].Rotation.Up)));
tile.Faces[2].UVScaleOffset(scale, scale, Math.Abs(Vector3.Dot(uvOffset, tile.Faces[2].Rotation.Right)), Math.Abs(Vector3.Dot(uvOffset, tile.Faces[2].Rotation.Up)));
tile.Faces[3].UVScaleOffset(scale, scale, Math.Abs(Vector3.Dot(uvOffset, tile.Faces[3].Rotation.Right)), Math.Abs(Vector3.Dot(uvOffset, tile.Faces[3].Rotation.Up)));
tile.Faces[4].UVScaleOffset(scale, scale, Math.Abs(Vector3.Dot(uvOffset, tile.Faces[4].Rotation.Right)), Math.Abs(Vector3.Dot(uvOffset, tile.Faces[4].Rotation.Up)));
tile.Faces[5].UVScaleOffset(scale, scale, Math.Abs(Vector3.Dot(uvOffset, tile.Faces[5].Rotation.Right)), Math.Abs(Vector3.Dot(uvOffset, tile.Faces[5].Rotation.Up)));


The UVScaleOffset method is as follows:



public void UVScaleOffset(float uScale, float vScale, float uOffset, float vOffset)
{
// Always use original full range coordinates for scaling
vertices[0].TexCoordDimension.X = textureCoordinates[0].X * uScale;
vertices[0].TexCoordDimension.Y = textureCoordinates[0].Y * vScale;
vertices[1].TexCoordDimension.X = textureCoordinates[1].X * uScale;
vertices[1].TexCoordDimension.Y = textureCoordinates[1].Y * vScale;
vertices[2].TexCoordDimension.X = textureCoordinates[2].X * uScale;
vertices[2].TexCoordDimension.Y = textureCoordinates[2].Y * vScale;
vertices[3].TexCoordDimension.X = textureCoordinates[3].X * uScale;
vertices[3].TexCoordDimension.Y = textureCoordinates[3].Y * vScale;

vertices[0].TexCoordDimension.X += uOffset;
vertices[0].TexCoordDimension.Y += vOffset;
vertices[1].TexCoordDimension.X += uOffset;
vertices[1].TexCoordDimension.Y += vOffset;
vertices[2].TexCoordDimension.X += uOffset;
vertices[2].TexCoordDimension.Y += vOffset;
vertices[3].TexCoordDimension.X += uOffset;
vertices[3].TexCoordDimension.Y += vOffset;
}


Has anyone got any ideas that might help, or advice on how to approach this differently?
Advertisement
By "quadrangle" do you mean "rectangle" or "convex quadrilateral"? From your description, you seem to want "rectangle", which is what I'll assume here.

Let the rectangle have vertices P00, P10, P01, and P11. The rectangle is in a plane with unit-length normal N; that is, the plane equation is Dot(N,X-P00) = 0, where X is any point on the plane (including any of the four vertices). Let U and V be unit-length vectors such that U, V, and N are mutually perpendicular. A point X in the plane can be represented as X = P00 + a*U + b*V. The 2-tuple (a,b) is a representation of X in the 2D coordinate system of the plane. Compute (a00,b00), (a10,b10), (a01,b01), and (a11,b11) for the vertices of the rectangle. These 2-tuples are an axis-aligned rectangle in ab-space. You can now subdivide this rectangle. For any (a,b) that is in the subdivision, you can always "lift" it back to 3D by computing x = P00 + a*U + b*V.
Hi Dave and thank you for the help.
By "quadrangle" do you mean "rectangle" or "convex quadrilateral"? From your description, you seem to want "rectangle", which is what I'll assume here.


I'm referring to a shape drawn using 3D coordinates that has 4 vertices and 4 sides (2 sets of parallel sides)

Let U and V be unit-length vectors such that U, V, and N are mutually perpendicular.[/quote]

I have to decide in which direction the U and V axes are orientated based on the plane normal. I can use a cross product but it needs to be tailored to force the U axis to point "right along the screen" and the V axis to point "up along the screen" when drawn using counter clockwise culling and viewed from a camera.

So a normal of (0, 1, 0) would produce:

U axis of (1, 0, 0)
V axis of (0, 0, 1)

The 2-tuple (a,b) is a representation of X in the 2D coordinate system of the plane. Compute (a00,b00), (a10,b10), (a01,b01), and (a11,b11) for the vertices of the rectangle.[/quote]

I'm not sure what you mean here.

I have my original vertices for the quadrangle being subdivided (P00, P10, P01, and P11). I would like to calculate the U and V texture coordinates for each of the subdivisions.

How would I calculate a00 if I have a 3D point for the vertexIs it a case of 'ab * Vector3.UnitX'?


Vector3 ab = new Vector3();
ab.X = tile.Faces[0].Vertices[0].Column4.X;
ab.Y = tile.Faces[0].Vertices[0].Column4.Y;
ab.Z = tile.Faces[0].Vertices[0].Column4.Z;
Vector3 x = P00 + (ab * Vector3.UnitX) + (ab * Vector3.UnitY);


This doesn't give me a UV coordinate for the subdivided quadrangle.

This topic is closed to new replies.

Advertisement