[résolu][python] divers problèmes en python

Blender: Grand logiciel open source de création d'images 3D.
Vi.
Messages : 23
Inscription : 15 févr. 2009, 17:48

[résolu][python] divers problèmes en python

Message par Vi. »

Bien le bonjour :)

Savez vous comment définir des coordonnées uv pour une vertice en python ?
Le tout en utilisant les modules Mesh ou Bpy.

Car j'ai trouvé ceci, concernant le module NMesh, mais il parait que ce module commence à se faire vieux.. >
http://jmsoler.free.fr/didacticiel/blen ... _uvmap.htm

Merci d'avance.
Dernière modification par Vi. le 07 avr. 2009, 01:28, modifié 7 fois.
ChArleS
Modérateur
Messages : 780
Inscription : 04 juil. 2006, 23:41
Localisation : Montréal

Message par ChArleS »

Bonjour et bienvenu sur les forums,

D'autres sauront te renseigner sur la programmation, mais je peux te proposer d'étudier les scripts travaillant sur les cartes UV venant avec Blender, comme celui pour exporter une carte UV en image.

Charles
Vi.
Messages : 23
Inscription : 15 févr. 2009, 17:48

Message par Vi. »

J'ai essayé, mais c'est vraiment pas simple du tout :(

Si ça pouvait être aussi simple que pour le module Nmesh, ça serait cool.
melwe
Messages : 444
Inscription : 22 avr. 2007, 02:46
Localisation : Nancy

Message par melwe »

Salut !
Bon, je ne connaissais pas grand chose à ton problème, donc j'ai commencé comme toi par regarder le script que tu as donné. Dedans, ce qui est fait, avec le module NMesh, c'est:
1) création d'un maillage
2) ajout de 4 sommets à ce mesh en carré
3) création d'une face, et assignation des quatre sommets à cette face
4) création des coordonnées UV des sommets, et assignation à la face

Le point important est que les coordonnées UV sont dans les faces, dans un attribut uv.
Ensuite, je suis allé voir dans l'API blender en python, qui détaille techniquement tout ce que le module blender apporte à python. Tu peux la trouver ici. Par analogie avec ce qui est fait précédemment, je suis allé voir dans le sous module Mesh, puis MFace, et dans les attributs, il y a bien un attribut similaire à ce que tu trouvais dans NMesh : MFace.uv. La description est donnée ici. L'API est différente selon la version de blender, je t'ai mis ici les liens pour la version 2.46, en lisant l'adresse, tu pourras sans problèmes deviner ce qu'il faut faire pour avoir la version 2.48 par exemple.

Je pense qu'il s'agit de ce que tu cherches. Si tu as besoin ensuite de détails pour un projet particulier, fais-nous signe !
Bon courage.
Vi.
Messages : 23
Inscription : 15 févr. 2009, 17:48

Message par Vi. »

Ohhh un Nancéen (comme moi) !!
Merci beaucoup pour ton aide, je vais décortiquer tout ça.

Pour expliquer un peu mon projet, j'essaye de réaliser 2 générateurs : générateur de rochers et générateur d'arbres (le tout en low poly et texturé prêt à être exporté vers un jeu).

Je vous tiens au courant ;)

