c4d python 插件_C4D逆向细分插件:Python : Subdivision inverse(原版+汉化版)

# Subdivision inverse - César Vonc - code.vonc.fr

# v 1.1

import os

import c4d

import webbrowser

from c4d import plugins, utils, bitmaps, Vector

from c4d.utils import Neighbor, VectorAngle

MODULE_ID = 1029594

VONC_SUBDINV_NOM = 1000

VONC_SUBDINV_TYPE = 1000

VONC_SUBDINV_TYPE_CC1 = 0

VONC_SUBDINV_TYPE_CC2 = 1

VONC_SUBDINV_TYPE_CC3 = 3

VONC_SUBDINV_TYPE_CCA = 2

VONC_SUBDINV_SUBD = 1002

VONC_SUBDINV_DEPA = 1003

VONC_SUBDINV_INFO = 1004

VONC_SUBDINV_SELP = 1005

VONC_SUBDINV_INVN = 1006

VONC_SUBDINV_DON = 1007

VONC_SUBDINV_ACTU = 1008

class SubdivisionInverse() :

obj = None

doc = None

obj_nbpts = 0

obj_nbpol = 0

obj_n = None

pts_traites = []

pol_traites = []

nouv_polys = []

pts_orig = []

nouv_pts = []

nouv_pts_inv = []

nouv_coor = []

pts_corres = []

pol_corres = []

cor_poly_polynet = [] # Correspondance [id nouv_polys] = id nouv_polys nettoyé

cor_polynet_poly = [] # Correspondance [id nouv_polys nettoyé] = id nouv_polys

_GetAllPolygons = []

_GetPointPolys = []

def _NettoieTab(self, tab) :

tab_net = []

j = 0

i = 0

for val in tab :

if val and len(val) > 2 :

tab_net.append(val)

self.cor_poly_polynet.append(j)

self.cor_polynet_poly.append(i)

j += 1

else : self.cor_poly_polynet.append(-1)

i += 1

return tab_net

def _SommeVecteur(self, obj, vecs) :

if not vecs : return Vector()

s = Vector()

for v in vecs :

s += obj.GetPoint(v)

return s

def _MoyenneVecteur(self, obj, vecs) :

q = len(vecs)

if not q : return Vector()

m = Vector()

for v in vecs :

m += obj.GetPoint(v)

m /= float(q)

return m

def _RempliCoorArete(self, i, pa, ps, nb) :

obj = self.obj

n = self.obj_n

for arete in pa :

pass

def _RempliCoor(self, i, pa, ps, nb, mode) :

obj = self.obj

Po = obj.GetPoint(i)

if mode == 2 :

self.nouv_coor[i] = Po

return

if nb < len(pa) : # Bordure

n = self.obj_n

pa_bor = []

pa_nb = 0

for arete in pa :

if pa_nb == 2 : break

a, b = n.GetEdgePolys(i, arete)

if a == -1 or b == -1 :

pa_bor.append(arete)

pa_nb += 1

Mpa = self._MoyenneVecteur(obj, pa_bor)

pos = 2.0 * Po - Mpa

elif nb == 3 :

if mode == 0 :

Mps = self._MoyenneVecteur(obj, ps)

pos = Po + (Po - Mps) * 2.0

elif mode == 1 or mode == 3 :

# Calcul des coordonnées PA fictives

Mpa = Vector()

Mps = self._MoyenneVecteur(obj, ps)

for arete in pa :

if not self.nouv_coor[arete] :

paA, psA, nbA = self._RecupPaPs(arete, False)

if nbA == 3 : continue

self._RempliCoor(arete, paA, psA, nbA, mode)

Mpa += self.nouv_coor[arete]

Mpa /= float(len(pa))

pos = (Mpa-Po) * 2.0 + Po - (Po-Mps) * 0.75 #0.58335

if mode == 3 :

pos = (pos + Po + (Po - Mps) * 2.0) * 0.5

#return (i, pa, ps, nb)

else :

Spa = self._SommeVecteur(obj, pa)

Sps = self._SommeVecteur(obj, ps)

pos = (Po*nb)/(nb-3.0) + (-4.0*Spa)/(nb*(nb-3.0)) + Sps/(nb*(nb-3.0))

self.nouv_coor[i] = pos

def _RempliPolys(self, i, pts_surf) :

for p in pts_surf :

poly = self.nouv_polys[p]

if not poly : self.nouv_polys[p] = [i]

else : self.nouv_polys[p].append(i)

# Correspondance polys subdivisés > nouv polys

pointpolys = self._GetPointPolys[p] #self.obj_n.GetPointPolys(p)

for pointpoly in pointpolys :

self.pol_corres[pointpoly] = p

def _RecupPo(self, po, pa) :

obj = self.obj

n = self.obj_n

pts_traites = self.pts_traites

pol_traites = self.pol_traites

pos = []

for a in pa :

polys = self._GetPointPolys[a] #n.GetPointPolys(a)

points = []

for pol in polys :

if pol_traites[pol] : continue

p = self._GetAllPolygons[pol] #obj.GetPolygon(pol)

points.extend([p.a, p.b, p.c, p.d])

pol_traites[pol] = True

points = list(set(points))

for pt in points :

if pts_traites[pt] : continue

arete = n.GetEdgePolys(a, pt)

if arete != (-1, -1) :

pos.append(pt)

break

return pos

def _RecupPaPs(self, po, traiteur=True) :

obj = self.obj

n = self.obj_n

pts_traites = self.pts_traites

pol_traites = self.pol_traites

polys = self._GetPointPolys[po] #n.GetPointPolys(po)

nb = len(polys)

points = []

ps = []

pa = []

for p in polys :

if traiteur : pol_traites[p] = True

p = self._GetAllPolygons[p] #obj.GetPolygon(p)

points.extend([p.a, p.b, p.c, p.d])

points = list(set(points))

for pt in points :

if traiteur :

self.pts_corres[pt].append(po)

pts_traites[pt] = True

if pt == po : continue

arete = n.GetEdgePolys(po, pt)

if arete == (-1, -1) :

ps.append(pt)

else :

pa.append(pt)

return pa, ps, nb

def Execute(self, mode, depart, selp, invn) :

if not self.Initialise(depart) : return

obj = self.obj

doc = self.doc

n = self.obj_n

pts_traites = self.pts_traites

pts_orig = self.pts_orig

nouv_pts = self.nouv_pts

nouv_pts_inv = self.nouv_pts_inv

nouv_polys = self.nouv_polys

nouv_coor = self.nouv_coor

_RecupPaPs = self._RecupPaPs

_RecupPo = self._RecupPo

_RempliPolys = self._RempliPolys

_RempliCoor = self._RempliCoor

bs = obj.GetPointS()

pts_a_calc = []

j = 0

i_n = 0

i_tot = 1

for i in pts_orig : # Points de départ pour la recherche des Points Originaux

i_n += 1

i_p = 0

if not pts_traites[i] : # Si le point n'a pas été traité

pts_traites[i] = True

# Récupère les points d'arête, de surface et le nombre de polys autour du point original

pts_arete, pts_surf, nb_poly_cote = _RecupPaPs(i)

# Calcule les nouvelles coordonnées du PO  # ou renvoie a_calc pour les calculer plus tard

_RempliCoor(i, pts_arete, pts_surf, nb_poly_cote, mode)

# a_calc = _RempliCoor(i, pts_arete, pts_surf, nb_poly_cote, mode)

# if a_calc : pts_a_calc.append(a_calc)

# Ajoute PO aux futurs nouveaux polys

_RempliPolys(i, pts_surf)

# Récupère les points originaux aux alentours des points d'arête

pts_orig_tour = _RecupPo(i, pts_arete)

pts_orig.extend(pts_orig_tour)

nouv_pts_inv[i] = j # Tableau [PO sur l'obj. subdivisé] = PO de l'obj. non subd.

nouv_pts.append(i) # Liste des PO sur l'obj. subdivisé

i_tot += len(pts_orig_tour)

i_p = 1

j += 1

if i_n+i_p >= i_tot : # Si on atteint le bout de pts_orig

if 0 in pts_traites : # S'il reste des points à traiter

nouv_depart = pts_traites.index(0)

pts_orig.append(nouv_depart) # Ajouter le non traité à traiter

i_tot += 1

### -- Création de l'objet -- ###

### -- Récupération des propriétés et sélections -- ###

proprietes = obj.GetTags()

_Spolsels = []

_Npolsels = []

_Sptnsels = []

_Nptnsels = []

_Suvws = []

_Nuvws = []

for prop in proprietes :

if prop.CheckType(c4d.Tpolygonselection) :

_Npolsels.append(prop)

_Spolsels.append(prop.GetClone())

elif prop.CheckType(c4d.Tpointselection) :

_Nptnsels.append(prop)

_Sptnsels.append(prop.GetClone())

elif prop.CheckType(c4d.Tuvw) :

_Nuvws.append(prop)

_Suvws.append(prop.GetClone())

_ASptnsel = obj.GetPointS().GetClone()

_ANptnsel = obj.GetPointS()

_ASpolsel = obj.GetPolygonS().GetClone()

_ANpolsel = obj.GetPolygonS()

