PDA

Voir la version complète : Objet UVW



César Vonc
07/03/2012, 23h55
v1.3

Script Python transformant les coordonnées UVW en un objet polygonal et inversement.

http://code.vonc.fr/details/s5-00.png


Sélectionnez un objet, lancez le script et cliquez sur Créer pour convertir la ou les propriétés UVW en objet(s) polygonaux.

Sélectionnez votre objet de base et l'objet UVW, lancez le script puis cliquez sur Texturer pour ainsi créer la propriété UVW correspondant à l'objet UVW.



import c4d
from c4d import gui, Vector
import math
from math import pi

class Dialogue(gui.GeDialog):
objs = None
uvws = None
obj_3d = None
obj_uvw = None
proj = 0
annuler = True
mode = 0
echelle = 1000
cadre = True

def __init__(self, ops):
self.objs = ops

def CreateLayout(self):
nb = len(self.objs)
if (nb == 2):
nom = self.objs[1].GetName()
else:
nom = "[Nouveau]"

self.SetTitle("Objet UVW v1.3")
self.GroupBegin(100, c4d.BFH_SCALEFIT, 2)

self.GroupBegin(101, c4d.BFH_SCALEFIT|c4d.BFV_TOP, 1, title = "Objet 3D")
self.GroupBorder(c4d.BORDER_GROUP_IN)
self.GroupBorderSpace(7, 7, 7, 7)
self.AddRadioGroup(200, c4d.BFH_LEFT, 1)
self.AddChild(200, 0, self.objs[0].GetName())
if (nb == 2): self.AddChild(200, 1, nom)
self.AddStaticText(205, c4d.BFH_SCALEFIT, inith = 14, name = "")
self.AddButton(203, c4d.BFH_SCALEFIT, inith = 20, name = "Texturer")
self.GroupEnd()

self.GroupBegin(102, c4d.BFH_SCALEFIT|c4d.BFV_TOP, 1, title = "Objet UVW")
self.GroupBorder(c4d.BORDER_GROUP_IN)
self.GroupBorderSpace(7, 7, 7, 7)
self.AddRadioGroup(201, c4d.BFH_LEFT, 1)
if (nb == 2): self.AddChild(201, 0, self.objs[0].GetName())
self.AddChild(201, 1, nom)
self.AddComboBox(204, c4d.BFH_SCALEFIT)
self.AddChild(204, 0, "Projection UVW")
self.AddChild(204, 1, "Projection Frontale (3D)")
self.AddButton(202, c4d.BFH_SCALEFIT, inith = 20, name = "Créer")
self.GroupEnd()

self.GroupEnd()
self.GroupBegin(100, c4d.BFH_SCALEFIT, 4)
self.GroupBorderSpace(20, 5, 20, 5)
self.AddStaticText(103, c4d.BFH_RIGHT, 0, 0, "Échelle : ")
self.AddEditNumberArrows(207, c4d.BFH_LEFT, 80)
self.AddCheckbox(208,c4d.BFH_SCALE, 0, 0, "Cadre")
self.AddButton(206, c4d.BFH_SCALE, 100, 15, name = "Annuler")
self.GroupEnd()
self.AddStaticText(103, c4d.BFH_SCALEFIT, 500, 0, "César Vonc - http://code.vonc.fr", 1)

self.SetLong(200, 0)
self.SetLong(201, 1)
self.SetReal(207, 1000)
self.SetBool(208, True)
if (nb == 1): self.Enable(203, False)
else:
self.Enable(202, False)
self.Enable(204, False)
return True

def Command(self, id, msg):
if (id == 200):
if self.GetLong(200) == 0: self.SetLong(201, 1)
else: self.SetLong(201, 0)

if (id == 201):
if self.GetLong(201) == 0: self.SetLong(200, 1)
else: self.SetLong(200, 0)

if (id == 202 or id == 203):
self.annuler = False
self.obj_3d = self.GetLong(200)
self.obj_uvw = self.GetLong(201)
self.proj = self.GetLong(204)
self.echelle = self.GetReal(207)
self.cadre = self.GetBool(208)
if (id == 202): self.mode = 0
else :self.mode = 1
self.Close()