edit :
J'ai déjà un soucis xD
Voilà en gros mon code (j'ai enlevé les parties inutiles pour la compréhension) :

Code : Tout sélectionner

import Blender et tout le tralala..

#ici il y a une partie concernant la suppression du précédent mesh généré

i=0

nz=0.7 #variable de noise concernant le maillage
rx=[] #en rapport aussi avec l'aspect aléatoire
ry=[] #
rz=[] #

vert=[]
faces=[]
uv=[]

#ici génération des rx, ry, rz

#ici on génère les vertices avec comme exemple :
vert.append([rx[0],ry[0],rz[0]])

#ici on relie les vertices pour former des faces :
faces.append([7,8,22,17])

#####ajout concernant l'uv qui bug#######
i=0
for i in range(0,70,1):
   uv.append( (0.0+i,0.0+i))

faces.uv=uv #ca bug a ce niveau là
C = Mesh.FaceModes
f.mode|=C['TEX']
#############################

me= bpy.data.meshes.new('rockmesh')

me.verts.extend(vert)
me.faces.extend(faces)

scn.objects.new(me, 'rocher')


#ici une partie pour recalculer les normals et smoother le tout.

Blender.Redraw()
melwe
Messages : 444
Inscription : 22 avr. 2007, 02:46
Localisation : Nancy

Message par melwe »

Tout d'abord, quel est le message d'erreur ?

Dans ton code, là, il y a en effet des soucis. À ce que je vois, tu as vert qui sera la liste de tes sommets, et faces la liste de tes faces. Les vert.append et faces.append me vont. Ensuite, il n'est pas nécessaire de dire i=0 avant de débuter la boucle for, car dedans, la variable i est redéfinie, et prendra l'ensemble des valeurs entières entre 0 et 70. En passant, le range(0,70,1) peut s'abbréger en range(70). Ensuite, tu fabriques une liste de coordonnées uv qui seront (0,0),(1,1),...,(69,69). Pourquoi pas, mais vu que toutes les coordonnées sont alignées sur la même ligne, la paramétrisation est pour le moins hasardeuse. Je ne vois d'ailleurs pas pourquoi tu dis 0.0+i, i devrait suffire amplement. Enfin je pense que le problème vient de là, tu dis "faces.uv=uv", mais a priori, faces est un objet de type liste, il n'a pas de raison d'avoir d'attribut uv. Si tu as lu l'API, l'uv est un attribut d'une FACE d'un objet de type MESH. Donc là, normalement, il te dit que faces n'a pas l'attribut uv.

Edit:
En fait, je dis nimp. En regardant l'API, il y a un exemple fabriquant un mesh avec extend comme tu le fais, donc mea culpa. En fait, il ne s'agit pas d'une liste, mais d'un objet de type MFaceSeq dont la méthode extent est refaite. Par contre, je maintiens le soucis pour faces.uv, car là, je pense bien que'une liste de tuples n'a pas d'attribut uv. Il faut donc que tu ajoutes tes faces, puis que pour chaque face, tu attribues les coordonnées UV.

Bon courage !

P.S. Nancéen depuis peu en fait :)
Vi.
Messages : 23
Inscription : 15 févr. 2009, 17:48

Message par Vi. »

Vi désolé pour les quelques aberrations de mon code :?
En ce qui concerne le i=0, j'avais vu ça dans un script, du coup depuis je le fou partout :D
Plus classe le range (70), merci pour l'info ;)

Ensuite concernant la génération d'uv, faut savoir que j'ai fait cette boucle aberrante, à la va vite, pour tester. C'est vrai qu'elle n'a aucun intérêt.

On les attributs comment les coordonnées uv ?
Ce qui est bizarre c'est que l'on trouve aucun code de démonstration à ce sujet sur internet.. A croire que personne n'a jamais voulu générer des uvmap par le biai d'un script :(
melwe
Messages : 444
Inscription : 22 avr. 2007, 02:46
Localisation : Nancy

Message par melwe »

l'API donne qu'une face possède un attribut uv, qui contient les coordonnées uv des sommets de la face. Ensuite, je suppose que le principe est le même que pour NMesh, dans les différents scripts de jmsoler, si f est un objet de type MFace, f.uv[n] correspond aux coorconnées uv du sommet f.vert[n] donc si tu crées une face (v1,v2,v3) dans ton ms.verts.extend(blabla), ensuite, dans la face, tu dois assigner les uv par un truc du genre f.uv = [les coordonnées uv de v1, les coordonnées uv de v2, les coordonnées uv de v3]

Pour faire bien les choses, je crois que dans le me.faces.extend(blabla) dont l'API est décrite ici tu peux spécifier True pour l'argument indexList, ce qui te donnera les indices de chaque face dans le mesh. Du coup, tu peux faire un truc du genre

1) créer la liste des sommets
2)créer la liste des faces
3) créer la liste des uv pour les faces
4)me.verts.extend(liste des sommets)
5)indexLi = me.faces.extend(liste des faces)
6)for oldi, newi in enumerate(indexLi)
me.faces[newi].uv = liste_des_uv[oldi]

Pour ce qui est des scripts avec traitement des UVs, une fois de plus, je te renvoie vers les sites officiels de blender, tu as ici un catalogue des scripts officiels, avec une section UV. En cherchant un peu, tu dois pouvoir trouver les sources. Sur mon système, debian, avec la version lenny du paquet blender, j'ai un dossier /usr/share/blender/scripts/blender/, dans lequel tu as les scripts uvcalc_* dont tu peux regarder les sources. Tu dois normalement avoir aussi les sources quelque part, c'est ce que Charles te conseillait de regarder.
Vi.
Messages : 23
Inscription : 15 févr. 2009, 17:48

Message par Vi. »

Merci beaucoup pour ton aide :)
Je sais maintenant comment modifier les coordonnées uv d'une face par le biais du python, seulement si l'objet à déjà été uvmappé avant.
Et c'est bien ça le dernier problème qu'il me reste.

Savez vous comment créer un uv layer pour le mesh ?
Vi.
Messages : 23
Inscription : 15 févr. 2009, 17:48

Message par Vi. »

Je crois avoir trouvé, avec le code suivant :

Code : Tout sélectionner

uvname = 'nom_du_layer'
ME.addUVLayer(uvname)
ME.activeUVLayer = uvname

Voir documentation ici :
http://www.blender.org/documentation/24 ... addUVLayer


Mais malheureusement, j'ai un soucis, la console me renvoie l'erreur suivante :
AttributeError : addUVLayer

Savez vous à quoi c'est du ? :(
jms
Messages : 56
Inscription : 20 sept. 2007, 21:33

Message par jms »

Vi. a écrit :Je crois avoir trouvé, avec le code suivant :

Code : Tout sélectionner

uvname = 'nom_du_layer'
ME.addUVLayer(uvname)
ME.activeUVLayer = uvname

Voir documentation ici :
http://www.blender.org/documentation/24 ... addUVLayer


Mais malheureusement, j'ai un soucis, la console me renvoie l'erreur suivante :
AttributeError : addUVLayer

Savez vous à quoi c'est du ? :(


A mon avis, tu n'es pas sur le bon forum pour obtenir les renseignements que tu cherches.
melwe
Messages : 444
Inscription : 22 avr. 2007, 02:46
Localisation : Nancy

Message par melwe »

A priori, ton erreur semble dire que ton objet ME n'a pas d'attribut UVLayer. Te serait-il possible de nous donner la ligne où tu définis ton objet ME, et le code entre la définition et l'ajout du calque UV ? Je vais faire un test de mon côté pour voir ce qu'il en est. Bon courage !
Vi.
Messages : 23
Inscription : 15 févr. 2009, 17:48

Message par Vi. »

Ouaip, effectivement, j'avais mal définit le "ME", merci bien :)
La création de l'uv layer fonctionne nikel maintenant..

