Spaces:
Sleeping
Sleeping
| import trimesh | |
| import torch | |
| import numpy as np | |
| def loadMesh(mesh_fn): | |
| mesh = trimesh.load(mesh_fn, force="mesh") | |
| #mesh = trimesh.load_mesh(mesh_fn) | |
| return mesh | |
| def getUVs(mesh): | |
| if (isinstance(mesh.visual,trimesh.visual.color.ColorVisuals)): | |
| uvs = mesh.visual.to_texture().uv | |
| else: | |
| uvs = mesh.visual.uv | |
| return uvs | |
| def setTexture(mesh,texture): | |
| from PIL import Image | |
| if texture.dtype == np.float32 or texture.dtype == np.float64: | |
| texture = (255*texture).astype(np.uint8) | |
| im = Image.fromarray(texture) | |
| tex = trimesh.visual.TextureVisuals(uv=getUVs(mesh),image=im) | |
| new_mesh=trimesh.Trimesh(vertices=mesh.vertices, faces=mesh.faces, visual=tex, validate=True, process=True) | |
| return new_mesh | |
| def sampleSurface(mesh,N,return_x=False,device='cpu'): | |
| result = trimesh.sample.sample_surface(mesh,N,face_weight=None,sample_color=return_x) | |
| pos3D = result[0] | |
| face_indexes = result[1] | |
| if return_x: | |
| x = result[2][:,:3]/255 # No alpha channels, between 0-1 | |
| # Determine normals (the same as face normals) | |
| normals = mesh.face_normals[face_indexes] | |
| if return_x: | |
| # Determine UVs associated with 3D points | |
| vertices_all = mesh.vertices | |
| uvs_all = getUVs(mesh) | |
| faces = mesh.faces[face_indexes] | |
| a = vertices_all[faces[:,0]] | |
| b = vertices_all[faces[:,1]] | |
| c = vertices_all[faces[:,2]] | |
| w0, w1, w2 = getBarycentricWeights(pos3D,a,b,c,use_numpy=True) | |
| w0 = np.expand_dims(w0,axis=1) | |
| w1 = np.expand_dims(w1,axis=1) | |
| w2 = np.expand_dims(w2,axis=1) | |
| uvs = w0 * uvs_all[faces[:,0]] + w1 * uvs_all[faces[:,1]] + w2 * uvs_all[faces[:,2]] | |
| uvs = torch.tensor(uvs,dtype=torch.float).to(device) | |
| # Return as tensor | |
| pos3D = torch.tensor(pos3D,dtype=torch.float).to(device) | |
| normals = torch.tensor(normals,dtype=torch.float).to(device) | |
| if return_x: | |
| x = torch.tensor(x,dtype=torch.float).to(device) | |
| return pos3D,normals,uvs,x | |
| else: | |
| return pos3D,normals | |
| def getBarycentricWeights(p,a,b,c,use_numpy=False): | |
| # Taken from https://gamedev.stackexchange.com/questions/23743/whats-the-most-efficient-way-to-find-barycentric-coordinates | |
| v0 = b-a | |
| v1 = c-a | |
| v2 = p-a | |
| if use_numpy: | |
| d00 = np.sum(v0*v0,axis=1) | |
| d01 = np.sum(v0*v1,axis=1) | |
| d11 = np.sum(v1*v1,axis=1) | |
| d20 = np.sum(v2*v0,axis=1) | |
| d21 = np.sum(v2*v1,axis=1) | |
| else: | |
| d00 = torch.sum(v0*v0,dim=1) | |
| d01 = torch.sum(v0*v1,dim=1) | |
| d11 = torch.sum(v1*v1,dim=1) | |
| d20 = torch.sum(v2*v0,dim=1) | |
| d21 = torch.sum(v2*v1,dim=1) | |
| denom = d00*d11 - d01*d01 | |
| w1 = (d11 * d20 - d01 * d21)/denom | |
| w2 = (d00 * d21 - d01 * d20)/denom | |
| w0 = 1 - w1 - w2 | |
| return w0,w1,w2 |