【python】处理3D模型

用meshio处理3D模型

import meshio
import os
def ply2obj():#格式转换
  for i in os.listdir("input"):
    name=i.split(".")[0]
    mesh = meshio.read("./input/"+name+".ply")
    mesh.write("./output/"+name+".obj", file_format="obj")
def getN(vertices,faces):#计算面法线
    ns=[];
    for f in faces:
        [v1, v2, v3] = f
        x1, y1, z1 = vertices[v1]#获取3个点的坐标
        x2, y2, z2 = vertices[v2]
        x3, y3, z3 = vertices[v3]
        p1 = np.array([x1, y1, z1])
        p2 = np.array([x2, y2, z2])
        p3 = np.array([x3, y3, z3])
        n=np.cross(p1-p2, p2-p3)
        l=np.dot(n,n)**0.5
        ns.append((n/l).tolist())
    return ns;

pymesh处理3D模型

import pymesh
import numpy as np
#加载
mesh=pymesh.load_mesh("×.obj")
#保存
pymesh.save_mesh("×.obj",mesh)
#对模型进行仿射变换
def applyMatrix(mesh,mat):#condition: mesh only have face and vertice
    vertices = mesh.vertices.copy()
    faces = mesh.faces
    nr=vertices.shape[0]
    for i in range(nr):
        v0=vertices[i]
        v=np.append(v0,1).T
        v=np.dot(mat,v)
        v=v.T
        v0=v[0:3]
        vertices[i]=v0
    return pymesh.form_mesh(vertices, faces)
#放缩
def scale(mesh,x=1.,y=1.,z=1.):
    return applyMatrix(mesh,np.array([
             [x,0,0,0],
             [0,y,0,0],
             [0,0,z,0],
             [0,0,0,1] ]))
#移动
def move(mesh,x=0,y=0,z=0):
    return applyMatrix(mesh,np.array([
             [1,0,0,x],
             [0,1,0,x],
             [0,0,1,x],
             [0,0,0,1]
             ]))
#合并网格
mesh=pymesh.merge_meshes([m1,m2])
#切割网络
def updateFlag(flag,mesh,mesh0):
    for i in range(mesh.vertices.shape[0]):
        if flag[i]==1:
            for j in range(mesh0.vertices.shape[0]):
                a=mesh.vertices[i]
                b=mesh0.vertices[j]
                if a[0]==b[0] and a[1]==b[1] and a[2]==b[2]:
                    flag[i]=0
    return flag
def submesh(mesh):
    meshs=[]
    nr = mesh.vertices.shape[0]
    flag=np.ones([nr,1])#flag is 1 means that this vertex need process
    for i in range(mesh.vertices.shape[0]):
        if flag[i]==1:
            mesh0 = pymesh.submesh(mesh, element_indices=i, num_rings=1)
            meshs.append(mesh0)
            flag = updateFlag(flag, mesh, mesh0)
    return meshs

QEM简化模型

#from Mesh import Mesh
import math
import numpy as np
class Simplify:
    def __init__(self, mesh,ratio):#ratio为压缩率
        self.mesh=mesh
        self.face=self.mesh.face
        self.vertex=self.mesh.vertex
        self.check()#合并重叠点
        self.normal=self.getNoraml()#法线不需要实时更新
        count=int((1-ratio)*len(self.vertex))#要合并的次数
        self.start(count)

    def start(self,count):
        edge=self.mesh.getEdge()
        for ii in range(count):
            #self.normal=self.getNoraml()#每次压缩都要重新计算法线
            print(""+str( round(100*ii/count,2) )+'%')
            listMerge=[]#记录所有合并方式
            for e in edge:
                if not e[0]==e[1]:
                    p1=self.vertex[e[0]-1]
                    p2=self.vertex[e[1]-1]
                    p3=[]
                    for j in range(3):
                        p3.append( (p1[j]+p2[j])/2 )
                    listMerge.append([ e[0],e[1],p1 ])
                    listMerge.append([ e[0],e[1],p2 ])
                    listMerge.append([ e[0],e[1],p3 ])
            if len(listMerge)==0:
                print('len(listMerge)==0')
                break
            param=listMerge[0]
            cMin=self.cost(param[0],param[1],param[2])
            #print()
            #print(cMin,param)
            for i in listMerge:
                c0=self.cost(i[0],i[1],i[2])
                #print(c0,i)
                if c0<cMin:
                    cMin=c0
                    param=i
            self.merge(param[0],param[1],param[2])
            for e in edge:
                for j in range(2):
                    if e[j]==param[1]:
                        e[j]=param[0]

        self.mesh.deDedundancy()
        self.mesh.updateFace()
        self.mesh.updateVertex()
         
    def getNoraml(self):
        normal=[]
        k=int(len(self.face[0])/3)
        for i in range(len(self.face)):
            i0=self.face[i][0]-1
            i1=self.face[i][k]-1
            i2=self.face[i][2*k]-1
            a=np.array(self.vertex[i0])
            b=np.array(self.vertex[i1])
            c=np.array(self.vertex[i2])
            v1=a-b
            v2=a-c
            v3=np.cross(v1, v2)
            v3=v3/np.linalg.norm(v3)
            normal.append(v3.tolist())
            #print(v1, v2,v3)
            #print(a,c,v2)#三个点的坐标
        return normal
    def check(self):#检查网格是否有重叠点
        for i in range(len(self.vertex)):
            for j in range(len(self.vertex)):
                if i<j:
                    a=self.vertex[i]
                    b=self.vertex[j]
                    if abs(a[0]-b[0])+abs(a[1]-b[1])+abs(a[2]-b[2])==0:
                        print(i,j)#l[j]=i

    def deleteErrorFace(self):#删除错误的三角面
        print('简化前-面个数:'+str(len(self.face)))
        if len(self.face)>0:            
            flag=[]#标记哪些边需要被删除
            for i in range(len(self.face)):
                flag.append(0)
            k=int(len(self.face[0])/3)
            for i in range(len(self.face)):
                a=self.face[i][0  ]
                b=self.face[i][k  ]
                c=self.face[i][2*k]
                if a==b or a==c or b==c:
                    flag[i]=1
            self.mesh.face=[]
            for i in range(len(flag)):
                if flag[i]==0:
                    self.mesh.face.append(self.face[i])
            self.face=self.mesh.face
            print('简化后-面个数:'+str(len(self.face)))
    def merge(self,v1,v2,pos):#修改v1 删除v2
        self.vertex[v1-1][0]=pos[0]
        self.vertex[v1-1][1]=pos[1]
        self.vertex[v1-1][2]=pos[2]
        if len(self.face)>0:
            k=int(len(self.face[0])/3)
            for i in range(len(self.face)):
                a=self.face[i][0  ]
                b=self.face[i][k  ]
                c=self.face[i][2*k]
                if a==v2:
                    self.face[i][0  ]=v1
                if b==v2:
                    self.face[i][k  ]=v1    
                if c==v2:
                    self.face[i][2*k]=v1   
    def cost(self,v1,v2,pos):
        import numpy as np
        vector1=np.array(self.vertex[v1-1])-np.array(pos)
        vector2=np.array(self.vertex[v2-1])-np.array(pos)
        c=0
        for i in range(len(self.face)):
            f=self.face[i]
            n=np.array(self.normal[i])
            #print(n,vector1,vector2)
            if f[0]==v1 or f[1]==v1 or f[2]==v1:
                c=c+abs( np.dot(n,vector1) )
            if f[0]==v2 or f[1]==v2 or f[2]==v2:
                c=c+abs( np.dot(n,vector2) )
        if math.isnan(c):
            c=999999
        return c
        #self.normal
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值