Mais je ne sais pas pourquoi, maintenant, le changement des coordonnées ne marche pas comme avant :(
Il y a une histoire de "vector".

Je vous laisse mon code, en espérant que vous puissiez m'aider :?

Code : Tout sélectionner

import Blender
import bpy
from Blender import Mesh, Object, Scene, Window

editmode = Window.EditMode()
if editmode: Window.EditMode(0)



############################################# Suppression de l'ancien objet rocher
scn= Blender.Scene.GetCurrent()
oldobj= Blender.Object.Get()

for i in oldobj :
   if i.getName() == "rocher" :
      oldrock= Blender.Object.Get("rocher")
      scn.unlink(oldrock)
      oldrock.name= 'oldrock'
      scn= Blender.Scene.GetCurrent()



############################################# Génération des valeurs randoms
nz=0.7
rx=[]
ry=[]
rz=[]

for i in range(70):
   rx.append((Blender.Noise.random()-0.5)*nz)
   ry.append((Blender.Noise.random()-0.5)*nz)
   rz.append((Blender.Noise.random()-0.5)*nz+1)



############################################# Génération des listes vertices,faces

v=[]
f=[]

# vertices centrales (XZ)
v.append([rx[0],ry[0],rz[0]-1.8])
v.append([rx[1]-1.5,ry[1],rz[1]-1.8])
v.append([rx[2]-2.7,ry[2],rz[2]-1.5])
v.append([rx[3]-4,ry[3],rz[3]-0.7])
v.append([rx[4]-4,ry[4],rz[4]+0.7])
v.append([rx[5]-2.7,ry[5],rz[5]+1.5])
v.append([rx[6]-1.5,ry[6],rz[6]+1.8])
v.append([rx[7],ry[7],rz[7]+2])
v.append([rx[8]+1.5,ry[8],rz[8]+1.8])
v.append([rx[9]+2.7,ry[9],rz[9]+1.5])
v.append([rx[10]+4,ry[10],rz[10]+0.7])
v.append([rx[11]+4,ry[11],rz[11]-0.7])
v.append([rx[12]+2.7,ry[12],rz[12]-1.5])
v.append([rx[13]+1.5,ry[13],rz[13]-1.8])

# vertices centrales (YZ)
v.append([rx[14],ry[14]-1.8,rz[14]-1.8])
v.append([rx[15],ry[15]-2.9,rz[15]-1])
v.append([rx[16],ry[16]-2.9,rz[16]+1])
v.append([rx[17],ry[17]-1.8,rz[17]+1.8])
v.append([rx[18],ry[18]+1.8,rz[18]+1.8])
v.append([rx[19],ry[19]+2.9,rz[19]+1])
v.append([rx[20],ry[20]+2.9,rz[20]-1])
v.append([rx[21],ry[21]+1.8,rz[21]-1.8])

# vertices peripheriques
v.append([rx[22]+1.6,ry[22]-1.7,rz[22]+1.5])
v.append([rx[23]+2.7,ry[23]-1.5,rz[23]+1.2])
v.append([rx[24]+3.7,ry[24]-1,rz[24]+0.6])
v.append([rx[25]+1.4,ry[25]-2.8,rz[25]+0.9])
v.append([rx[26]+2.4,ry[26]-2.5,rz[26]+0.6])
v.append([rx[27]+3.1,ry[27]-2,rz[27]+0.3])

v.append([rx[28]+1.6,ry[28]-1.7,rz[28]-1.5])
v.append([rx[29]+2.7,ry[29]-1.5,rz[29]-1.2])
v.append([rx[30]+3.7,ry[30]-1,rz[30]-0.6])
v.append([rx[31]+1.4,ry[31]-2.8,rz[31]-0.9])
v.append([rx[32]+2.4,ry[32]-2.5,rz[32]-0.6])
v.append([rx[33]+3.1,ry[33]-2,rz[33]-0.3])
#
v.append([rx[34]+1.6,ry[34]+1.7,rz[34]+1.5])
v.append([rx[35]+2.7,ry[35]+1.5,rz[35]+1.2])
v.append([rx[36]+3.7,ry[36]+1,rz[36]+0.6])
v.append([rx[37]+1.4,ry[37]+2.8,rz[37]+0.9])
v.append([rx[38]+2.4,ry[38]+2.5,rz[38]+0.6])
v.append([rx[39]+3.1,ry[39]+2,rz[39]+0.3])

v.append([rx[40]+1.6,ry[40]+1.7,rz[40]-1.5])
v.append([rx[41]+2.7,ry[41]+1.5,rz[41]-1.2])
v.append([rx[42]+3.7,ry[42]+1,rz[42]-0.6])
v.append([rx[43]+1.4,ry[43]+2.8,rz[43]-0.9])
v.append([rx[44]+2.4,ry[44]+2.5,rz[44]-0.6])
v.append([rx[45]+3.1,ry[45]+2,rz[45]-0.3])
#
v.append([rx[46]-1.6,ry[46]+1.7,rz[46]+1.5])
v.append([rx[47]-2.7,ry[47]+1.5,rz[47]+1.2])
v.append([rx[48]-3.7,ry[48]+1,rz[48]+0.6])
v.append([rx[49]-1.4,ry[49]+2.8,rz[49]+0.9])
v.append([rx[50]-2.4,ry[50]+2.5,rz[50]+0.6])
v.append([rx[51]-3.1,ry[51]+2,rz[51]+0.3])

v.append([rx[52]-1.6,ry[52]+1.7,rz[52]-1.5])
v.append([rx[53]-2.7,ry[53]+1.5,rz[53]-1.2])
v.append([rx[54]-3.7,ry[54]+1,rz[54]-0.6])
v.append([rx[55]-1.4,ry[55]+2.8,rz[55]-0.9])
v.append([rx[56]-2.4,ry[56]+2.5,rz[56]-0.6])
v.append([rx[57]-3.1,ry[57]+2,rz[57]-0.3])
#
v.append([rx[58]-1.6,ry[58]-1.7,rz[58]+1.5])
v.append([rx[59]-2.7,ry[59]-1.5,rz[59]+1.2])
v.append([rx[60]-3.7,ry[60]-1,rz[60]+0.6])
v.append([rx[61]-1.4,ry[61]-2.8,rz[61]+0.9])
v.append([rx[62]-2.4,ry[62]-2.5,rz[62]+0.6])
v.append([rx[63]-3.1,ry[63]-2,rz[63]+0.3])

v.append([rx[64]-1.6,ry[64]-1.7,rz[64]-1.5])
v.append([rx[65]-2.7,ry[65]-1.5,rz[65]-1.2])
v.append([rx[66]-3.7,ry[66]-1,rz[66]-0.6])
v.append([rx[67]-1.4,ry[67]-2.8,rz[67]-0.9])
v.append([rx[68]-2.4,ry[68]-2.5,rz[68]-0.6])
v.append([rx[69]-3.1,ry[69]-2,rz[69]-0.3])



# faces peripheriques
for i in range(0,43,6):
   f.append([22+i,23+i,26+i,25+i])
   f.append([23+i,24+i,27+i,26+i])

# faces centrales
f.append([7,8,22,17])
f.append([8,9,23,22])
f.append([9,10,24,23])
f.append([10,11,30,24])
f.append([11,12,29,30])
f.append([12,13,28,29])
f.append([13,0,14,28])

f.append([7,8,34,18])
f.append([8,9,35,34])
f.append([9,10,36,35])
f.append([10,11,42,36])
f.append([11,12,41,42])
f.append([12,13,40,41])
f.append([13,0,21,40])

f.append([7,6,58,17])
f.append([6,5,59,58])
f.append([5,4,60,59])
f.append([4,3,66,60])
f.append([3,2,65,66])
f.append([2,1,64,65])
f.append([1,0,14,64])

f.append([7,6,46,18])
f.append([6,5,47,46])
f.append([5,4,48,47])
f.append([4,3,54,48])
f.append([3,2,53,54])
f.append([2,1,52,53])
f.append([1,0,21,52])

f.append([60,63,69,66])
f.append([63,62,68,69])
f.append([62,61,67,68])
f.append([61,16,15,67])
f.append([16,25,31,15])
f.append([25,26,32,31])
f.append([26,27,33,32])
f.append([27,24,30,33])

f.append([48,51,57,54])
f.append([51,50,56,57])
f.append([50,49,55,56])
f.append([49,19,20,55])
f.append([19,37,43,20])
f.append([37,38,44,43])
f.append([38,39,45,44])
f.append([39,36,42,45])

f.append([17,16,25,22])
f.append([17,16,61,58])
f.append([14,15,31,28])
f.append([14,15,67,64])
f.append([18,19,37,34])
f.append([18,19,49,46])
f.append([21,20,43,40])
f.append([21,20,55,52])



############################################# Création du mesh à partir des listes
me= bpy.data.meshes.new('rockmesh')

me.verts.extend(v)
me.faces.extend(f)

scn.objects.new(me, 'rocher')



############################################# Recalc des normals et Smooth
obj = Blender.Object.Get("rocher")
me = obj.getData(mesh=True)
faces = me.faces
me.recalcNormals()
for f in faces :
   f.smooth=1
me.update()



############################################# Création et Activation d'un uv layer
uvname = 'Col'
me.addUVLayer(uvname)
me.activeUVLayer = uvname
me.update()



################## FONCTIONNE PAS ########### Test de changement de coord. d'uv
uv=me.faces[2].uv
print uv
me.faces[2].uv=[(2.5, 2.5), (1, 1), (3, 7), (5, 2)]
uv=me.faces[2].uv
print uv
me.update()





Blender.Redraw()

if editmode: Window.EditMode(1)
melwe
Messages : 444
Inscription : 22 avr. 2007, 02:46
Localisation : Nancy

Message par melwe »

Le message d'erreur exact serait pratique :)
Vi.
Messages : 23
Inscription : 15 févr. 2009, 17:48

Message par Vi. »

Désolé, je croyais que tu testerai mon code :)
Image
Répondre