PDA

Voir la version complète : Déformation cylindrique



César Vonc
19/03/2016, 11h53
Salut,


J'ai un petit souci de géométrie qui me semble vraiment tout bête, mais sur lequel je bloque bêtement. : /


J'ai un objet cylindrique avec un des couvercles aplati sur un axe (ici le Z), comme ceci :

17420

Et j'aimerais le transformer en un beau cylindre normal.

Donc, logiquement, je créé un facteur entre le bas et le haut du cylindre, où le bas vaut 0 % et le haut 100 %, que je multiplie à l'échelle Z de mes points, mais j'obtiens un effet bombé, comme si l'influence était plus forte en bas qu'en haut :

17422


Voici le bout de code et le fichier C4D avec l'objet et le scripte Python. Je pige pas, ça devrait marcher pourtant. :icon_banghead:



centre = obj.GetMp()
boite = obj.GetRad()
boite2 = boite * 2
pts = obj.GetAllPoints()

for i, p in enumerate(pts) :
fac = (p.y - centre.y + boite.y) / boite2.y
fac *= 3 # Intensité
fac += 1
pts[i].z = p.z * fac

obj.SetAllPoints(pts)

yayaprod
19/03/2016, 12h03
Avec un peau nurb ? ce serait plus facile à gérer, tu déformes sans problème!

César Vonc
19/03/2016, 12h06
J'aimerais faire ça en programmation, car en réalité c'est pour un autre projet que C4D. ^^

yayaprod
19/03/2016, 12h13
En définissant une zone d'influence sur l'objet ? Bon je te laisse :icon_redface: la programmation et moi c'est pas possible, bien que j'avais commencé
sur Director7 et depuis j'ai abandonné.

gr4ph0s
19/03/2016, 14h09
Je dis peut être une connerie mais tu ne calcul pas le coefficient entre min z max z du coup tu appliques un coefficient de 1 ce qui est correcte pour le top mais logiquement pas pour le reste.

Après tu peux recup l'endroit le plus large et faire avec des sweep mais ut souhaite surement conserver le maillage. J'ai tout placé en 0.0.0 mais je pense que t'a capté l'idée ^^


import c4d
import math


def main():
obj = op.GetDown()
if not obj : return None
obj = obj.GetClone()

centre = obj.GetMp()
boite = obj.GetRad()
boite2 = boite * 2
pts = obj.GetAllPoints()

min_y = -boite2.y
max_y = boite2.y


max_z = 0
for i, p in enumerate(pts) :
if p.z > max_z:
max_z = p.z

circleSize = (3.14 * math.sqrt(max_z)) * 2.25
baseCircle = c4d.BaseObject(c4d.Osplinecircle)
baseCircle[c4d.PRIM_PLANE] = 2
baseCircle[c4d.PRIM_CIRCLE_RADIUS] = circleSize

TopCircle = c4d.BaseObject(c4d.Osplinecircle)
TopCircle[c4d.PRIM_PLANE] = 2
TopCircle[c4d.PRIM_CIRCLE_RADIUS] = circleSize
TopCircle[c4d.ID_BASEOBJECT_ABS_POSITION] = c4d.Vector(0,max_y,0)

null = c4d.BaseObject(c4d.Onull)

loft = c4d.BaseObject(c4d.Oloft)

baseCircle.InsertUnder(loft)
TopCircle.InsertUnder(loft)

loft.InsertUnder(null)


return null

César Vonc
19/03/2016, 15h12
Ouais, non, je veux modifier le maillage de l'objet existant, qui peut être irrégulier, pour faire comme un déformateur, en somme.

Enfin, merci pour ton essai. : p

valkaari
20/03/2016, 04h11
M'a fallut une plombe pour réfléchir correctement ...

C'est comme calculer un % sauf que t'as un taux variable.

0.8 c'est ton taux de déformation, variable en fonction de fac qui est le rapport point/ hauteur de l'objet.
diviser par 1.0 - tauxVariable pour revenir à la valeur avant déformation.




fac = (py / boite2.y)
pts[i].z = p.z / (1.0 - (0.8 * fac ))

César Vonc
20/03/2016, 10h06
:icon_prie:

Chapeau Val, oui je pense que c'était moins évident que ce qui n'y parait, j'étais parti dans des exponentielles, des carrés, des machins, pour un résultat à peu près cylindrique.

Mais là c'est parfait, et finalement tout con quand on regarde bien, grand merci !