Code Vonc

Lissage Catmull-Clark

v 1.0

Script Python pour Cinéma 4D R13+.

TéléchargerDownload
Faire un donMake a donation
Comment installer ?How to install ?
CommentairesComments

Lisse un objet selon la méthode Catmull-Clark sans le subdiviser.



import c4d
from c4d import gui, Vector
from c4d.utils import Neighbor

def moyenneVecteur(obj, vecs) :
    q = len(vecs)
    if not q : return Vector()
    
    m = Vector()
    for v in vecs :
        m += obj.GetPoint(v)
    m /= q
    
    return m

def catmullclark(obj, i, n, ) :
    polys = n.GetPointPolys(i)
    points = [] # Points adjacents au point i
    
    nb = len(polys) # Nombre de polys adjacents au point i
    ps = [] # Points de surface
    pma = [] # Points de milieu d'arête
    
    for p in polys :
        p = obj.GetPolygon(p)
        points.extend([p.a, p.b, p.c, p.d])
    points = list(set(points))
    
    for pt in points :
        if pt == i : continue
        arete = n.GetEdgePolys(i, pt)
        if arete == (-1, -1) :
            ps.append(pt)
        else :
            pma.append(pt)
    
    Mps = moyenneVecteur(obj, ps)
    Mpma = moyenneVecteur(obj, pma)
    Po = obj.GetPoint(i)
    
    if not ps :
        pos = Mpma
    elif nb > 2 :
        pos = Mps + 2*Mpma + (nb-3)*Po
        pos /= nb
    else :
        pos = Mpma
    
    #pos = (Po - pos) + Po
    
    return (i, pos)

def convertiSel(doc, obj) :
    bs = obj.GetPointS()
    bs = bs.GetClone()
    mode = doc.GetMode()
    
    if mode != c4d.Mpoints :
        bs.DeselectAll()
    
    if mode == c4d.Mpolygons :
        bsp = obj.GetPolygonS()
        bspNb = bsp.GetCount()
        if not bspNb :
            bs.DeselectAll()
        else :
            nbpolys = obj.GetPolygonCount()
            for index, selec in enumerate(bsp.GetAll(nbpolys)) :
                if not selec : continue
                poly = obj.GetPolygon(index)
                bs.Select(poly.a)
                bs.Select(poly.b)
                bs.Select(poly.c)
                bs.Select(poly.d)  
        
    return bs

def main(obj):
    if not obj : return
    if not obj.CheckType(c4d.Opolygon) : return
    
    n = Neighbor()
    n.Init(op)
    
    nbpts = obj.GetPointCount()
    nouvPts = []
    
    bs = convertiSel(doc, obj)
    nbsel = bs.GetCount()
    if not nbsel :
        for point in xrange(nbpts) :
            ipos = catmullclark(obj, point ,n)
            nouvPts.append(ipos)
    else :
        for index, selec in enumerate(bs.GetAll(nbpts)) :
            if not selec : continue
            ipos = catmullclark(obj, index ,n)
            nouvPts.append(ipos)
    
    doc.StartUndo()
    doc.AddUndo(c4d.UNDOTYPE_CHANGE_NOCHILDREN, obj)
    
    for i, pos in nouvPts :
        obj.SetPoint(i, pos)
    
    obj.Message(c4d.MSG_UPDATE)
    doc.EndUndo()
    c4d.EventAdd()
    

if __name__=='__main__':
    main(op)