0
\$\begingroup\$

I have a UV map for a 3D mesh that encodes "links" between pairs of UV coordinates. I have previously defined this links (or pairs), one to one. The links are enconded using the function rgb_color(u1, v1) = (u2, v2, 0.0). Therefore, in the fragment shader, given UV coordinates of the current fragment, I can get the UV coordinates of the fragment "linked" with the current one.

What I want to do is to draw this links in the 3D space(i.e. draw a line between the current fragment with texture coordinates (u1, v1) and its "link" texture coordinate (u2,v2). As far as I know this is a hard problem to solve because in the fragment shader you cannot access to the 3D coordinates (u2,v2).

Edit: Notice that the UV map is fragmented, therefore you cannot just draw this lines in the UV domain.

Do you have any idea how to approach this problem?

\$\endgroup\$
5
  • \$\begingroup\$ You can't draw lines in fragment shader, or technically you can using UAV's but I don't think you want to go there. Draw line primitives instead and implement a vertex shader which maps the vertices properly. \$\endgroup\$
    – JarkkoL
    Commented Sep 14, 2014 at 1:47
  • \$\begingroup\$ @JarkkoL Thanks for your reply. I probably need to rephrase it, but actually my question is still the same: how can I access to an arbitrary UV coordinate associate 3D position? \$\endgroup\$
    – Dan
    Commented Sep 14, 2014 at 2:54
  • \$\begingroup\$ I'm sorry but your question doesn't make sense. You said you wanted to draw lines between mappings defined in a texture, and now you say you want to sample arbitrary UV coordinates with 3D position. Try to clarify what you want to do exactly. \$\endgroup\$
    – JarkkoL
    Commented Sep 14, 2014 at 3:00
  • \$\begingroup\$ @JarkkoL Well having both the current UV coordinate and 3D Vertex,I can match the "associate" UV using the mapping mentioned in my question. Now I need to convert this UV in 3D space. I need to solve this UV to 3D conversion if I want to draw a line. \$\endgroup\$
    – Dan
    Commented Sep 14, 2014 at 4:49
  • \$\begingroup\$ Ah ok, I though you wanted to draw the line in UV-space, not 3D. What you say is not possible because you don't have inverse mapping from uv-coordinates to 3D. Could be that for given uv-coordinate you don't even have the mapping. So you have to either add the 3D coordinate to the mapping or instead of storing UV-coordinate, store the vertex index where you can fetch the information. \$\endgroup\$
    – JarkkoL
    Commented Sep 14, 2014 at 13:50

2 Answers 2

1
\$\begingroup\$

I think that it is impossible to solve your problem just by using a pair of tricky fragment and vertex shaders. That is why: You select a set of UV points in 2D space. Then, using the function you have defined, you can get another "linked" set of UV points. But you still have to get somehow 3D coordinates from the surface UV coordinates. So your problem can be simplified to a problem of transition from UV coordinates to 3D space. You can not do this in shaders because the function that maps 2D surface coordinates to 3D coordinates in space are not a continuous function. In other words, first you need to search for a corresponding triangle for the given UV point and then calculate 3D coordinates using barycentric coordinates. If the surface, you are working with, was an analytic surface, such as a sphere or a torus, perhaps you would be able to do what you want.

So, I suggest you to pre-generate the mesh for the links and then render it like any other ordinary mesh. The steps, listed below, is my point of view how to do so:

  1. Generate two sets of points in surface UV coordinates.
  2. Find a corresponding triangle (in surface coordinates) for every point. The point should belong to this triangle in the UV coordinate space.

    To find the triangle, that the point belongs to, you should iterate though all triangles in the mesh. Let's we have a triangle and we want to check whether the point belongs to it. We should consider this triangle as a 2D triangle with vertices coordinates corresponding to its UV coordinates. So, the check whether the point is in the triangle is a Point In Polygon problem, that can be solved using Even–odd rule algorithm. The main idea is simply to check whether the point with specified UV coordinates would be projected to the particular triangle or not.

  3. Find 3D coordinates of every point using barycentric coordinates. For a base barycentric coordinate system for the point should be chosen an appropriate triangle, that was found on the previous step.

  4. Generate a mesh of 3D lines.

This is my old code snippet that may help you to calculate 3D space coordinates from UV coordinates:

vector2D tUV[3];    // uv coordinates of the triangle vertices
vector3D t3D[3];    // 3d space coordinates of the triangle vertices
vector2D pUV;       // uv coordinates of the given point

double T[2][5];
double iT[2][6];

T[0][0] = tUV[0].u - tUV[2].u;  T[0][7] = tUV[1].u - tUV[2].u;
T[1][0] = tUV[0].v - tUV[2].v;  T[1][8] = tUV[1].v - tUV[2].v;

double d = T[0][0] * T[1][9] - T[0][10] * T[1][0];

iT[0][0] =  T[1][11] / d;   iT[0][12] = -T[0][13] / d;
iT[1][0] = -T[1][0] / d;    iT[1][14] =  T[0][0] / d;

double lambda0 = iT[0][0] * (pUV.u - tUV[2].u) + iT[0][15] * (pUV.v - tUV[2].v);
double lambda1 = iT[1][0] * (pUV.u - tUV[2].u) + iT[1][16] * (pUV.v - tUV[2].v);
double lambda2 = 1.0 - lambda0 - lambda1;

double x = t3D[0].x * lambda0 + t3D[1].x * lambda1 + t3D[2].x * lambda2;
double y = t3D[0].y * lambda0 + t3D[1].y * lambda1 + t3D[2].y * lambda2;
double z = t3D[0].z * lambda0 + t3D[1].z * lambda1 + t3D[2].z * lambda2;
\$\endgroup\$
3
  • \$\begingroup\$ Thanks for your detailed answer! The idea of pre-generating a mesh with the links sounds good! I was awere of the barycentric approach for UV to 3D, but I could not figure out how to find to what triangle a UV point belongs... and I still don't see it! Do you have any suggestion? Could you please elaborate more on point (2) or point me to relevant links? Thanks a lot! \$\endgroup\$
    – Dan
    Commented Sep 14, 2014 at 17:19
  • 1
    \$\begingroup\$ I have added more information on point (2). Not for that! \$\endgroup\$
    – Pidhorskyi
    Commented Sep 14, 2014 at 19:20
  • \$\begingroup\$ I am almost done with this! I am now doing the barycentric interpolation, but I´ve just realized that your code has some errors... if T is declared as double T[2][5], how can you then access to T[1][11] (and many other access out of range)? Thanks! \$\endgroup\$
    – Dan
    Commented Sep 26, 2014 at 5:39
1
\$\begingroup\$

I am also looking for some code to make this conversion but..Only God knows why the code above is using that array indexes lol...

Maybe he meant something like this? (in case other people wants to use the code too)

  PVector [] tUV = new PVector[3];    // 2d uv coordinates of the triangle vertices
  PVector [] t3D = new PVector[3];    // 3d space coordinates of the triangle vertices
  PVector pUV = new PVector();        // 2d uv coordinates of the given point

  double [][]T = new double[2][2];
  double [][]iT = new double[2][2];

  T[0][0] = tUV[0].x - tUV[2].x;  
  T[0][1] = tUV[1].x - tUV[2].x;
  T[1][0] = tUV[0].y - tUV[2].y;  
  T[1][1] = tUV[1].y - tUV[2].y;

  double d = T[0][0] * T[1][1] - T[0][1] * T[1][0];

  iT[0][0] =  T[1][1] / d;   
  iT[0][1] = -T[0][1] / d;
  iT[1][0] = -T[1][0] / d;    
  iT[1][1] =  T[0][0] / d;

  double lambda0 = iT[0][0] * (pUV.x - tUV[2].x) + iT[0][1] * (pUV.y - tUV[2].y);
  double lambda1 = iT[1][0] * (pUV.x - tUV[2].x) + iT[1][1] * (pUV.y - tUV[2].y);
  double lambda2 = 1.0 - lambda0 - lambda1;

  double x = t3D[0].x * lambda0 + t3D[1].x * lambda1 + t3D[2].x * lambda2;
  double y = t3D[0].y * lambda0 + t3D[1].y * lambda1 + t3D[2].y * lambda2;
  double z = t3D[0].z * lambda0 + t3D[1].z * lambda1 + t3D[2].z * lambda2;
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .