C4D UV脚本 Python : ProjUV
Fichier d'exemple : Télécharger
Projette le dépliage UV d'un objet sur un autre.
L'outil se présente sous la forme d'une propriété à appliquer sur l'objet à texturer.
L'utilisation d'une même projection sur deux modèles différents permet de les texturer de la même façon malgré leur différence de maillage.
v 1.2 :
- Correction de l'absence de rafraîchissement sous l'OpenGL.
v 1.15 :
- Modèle de projection d'exemple modifié.
v 1.1 :
- Les polygones affectés par la projection sont enregistrés.
- Correction d'une faute de frappe dans le menu.
Copier le dossier « vonc_projuv » dans le dossier « plugins » du répertoire de Cinéma 4D.
Fichier vonc_projuv.PYP :
- # ProjUV - v 1.2 - vonc.fr
- import os
- import c4d
- from c4d import bitmaps, plugins, utils, Vector
- from c4d.utils import GeRayCollider, Neighbor
- MODULE_ID = 1029370
- VONCPROJUV_MAJAUTO = 1000
- VONCPROJUV_OBJ = 1001
- VONCPROJUV_UVW = 1002
- VONCPROJUV_SEL = 1003
- VONCPROJUV_ACTU = 1004
- VONCPROJUV_PLAN = 1005
- VONCPROJUV_INVNOR = 1006
- VONCPROJUV_INFO = 1007
- VONCPROJUV_AFF = 1008
- class ProjUV(plugins.TagData):
- lienObj = None
- lienUVW = None
- lienSel = None
- lienAff = None
- majauto = False
- actuprio = False
- creerplan = False
- invnor = False
-
- def InitDonneeAff(self, donnees, obj) :
- if self.lienAff : return
- propAff = c4d.BaseTag(c4d.Tpolygonselection)
- propAff[c4d.ID_BASELIST_NAME] = "ProjUV Sel"
- obj.InsertTag(propAff)
- donnees.SetLink(VONCPROJUV_AFF, propAff)
- self.lienAff = propAff
-
- def InitDonneeUVW(self, donnees, obj) :
- if self.lienUVW : return
- propUVW = obj.GetTag(c4d.Tuvw)
- if propUVW :
- donnees.SetLink(VONCPROJUV_UVW, propUVW)
- self.lienUVW = propUVW
-
- def RecupDonnees(self, donnees, doc) :
- self.lienObj = donnees.GetLink(VONCPROJUV_OBJ, doc)
- self.lienUVW = donnees.GetLink(VONCPROJUV_UVW, doc)
- self.lienSel = donnees.GetLink(VONCPROJUV_SEL, doc)
- self.lienAff = donnees.GetLink(VONCPROJUV_AFF, doc)
- self.majauto = donnees.GetBool(VONCPROJUV_MAJAUTO)
- self.invnor = donnees.GetBool(VONCPROJUV_INVNOR)
-
- def Verifieur(self, obj, uvw, tex) :
- if self.actuprio :
- self.actuprio = False
- return True
- if not self.majauto : return False
- if not uvw or not tex : return False
- if not obj.CheckType(c4d.Opolygon) : return False
- if obj.IsDirty(c4d.DIRTY_MATRIX) : return True
- if obj.IsDirty(c4d.DIRTY_DATA) : return True
- texEtGosses = [tex]
- for o in texEtGosses :
- if o.IsDirty(c4d.DIRTY_DATA) or o.IsDirty(c4d.DIRTY_MATRIX) :
- return True
- texEtGosses.extend(o.GetChildren())
-
- return False
-
- def Applatisseur(self, o, doc) :
- if not o : return
- obj = utils.SendModelingCommand(command=c4d.MCOMMAND_CURRENTSTATETOOBJECT, list=[o], doc=doc)
- if not obj : return
- neutre = c4d.BaseObject(c4d.Onull)
- obj[0].InsertUnder(neutre)
- obj = utils.SendModelingCommand(command=c4d.MCOMMAND_JOIN, list=[neutre], doc=doc)
- if not obj : return
- utils.SendModelingCommand(command=c4d.MCOMMAND_TRIANGULATE, list=obj, doc=doc)
- if self.invnor :
- utils.SendModelingCommand(command=c4d.MCOMMAND_REVERSENORMALS, list=obj, doc=doc)
- return obj[0]
-
- def CalculNormaleEtUVW(self, o) :
- uvw = o.GetTag(c4d.Tuvw)
- if not uvw : return None, None
- polygones = o.GetAllPolygons()
- nbPoints = o.GetPointCount()
- normales = [Vector()] * nbPoints
- uvws = [Vector()] * nbPoints
- i = 0
-
- for poly in polygones :
- a = poly.a
- b = poly.b
- c = poly.c
- d = poly.d
- ap = o.GetPoint(a)
- bp = o.GetPoint(b)
- cp = o.GetPoint(c)
- dp = o.GetPoint(d)
- n = (ap - cp).Cross(bp - dp)
- normales[a] += n
- normales[b] += n
- normales[c] += n
- normales[d] += n
- uvwdict = uvw.GetSlow(i)
- uvws[a] = uvwdict["a"]
- uvws[b] = uvwdict["b"]
- uvws[c] = uvwdict["c"]
- uvws[d] = uvwdict["d"]
-
- i += 1
-
- return normales, uvws
-
- def CompleteNormales(self, n, obj, objNbPts, objNor, objNorBol) :
- for ip in xrange(objNbPts) :
- ipolys = n.GetPointPolys(ip)
- if not objNorBol[ip] : continue
- direc = objNor[ip]
- for ipoly in ipolys :
- poly = obj.GetPolygon(ipoly)
- a = poly.a
- b = poly.b
- c = poly.c
- d = poly.d
- if objNor[a] == Vector() : objNor[a] = direc
- if objNor[b] == Vector() : objNor[b] = direc
- if objNor[c] == Vector() : objNor[c] = direc
- if objNor[d] == Vector() : objNor[d] = direc
- objNorBol[a] = True
- objNorBol[b] = True
- objNorBol[c] = True
- objNorBol[d] = True
-
- def CreerProjPlanaire(self, doc, donnees) :
- self.creerplan = False
- bd = doc.GetActiveBaseDraw()
- cam = bd.GetSceneCamera(doc)
- mg = cam.GetMg() * c4d.utils.MatrixMove(c4d.Vector(0,0,300))
-
- hn = c4d.BaseObject(c4d.Osds)
- hn[c4d.SDSOBJECT_SUBDIVIDE_UV] = c4d.SDSOBJECT_SUBDIVIDE_UV_EDGE
- hn[c4d.SDSOBJECT_SUBEDITOR_CM] = 2
- hn[c4d.SDSOBJECT_SUBRAY_CM] = 2
- hn.SetMg(mg)
- plan = c4d.BaseObject(c4d.Oplane)
- plan[c4d.PRIM_PLANE_WIDTH] = 200
- plan[c4d.PRIM_PLANE_HEIGHT] = 200
- plan[c4d.PRIM_PLANE_SUBW] = 3
- plan[c4d.PRIM_PLANE_SUBH] = 3
- plan[c4d.PRIM_AXIS] = 4
- plan[c4d.ID_BASEOBJECT_USECOLOR] = 2
- plan[c4d.ID_BASEOBJECT_COLOR] = c4d.Vector(1.0, 0.8, 0.0)
- aff = c4d.BaseTag(c4d.Tdisplay)
- aff[c4d.DISPLAYTAG_AFFECT_DISPLAYMODE] = True
- aff[c4d.DISPLAYTAG_SDISPLAYMODE] = c4d.DISPLAYTAG_SDISPLAY_NOSHADING
- aff[c4d.DISPLAYTAG_WDISPLAYMODE] = c4d.DISPLAYTAG_WDISPLAY_ISOPARMS
- hn.InsertTag(aff)
- plan.InsertUnder(hn)
- res = utils.SendModelingCommand(command = c4d.MCOMMAND_MAKEEDITABLE, list = [plan], doc = doc)
- res[0].InsertUnder(hn)
- doc.InsertObject(hn)
- donnees.SetLink(VONCPROJUV_OBJ, hn)
-
- def Init(self, node):
- donnees = node.GetDataInstance()
- donnees.SetBool(VONCPROJUV_MAJAUTO, True)
- return True
-
- def Execute(self, tag, doc, op, bt, priority, flags):
- donnees = tag.GetDataInstance()
- if not donnees : return c4d.EXECUTIONRESULT_OK
-
- if self.creerplan : self.CreerProjPlanaire(doc, donnees)
-
- self.RecupDonnees(donnees, doc)
- self.InitDonneeUVW(donnees, op)
- self.InitDonneeAff(donnees, op)
-
- obj = op
- objPropUVW = self.lienUVW
- tex = self.lienObj
- selPolys = self.lienSel
-
- verif = self.Verifieur(obj, objPropUVW, tex)
- if not verif : return c4d.EXECUTIONRESULT_OK
-
- tex = self.Applatisseur(tex, doc)
- if not tex : return c4d.EXECUTIONRESULT_OK
-
- texNor, texUVW = self.CalculNormaleEtUVW(tex)
- if not texUVW : return c4d.EXECUTIONRESULT_OK
-
- texPts = tex.GetAllPoints()
- texMg = tex.GetMg()
-
- objNbPolys = obj.GetPolygonCount()
- objNbPts = obj.GetPointCount()
- objPts = obj.GetAllPoints()
- objMg = obj.GetMg()
- objIMg = ~objMg
- objUVW = [None] * objNbPts
- objNor = [Vector()] * objNbPts
- objNorBol = [False] * objNbPts
-
- bs = None
- objPtsSel = [False] * objNbPts
- if selPolys :
- bs = selPolys.GetBaseSelect()
- for index, sele in enumerate(bs.GetAll(objNbPolys)) :
- if not sele : continue
- poly = obj.GetPolygon(index)
- objPtsSel[poly.a] = True
- objPtsSel[poly.b] = True
- objPtsSel[poly.c] = True
- objPtsSel[poly.d] = True
-
- distance = (obj.GetRad() + obj.GetMp() + objMg.off + (tex.GetRad() + tex.GetMp() + texMg.off)).GetLength()
- distance *= 2
-
- rayon = GeRayCollider()
- rayon.Init(obj)
- i = 0
- for pt in texPts :
- depart = objIMg.Mul(pt) + 0.0001
- direc = objIMg.MulV(texNor[i])
- #ajVec(depart, direc)
- coll = rayon.Intersect(depart, direc, distance)
- inter = rayon.GetNearestIntersection()
-
- if inter :
- pos = inter["hitpos"]
- poly = inter["face_id"]
- poly = obj.GetPolygon(poly)
- nor = direc.GetNormalized() * -1
- #ajVec(pos, direc)
- objNor[poly.a] += nor
- objNor[poly.b] += nor
- objNor[poly.c] += nor
- objNor[poly.d] += nor
- objNorBol[poly.a] = True
- objNorBol[poly.b] = True
- objNorBol[poly.c] = True
- objNorBol[poly.d] = True
- i += 1
-
- n = Neighbor()
- n.Init(obj)
- somme = sum(objNorBol)
- while somme != objNbPts :
- sommeAns = somme
- self.CompleteNormales(n, obj, objNbPts, objNor, objNorBol)
- somme = sum(objNorBol)
- if sommeAns == somme : break
-
- rayon.Init(tex)
- i = 0
- for pt in objPts :
- if bs :
- if not objPtsSel[i] :
- i += 1
- continue
- depart = objMg.Mul(pt) + 0.0001
- direc = objMg.MulV(objNor[i].GetNormalized())
- #ajVec(depart, direc)
- coll = rayon.Intersect(depart, direc, distance)
- inter = rayon.GetNearestIntersection()
-
- if inter :
- bc = inter['barrycoords']
- poly = inter["face_id"]
- poly = tex.GetPolygon(poly)
- a = poly.a
- b = poly.b
- c = poly.c
- objUVW[i] = texUVW[a]*bc.x + texUVW[b]*bc.y + texUVW[c]*bc.z
-
- i += 1
-
- #doc.AddUndo(c4d.UNDOTYPE_CHANGE, objPropUVW)
-
- objPolAff = self.lienAff.GetBaseSelect()
- objPolAff.DeselectAll()
-
- if bs :
- for index, sele in enumerate(bs.GetAll(objNbPolys)):
- if not sele : continue
- poly = obj.GetPolygon(index)
- a = objUVW[poly.a]
- b = objUVW[poly.b]
- c = objUVW[poly.c]
- d = objUVW[poly.d]
- if not a or not b or not c or not d : continue
- objPolAff.Select(index)
- objPropUVW.SetSlow(index, a, b, c, d)
-
- else :
- for j in xrange(obj.GetPolygonCount()) :
- poly = obj.GetPolygon(j)
- a = objUVW[poly.a]
- b = objUVW[poly.b]
- c = objUVW[poly.c]
- d = objUVW[poly.d]
- if not a or not b or not c or not d : continue
- objPolAff.Select(j)
- objPropUVW.SetSlow(j, a, b, c, d)
-
- #doc.EndUndo()
- #c4d.EventAdd()
-
- obj.Message(c4d.MSG_UPDATE)
-
- return c4d.EXECUTIONRESULT_OK
-
- def Message(self, op, type, donnees) :
- if type == c4d.MSG_DESCRIPTION_COMMAND :
- id = donnees["id"][0].id
- if id == VONCPROJUV_ACTU :
- self.actuprio = True
- elif id == VONCPROJUV_PLAN :
- self.creerplan = True
- return True
- if __name__ == "__main__":
- bmp = bitmaps.BaseBitmap()
- dir, file = os.path.split(__file__)
- fn = os.path.join(dir, "res", "vonc_projuv.tif")
- bmp.InitWith(fn)
- plugins.RegisterTagPlugin(id=MODULE_ID, str="ProjUV",
- info=c4d.TAG_EXPRESSION | c4d.TAG_VISIBLE, g=ProjUV,
- description="vonc_projuv", icon=bmp)
复制代码
Fichier vonc_projuv.H :
- #ifndef _vonc_projuv_H_
- #define _vonc_projuv_H_
- enum
- {
- VONCPROJUV_MAJAUTO = 1000,
- VONCPROJUV_OBJ = 1001,
- VONCPROJUV_UVW = 1002,
- VONCPROJUV_SEL = 1003,
- VONCPROJUV_ACTU = 1004,
- VONCPROJUV_PLAN = 1005,
- VONCPROJUV_INVNOR = 1006,
- VONCPROJUV_INFO = 1007,
- VONCPROJUV_AFF = 1008
- }
- #endif
复制代码 Fichier vonc_projuv.RES :
- CONTAINER vonc_projuv
- {
- NAME VONCPROJUV_TITRE;
- INCLUDE Texpression;
-
- GROUP ID_TAGPROPERTIES
- {
- GROUP {
- BUTTON VONCPROJUV_PLAN { }
- }
- SEPARATOR { LINE; }
- GROUP {
- LINK VONCPROJUV_OBJ { ACCEPT { Obase; } }
- LINK VONCPROJUV_UVW { ACCEPT { Tuvw; } }
- LINK VONCPROJUV_AFF { ACCEPT { Tpolygonselection; } }
- LINK VONCPROJUV_SEL { ACCEPT { Tpolygonselection; } }
- BOOL VONCPROJUV_INVNOR { }
- }
- SEPARATOR { LINE; }
- GROUP {
- COLUMNS 2;
- BOOL VONCPROJUV_MAJAUTO { }
- BUTTON VONCPROJUV_ACTU { }
- }
- SEPARATOR { LINE; }
- GROUP {
- STATICTEXT VONCPROJUV_INFO { }
- }
- }
- }
复制代码
Fichier vonc_projuv.STR :
- STRINGTABLE vonc_projuv
- {
- VONCPROJUV_TITRE "ProjUV";
- VONCPROJUV_MAJAUTO "Mise \u00E0 jour auto";
- VONCPROJUV_ACTU "Actualiser";
- VONCPROJUV_OBJ "Projection";
- VONCPROJUV_UVW "UVW";
- VONCPROJUV_SEL "Limiter \u00E0 la s\u00E9lection";
- VONCPROJUV_AFF "Polygones affect\u00E9s";
- VONCPROJUV_PLAN "Cr\u00E9er une projection planaire modifiable";
- VONCPROJUV_INVNOR "Inverser la direction";
- VONCPROJUV_INFO "v 1.2 - C\u00E9sar Vonc - http://code.vonc.fr";
- }
复制代码
|
|
Comment :1