Skip to content

Instantly share code, notes, and snippets.

@nobnak
Last active August 17, 2023 08:40
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nobnak/d64bb638ff445a6de83a to your computer and use it in GitHub Desktop.
Save nobnak/d64bb638ff445a6de83a to your computer and use it in GitHub Desktop.
UV -> World Position (For Unity)
public class UVWorld : MonoBehaviour {
Mesh _mesh;
Vector3[] _vertices;
int[] _triangles;
Vector2[] _uvs;
Vector3[] _normals;
Triangle2D[] _uvTris;
void Awake() {
_mesh = GetComponent<MeshFilter>().sharedMesh;
Init();
}
public void Init() {
_triangles = _mesh.triangles;
_vertices = _mesh.vertices;
_normals = _mesh.normals;
_uvs = _mesh.uv;
var triangleCount = _triangles.Length / 3;
_uvTris = new Triangle2D[triangleCount];
for (var i = 0; i < triangleCount; i++) {
Vector2 uva, uvb, uvc;
TriangleUvs(i, out uva, out uvb, out uvc);
_uvTris[i] = new Triangle2D(uva, uvb, uvc);
}
}
public bool Local(Vector2 uv, out Vector3 pos, out Vector3 normal) {
for (var i = 0; i < _uvTris.Length; i++) {
var uvTri = _uvTris[i];
float s, t;
if (uvTri.Solve(uv, out s, out t)) {
var r = 1f - (s + t);
pos = InterpolatePosition(i, s, t, r);
normal = InterpolateNormal(i, s, t, r);
return true;
}
}
pos = default(Vector3);
normal = default(Vector3);
return false;
}
public bool World(Vector2 uv, out Vector3 pos, out Vector3 normal) {
var result = Local (uv, out pos, out normal);
if (result) {
pos = transform.TransformPoint (pos);
normal = transform.TransformDirection (normal);
}
return result;
}
public void TriangleUvs(int i, out Vector2 uva, out Vector2 uvb, out Vector2 uvc) {
var i3 = 3 * i;
uva = _uvs [_triangles [i3]];
uvb = _uvs [_triangles [i3 + 1]];
uvc = _uvs [_triangles [i3 + 2]];
}
public void TriangleVertices(int i, out Vector3 va, out Vector3 vb, out Vector3 vc) {
var i3 = 3 * i;
va = _vertices [_triangles [i3]];
vb = _vertices [_triangles [i3 + 1]];
vc = _vertices [_triangles [i3 + 2]];
}
public void TriangleNormals(int i, out Vector3 na, out Vector3 nb, out Vector3 nc) {
var i3 = 3 * i;
na = _normals [_triangles [i3]];
nb = _normals [_triangles [i3 + 1]];
nc = _normals [_triangles [i3 + 2]];
}
public Vector3 InterpolatePosition (int i, float s, float t, float r) {
Vector3 va, vb, vc;
TriangleVertices(i, out va, out vb, out vc);
return r * va + s * vb + t * vc;
}
public Vector3 InterpolateNormal(int i, float s, float t, float r) {
Vector3 na, nb, nc;
TriangleNormals (i, out na, out nb, out nc);
return r * na + s * nb + t * nc;
}
public class Triangle2D {
public Vector2 a;
public Vector2 ab;
public Vector2 ac;
public float inv_det_abac;
public bool valid;
public Triangle2D(Vector2 a, Vector2 b, Vector2 c) {
this.a = a;
this.ab = b - a;
this.ac = c - a;
var det_abac = (ab.x * ac.y - ab.y * ac.x);
this.inv_det_abac = 1f / det_abac;
this.valid = (det_abac < -Mathf.Epsilon || Mathf.Epsilon < det_abac);
}
public bool Solve(Vector2 uv, out float s, out float t) {
if (!valid) {
s = 0f;
t = 0f;
return false;
}
var ap = uv - a;
var det_apac = ap.x * ac.y - ap.y * ac.x;
if ((s = det_apac * inv_det_abac) < 0f) {
t = 0f;
return false;
}
var det_abap = ab.x * ap.y - ab.y * ap.x;
if ((t = det_abap * inv_det_abac) < 0f)
return false;
var r = 1f - (s + t);
return r >= 0f;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment