Boutique Cinema 4D
Page 1 sur 2 12 DernièreDernière
Affichage des résultats 1 à 30 sur 58

Discussion: Plug-In et Ressorts.

  1. #1
    Gourou Avatar de Jean-Laurent
    Date d'inscription
    mai 2006
    C4D version
    R11.5
    Messages
    3 407

    Plug-In et Ressorts.

    Bonjour à tous, :odile:
    De nombreuses questions sur le forum (faire flotter un objet sur une mer, animer un bras mécanique, chute libre d'objets etc...) m'ont donné envie de lier mes deux loisirs, la 3D et la physique.

    Pour cela, je vais tenter de créer un Plug-In contenant différents tags (très simples) en rapport avec les lois de la physique.
    Tout cela existe déjà et se fait certainement facilement avec de nombreux Plug-In spécialisées, ou évidemment le module Dynamic, mon but n'est donc absolument pas de les concurrencer (pas le temps, pas le niveau, pas les moyens). :oops:
    C'est juste pour le plaisir. J'espère que ça me permettra de progresser en programmation avec l'aide des personnes du forum ou que ça permettra à d'autres d'utiliser plus facilement le langage COFFEE. Les exemples ne sont jamais trop nombreux.

    - Le premier tag concernera donc LES RESSORTS.

    Il s'agit juste de pouvoir lier entre eux plusieurs objets avec des ressorts (visibles ou non) aux caractéristiques réglables.


    Commençons tout en douceur avec un ressort à une dimension et une extrémité fixe.
    Avant de développer l'interface (ExpressionPlugIn) , mettons en place l'expression coffee.

    Les objets seront symbolisés par des sphères (Sphere1 et Sphere2) placées sur l'axe z et le ressort par une primitive "Helix" suivant le même axe.
    L'élongation du ressort se fera donc suivant l'axe z.

    [img width=850 height=605]http://cinema4d.chez-alice.fr/r2.JPG[/img]

    On placera l'expression coffee sur un Null provisoirement.

    Pour que le ressort ai toujours la même longueur que la distance entre les sphères auxquelles il est attaché:

    Code:
     main(doc,op)
    {
    
    var helix = doc->FindObject("Helix");        // On repère les objets dans le document.
    var Sphere2 = doc->FindObject("Sphere2");
    var Sphere1 = doc->FindObject("Sphere1");
    
    var pos2= Sphere2->GetPosition();	 // On récupère dans des variables la position des objets.
    var pos1= Sphere1->GetPosition();
    var posh =helix->GetPosition();
    
    var distance= vlen(pos2-pos1);           // On mesure la distance entre les deux sphères.
    
    var chelix= helix->GetContainer();   
    // On récupère les données (taille etc...) de la primitive   "ressort"
    
    chelix->SetData(PRIM_HELIX_HEIGHT,distance);  
    helix->SetContainer(chelix);
    // On règle la longueur du ressort, celle-ci est identique à la distance entre les sphères.
    
    helix->SetPosition(pos2);
    
    // On fixe l'extrémité du ressort sur la sphère2
    
    }
    On a maintenant créé un ressort qui s'étire ou se compresse entre les 2 sphères lorsqu'on les déplace suivant l'axe z.
    Pour plus d'esthétisme, on peut réduire le rayon à 50m et augmenter le nombre de spires (

    [img width=850 height=413]http://cinema4d.chez-alice.fr/r3.JPG[/img]

    Il reste maintenant à rendre le ressort dynamique pour qu'il agisse sur les sphères.

    Petit rappel:


    Les caractéristiques les plus importantes d'un ressort sont l0: sa longueur au repos et K: Sa raideur.

    Lorsqu'on l'étire ou le compresse d'une longueur x, la force qu'il exerce alors vaut:
    F= -K*x.

    Un objet de masse m soumis à cette force a une accélération a = F/m.
    (On négligera la masse des sphères dans un tout premier temps).

    L'accélération est liée à la vitesse par la formule: a=dv/dt (variation de vitesse et de temps, très courtes).
    Et la variation de position de l'objet: dx = v * dt.

    En coffee:

    Code:
    var v=0;			// Ces paramètres seront déclarées avant main (op,doc)
    var k =5;			// On peut les changer manuellement pour l'instant.
    var l0 =800;
    var dt =0.1;			// Temps en seconde entre chaque frame.
    
    var force = -k*(distance-l0); // On définit la force.
    
    v+=force*dt; 		// On définit la vitesse.	
    pos2.z+=v*dt;		// On change la position suivant l'axe z de la sphère.
    
    Sphere2->SetPosition(pos2);
    La sphère 2 oscille maintenant comme si elle était reliée à un ressort.
    Attention, si on tend trop le ressort pour l'instant (d > 2*l0) il casse.

    Si on souhaite que la sphère 1 oscille également (pas d'attache fixe) il suffit de rajouter:

    Code:
    pos1.z-=v*dt;
    Sphere1->SetPosition(pos1);
    Puisque les deux forces sont égales et opposées.

    Toutes remarques, questions etc... sont les bienvenues. :poucehaut:

    La suite: Un ressort dans toutes les directions de l'espace et prévision des limites. :odile:
    SMC fan.

  2. #2
    Pilier Avatar de phanault
    Date d'inscription
    décembre 2004
    C4D version
    R10
    OS
    OSX Lion
    Messages
    1 085

    Re: Plug-In et Ressorts.

    Ouahh ! Un wip scientifique avec Jean-Laurent !!!! :bounce:

    Ça promet déjà.

    Je te suis, tu peux en être assuré.
    Mac Pro 3GHz, 4Go Ram, R10 XL + Hair, CinemaDisplay 30"

  3. #3
    Gourou Avatar de GaazMaster
    Date d'inscription
    juillet 2005
    C4D version
    R25 Souscription
    OS
    Ventura 13.5
    Messages
    4 597

    Re: Plug-In et Ressorts.

    Animer un bras mécanique ... chute libre d'objets .... Hum ...
    Toi je vais être obligé de te sponsoriser !* *

    Bon alors déjà j'ai tout compris la théorie, ce qui est déjà une bonne chose ... pour ce qui est du côté plus pratique ( en l'occurence le coffee ) la ... bon ... euh ...* :mrgreen:

    Donc première question .... tu as utilisé une spline spirale, est ce que l'on peut adapter le principe avec une spline formule ?

    Par exemple : avec laquelle je simule le ressort d'un amortos
    X(t) : 6*sin(t*pi)
    Y(t) : 16*tanh(0.12*t)
    Z(t) : 6*cos(t*pi)
    Tmin : -10
    Tmax : 10
    Echantillon : 500

    Voila ... super initiative .... forcément !* :mrgreen:
    www.gaazmaster.com - Ça passait c'était beau ...

  4. #4
    Pilier
    Date d'inscription
    novembre 2003
    Messages
    1 240

    Re: Plug-In et Ressorts.

    EXELLENTE initiative Jean-Laurent, je met dans un coin et je prend des notes :prie:

  5. #5

    Re: Plug-In et Ressorts.

    Bon alors je vais regarder tout ca, par curiosité parce que j'y connais rien en prog' COFFEE (c'est quoi comme language déja? :nono

    ET j'oublie pas mon tube d'aspirine, j'ai déja vu Jean-Laurent sur des résolutions de problèmes.. :coup:


    Je suis, donc :odile:
    Cinema 4D R10

  6. #6
    Gourou Avatar de Jean-Laurent
    Date d'inscription
    mai 2006
    C4D version
    R11.5
    Messages
    3 407

    Re: Plug-In et Ressorts.

    Wahou, toutes ces réponses me font chaud au coeur.

    phanault: scientifique est un grand mot, les maths ne dépasseront pas le niveau lycée, promis. :wink:

    Gaaz: Oui, oui on peut l'adapter pour l'instant à une spline formule (je te mettrai un exemple) mais le principe est alors un poil différent.

    Ta spline formule est une "simple" spline paramétrique. Elle fait déjà tout ce que tu veux et se comporte en apparence comme un ressort. Tout simplement parceque tu as rentré la formule de l'équation résolue d'un ressort.

    J'aurais pu faire la même chose (en moins de lignes de code) du coup en rentrant directement la formule:
    Z= A*sin (wt + phi) qui décrit le déplacement d'un ressort dans une dimension.
    Dont ta "spline formule" est une simplification.

    Ou même en allant plus loin, si tu veux un ressort plus réaliste avec un amortissement:
    Z= A*exp(-landa*t)*sin (wt + phi)

    Le problème c'est que ça ne marchera qu'avec 1 ressort (ou évidemment plusieurs mais indépendants les uns des autres).

    Or je souhaite pouvoir connecter plusieurs ressorts entre eux et dans différentes positions.
    (En réalité c'est déjà fait, mais il faut mettre un peu ça au propre.)

    Dans ce cas là, la résolution des équations est extrémement compliquée (modes propres etc...), voir impossible dans l'espace à 3 dimensions.

    D'où la nécessité d'une "simulation".

    En résumé: Si la spline formule est plus pratique que la primitive (il faudrait que tu me dises pourquoi) on peut évidemment l'utiliser à la place de celle-ci mais pas avec les formules que tu as entré.
    Pour pouvoir créer un systéme plus complexe, je n'utilise volontairement pas de formules toutes faites de ressorts en mouvement mais essaye de partir de la notion de "force" pour réaliser une "simulation" du mouvement.

    Je sais pas si j'ai été clair. :oops:

    Kald: Pourqoui se contenter de prendre des notes? :bounce:

    Pyerow: Comme pour les autres, ce qui serait dommage c'est que le côté COFFEE vous échappe, d'autant plus que c'est un peu le but de ce post. :cry2:

    Petit résumé de COFFEE:

    main (doc,op) { }
    C'est la fonction principale, on place entre les accolades le code qui sera exécuté à chaque frame ou à chaque action dans le logiciel (copier-coller,création d'une primitive etc...).

    var xyz = 12;
    Ligne de code (toujours finir par un point virgule) qui définit une variable dont le nom est xyz et la valeur 12.
    A chaque fois qu'on écrira xyz dans le programme, le logiciel le remplacera par 12.
    EX: println(10*xyz); Ecrira dans la console 120.

    var helix=doc->FindObject("helix");

    La fonction doc->FindObject() permet de chercher un objet dans le gestionnaire d'objet.
    Ici, on cherche donc l'objet qui se nomme "helix", les " " signifient que c'est un texte et pas une variable.
    Si cette objet existe alors la fonction renvoie sont "ID" (un numéro qui désigne l'objet).

    Au final, on a créé la variable helix, et chaque fois qu'on tapera helix comme code, le logiciel comprendra qu'il s'agit de l'objet helix.

    var posh =helix->GetPosition();

    On crée une nouvelle variable qui a pour valeur la position du ressort.
    Puisque le logiciel sait maintenant que helix c'est le ressort.
    helix->GetPosition(); renvoi un vecteur avec les 3 position [x,y,z]
    Donc posh est un vecteur.

    var distance= vlen(pos2-pos1);

    la fonction vlen () (vector lenght) mesure la longeur d'un vecteur.
    Donc là, la variable distance a pour valeur la distance entre les deux sphères.

    var chelix= helix->GetContainer();


    La fonction GetContainer() est très importante, elle permet de récupérer toutes les données d'un objet (sa taille,
    la distance focale si c'est une caméra, etc...)
    Donc là, la variable chelix contient maintenant toutes les données du ressort (nombre de spire, longueur etc...)

    chelix->SetData(PRIM_HELIX_HEIGHT,distance);

    SetData() permet de modifier l'une des données précédentes. (contenues dans chelix)
    on modifie "PRIM_HELIX_HEIGHT" la hauteur de l'hélice (donc du ressort) et on la met à la longueur "distance", notre variable précédente.
    Remarque: Inutile de retenir les codes comme "PRIM_HELIX_HEIGHT", il suffit de faire un glisser-déposer du gestionnaire d'attribut vers l'expression coffee.

    helix->SetContainer(chelix);

    On a modifier le container précédemment, mais ça ne modifie pas l'objet immédiatement à l'image.
    Il faut pour obtenir les modification, renvoyer le nouveau container à l'objet.
    La fonction SetContainer() s'en occupe. On renvoi le chelix modifié.

    helix->SetPosition(pos2);

    La fonction SetPosition() place un objet à la position voulue. Il faut rentrer dedans un vecteur.
    Ex: objet->SetPosition(vector(0,0,0)); Placerait l'objet en 0,0,0.
    Je rappel que plus haut pos2 est la variable qui contient le vecteur position de l'objet 2.
    Donc on fixe le ressort à l'objet2.

    Dernière explication:

    v+=force*dt;
    C'est un raccourci qui signifie la même chose que:
    v=v+force*dt;

    v,force et dt sont 3 variables définies précédemment.
    On dit ainsi que la nouvelle valeur de v, c'est la précédente + la valeur de force*dt.

    Je ne détaillerai plus chaque ligne je vous rassure mais je pense qu'il est important de bien comprendre le code.
    SMC fan.

  7. #7
    Vieux Croûton Avatar de Aurety
    Date d'inscription
    juillet 2002
    C4D version
    R17 Studio
    OS
    Mac
    Messages
    14 477
    Billets dans le blog
    3

    Re: Plug-In et Ressorts.

    Jean-Laurent, je t'aime ! Quelle merveille à lire :prie: je vais essayer de suivre même si les dernières formules m'ont fait reculer :nono:
    kenavo !! // Pinterest KAMIGAZ®

  8. #8
    Dépendant
    Date d'inscription
    septembre 2004
    C4D version
    R14 Studio
    OS
    windows 8 64bit
    Messages
    409

    Re: Plug-In et Ressorts.

    bravo pour l'initiative... :efface: :efface: :efface: :prie: :prie:

    je te suis aussi avec grand intéret...
    Cinema 4D addicted<br />D.A. post-production &amp; 3D

  9. #9
    Gourou Avatar de Jean-Laurent
    Date d'inscription
    mai 2006
    C4D version
    R11.5
    Messages
    3 407

    Re: Plug-In et Ressorts.

    Citation Envoyé par Aurety
    Jean-Laurent, je t'aime ! Quelle merveille à lire :prie: je vais essayer de suivre même si les dernières formules m'ont fait reculer :nono:
    :oops: :love:

    Il va falloir que je développe un peu plus alors. :mrgreen:

    Blague à part n'hésitez pas à questionner ou à me corriger.
    Là, ça fait un peu cours magistral, alors que je suis bien moins avancé que beaucoup sur le forum en programmation. :oops:

    Merci à toi johnc.
    SMC fan.

  10. #10
    Pilier
    Date d'inscription
    novembre 2003
    Messages
    1 240

    Re: Plug-In et Ressorts.

    C'est super Jean Laurent, le coffee expliqué pas à pas comme ça :love:


    Kald: Pourqoui se contenter de prendre des notes?
    Parce que j'ai un niveau collège en math moi, après j'ai une formation exclusiment littéraire, alors j'ai quelques soucis avec les langages de programmation :oops:
    J'apprécie à ce titre ta merveilleuse pédagogie :prie:

  11. #11
    Pilier
    Date d'inscription
    décembre 2003
    Messages
    942

    Re: Plug-In et Ressorts.

    Très belle initiative, je suis et je décortique !
    G5 2x2GHz • 1Go DDR • GeForce FX 5200 Mon Portfolio

  12. #12

    Re: Plug-In et Ressorts.

    :shock:
    Voilà un sujet comme on aimerait en voir plus!
    Merci jean-laurent :love:


    Je suis avec grand intérêt. je n'ai pas eut le temps de tout tout lire et tout tout décortiquer, mais je me réserve un créneau prochainement pour examiner la question.
    En attandant :arrow: Abonné

    ++
    moebius | Phenom X4 9600+ 3Go DDRII GeForce 8600GT 250Go SATA&nbsp; | Linux [cf tuto ] | win xp 32b.&nbsp;

  13. #13
    Pilier Avatar de phanault
    Date d'inscription
    décembre 2004
    C4D version
    R10
    OS
    OSX Lion
    Messages
    1 085

    Re: Plug-In et Ressorts.

    Et en boni, on a droit à une doc plus détaillée du langage COFFEE !

    :poucehaut:

    C'est super comme truc.* :bounce:


    Un petit truc de programmation pour les intéressés : Étant donné que le langage COFFEE n'est pas typé (c'est à dire qu'il n'est pas nécessaire de déterminer le type de donnée assigné à une variable), il est d'usage d'utiliser la méthode dite "Ungarian" pour nommer les variables. Cette méthode propose de placer un préfix donnant le type du contenu de la variable. Par exemple, si une variable doit contenir un objet, on débute par la lette "o". Pour un entier, on débute par "i" (Integer en anglais). Des exemples :

    oDoc : Objet document
    iLoop: Compteur de boucle / itération
    vVec: Un vecteur
    cChaine: Une chaine de caractere

    etc..

    Voilà pour ma très petite contribution.
    Mac Pro 3GHz, 4Go Ram, R10 XL + Hair, CinemaDisplay 30&quot;

  14. #14
    Pilier Avatar de phanault
    Date d'inscription
    décembre 2004
    C4D version
    R10
    OS
    OSX Lion
    Messages
    1 085

    Re: Plug-In et Ressorts.

    Jean-Laurent,

    J'ai codé le COFFEE mais je n'arrive pas à obtenir le résultat souhaîté au niveau de l'hélix. Celui-ci demeure toujours de la même longueur, même si le code est explicite à ce niveau. Je bosse sur la R10. Y aurait-il des changements à ce niveau ?


    chelix->SetData(PRIM_HELIX_HEIGHT,distance);
    helix->SetContainer(chelix);


    EDIT : Oublie ça, j'ai tenté de changer manuellement la valeur Height de l'hélix dans le gestionnaire d'objets puis Boom ! Tout s'est placé comme par enchantement. Probablement un bug ou une fonctionnalité mal implantée !!!
    Mac Pro 3GHz, 4Go Ram, R10 XL + Hair, CinemaDisplay 30&quot;

  15. #15

    Re: Plug-In et Ressorts.

    D'après ce que j'ai compris donc, le COFFEE (le language de programmation utilisé sur C4D apparement) ressemble assez au C/C++ j'ai l'impression..
    POO == :puke: ( :mrgreen


    Bon j'vais suivre quand même, ca à l'air utile. Merci d'apporter ton savoir.

    :efface: :odile:
    Cinema 4D R10

  16. #16
    Pilier Avatar de phanault
    Date d'inscription
    décembre 2004
    C4D version
    R10
    OS
    OSX Lion
    Messages
    1 085

    Re: Plug-In et Ressorts.

    Oui, le langage ressemble au C/C++ au niveau de la structure sans toutefois être aussi complexe. Puis la programmation OO est tellement plus simple. Y'a qu'à regarder comment on peut accéder aux propriétés des objets de C4D :

    oTest = doc->FindObject("XYZ");

    qui se traduit ainsi : Utilise la fonction nommée FindObject de l'objet document, pour trouver et retourner l'objet dénommé "XYZ". Met cet objet dans la variable oTest pour utilisation future. termine la ligne avec un ;

    Voilà, tout simple !
    Mac Pro 3GHz, 4Go Ram, R10 XL + Hair, CinemaDisplay 30&quot;

  17. #17
    Gourou Avatar de Jean-Laurent
    Date d'inscription
    mai 2006
    C4D version
    R11.5
    Messages
    3 407

    Re: Plug-In et Ressorts.

    Et là c'est que le début. :mrgreen:

    C'est vrai que de toute manière tous les langages de programmation se ressemblent.

    La création de l'interface et des fichiers .cof ressemble encore plus à du C++, avec tout un tas de classes etc...

    Je sens qu'on va apprendre plein de trucs avec phanault. :poucehaut:
    Il faudra certainement me reprendre sur beaucoup de noms de variables. :wink:

    Un peu à la bourre aujourd'hui, je me suis rendu compte que sur les grandes vitesses le ressort ne suit pas exactement l'objet, puisque la position de l'objet est calculée après la taille du ressort.
    Quelques modif et demain je poste la suite.
    SMC fan.

  18. #18

    Re: Plug-In et Ressorts.

    Quand je parlais de POO, c'est surtout que je préfère la programmation Web :mrgreen:
    La puissance du PHP combiné avec un peu d'xAjax et Perl :love: J'ai jamais aimé le C/C++, j'préfère Python et Ruby :mrgreen:

    J'vais me pencher sur COFFEE alors, vous m'avez donné envi avec vos bétises :bounce:


    :odile:
    Cinema 4D R10

  19. #19
    Pilier Avatar de phanault
    Date d'inscription
    décembre 2004
    C4D version
    R10
    OS
    OSX Lion
    Messages
    1 085

    Re: Plug-In et Ressorts.

    Pyerow,

    c'est vrai que la programmation web est beaucoup plus linéaire que le C++ ou COFFEE et aussi plus amusante. Personnellement, j'aime bien le PHP, même si je n'ai pas souvent l'occasion de l'utiliser. Mon langage de prédilection est présentement Delphi.
    Mac Pro 3GHz, 4Go Ram, R10 XL + Hair, CinemaDisplay 30&quot;

  20. #20
    Pilier Avatar de phanault
    Date d'inscription
    décembre 2004
    C4D version
    R10
    OS
    OSX Lion
    Messages
    1 085

    Re: Plug-In et Ressorts.

    Citation Envoyé par Jean-Laurent
    Je sens qu'on va apprendre plein de trucs avec phanault. :poucehaut:
    Je ne suis pas certain que j'aurais des choses à t'apprendre. Ce serait plutôt le contraire ! :wink:

    En ce qui concerne les noms de variables, il n'y a pas de lois ni d'obligations. Le truc sert uniquement à détecter rapidement le type de donnée contenu dans une variable simplement en regardant le préfix de celle-ci. Je n'ai rien inventé, c'est courrement utilisé en Clipper et d'autres langages.
    Mac Pro 3GHz, 4Go Ram, R10 XL + Hair, CinemaDisplay 30&quot;

  21. #21
    Pilier Avatar de Machaon
    Date d'inscription
    juin 2006
    C4D version
    R9
    OS
    XP
    Messages
    639

    Re: Plug-In et Ressorts.

    Alors là je campe ... enfin un cours de programmation COFFEE et avec qui !!!* :bounce:
    The best one* : Jean-Laurent and the best two : Phanault* :odile:

    J'peux pas résister : un looping (de papillon) pour Jean-Laurent !

  22. #22
    Pilier Avatar de phanault
    Date d'inscription
    décembre 2004
    C4D version
    R10
    OS
    OSX Lion
    Messages
    1 085

    Re: Plug-In et Ressorts.

    Citation Envoyé par Machaon
    The best one* : Jean-Laurent and the best two : Phanault* :odile:
    Alors là, faut pas exagérer. Je suis programmeur de métier, mais j'y connaît pas grand chose en COFFEE. Le langage en lui-même ça va, mais il me faut apprendre la hiérarchie des classes au complet, ainsi que les fonctions. La documentation fournie par Maxon est bien, sans plus.

    Mais avec Jean-Laurent dans les parrages... c'est certain que nous allons tous en apprendre.
    Mac Pro 3GHz, 4Go Ram, R10 XL + Hair, CinemaDisplay 30&quot;

  23. #23
    Gourou Avatar de Jean-Laurent
    Date d'inscription
    mai 2006
    C4D version
    R11.5
    Messages
    3 407

    Re: Plug-In et Ressorts.

    Allez, la suite en douceur: Les limitations. :wink:

    Pour l'instant si on sépare les sphères d'une distance exactement égale à l0 c'est à dire 800 m (valeur arbitraire), le ressort ne bouge pas. (logique).

    Si on les sépare d'une distance de 1000m, il oscille entre 1000 et 600m. Comme dans la réalité en l'absence de frottement. (Dont on s'occupera par la suite).

    Mais si on les sépare d'une distance supérieure à 2*l0 (2000m par exemple) il revient trop fort, dépasse la sphère1 et s'en va ensuite à l'infini car la force exercée n'est plus dans le bon sens (la distance restant positive).

    Cela correspond au cas réel où tirant trop fort sur le ressort, l'objet frappe violemment l'autre extrémité. (Et on a mal aux doigts).

    Dans la réalité, le choc de l'objet sur un mur solide et en l'absence de frottement et de déformation aurait pour effet d'inverser le sens de la vitesse.
    (Les chocs solides-solides élastiques seront traitée par la suite aussi).

    On se contentera dans un premier temps d'arrêter la sphère2 lorsqu'elle touche la sphère1.
    Il suffit pour cela de mettre la vitesse à 0.
    Toujours pour simplifier un maximum au départ, on considérera que le rayon des sphères étant de 100m le ressort est comprimé au maximum si sa longueur est de 200m.

    Le code:
    Code:
    if (fDistance<250) {v=0;}
    30 lignes de commentaires pour une ligne de code. :mrgreen:

    250 au lieu de 200, car on prend une petite marge de sécurité (Plus tard calculée à partir de la vitesse).

    Profitons en pour corriger un bug.
    On réglait la taille du ressort, puis après la nouvelle position de la sphère.
    D'où un léger retard d'une frame entre le ressort et la sphère, visible sur les grandes élongations.

    Pour régler ça, je recalcule la nouvelle distance et ajuste la taille du ressort.

    Code:
    oSphere2->SetPosition(vPos2);
    
    fDistance= vlen(vPos2-vPos1);
    oHelix->SetPosition(vPos2);
    oChelix->SetData(PRIM_HELIX_HEIGHT,fDistance);  
    oHelix->SetContainer(oChelix);
    Je trouve ça un peu lourd.
    J'aurais préféré que ce code ne soit exécuté qu'une fois mais je ne vois pas comment faire.
    Il faut également qu'il soit exécuter en début de programme.
    Peut-être avec un "if (fDistance)" en début de programme qui n'effectue le calcul qu'en début de la deuxième frame.

    Une autre limitation maintenant (facultative), l'élongation.
    Passé une certaine longueur, le ressort se déforme et ne fonctionne plus.
    Il suffit de rajouter une condition:

    Code:
    var fLimite=3000;
    
    if (fDistance<fLimite) 
    {v+=force*dt; 		
    vPos2.z+=v*dt;		
    }
    Petite astuce: Pour déplacer facilement les sphères sans être gêné par le code, on peut en désactiver des parties en tapant devant "//" qui transforme le code en commentaires.

    Ex:
    Code:
    oSphere2->SetPosition(vPos2);
    //oSphere1->SetPosition(vPos1);
    Seule la sphère2 est soumise au ressort, la sphère1 reste fixe.

    Profitons en pour rajouter un petit détail, utile par la suite lorqu'il y aura plusieurs ressorts différents.
    Changeons le nombre de spires en fonction de la raideur du ressort.
    (La raideur d'un ressort dépendant de sa forme géométrique et de la matière qui le compose.
    Des amortisseurs de voiture ont une forte raideur contrairement à un ressort de stylo bille)

    Plus le ressort est raide, plus il oscille rapidemment.

    Code:
    oChelix->SetData(PRIM_HELIX_END,10*k);
    Attention l'angle est affiché en degrés dans le gestionnaire, mais est entré en radian dans le code.

    Le code pour l'instant. Par la suite je n'afficherai que les modifications et fournirai un fichier.

    Code:
    var v=0;			
    var k =5;			
    var l0 =800;
    var dt =0.1;		
    var fLimite=3000;
    
    main(doc,op)
    {
    
    var oHelix = doc->FindObject("Helix");        
    var oSphere2 = doc->FindObject("Sphere2");
    var oSphere1 = doc->FindObject("Sphere1");
    
    var vPos2= oSphere2->GetPosition();	 
    var vPos1= oSphere1->GetPosition();
    
    var oChelix= oHelix->GetContainer(); 
    
    var fDistance= vlen(vPos2-vPos1);
    oHelix->SetPosition(vPos2);
    oChelix->SetData(PRIM_HELIX_HEIGHT,fDistance); 
    oChelix->SetData(PRIM_HELIX_END,10*k); 
       
    
    oHelix->SetContainer(oChelix);
    
    var force = -k*(fDistance-l0); 
    
    if (fDistance<200) {v=0;}
    
    if (fDistance<fLimite) 
    {v+=force*dt; 		
    vPos2.z+=v*dt;		
    //vPos1.z-=v*dt;
    }
    
    oSphere2->SetPosition(vPos2);
    //oSphere1->SetPosition(vPos1);
    
    fDistance= vlen(vPos2-vPos1);
    oHelix->SetPosition(vPos2);
    oChelix->SetData(PRIM_HELIX_HEIGHT,fDistance);  
    oHelix->SetContainer(oChelix); 
    
    }
    Demain si tout va bien, on s'occupe d'un déplacement dans toutes les directions de l'espace.

    Citation Envoyé par phanault
    Citation Envoyé par Machaon
    The best one : Jean-Laurent and the best two : Phanault :odile:
    Mais avec Jean-Laurent dans les parrages... c'est certain que nous allons tous en apprendre.
    Heu. :oops:
    Moi par contre je ne suis pas du tout programmeur. Je suis une bille en algorythmique donc tout n'est peut-être pas à sa place dans le code.
    Sans parler des lourdeurs.
    Ne pas hésiter à intervenir. :odile:
    SMC fan.

  24. #24
    Gourou Avatar de Jean-Laurent
    Date d'inscription
    mai 2006
    C4D version
    R11.5
    Messages
    3 407

    Re: Plug-In et Ressorts.

    Je suis mon bonhomme de chemin, tranquillement à mon rythme.

    Pour étendre le mouvement du ressort à toutes les directions on pourrait évidemment le mettre dans un null et faire tourner celui-ci. La solution serait bonne pour un ressort mais pas pour plusieurs ressorts couplés donc je la laisse tomber.

    J'ai pensé ensuite à calculer l'angle entre les deux objets et ça marche mais ça entraîne des calculs supplémentaires inutiles.
    La meilleure solution à mon avis est donc d'utiliser une "expression target" pour alléger le code.
    Après quelques réglages que j'expliquerai dans le post suivant ça marche.
    Par contre je n'ai pas encore réussi à placer un tag "target" à partir de la fonction coffee "allocatetag()" (un truc comme ça), si quelqu'un sait exactement comment elle fonctionne ça me fera gagner un temps précieux. :poucehaut:

    En attendant ces joyeusetés encore une petite modif:

    L'amortissement.

    Les ressorts n'oscillent pas éternellement puisqu'ils sont soumis aux frottements.
    Frottement de l'air par exemple. Ces frottements sont généralement proportionnels à la vitesse et la force de frottement qui s'oppose au mouvement vaut: F = -h*v ou h est un coefficient de frottement qui dépend de la géométrie de l'objet et du milieu traversé.

    On remplace donc le code:

    Code:
    v+=force*dt;
    par :
    Code:
    var h=0.3;
    v+=(force-h*v)*dt;
    Le ressort a maintenant un comportement beaucoup plus naturel.
    Pour essayer, lancer l'animation et agiter suivant l'axe z la sphère 1, puis regarder.
    http://cinema4d.chez-alice.fr/ressort2.c4d

    Le ressort a maintenant un mouvement amorti de la forme:
    Z= A*exp(-l*t) sin(w*t+p)
    Mais qu'on a obtenu d'une façon dynamique et non pas par un calcul savant.

    J'espère que cette démarche basée sur les forces me permettra de coupler facilement les ressorts entre eux et d'ajouter d'autres forces par la suite comme par exemple la pesanteur. :odile:
    SMC fan.

  25. #25
    Gourou Avatar de Jean-Laurent
    Date d'inscription
    mai 2006
    C4D version
    R11.5
    Messages
    3 407

    Re: Plug-In et Ressorts.

    Ressort dans toutes les directions.

    La vitesse et la force étaient jusqu'à présent de simples variables de type "float" puisqu'il n'y avait qu'une direction.
    Si on veut que le ressort se déplace dans toutes les directions il faut les transformer en vecteurs de la forme: V= (vx,vy,vz) et F= (fx,fy,fz).

    La valeur de l'intensité de la force reste la même ("fNorme") , mais il faut projeter celle-ci dans toutes les directions de l'espace.

    Ex: Dans 2 dimensions.



    Dans les 3 dimensions:

    Code:
    var vRoth= oHelix->GetRotation();
    
    var fNorme = -k*(fDistance-l0); 
    
    var vForce = vector(fNorme*cos(vRoth.y)*sin(vRoth.x),-fNorme*sin(vRoth.y),
    -fNorme*cos(vRoth.y)*cos(vRoth.x));
    On relève donc la rotation du ressort et en fonction de cet angle on projette la force suivant les différents axes.

    Au passage on pourra noter que pour définir un vecteur on utilise la fonction vector(x,y,z).

    La force est maintenant un vecteur, on fait de même pour la vitesse:

    Code:
    if (fDistance<200) {vx=0;vy=0;vz=0;}
    
    if (fDistance<fLimite) 
    {vx+=vForce.x*dt; 
    vy+=vForce.y*dt; 
    vz+=vForce.z*dt;
    	
    vPos2.x+=vx*dt;	
    vPos2.y+=vy*dt;		
    vPos2.z+=vz*dt;	
    	
    }
    Il ne faut pas oublier en début de code de déclarer les nouvelles variables vy, vy et vz et de les fixer à 0.

    J'aurais préféré déclaré la vitesse sous forme d'un vecteur, comme la force :
    var vVitesse= vector(vx,vy,vz)
    mais il n'est visiblement pas possible d'utiliser "vector" avant la fonction main().
    Si quelqu'un a une idée.


    Autrement je pourrais utiliser un variable "first" associé à une condition qui ne serait exécutée qu'en début de programme.

    Genre: var first=1;
    var vVitesse;

    if (first) {vVitesse=vector(0,0,0);}
    first=0;

    Pour que le ressort soit à chaque instant entre les deux sphères il suffit de placer dessus une expression cible "target".



    Je n'ai pas encore cherché à l'intégrer au code. :oops:

    Comme l'expression cible fait pointer l'axe z vers l'objet cible, il faut modifier le code en conséquence et simplement remplacer:

    Code:
     oChelix->SetData(PRIM_HELIX_HEIGHT,fDistance);
    par:
    Code:
     oChelix->SetData(PRIM_HELIX_HEIGHT,-fDistance);
    On a maintenant un ressort qui fait se mouvoir un objet dans n'importe quelle direction de l'espace. L'approximation dans la valeur des sinus et cosinus entraîne néanmoins une petite dérive au bout de quelques minutes d'animation. Je corrigerai ça par la suite.

    Remarques: La mise en place d'un code entraîne de nombreuses étourderies, erreurs etc... (particulièrement avec moi). :wink:
    Une fonction très utile est la fonction println(); qui affiche une donnée dans la console (window->console). Console qui affiche également les erreurs de code.

    Ex: println("salut"); affichera salut dans la console.
    println(vRoth); affichera [0.000000,2.12123213,0.0000000]

    Pratique pour voir évoluer une variable. :poucehaut:



    Je fais une petite pause pour le côté physique à proprement parler et je vais tenter de rendre l'ensemble un peu plus sympa en débutant une ébauche d'interface.

    Pour les allergiques à la physique et aux ressorts, vous pouvez oublier les pages précédentes.
    Ce qui suit sera presque indépendant et concernera la mise en place de la partie Plug-In.
    (Comme Steph et Majoul l'ont fait un peu plus bas) :prie:.

    Vous pourrez donc le transposer à vos propres passions. Une Pin-Up à la poitrine paramétrable par exemple. :wink:

    N'hésitez pas à questionner, modifier, décrier. :odile:
    SMC fan.

  26. #26
    Dépendant
    Date d'inscription
    janvier 2003
    C4D version
    R14 Prime
    Messages
    449

    Re: Plug-In et Ressorts.

    Pour attribuer un nouveau tag "target" à un objet ( Obj )
    Code:
    var tag = AllocTag(Ttargetexpression) ;
    Obj->InsertTag(tag, NULL) ;
    - Sinon petite remarque importante, lorsque tu pointe vers des objets comme dans ton code avec la fonction* doc->FindObject(nom de l’objet), il faut toujours s’assurer que les objets existent .
    Code:
    var oHelix = doc->FindObject("Helix");
    var oSphere2 = doc->FindObject("Sphere2");
    var oSphere1 = doc->FindObject("Sphere1");
    
    if(!oHelix || !oSphere2 || !oSphere1) return ;
    Si l’un de ces objets n’existe pas alors on stoppe le programme.


    - Autre remarque de commodité, depuis la version 9 tu peut utiliser les opérateurs "objet#Id" pour lire et modifier les paramètres du container d’un objet.
    Code:
    var oChelix= oHelix->GetContainer(); 
    oChelix->SetData(PRIM_HELIX_HEIGHT,fDistance);* 
    oHelix->SetContainer(oChelix);
    c’est la même chose que :
    Code:
    oHelix#PRIM_HELIX_HEIGHT =* fDistance ;
    tout simplement par un drag & drop du paramètre dans la fenêtre de l’éditeur

    Pour attribuer une valeur* V :*
    Code:
    oHelix#PRIM_HELIX_HEIGHT =* V;
    Pour lire*une valeur* V :
    Code:
     V = oHelix #PRIM_HELIX_HEIGHT* ;
    Plus pratique et rapide à mettre en place

    Bonne continuation.

  27. #27
    Gourou Avatar de Jean-Laurent
    Date d'inscription
    mai 2006
    C4D version
    R11.5
    Messages
    3 407

    Re: Plug-In et Ressorts.

    Magnifique. :love:
    Je corrige de suite tout ça.
    C'est donc à ça que sert le # lorsqu'on fait un glisser-déplacer. :prie:
    SMC fan.

  28. #28

    Re: Plug-In et Ressorts.

    j'applaudis des 3 mains et des 4 pieds :mrgreen: :prie:

    Citation Envoyé par phanault

    Un petit truc de programmation pour les intéressés : Étant donné que le langage COFFEE n'est pas typé (c'est à dire qu'il n'est pas nécessaire de déterminer le type de donnée assigné à une variable), il est d'usage d'utiliser la méthode dite "Ungarian" pour nommer les variables. Cette méthode propose de placer un préfix donnant le type du contenu de la variable. Par exemple, si une variable doit contenir un objet, on débute par la lette "o". Pour un entier, on débute par "i" (Integer en anglais).
    Je ne peux que te remercier de dire ceci, c'est grace à ce genre de (très) bonnes pratiques qu'un code est maintenable decemment. par contre, je trouve que c'est aussi une bonne idée de le faire même si le langage est typé. On peut pousser l'expressivité des noms de variables encore plus loin en les prefixant ou suffixant pour indiquer leur contexte de declaration. Par exemple, mettre un "m_" pour indiquer que la variable est membre de la classe, suffixer par un "_" pour dire que la variable est un parametre de fonction...
    ca permet par exemple de savoir que dans l'expression (dont on ne sait a priori rien, ni son origine, ni quoique ce soit d'autre)

    ma_var = m_ma_var + ma_var_;

    "ma_var" est une variable locale, "m_ma_var" un membre de la classe dans laquelle on est et "ma_var_" un parametre de la fonction dans laquelle on est. ca évite d'avoir à chercher la declaration de chaque variable, et ca peut faire gagner un temps précieux. Par contre, c'est une pratique que j'ai, mais je ne sais pas s'il y a un equivalent "consacré", je ne fais que proposer un petit "truc" en plus.

    bonne continuation jean-laurent !
    Le rendu, c'est juste de l'intégration numérique sur un espââââââce de dimension infinie...trivial quoi

  29. #29
    Squatteur
    Date d'inscription
    février 2006
    Messages
    238

    Re: Plug-In et Ressorts.

    alors la c'est du lourd :shock:

    Comme il ne reste plus de place je reste debout au fond mais j'observe quand même. :love:
    On peut douter de tout sauf de la necéssiter de se trouver du coter de celui qui a le pognon.<br /><br />Kaamelot

  30. #30
    Gourou Avatar de Jean-Laurent
    Date d'inscription
    mai 2006
    C4D version
    R11.5
    Messages
    3 407

    Re: Plug-In et Ressorts.

    Je suis preneur de tout ce qui peut améliorer la lisibilité du code. :poucehaut:
    Par contre il faudra que tu m'aides un peu. J'ai un peu de mal avec ton exemple. :oops:
    Paramètre de fonction? Si une variable est définie dans une classe, on ne peut pas la retrouver ailleurs, non? Elle appartient donc obligatoirement à la classe? Il faudra que tu me montres tout ça sur un exemple de code un peu plus long.

    Toujours tout en douceur la suite: Création du tag.

    Je rappel que je ne suis pas programmeur, donc que les vrais spécialistes (tarlack, phanault, majoul pour ne citer que ceux qui sont déjà intervenus sur ce post) n"hésitent pas à me corriger ou à apporter des précisions. (Comme ils l'ont déjà fait :prie.

    Il ne s'agit pour l'instant que de l'ébauche d'une interface. Par la suite, l'interface et le code seront développés conjointement. Ce n'est pas pour me disperser, mais une fois une petite interface en place, il est souvent plus facile de faire varier rapidement plusieurs paramètres du code. (Un peu comme les DU en Xpresso).

    Pour créer un Plug-In, il suffit de créer un fichier texte avec le code et que ce fichier termine par l'extension .cof , on peut donc utiliser le bloc-note.
    Ce n'est certainement pas l'idéal et il me semble qu'il existe des éditeurs de code qui permettent de "coloré" le code automatiquement (pour repérer les variables, les fonctions etc...) et d'afficher les numéros de ligne. (Pratique lorsque la console annonce une erreur à la ligne 408).

    Toujours par soucis de simplifier au maximum la démarche initiale, je partirai d'un seul fichier .cof , mais par la suite on pourra hiérarchiser un peu mieux le Plug-In en utilisant plusieurs fichiers. (Un dossier ressource, langue etc...)

    Il existe plusieurs sorte de Plug-In. Pour l'instant je partirai sur la base d'un "Expression Plugin Tag" qui est ce qu'il y a de plus proche pour l'instant du code qu'on a tapé.

    Pour créer un tel Plug-In on utilisera 2 classes pour l'instant.

    La classe "ExpressionPluginTag" et la classe "GeBaseDialog".

    Pour ceux qui ne sauraient pas ce qu'est une classe (ce qui n'est pas loin d'être mon cas), il y a une très bonne explication dans le SDK ("code primer").
    En résumé, il existe des classes toutes faites qui contiennent des fonctions et des variables prêtes à l'utilisation mais on peut aussi créer ses propres classes.

    EX: Quand on utilise la classe "BaseObject" on dispose de fonctions comme GetPosition() qui permettent d'obtenir la position d'un objet.

    A partir des classes existantes on peut créer des classes dérivées (et on pourra utiliser les mêmes fonctions) de la façon suivante:

    class Ma_classe :GeBaseDialog
    (Ma classe sera une classe dérivée de la classe "GeBaseDialog")
    Puis on cite les fonctions et les variables que l'on souhaite utiliser.

    { public:
    var ma_variable;
    Ma_classe();
    Ma_fonction();
    }

    Et pour définir une fonction appartenant à une classe:

    Ma_classe:: Ma_fonction() { };


    On peut y aller.

    Pour commencer, on se contentera d'un code qui affiche le nom du tag et place une icône du tag sur un objet.

    Code:
    var iPLUGIN_ID  = 1234567 ;
    var sPLUGIN_NAME = "Ressort" ;
    var sPLUGIN_HELP = "Gestion de ressorts" ;
    
    var oTagIcon;
    On définit quelques variables qu'on utilisera par la suite dans le code.

    Code:
    class Ressort_Tag : ExpressionPluginTag
    {
     
     public:
    
       Ressort_Tag();
     
       GetID();
    
       MultipleAllowed();
       DisplayAllowed();
    
       GetIcon(); 
       GetHelpText(); 
     
       UseMenu();
       GetName(); 
     
       Edit();
    
       Execute(doc, op);	
    }
    On définit une classe "Ressort-Tag" (très personnelle) qui est une classe dérivée de la classe "ExpressionPluginTag" (toute faite avec tout un tas de fonctions pratiques.)

    On cite ensuite dans "public:" toutes les fonctions de la classe "ExpressionPluginTag" que l'on va utiliser (pour l'instant).

    Puis on utilise ces fonctions.

    Code:
    Ressort_Tag::Ressort_Tag() { super();}
    super() est une fonction qui appelle le constructeur de la classe parent.
    (Pour moi c'est du chinois :oops:, je sais juste qu'il faut le faire).

    Code:
    Ressort_Tag::GetID()    { return iPLUGIN_ID ;}
    On donne le numéro du Plug-In (on utilise la variable définie plus haut).
    Ce numéro doit être unique, si deux Plug-In ont le même numéro aucun ne fonctionnera.
    Pour être certain d'avoir un numéro unique, il faut en demander un gratuit.
    Il me semble également qu'il existe des numéros tests??
    Attention, j'ai mis ici un nombre arbitraire. :!:

    Code:
    Ressort_Tag::MultipleAllowed()   { return False ;}
    On précise qu'un seul tag de ce type pourra être associer à l'objet. Pour pouvoir mettre plusieurs tag on aurait mis TRUE.

    Code:
    Ressort_Tag::DisplayAllowed()   { return TRUE;}
    On précise que le tag sera visible. (False, si on le souhaite invisible).

    Code:
    Ressort_Tag::GetIcon()		{ return oTagIcon ;}
    Ca va afficher l'icone du tag.
    Code:
    Ressort_Tag::GetHelpText()     { return sPLUGIN_HELP ;}
    C'est le message à afficher quand on demandera de l'aide sur le tag.
    Code:
    Ressort_Tag::UseMenu() 		{ return TRUE ;}
    Le nom du tag sera mis dans le menu.
    Code:
    Ressort_Tag::GetName() 	{return sPLUGIN_NAME ;}
    C'est le nom du tag qui sera affiché. (sPLUGIN_NAME renvoit à "Ressort")
    Code:
    Ressort_Tag::Edit()   {	}
    On verra cette fonction par la suite, elle ouvrira l'interface.
    Code:
    Ressort_Tag::Execute(doc, op) {  }
    Idem, c'est là qu'on mettra le code qui anime le ressort.
    Code:
    main()
    
    {
    
     var fn = GeGetRootFilename();
     fn->RemoveLast();
     fn->AddLast("ressort.tif");
    
     oTagIcon = new(BaseBitmap,1,1);
     oTagIcon->Load(fn);
     
    	Register(Ressort_Tag);
    }
    Ces dernières lignes vont chercher le fichier nommé "ressort.tif" qui contiendra l'image du tag. Au final cette image sera "contenue" dans la variable "oTagIcon" que l'on affiche un peu plus haut. (Ressort_Tag::GetIcon() { return oTagIcon ;})

    Je présume qu'il y a aussi une précaution à prendre si le fichier n'existe pas? Je ferrai une petite recherche.

    Résumé:
    Code:
    var PLUGIN_ID  = 1234567 ;
    var PLUGIN_NAME = "Ressort" ;
    var PLUGIN_HELP = "Gestion de ressorts" ;
    
    var oTagIcon;
    
    class Ressort_Tag : ExpressionPluginTag
    {
     
     public:
    
       Ressort_Tag();
     
       GetID();
    
       MultipleAllowed();
       DisplayAllowed();
    
       GetIcon(); 
       GetHelpText(); 
     
       UseMenu();
       GetName(); 
     
       Edit();
    
       Execute(doc, op);
    	
    }
    
    Ressort_Tag::Ressort_Tag() { super();}
    
    Ressort_Tag::GetID()    { return iPLUGIN_ID ;}
    
    Ressort_Tag::MultipleAllowed()   { return False ;}
    Ressort_Tag::DisplayAllowed()   { return TRUE;}
    
    Ressort_Tag::GetIcon()		{ return oTagIcon ;}
    Ressort_Tag::GetHelpText()     { return sPLUGIN_HELP ;}
    
    Ressort_Tag::UseMenu() 		{ return TRUE ;}
    Ressort_Tag::GetName() 	{return sPLUGIN_NAME ;}
    
    Ressort_Tag::Edit()   {	}	  	
    
    Ressort_Tag::Execute(doc, op) {  }
    
    
    main()
    
    {
    
     var fn = GeGetRootFilename();
     fn->RemoveLast();
     fn->AddLast("ressort.tif");
    
     oTagIcon = new(BaseBitmap,1,1);
     oTagIcon->Load(fn);
     
    	Register(Ressort_Tag);
    }
    Pour l'instant notre tag se contente de placer une icône sur un objet.


    Demain on crée l'interface. :odile:
    SMC fan.

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •  
Mediaworks - Logiciels 3D | Design Internet - Creation site internet