if (id == 206):
self.annuler = True
self.Close()

return True

def erreur(n):
message = ["Veuillez sélectionner un ou deux objets.",
"L'objet 3D ne correspond pas avec l'objet UVW : leur nombre de polygones diffère.",
"L'objet 3D ne contient pas de propriété UVW.",
"L'objet 3D n'est pas un objet polygonal.",
"L'objet UVW n'est pas un objet polygonal."]
gui.MessageDialog(message[n])

def modCoor(v, ech):
v *= ech
return v

def demodCoor(v, ech):
v *= 1/ech
return v

def trouve_sel(sels, nom):
for s in sels:
if nom == s[c4d.ID_BASELIST_NAME]:
return s

def creer_obj_uvw(p_uvw, p_texs, obj_3d, proj, ech, sels, cadre):
objet = c4d.BaseObject(c4d.Opolygon)
nb_polys = obj_3d.GetPolygonCount()
nb_pts = 0
maillage = []
points = []
if proj == 0: # UVW
for i in xrange(p_uvw.GetDataCount()):
p_uvw_pol = p_uvw.GetSlow(i)
poly = obj_3d.GetPolygon(i)

points.append(modCoor(p_uvw_pol["a"], ech))
points.append(modCoor(p_uvw_pol["b"], ech))
points.append(modCoor(p_uvw_pol["c"], ech))

if (poly.c == poly.d):
nouv_poly = c4d.CPolygon(nb_pts, nb_pts+1, nb_pts+2, nb_pts+2)
nb_pts += 3
else:
nouv_poly = c4d.CPolygon(nb_pts, nb_pts+1, nb_pts+2, nb_pts+3)
nb_pts += 4
points.append(modCoor(p_uvw_pol["d"], ech))

maillage.append(nouv_poly)

elif proj == 1: # Frontale
points = obj_3d.GetAllPoints()
maillage = obj_3d.GetAllPolygons()
mob = Vector(ech/2, ech/2, 0)
points = [p + mob for p in points]
nb_pts = len(points)

objet.ResizeObject(nb_pts, nb_polys)
objet.SetAllPoints(points)
for p in range(nb_polys):
objet.SetPolygon(p, maillage[p])

doc.StartUndo()
objet.Message(c4d.MSG_UPDATE)
objet[c4d.ID_BASELIST_NAME] = obj_3d[c4d.ID_BASELIST_NAME] + " UVW"
p_texs.reverse()
for p_tex in p_texs:
if not p_tex: continue
p_tex2 = c4d.BaseTag(c4d.Ttexture)
p_tex2[c4d.TEXTURETAG_MATERIAL] = p_tex[c4d.TEXTURETAG_MATERIAL]
p_tex2[c4d.TEXTURETAG_SIZE] = Vector(ech/2, ech/2, ech/2)
p_tex2[c4d.TEXTURETAG_POSITION] = Vector(ech/2, ech/2, 0)
p_tex2[c4d.TEXTURETAG_ROTATION] = Vector(0, pi, 0)
p_tex2[c4d.TEXTURETAG_PROJECTION] = 2
p_tex2[c4d.TEXTURETAG_OFFSETX] = p_tex[c4d.TEXTURETAG_OFFSETX]
p_tex2[c4d.TEXTURETAG_OFFSETY] = p_tex[c4d.TEXTURETAG_OFFSETY]
p_tex2[c4d.TEXTURETAG_LENGTHX] = p_tex[c4d.TEXTURETAG_LENGTHX]
p_tex2[c4d.TEXTURETAG_LENGTHY] = p_tex[c4d.TEXTURETAG_LENGTHY]
p_tex2[c4d.TEXTURETAG_TILESX] = p_tex[c4d.TEXTURETAG_TILESX]
p_tex2[c4d.TEXTURETAG_TILESY] = p_tex[c4d.TEXTURETAG_TILESY]
p_tex2[c4d.TEXTURETAG_REPETITIONX] = p_tex[c4d.TEXTURETAG_REPETITIONX]
p_tex2[c4d.TEXTURETAG_REPETITIONY] = p_tex[c4d.TEXTURETAG_REPETITIONY]
p_tex2[c4d.TEXTURETAG_RESTRICTION] = p_tex[c4d.TEXTURETAG_RESTRICTION]
objet.InsertTag(p_tex2)
if p_tex[c4d.TEXTURETAG_RESTRICTION]:
selp = objet.MakeTag(c4d.Tpolygonselection)
selp[c4d.ID_BASELIST_NAME] = p_tex[c4d.TEXTURETAG_RESTRICTION]
bs2 = selp.GetBaseSelect()
sel = trouve_sel(sels, p_tex[c4d.TEXTURETAG_RESTRICTION])
if sel:
bs = sel.GetBaseSelect()
bs.CopyTo(bs2)
if cadre is True:
rect = c4d.BaseObject(c4d.Osplinerectangle)
rect[c4d.PRIM_RECTANGLE_WIDTH] = ech
rect[c4d.PRIM_RECTANGLE_HEIGHT] = ech
rect[c4d.ID_BASEOBJECT_REL_POSITION] = Vector(ech/2, ech/2, 0)
rect[c4d.ID_BASELIST_NAME] = "Cadre"
doc.InsertObject(rect, objet)
doc.AddUndo(c4d.UNDOTYPE_NEW, rect)
objet[c4d.ID_BASEOBJECT_REL_ROTATION] = Vector(0, pi/2, 0)
doc.InsertObject(objet)
doc.AddUndo(c4d.UNDOTYPE_NEW, objet)
doc.SetActiveObject(objet)
c4d.EventAdd()
doc.EndUndo()

