| import numpy as np
|
| import torch
|
| from torch.nn import functional as F
|
|
|
|
|
| def uv_to_xyz_and_normals(verts, f, fmap, bmap, ftov):
|
| vn = estimate_vertex_normals(verts, f, ftov)
|
| pixels_to_set = torch.nonzero(fmap+1)
|
| x_to_set = pixels_to_set[:,0]
|
| y_to_set = pixels_to_set[:,1]
|
| b_coords = bmap[x_to_set, y_to_set, :]
|
| f_coords = fmap[x_to_set, y_to_set]
|
| v_ids = f[f_coords]
|
| points = (b_coords[:,0,None]*verts[:,v_ids[:,0]]
|
| + b_coords[:,1,None]*verts[:,v_ids[:,1]]
|
| + b_coords[:,2,None]*verts[:,v_ids[:,2]])
|
| normals = (b_coords[:,0,None]*vn[:,v_ids[:,0]]
|
| + b_coords[:,1,None]*vn[:,v_ids[:,1]]
|
| + b_coords[:,2,None]*vn[:,v_ids[:,2]])
|
| return points, normals, vn, f_coords
|
|
|
| def estimate_vertex_normals(v, f, ftov):
|
| face_normals = TriNormalsScaled(v, f)
|
| non_scaled_normals = torch.einsum('ij,bjk->bik', ftov, face_normals)
|
| norms = torch.sum(non_scaled_normals ** 2.0, 2) ** 0.5
|
| norms[norms == 0] = 1.0
|
| return torch.div(non_scaled_normals, norms[:,:,None])
|
|
|
| def TriNormalsScaled(v, f):
|
| return torch.cross(_edges_for(v, f, 1, 0), _edges_for(v, f, 2, 0))
|
|
|
| def _edges_for(v, f, cplus, cminus):
|
| return v[:,f[:,cplus]] - v[:,f[:,cminus]]
|
|
|
| def psbody_get_face_visibility(v, n, f, cams, normal_threshold=0.5):
|
| bn, nverts, _ = v.shape
|
| nfaces, _ = f.shape
|
| vis_f = np.zeros([bn, nfaces], dtype='float32')
|
| for i in range(bn):
|
| vis, n_dot_cam = visibility_compute(v=v[i], n=n[i], f=f, cams=cams)
|
| vis_v = (vis == 1) & (n_dot_cam > normal_threshold)
|
| vis_f[i] = np.all(vis_v[0,f],1)
|
| return vis_f
|
|
|
| def compute_uvsampler(vt, ft, tex_size=6):
|
| """
|
| For this mesh, pre-computes the UV coordinates for
|
| F x T x T points.
|
| Returns F x T x T x 2
|
| """
|
| uv = obj2nmr_uvmap(ft, vt, tex_size=tex_size)
|
| uv = uv.reshape(-1, tex_size, tex_size, 2)
|
| return uv
|
|
|
| def obj2nmr_uvmap(ft, vt, tex_size=6):
|
| """
|
| Converts obj uv_map to NMR uv_map (F x T x T x 2),
|
| where tex_size (T) is the sample rate on each face.
|
| """
|
|
|
| uv_map_for_verts = vt[ft]
|
|
|
|
|
| uv_map_for_verts[:, :, 1] = 1 - uv_map_for_verts[:, :, 1]
|
|
|
|
|
| uv_map_for_verts = (2 * uv_map_for_verts) - 1
|
|
|
| alpha = np.arange(tex_size, dtype=float) / (tex_size - 1)
|
| beta = np.arange(tex_size, dtype=float) / (tex_size - 1)
|
| import itertools
|
|
|
| coords = np.stack([p for p in itertools.product(*[alpha, beta])])
|
|
|
|
|
| v2 = uv_map_for_verts[:, 2]
|
| v0v2 = uv_map_for_verts[:, 0] - uv_map_for_verts[:, 2]
|
| v1v2 = uv_map_for_verts[:, 1] - uv_map_for_verts[:, 2]
|
|
|
| uv_map = np.dstack([v0v2, v1v2]).dot(coords.T) + v2.reshape(-1, 2, 1)
|
|
|
|
|
| uv_map = np.transpose(uv_map, (0, 2, 1)).reshape(-1, tex_size, tex_size, 2)
|
|
|
| return uv_map
|
|
|