Blender
2.25/2.26...etc.
|
Python
:
Modélisation
et structure:
repérer
les segments d'un mesh
et
accessoirement
les faces qui
empêchent
de décimer un mesh
|
|
Avant d'utiliser ce script, il est indispensable
de d'assimiler certaines notions:
1/ Les meshes de Blender
sont comme des voiles qui enrobent les objets : Sphere, Cube, Tore,
Cone etc. Fondamentalement rien ne les distingue.
2/ Ces voiles ne sont pas de vrais
d'objet << mathématiques >>, ils en imitent seulement
la forme.
3/ Le système de décimation
de Blender n'accepte que des voiles continus
4/ Si un voile est << cousu
>> sur un premier ailleurs que sur la limite extérieure, la décimation
ne fonctionnera plus.
Ces voiles continus ont, malgré tout,
certaines propriétés qui les regroupent sous le nom de "manifold".
Exemple de mesh reconnu comme un manifold
Exemple de mesh non reconnu comme un
manifold
L'axe central de ce mesh partagé
par plus de deux faces rend impossible l'utilisation de l'outil de décimation
.
Après application du script
en mode faceselect toutes les face concernées sont sélectionnées
et peuvent être traitées par un Separate, pkey
ou un Split :
#------------------------------------
# Reperage des faces engendrant
# des erreurs de type no manifold mesh
# (c) J-M Soler mai 2003
#------------------------------------
#------------------------------------
# L'objectif premier de ce script etait de
# creer un objet qui n'est pas gere
# pas la structure de donnes de
# Blender: les segments
#
# Ces segments sont reperes par
# face et cette attribution est utilisee
# pour retrouver ceux qui n'appartiennent
# qu'a une seule.
#
#
# Accidentellemeent la premiere version
# du script original montrait aussi
# ceux qui étaient relies a plus d'une
# face et ainsi de reperer ce
# qui empeche blender de realiser
# une decimation correcte.
#
# Plusieurs conditions sont necessaires
# pour donner à ce script un peu d'efficacite:
#
# 1/ le mesh cree en fin de parcourt
# qui se nomme "test" doit être efface
# avant de relancer le script une seconde
# fois
#
# 2/ le mesh original doit avoir recu
# des coordonnees uv pour que le script puisse
# les utiliser afin de pointer aussi les faces
# fautives en mode FaceSelect. L'execution
# du script lui-même ne doit pas se faire
# en mode FaceSelect.
#------------------------------------
import Blender
#------------------------------------
# o est un objet mesh que l'on doit
# imperativement nommer
#------------------------------------
o=Blender.Object.Get('Plane')
#------------------------------------
# m copie des donnees du mesh
#------------------------------------
m=Blender.NMesh.GetRaw(o.data.name)
#------------------------------------
# mn est second receptacle pour les donnees
# traitees
#------------------------------------
mn=Blender.NMesh.GetRaw()
#------------------------------------
# un tableau pou regrouper toutes les
# paires de sommets qui constitue un
# segment
#------------------------------------
segment=[]
#------------------------------------
# un tableau pour identier les segments
# qui sont utilises par une face
#------------------------------------
faceseg=[]
#------------------------------------
# On analyse toutes les faces
#------------------------------------
for f in m.faces:
#------------------------------------
# Verifier que le travail est necessaire
#------------------------------------
#if len(f.v)>=3:
if 1==1:
#----------------------
# Creation d'un receptacle
# pour les infos collectees
# on ne s'interesse qu'aux
# valeur d'index des sommets
#----------------------
face=[]
#----------------------
# Analyser chaque paire de sommets...
#----------------------
for n in range(len(f.v)-1):
#----------------------
# Comme les extremites peuvent
# apparaitre dans un sens ou
# dans l'autre...
#----------------------
s0=[f.v[n].index,
f.v[n+1].index]
s1=[f.v[n+1].index,
f.v[n].index]
#----------------------
# on teste la presence des
# deux combinaisons dans
# la liste de segments qui
# sont donc des paires de
# positions de sommets dans
# la listes des mesh.verts
#----------------------
if s0 not in segment and\
s1 not in segment:
#----------------------
# ...si elle n'y est pas
# on l'ajoute
#----------------------
segment.append(s0)
#----------------------
# On enregistre la position
# dans la liste de segments
# de la face courante.
#
# Comme on ne sait pas dans quel
# ordre les sommets du
# segment ont ete enregistres
# on essaye les deux possibilites.
#----------------------
try:
face.append(segment.index(s0))
except:
face.append(segment.index(s1))
#----------------------
# On complete le face en
# testant le segment constitue
# du premier et du dernier
# sommet de la liste
#----------------------
s2=[f.v[0].index,f.v[n+1].index]
s3=[f.v[n+1].index,f.v[0].index]
#----------------------
# Meme procedure que les autres
# paires...
#----------------------
if s2 not in segment and\
s3 not in segment:
segment.append(s2)
#----------------------
# ...
#----------------------
try:
face.append(segment.index(s2))
except:
face.append(segment.index(s3))
#----------------------
# On ajoute la liste des segments
# de la face traitee
# a la liste des faces
# deja analysees
#----------------------
faceseg.append(face[:])
#----------------------
# lordre de la liste faceseg correspont
# exactement a celui de la liste mesh.faces
#----------------------
else:
pass
#print len(faceseg), len(segment)
#------------------------------------
# Le principe consiste à filtrer toute la
# liste de segment face par face.
#
# Si un segment se trouve deja dans la liste
# alors il est marque' ...
#
# Si un segment n'a recu qu'une marque
# il appartient au perimetre de la forme
# S'il en a deux c'est qu'il fait partie
# d'un voile/enveloppe/plan gauchi au choix
# qui pourra être decime.
#
# S'il y en a 3 et plus les faces qui portent
# ce segment devront être separees du
# mesh principal.
#
# La liste segmentface gardera les
# marques de ce tri.
#------------------------------------
segmentface=len(segment)*[0]
tampon=[]
#------------------------------------
# nomanifoldkiller gere la liste des
# faces qui partagent un segment
# avec plus de 2 marques.
#------------------------------------
nomanifoldkiller=[]
m0=0
for f in faceseg:
for s in f:
if s in tampon:
segmentface[s]+=1
if segmentface[s]>1:
if m0 not in nomanifoldkiller:
nomanifoldkiller.append(m0)
else:
tampon.append(s)
m0+=1
m0=0
#------------------------------------
# Au premier passage, les faces fautives
# ne sont pas toutes marquees. Il faut donc
# les reprendre a partir de de la liste de segments
# pour reconnaitre celles qui n'ont pas ete
# deja enregistrees dans nomanifoldkiller
#------------------------------------
for f in faceseg:
for s in f:
if segmentface[s]>1:
if m0 not in nomanifoldkiller:
nomanifoldkiller.append(m0)
m0+=1
#------------------------------------
# Creation d'un mesh concretisant la limite
# du champ de faces genantes
#------------------------------------
s=0
for s0 in segmentface:
if s0>1:
for n in [0,1]:
vo=m.verts[segment[s][n]].co
vn=Blender.NMesh.Vert()
vn.co.x=vo.x
vn.co.y=vo.y
vn.co.z=vo.z
mn.verts.append(vn)
l=len(mn.verts)
f=Blender.NMesh.Face()
f.append(mn.verts[l-1])
f.append(mn.verts[l-2])
mn.faces.append(f)
s+=1
#------------------------------------
# Marquage des faces fautives dans le
# la zone uvmapping de telle maniere
# qu'un passage en mode FaceSelect
# les rende pleinement visibles sur
# l'objet meme.
#------------------------------------
for f in m.faces:
f.flag=0
for f in nomanifoldkiller:
m.faces[f].flag=1
Blender.NMesh.PutRaw(m,m.name)
o2=Blender.NMesh.PutRaw(mn,'test')
#print o2.name
o2.LocX,o2.LocY,o2.LocZ=o.LocX,o.LocY,o.LocZ
o2.SizeX,o2.SizeY,o2.SizeZ=o.SizeX,o.SizeY,o.SizeZ
o2.RotX,o2.RotY,o2.RotZ=o.RotX,o.RotY,o.RotZ
del nomanifoldkiller
del segmentface
del faceseg
del segment
|
Les questions concernant cette page
peuvent être posées sur :
news://news.zoo-logique.org/3D.Blender
|