def creer_prop_uvw(obj_3d, obj_uvw, ech):
nb_polys = obj_uvw.GetPolygonCount()
nb_polys_obj = obj_3d.GetPolygonCount()
if nb_polys != nb_polys_obj:
erreur(1)
return
doc.StartUndo()
doc.AddUndo(c4d.UNDOTYPE_CHANGE_NOCHILDREN, obj_3d)
p_uvw = obj_3d.MakeVariableTag(c4d.Tuvw, nb_polys)
for p in range(nb_polys):
pol = obj_uvw.GetPolygon(p)
pA = demodCoor(obj_uvw.GetPoint(pol.a), ech)
pB = demodCoor(obj_uvw.GetPoint(pol.b), ech)
pC = demodCoor(obj_uvw.GetPoint(pol.c), ech)
pD = demodCoor(obj_uvw.GetPoint(pol.d), ech)
p_uvw.SetSlow(p, pA, pB, pC, pD)
c4d.EventAdd()
doc.EndUndo()

def objetuvw():
objs = doc.GetActiveObjects(c4d.GETACTIVEOBJECTFLAGS_0)
nb = len(objs)
if nb > 2 or nb == 0:
erreur(0)
return False

dial = Dialogue(objs)
dial.Open(c4d.DLG_TYPE_MODAL)
if dial.annuler is True: return False

ech = dial.echelle
cadre = dial.cadre
obj_3d = objs[dial.obj_3d]
if nb > 1: obj_uvw = objs[dial.obj_uvw]
else: obj_uvw = None
if obj_3d.GetType() != c4d.Opolygon :
erreur(3)
return False

if obj_uvw:
if obj_uvw.GetType() != c4d.Opolygon:
erreur(4)
return False

props = obj_3d.GetTags()
props_uvw = []
props_tex = []
props_tex_tous = []
props_sel = []
prec = []
for p in props:
if p.GetType() == c4d.Tpolygonselection:
props_sel.append(p)
if p.GetType() == c4d.Ttexture:
props_tex_tous.append(p)
if p[c4d.TEXTURETAG_PROJECTION] == c4d.TEXTURETAG_PROJECTION_UVW:
prec.append(p)
if p.GetType() == c4d.Tuvw:
props_uvw.append(p)
props_tex.append(prec)
prec = []
if len(prec) > 0:
if len(props_tex) == 0:
props_tex.append(prec)
else: props_tex[0].extend(prec)

