Jump to content
  • Advertisement

Archived

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

johnp

Direct3D Texture Coordinates

This topic is 6941 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

Okay, I give up. For the last week I have been killing myself trying to find out how to calculate vertex texture coordinates in Direct3D immediate mode. I have found plenty of tutorials on doing the actual mapping, but i''m not drawing the polygons, Direct3D is doing that. I just want a u/v coordinate from an x/y/z. Surely it can''t be that tricky? Please help with this one as I''m close to giving up with this 3D stuff. Regards. John.

Share this post


Link to post
Share on other sites
Advertisement
It can be tricky

I have this Problem too, and i only get some Planar Mapping working (Projecting the 3D Coordinates onto 2D ones), and
simple spherical Mapping.
I am still working on an algorithm that equally distributes an Rectangle Texture on to an Complex 3D Mesh without to much streching.

But for the simple Planarmapping, just assign the x Values to u and the z Value to v and scale them, so that they go from 0 to 1.

Lars

Share this post


Link to post
Share on other sites
Will assigning x to u and z to v work for triangles. Also will it work for triangles at any angle, even with a 0 z value?

Thanks for your response.

Share this post


Link to post
Share on other sites
For me, I let the texture coordinates go beyond 1 and 0. All I did was check which direction the plane normal is facing. (if nx > ny and nx > nz etc.) After that I got the position of the vertex and divided it by a constant 256. This is what the code looks like (in visual basic)

With TriangleList(I).TriangleVerts(II)
NormalVec.X = Abs(.nx)
NormalVec.Y = Abs(.ny)
NormalVec.Z = Abs(.nz)
If NormalVec.X >= NormalVec.Y And NormalVec.X >= NormalVec.Z Then
.tu = .Z / TexSizeU
.tv = .Y / TexSizeV
End If
If NormalVec.Y >= NormalVec.X And NormalVec.Y >= NormalVec.Z Then
.tu = .X / TexSizeU
.tv = .Z / TexSizeV
End If
If NormalVec.Z >= NormalVec.Y And NormalVec.Z >= NormalVec.X Then
.tu = .X / TexSizeU
.tv = .Y / TexSizeV
End If
End With

Share this post


Link to post
Share on other sites
There are 2 sides to the texture co-ordinate problem, one incredibly easy, and one much more difficult, and I am unsure which side you are on. On the difficult side, there are numerous complex ways of mapping a skin onto a mesh, which I''m not going to go into because I am no expert in that field. But if you''re just starting out, to get a triangle to map part of your texture is very simple. There is no set formula for mapping x,y,z to u,v as that would defeat the object. These variables are for you to do what you want with. But to get started, you can just pick some arbitrary scheme. Imagine you have a right angled triangle, vertical line on the left, horizontal line on the bottom, diagonal line (hypotenuse) from top-left to bottom right. To map the bottom left half of a square texture onto that triangle, you would assign (0,0) to the top left vertex, (0, 1) to the bottom left vertex, and (1,1) to the bottom right vertex. If it helps, think of the U and V values as percentages of the source texture. A vertex with U=0.5 and V=0.5 will be drawing whatever is right in the middle of your texture.

I may not be understanding (and therefore answering) your question, in which case, I apologize and wish you the best of luck

Share this post


Link to post
Share on other sites
It works with z-Values of 0, but it doesn''t look that good, so if you want it simple check if your objects largest side is lying in the x,y Plane or is it in the x,z plane or the y,z plane, and use the appropriate Values for u,v. You could even decide that per Vertex instead of per Object (like nes8bit) by checking the normals of the Triangle.
So you achieve somekind of Boxed Mapping.

Lars

Share this post


Link to post
Share on other sites
Thanks for the input on this everyone. I have tried the nes8bit solution but and tried tecturing a triangle at all different angles but it does not seem to work if the triangle is on the z axis (all x values the same). Any ideas? Lars W, your ideas sonds interesting. Are you saying I can calculate texture coordinates per vertex based on just the vertex normal? Can you explain a bit further please.

Regards.

John

Share this post


Link to post
Share on other sites
I got some code working based on the suggestions given and it seems to work triangles on any axis. Here it is. This may not be the best way but it works.

//----------------------------------------------------------
void CalculateTextureCoords()
{
//fdata is an array of vertex indices.
//vlist is an array of vertexes
for (unsigned int n = 0; n < fdata.size(); n += 3)
{

//Reference the 3 vertexes that make up the
//triangle
D3DVERTEX& ve1 = vlist[fdata[n]];
D3DVERTEX& ve2 = vlist[fdata[n+1]];
D3DVERTEX& ve3 = vlist[fdata[n+2]];

//create 3 vectors from the vertex structure
D3DVECTOR v1 = D3DVECTOR(ve1.x, ve1.y, ve1.z);
D3DVECTOR v2 = D3DVECTOR(ve2.x, ve2.y, ve2.z);
D3DVECTOR v3 = D3DVECTOR(ve3.x, ve3.y, ve3.z);

//calculate the face normal
D3DVECTOR norm = Normalize( CrossProduct( v3-v2, v3-v1));
norm.x = fabs(norm.x);
norm.y = fabs(norm.y);
norm.z = fabs(norm.z);

//Determine axis and setup x/y variables for min/max tests
float x1, y1, x2, y2, x3, y3;

if (norm.x >= norm.y && norm.x >= norm.z)
{
x1 = v1.z;
y1 = v1.y;
x2 = v2.z;
y2 = v2.y;
x3 = v3.z;
y3 = v3.y;
}
else if (norm.y >= norm.z && norm.y >= norm.z)
{
x1 = v1.x;
y1 = v1.z;
x2 = v2.x;
y2 = v2.z;
x3 = v3.x;
y3 = v3.z;
} else if (norm.z >= norm.y && norm.z >= norm.x)
{
x1 = v1.x;
y1 = v1.y;
x2 = v2.x;
y2 = v2.y;
x3 = v3.x;
y3 = v3.y;
}

TFloatRect r = BoundingRect(x1, y1, x2, y2, x3, y3);

float width = r.right - r.left;
float height = r.top - r.bottom;


//Set the u/v coordinates. This will stretch the entire texture
//over the triangle.
ve1.tu = (x1 - r.left) / width;
ve1.tv = (r.top - y1) / height;

ve2.tu = (x2 - r.left) / width;
ve2.tv = (r.top - y2) / height;

ve3.tu = (x3 - r.left) / width;
ve3.tv = (r.top - y3) / height;

}
}
//----------------------------------------------------------
TFloatRect BoundingRect(float x1, float y1, float x2, float y2, float x3, float y3)
{
//Initialise bounding box to maximum size and do min max
//tests on the 3 xy pairs
TFloatRect r(FLT_MAX, -FLT_MAX, -FLT_MAX, FLT_MAX);

r.left = std::min(x1, r.left);
r.right = std::max(x1, r.right);
r.left = std::min(x2, r.left);
r.right = std::max(x2, r.right);
r.left = std::min(x3, r.left);
r.right = std::max(x3, r.right);

r.bottom = std::min(y1, r.bottom);
r.top = std::max(y1, r.top);
r.bottom = std::min(y2, r.bottom);
r.top = std::max(y2, r.top);
r.bottom = std::min(y3, r.bottom);
r.top = std::max(y3, r.top);

return r;
}


Share this post


Link to post
Share on other sites
Thanks Lars. For now this solution seems to work. Thanks again the help I got from yourself and others on this. Posting the code will hopefully help others.

Regards.

John

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!