I am writing a map decompiler for the video game Tron 2.0 and its map editor, DEdit. DEdit requires a set of three vectors in order to correctly map textures to each model. The vectors are what I believe to be the texture origin, the U-axis, and the V-axis. All three vectors are in world space and U and V are normalized but may have a scalar applied.

The problem I'm having is that the texture origin does not match the model's center, likely on account of offsets and rotation. The U and V axes do not match any vertex, triangle, or plane tangent / bitangent I have found either. Ideally, I'd like to know how to solve all three, but I'd rather just focus on the origin for now. (I couldn't find any past questions related to this subject either.) Here's what I know:

Tron 2.0 is based on a modified Lithtech Jupiter engine. This is the same engine that was used to power No One Lives Forever 2 and fortunately, one whose source code has been made available. (For the sake of simplicity, I am going to refer to No One Lives Forever 2 as NOLF2 from here on.)

The binary map files I am analyzing contain vertex normals, positions, and UV's. I also have plane normals and texture dimensions.

Per the NOLF2 source, UV's are calculated in the following manner:

//O is the texture origin.

uv.u = U.Dot(pos - O) / tex.width;
uv.v = V.Dot(pos - O) / tex.height;

I have found no reason to believe either formula was changed for Tron 2.0 as the UV's I'm seeing in the compiled map match the vectors I'm seeing in the source map:

//Source Map (LTA file):

O = XYZ(61.142525, -66.681351, -2.681343);

tex.width = 128;
tex.height = 128;   

scale.u = 64;       //U *= tex.width / scale.u
scale.v = 128;      //V *= tex.height / scale.v

U = XYZ(0.551275, -1.359429, -1.359429);
V = XYZ(0.679715, -0.362181, 0.637819);

//Compiled Map (DAT file):

center = XYZ(69.746429, -57.017303, -5.2882347)

planes[0].normal = XYZ(0.456155, -0.690651, -0.561181);

tris[0].pos[0] = XYZ(69.962921, -88.432220, -24.432213);
tris[0].pos[1] = XYZ(82.267418, -75.580544, -30.247208);
tris[0].pos[2] = XYZ(109.21921, -85.164658, 3.4558060);

tris[0].uvs[0] = UV(0.49999994, -8.0748791e-008);
tris[0].uvs[1] = UV(0.47826001, -5.4909982e-008);
tris[0].uvs[2] = UV(0.33818126, 0.33818075);

What I believe has changed is how Tron 2.0 calculates the three vectors from the UV values. Here is a brief summary of how NOLF2 does it:

//Project UV coordinates into 3D space.

//uv.v is negated for... reasons?

a = XYZ(uv1.u, -uv1.v, 0.0f);
b = XYZ(uv2.u, -uv2.v, 0.0f);
c = XYZ(uv3.u, -uv3.v, 0.0f);

//Find the barycentric coordinates for O, U, and V in UV space.

//Barycentric coordinates are not clamped between 1 and -1.

//That said, if the triangle area is nearly zero,
//XYZ(1.0f, 0.0f, 0.0f) is returned.

bcO = GetBaryCoords(a, b, c, XYZ(0.0f, 0.0f, 0.0f));
bcU = GetBaryCoords(a, b, c, XYZ(1.0f, 0.0f, 0.0f));
bcV = GetBaryCoords(a, b, c, XYZ(0.0f, 1.0f, 0.0f));

//Convert O, U, V to world space.

O = bcO.x * pos1 + bcO.y * pos2 + bcO.z * pos3;
U = (bcU.x * pos1 + bcU.y * pos2 + bcU.z * pos3) - O;
V = (bcV.x * pos1 + bcV.y * pos2 + bcV.z * pos3) - O;

//Find the scale of U and V.

scale.u = texwidth / U.Mag();
scale.v = texheight / V.Mag();

There's a little more done to ensure U and V are perpendicular to the normal and to each other but you get the idea.

That said, none of it works for Tron 2.0. I have tried variations: not negating the v values, clamping the barycentric coordinates, and working with near-zero areas. I have also tried using Lengyel’s Method to at least find U and V but my results are always incorrect.

Attacking the problem mathematically, the best I can do is to solve for the magnitude of O. That doesn't seem very helpful however, and I would still need to know the value of U or V, which I don't.

Is there another way to calculate the texture origin that I'm not aware of? My Linear Algebra skills are rusty, and I could be missing something obvious.

Edit# 1:

I apologize I did not explain the texture origin in better detail.

DEdit, the map editor, keeps track of the initial position where a texture is applied. This position is usually the center of the model but not always. (Dome primitives have the same "center" as sphere primitives, for example.) The texture origin value reflects that initial position plus any transformations applied.

As for UV values, DEdit generates them when compiling the map but it doesn't make use of them otherwise. Reversing the process should be possible because the UV's generated reflect the transformations applied to O, U, and V. From my understanding, the texture origin is the UV center in world space.

Before compilation, After decompilation

  • \$\begingroup\$ It's not clear to me where you want the texture origin to be. This seems like it would be arbitrary, or chosen based on the image contents of the texture according to artistic direction. If you have UVs for each vertex, then I'm not sure what you'd use the O U and V vectors for at all - the vertex UVs should be sufficient for texture mapping, no? Could you try including some screenshots or diagrams demonstrating the consequences of a correct versus incorrect value for these parameters? \$\endgroup\$ – DMGregory Jul 21 '18 at 12:59
  • \$\begingroup\$ That's a good point, and I apologize for not making that clearer in my original post. I will revise it shortly and work on getting before and after shots demonstrating the problem visually. \$\endgroup\$ – KainXavier Jul 21 '18 at 20:54

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Browse other questions tagged or ask your own question.