if dial.mode == 0: # Créer l'objet UVW
if dial.proj == 0: # Projection UVW
if len(props_uvw) == 0:
erreur(2)
return False
for i in range(len(props_uvw)):
creer_obj_uvw(props_uvw[i], props_tex[i], obj_3d, dial.proj, ech, props_sel, cadre)
else:
creer_obj_uvw(None, props_tex_tous, obj_3d, dial.proj, ech, props_sel, cadre)

elif dial.mode == 1: # Créer la propriété UVW à partir de l'objet UVW
creer_prop_uvw(obj_3d, obj_uvw, ech)

if __name__=='__main__':
objetuvw()-------


Lien alternatif (http://code.vonc.fr/?a=16)


Voici donc la version supérieure du script Objet UVW, anciennement codé en Coffee.

C'est, à ma connaissance, la seule manière de voir et modifier l'axe W des coordonnées UVW (pas très utile, certes, mais sait-on jamais !).

On peut ainsi déplier un maillage avec les outils de modélisation de c4d qui sont, je trouve, bien plus précises que celles de BP UV edit.


Si vous avez des remarques ou des idées pour une ergonomie meilleure, n'hésitez pas !

Aurety
08/03/2012, 00h26
viens ici que je t'embrasse ! c'est juste un vieux rêve que tu réalises ! :icon_eek::icon_eek:

shtl
08/03/2012, 01h11
Magnifique!

Merci beaucoup !

:icon_prie:

geantvert
08/03/2012, 11h32
Pitin c'est limite un uv master complet :icon_eek:
Je trouvais l'option flaten de zbrush excellente... ben voila :icon_clap:
Il faut donc rendre à César ce qui lui appartient :thumbup1:

Sir Gong
08/03/2012, 11h46
Cool César, merci beaucoup !

tabou
08/03/2012, 12h31
Excellent, je viens de le tester sur un objet d'un million de polygones, déplié en moins de 5 secondes :icon_eek:
Merci beaucoup :icon_prie:

Fredaubailly
08/03/2012, 12h44
Heu... Comment dire...
Quelqu'un pourrait me dire à quoi ça sert ? Quel est l'intérêt de faire ça ? On en fait quoi après ?

Pas taper... :icon_redface:

César Vonc
08/03/2012, 16h00
Cela sert à modifier les coordonnées UVW sans Bodypaint, Fredaubailly, car le script marche dans les deux sens : tu peux récupérer le dépliage UVW sous forme d'objet, mais tu peux aussi convertir cet objet en propriété UVW.


Perso je m'en sers pour la précision, car pour placer des points UV à une position précise, les bouger sur un axe ou bien en souder deux, je vois pas comment faire dans BP !



En tout cas ça me fait plaisir que cela vous plaise !

Elric
08/03/2012, 23h31
Merci tout plein César Vonc, c'est simple à utiliser et rudement efficace.

Un grand bravo et une fois de plus, merci !

sammael95
12/03/2012, 11h18
Un Grand merci, c'est étonnant de simplicité et d'efficacité!

Je viens de l'utiliser pour regrouper plein de textures 512px et 1024px en une seule de 4096px (je suis en train de créer un robot type Gundam jouable dans unity pour le projet d'un ami, donc plein de pièces), autant pour positionner les textures dans photoshop c'est tout simple avec la transformation manuelle, autant je ne vois pas comment j'aurais fais pour déplacer les UVs si précisément sans toi ^^

Un GRAND merci donc! :D

amateur
12/03/2012, 11h39
merci
César !

paspas
16/03/2012, 14h15
hello

quelqu'un sait me dire ou et comment on l installe j' y arrive pas :icon_pleure:

paspas

César Vonc
16/03/2012, 15h09
Salut,

Soit en faisant Fichier > Importer dans le gestionnaire de script, soit en copiant les fichiers de l'archive dans le dossier library/scripts du dossier des préférences de C4D.

Voir la Procédure d'installation (http://frenchcinema4d.fr/showthread.php?74044-Proc%E9dure-d-installation).