### -- Création de l'objet -- ###

nouv_polys_sale = nouv_polys[:]

nouv_polys = self._NettoieTab(nouv_polys)

nouv_nbpts = len(nouv_pts)

nouv_nbpolys = len(nouv_polys)

# objet  = c4d.BaseObject(c4d.Opolygon)

obj.ResizeObject(nouv_nbpts, nouv_nbpolys)

for pti in xrange(nouv_nbpts) :

ans_id = nouv_pts[pti]

nouv_id = nouv_pts_inv[ans_id]

position = nouv_coor[ans_id]

obj.SetPoint(pti, position)

posi = obj.GetPoint

for poli in xrange(nouv_nbpolys) :

poly = nouv_polys[poli]

pa = nouv_pts_inv[poly[0]]

pb = nouv_pts_inv[poly[1]]

pd = nouv_pts_inv[poly[2]]

if len(poly) != 3 :

pc = nouv_pts_inv[poly[3]]

posa = posi(pa)

posb = posi(pb)

posc = posi(pc)

posd = posi(pd)

vAB = posa - posb

vAC = posa - posc

vAD = posa - posd

vBA = posb - posa

vBC = posb - posc

vCA = posc - posa

vCD = posc - posd

# Dénoue les polys si le point D est à l'ouest

if VectorAngle(vCA, -vAD) < VectorAngle(vCA, -vAB) :

if VectorAngle(vBA, -vAD) < VectorAngle(vBA, -vAC) :

pc, pd = pd, pc

else :

if VectorAngle(vBC, -vCD) < VectorAngle(vBC, -vCA) :

pa, pd = pd, pa

else : pc = pd

cpoly = c4d.CPolygon(pa, pb, pc, pd)

obj.SetPolygon(poli, cpoly)

obj.Message(c4d.MSG_UPDATE)

commande = utils.SendModelingCommand(command = c4d.MCOMMAND_ALIGNNORMALS, list = [obj], doc = doc)

if invn : commande = utils.SendModelingCommand(command = c4d.MCOMMAND_REVERSENORMALS, list = [obj], doc = doc)

### -- Modifs des propriétés -- #

cor_polyS_polyN = [] # Correspondance [polys subdivisés] = nouveaux polys NETTOYé

for _p in self.pol_corres : cor_polyS_polyN.append(self.cor_poly_polynet[_p])

for _i, _Npolsel in enumerate(_Npolsels) : # Sélection de polygones

_Spolsel = _Spolsels[_i]

_Sbs = _Spolsel.GetBaseSelect()

_Nbs = _Npolsel.GetBaseSelect()

_Nbs.DeselectAll()

for i, sel in enumerate(_Sbs.GetAll(self.obj_nbpol)) :

if not sel : continue

_p = cor_polyS_polyN[i]

if _p != -1 : _Nbs.Select(_p)

for _i, _Nptnsel in enumerate(_Nptnsels) : # Sélection de points

_Sptnsel = _Sptnsels[_i]

_Sbs = _Sptnsel.GetBaseSelect()

_Nbs = _Nptnsel.GetBaseSelect()

_Nbs.DeselectAll()

for i, sel in enumerate(_Sbs.GetAll(self.obj_nbpts)) :

if not sel : continue

_p = nouv_pts_inv[i]

if _p != -1 and _p < self.obj_nbpts : _Nbs.Select(_p)

_ANpolsel.DeselectAll() # Sélection de polygones active

for i, sel in enumerate(_ASpolsel.GetAll(self.obj_nbpol)) :

if not sel : continue

_p = cor_polyS_polyN[i]

if _p != -1 : _ANpolsel.Select(_p)

_ANptnsel.DeselectAll() # Sélection de points active

for i, sel in enumerate(_ASptnsel.GetAll(self.obj_nbpts)) :

if not sel : continue

_p = nouv_pts_inv[i]

if _p != -1 and _p < self.obj_nbpts : _ANptnsel.Select(_p)

for _i, _Nuvw in enumerate(_Nuvws) : # UVW

_Suvw = _Suvws[_i]

for i in xrange(_Nuvw.GetDataCount()):

k = self.cor_polynet_poly[i]

polys = self._GetPointPolys[k]

# points = nouv_polys[i]

points = []

Npoly = obj.GetPolygon(i)

points.append(nouv_pts[Npoly.a])

points.append(nouv_pts[Npoly.b])

points.append(nouv_pts[Npoly.c])

points.append(nouv_pts[Npoly.d])

abcd = [Vector(), Vector(), Vector(), Vector()]

for poly in polys :

pol = self._GetAllPolygons[poly]

for j, pt in enumerate(points) :

