PDA

Voir la version complète : Problème Cadre paramétrable - Xpresso comment agir sur une sélection de polygones



JIMYAR
22/10/2014, 12h33
Bonjour à tous,
un problème pour moi.
Il s'agit de faire 1 cadre paramétrable en longueur et largeur (sans déformation) piloté par des données utilisateurs (cf fichier joint)
J'ai imaginé pouvoir piloter ma sélection de polygones, glissée/déposée dans le Gestionnaire Xpresso, en la déplaçant sur l'axe des y par ex.

Et là surprise. En entrée et sortie de mon noeud je n'ai que 3 possibilités : activé / caractéristiques de base / et objet.
Quelqu'un peut m'aider sur le sujet (en espérant que je suis sur le bon groupe).
Merci
NB: solutions sans mograph SVP (Visualize oblige !)

http://jim.olympe.in/pb%20cadre.png

tabou
22/10/2014, 13h43
Pour modifier la géométrie avec Xpresso il faut utiliser le nœud polygone (ou point selon le cas), ce qui peut être laborieux si il y a de nombreux polys à contrôler.
Pour faire un cadre le plus simple c'est d'utiliser une extrusion contrôlée avec deux splines rectangles dont les dimensions seront pilotées par les DU.

JIMYAR
22/10/2014, 19h52
J'ai opté pour la version spline comme suggérée très justement par Tabou, ça fonctionne bien (pourquoi j'y ai pas pensé !)
Par contre je ne serai pas opposé à une aide sur le noeud polygone dont tu parles (pas trouvé sur le forum pour l'instant). Dans tous les cas merci bien !

tabou
22/10/2014, 23h03
Le nœud polygone ne permet pas d'agir directement sur celui ci. En fait il est utile pour récupérer l'index des points qui le définissent et les injecter dans des nœuds point qui eux permettent d'agir sur la position, donc pour bouger un quad il faudra utiliser 4 nœuds point.

Pour connaitre l'index d'un polygone il faut afficher le gestionnaire de structure et le passer en mode polygones (il est en mode point par défaut).
Le poly sélectionné dans la vue apparait en surbrillance dans le gestionnaire de structure, ce qui permet de repérer facilement le n° d'indice qui est affiché dans la colonne de gauche. Il y a d'ailleurs un menu qui permet d'accéder directement au premier poly sélectionné, pratique quand il y en a des centaines.

Sinon ce nœud sert aussi à récupérer le nombre de polys composant un objet. Il sort aussi le centre et la normale d'un poly, utiles par exemple pour fixer et orienter un objet à la surface du poly.

Machaon
22/10/2014, 23h33
Très bien décrit Tabou les noeuds point et polygone. :icon_mrgreen:

Si tu me le permets je joins un lien sur un p'tit tuto vidéo (court et didactique) décrivant parfaitement ce que tu expliques pour que JIMYAR visualise bien le sujet et comprenne également toute la difficulté de gestion de ces 2 noeuds dans son futur projet.
https://www.youtube.com/watch?v=DGicx8FXufU

En bonus pour JIMYAR le lien de la bible d'Xpresso (bible est un bien grand mot mais ce guide présente les prérequis à l'utilisation d'Xpresso). Bible que JIMYAR a peut-être déjà lu !
http://frenchcinema4d.fr/downloads.php?do=file&id=608

xs_yann
23/10/2014, 18h08
Salut,

La solution de tabou est sans aucun doute la plus simple et la meilleure, mais j’ai quand même essayé de le faire avec des sélections de polygones. Voici ce que ça donne (avec deux noeuds python):

http://www.xsyann.com/fc4d/ts_xpresso.jpg

La sélection du bas :

http://www.xsyann.com/fc4d/ts_bottom.jpg

Pour modifier l’épaisseur du cadre, le but est de pouvoir faire une mise à l’échelle sur cet axe :

http://www.xsyann.com/fc4d/ts_bottom_axis.jpg

Afin que les points les plus bas restent à zero et que la mise à l’échelle s’effectue vers le haut.

http://www.xsyann.com/fc4d/ts_xpresso_bottom.jpg

‘bottom’ (en haut à gauche) est le tag de sélection de polygones. Il est relié au noeud python BoundingBox qui calcule la bounding box de la sélection (taille et centre).
Le centre est déplacé en fonction d’un vecteur (‘axis’), c’est le même fonctionnement que dans l’outil de sélection ou AxisCenter avec :
-1 = -100%
0 = 0%
0.5 = 50%
1 = 100%

Ici, il est relié à une constante (0, -1, 0) pour placer l’axe tout en bas de la bounding box en Y, et au milieu en X et en Z.

Maintenant que l’on a la taille et la position de la sélection, on peut modifier la composante qui nous intéresse.
Le bas du cadre reste toujours à la même position, on relie donc l’ancienne position à la nouvelle (‘pos’ -> ‘pos’).
Pour la taille, il faut décomposer le vecteur en 3 réels (Vector2Reals), garder les anciens X et Z et choisir notre taille en Y (la donnée utilisateur “Thickness Y”).

‘enable’ est relié à une constante qu’il est conseillé de mettre à False (pour désactiver l’xpresso) lors de modifications dans les connexions. Si, par exemple, le port ‘pos’ ou ‘size’ du noeud ‘TransformSelection’ n’est pas relié, c’est un vecteur (0, 0, 0) par défaut qui est pris en compte, ce qui n’est pas forcément souhaitable.

Pour la barre de droite :

http://www.xsyann.com/fc4d/ts_right_axis.jpg
http://www.xsyann.com/fc4d/ts_xpresso_right.jpg

Ici on place l’axe tout à droite, soit 100% en X = (1, 0, 0). Pour la position on divise par deux la longueur. Il n’y a pas besoin de soustraire la moitié de l’épaisseur étant donné que l’axe est à 100 % en X.

Le fichier : http://www.xsyann.com/fc4d/frame_xpresso.c4d.zip

J’ai ajouté un exemple avec un slider pour contrôler la taille d’une sélection de polygones sur notre ami Fred (avec son nez, restons correct :icon_mrgreen:).

http://www.xsyann.com/fc4d/ts_fred.jpg

http://www.xsyann.com/fc4d/ts_fred.gif

Avec l’axe en (0, 0, 1).

En ce qui concerne le python, pour calculer la bounding box :


import c4d

def getPoints(obj, polygons):
points = dict([(point, obj.GetPoint(point)) for poly in polygons for point in [poly.a, poly.b, poly.c, poly.d]])
return points

def splitVectors(vectors):
x, y, z = [], [], []
for v in vectors:
x.append(v.x)
y.append(v.y)
z.append(v.z)
return x, y, z

def getBoundingBox(obj, points, axis):
x, y, z = splitVectors(points.values())
min_pos, max_pos = c4d.Vector(min(x), min(y), min(z)), c4d.Vector(max(x), max(y), max(z))
pos, size = (min_pos + max_pos) / 2.0, max_pos - min_pos
return pos + (axis ^ (size / 2.0)), size

def main():
global pos, size
obj = selection.GetObject()
bs = selection.GetBaseSelect()
selected = [obj.GetPolygon(i) for i, s in enumerate(bs.GetAll(obj.GetPolygonCount())) if s]
pos, size = getBoundingBox(obj, getPoints(obj, selected), axis)



Pour modifier une sélection de polygones :


import c4d

DELTA = 0.01

def getPoints(obj, polygons):
points = dict([(point, obj.GetPoint(point)) for poly in polygons for point in [poly.a, poly.b, poly.c, poly.d]])
return points

def splitVectors(vectors):
x, y, z = [], [], []
for v in vectors:
x.append(v.x)
y.append(v.y)
z.append(v.z)
return x, y, z

def mapVector(v, w, func):
return c4d.Vector(func(v.x, w.x), func(v.y, w.y), func(v.z, w.z))

def getBoundingBox(obj, points):
x, y, z = splitVectors(points.values())
min_pos, max_pos = c4d.Vector(min(x), min(y), min(z)), c4d.Vector(max(x), max(y), max(z))
return (min_pos + max_pos) / 2.0, max_pos - min_pos

def transformPoints(obj, points, center, offset, scale):
for i, point in points.iteritems():
obj.SetPoint(i, ((point - center) ^ scale) + center + offset)

def transformPolygonSelection(obj, bs, pos, size, axis):
selected = [obj.GetPolygon(i) for i, s in enumerate(bs.GetAll(obj.GetPolygonCount())) if s]
points = getPoints(obj, selected)
center, poly_size = getBoundingBox(obj, points)
center += (axis ^ (poly_size / 2.0))
offset = pos - center
scale = mapVector(size, poly_size, lambda x, y: max(x, DELTA) / y)
transformPoints(obj, points, center, offset, scale)
obj.Message(c4d.MSG_UPDATE)

def main():
if not enable or not selection:
return
transformPolygonSelection(selection.GetObject(), selection.GetBaseSelect(), pos, size, axis)

Math1712
23/10/2014, 19h06
Haha le killer :whistling:

JIMYAR
24/10/2014, 20h48
Vraiment grands remerciements à tous, effectivement j'ai bien eu en main la "Bible Xpresso" très instructive, mais pour les débutants pas évident de voir les tenants/aboutissants, donc parfait Machaon pour la piste du petit tuto qui est simple et très efficace.

Pour ce qui est du "killer xs_yann" merci d'avoir planché sur le pb original de la question.
Si j'ai compris les grandes lignes, il par contre me falloir 1 peu de tps pour tout décortiquer mais c hyper instructif et ça marche bien aussi.

En fait je me rends compte maintenant que je me suis fixé 1 projet qui me semble difficilement accessible pour le moment :
il s'agissait de faire une brise soleil (à lamelles orientables) entièrement paramétrable :huh: (cf capture)

http://jim.olympe.in/Brise_soleil_projet.jpg

Du coup je ne suis peut-être plus sur la bonne discussion (la problématique du cadre ayant été résolue) !!! qu'en disent Mrs les modérateurs ?
En tout cas mes plus vifs remerciement pour toutes les réponses si pertinentes

Realzeb
24/10/2014, 22h53
Si ça peut t'aider en quelque chose, j'ai fait un store il y a quelque temps :

http://frenchcinema4d.fr/showthread.php?50976-La-R%E9cr%E9ation-de-Zeb-(RDV-en-derni%E8res-pages)-Rover-Curiosity-en-cours&p=1036643&viewfull=1#post1036643

;)

geantvert
27/10/2014, 16h50
Ce genre de question donne envie de tester sois même :)
La solution de master xs-yann, et en reprenant l'idée de Tabou, voila ce que j'aurais fait en xpresso (http://space-rabbit.com/echanges/french/persiennes.zip).
J'utilise juste le plugin smart outline pour l’épaisseur.