FastSplatStyler / mesh_helpers.py
incrl's picture
Initial Upload (attempt 2)
5b557cf verified
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