if pol.a == pt :

abcd[j] = _Suvw.GetSlow(poly)["a"]

break

elif pol.b == pt :

abcd[j] = _Suvw.GetSlow(poly)["b"]

break

elif pol.c == pt :

abcd[j] = _Suvw.GetSlow(poly)["c"]

break

elif pol.d == pt :

abcd[j] = _Suvw.GetSlow(poly)["d"]

break

_Nuvw.SetSlow(i, abcd[0], abcd[1], abcd[2], abcd[3])

# c4d.EventAdd()

def Initialise(self, depart) :

if not self.obj : return

if not self.doc : return

obj = self.obj

if not obj.CheckType(c4d.Opolygon) : return

self.obj_nbpts = obj.GetPointCount()

self.obj_nbpol = obj.GetPolygonCount()

if not self.obj_nbpts or not self.obj_nbpol : return

self.obj_n = Neighbor()

self.obj_n.Init(obj)

self.pts_orig = depart

self.pts_traites = [False] * self.obj_nbpts

self.pol_traites = [False] * self.obj_nbpol

self.nouv_polys = [0] * self.obj_nbpts

self.nouv_pts = []

self.nouv_pts_inv = [-1] * self.obj_nbpts

self.nouv_coor = [0] * self.obj_nbpts

self.pol_corres = [0] * self.obj_nbpol

self.pts_corres = [[] for a in range(self.obj_nbpts)]

self.cor_poly_polynet = []

self.cor_polynet_poly = []

self._GetAllPolygons = obj.GetAllPolygons()

self._GetPointPolys = []

for i in xrange(self.obj_nbpts) : self._GetPointPolys.append(self.obj_n.GetPointPolys(i))

return True

def __init__(self, doc, obj) :

self.obj = obj

self.doc = doc

class SubdivisionInverseObjet(c4d.plugins.ObjectData):

subdinv = None

type = 0

subd = 1

depa = 0

selp = False

invn = False

def Message(self, node, type, data) :

if type == c4d.MSG_MENUPREPARE :

node.SetDeformMode(True)

if type == c4d.MSG_DESCRIPTION_COMMAND :

id = data['id'][0].id

if id == VONC_SUBDINV_DON : webbrowser.open("http://code.vonc.fr/", 2, True)

elif id == VONC_SUBDINV_ACTU : node.SetDirty(c4d.DIRTY_DATA)

return True

def Init(self, op) :

donnees = op.GetDataInstance()

self.InitAttr(op, int, [VONC_SUBDINV_TYPE])

self.InitAttr(op, int, [VONC_SUBDINV_SUBD])

self.InitAttr(op, int, [VONC_SUBDINV_DEPA])

self.InitAttr(op, bool, [VONC_SUBDINV_SELP])

self.InitAttr(op, bool, [VONC_SUBDINV_INVN])

op[VONC_SUBDINV_TYPE] = self.type

op[VONC_SUBDINV_SUBD] = self.subd

op[VONC_SUBDINV_DEPA] = self.depa

op[VONC_SUBDINV_SELP] = self.selp

op[VONC_SUBDINV_INVN] = self.invn

return True

def ModifyObject(self, mod, doc, op, op_mg, mod_mg, lod, flags, thread):

if not op.CheckType(c4d.Opolygon) : return True

if not op.GetPointCount() : return True

if not op.GetPolygonCount() : return True

self.type = mod[VONC_SUBDINV_TYPE]

self.subd = mod[VONC_SUBDINV_SUBD]

self.depa = mod[VONC_SUBDINV_DEPA]

self.selp = mod[VONC_SUBDINV_SELP]

self.invn = mod[VONC_SUBDINV_INVN]

self.subdinv = SubdivisionInverse(doc, op)

for k in xrange(self.subd) :

nbp = op.GetPointCount()

depart = [self.depa % nbp]

if self.selp :

depart = []

bs = op.GetPointS()

for i, sel in enumerate(bs.GetAll(nbp)) :

if not sel : continue

depart.append(i)

if not depart : depart = [0]

self.subdinv.Execute(self.type, depart, self.selp, self.invn)

return True

if __name__ == "__main__":

bmp = bitmaps.BaseBitmap()

dir, f = os.path.split(__file__)

fn = os.path.join(dir, "res", "vonc_subdinv.tif")

bmp.InitWith(fn)

c4d.plugins.RegisterObjectPlugin(id=MODULE_ID, str=c4d.plugins.GeLoadString(VONC_SUBDINV_NOM),

g=SubdivisionInverseObjet,

description="vonc_subdinv",

icon=bmp,

info=c4d.OBJECT_MODIFIER)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值