#0 

04-03-2013 01:40:08

jonath313
Abonné
Date d'inscription: 28-12-2009
Messages: 240

Bonjour,

Je suis entrain de réaliser une animation via la programmation, lorsque j'appui sur une touche je voudrais faire bouger les Bones de mon mesh 3d. Au début çà fonctionne puis ensuite le mouvement est bloqué.

Enfait ce qui est compliqué à réalisé c'est que en appuyant sur la touche avancer, un Bone de la jambe ce met en rotation jusqu'à une certaine valeur (angle -60° par exemple) et revient ensuite dans l'autre sens jusqu'à 30° et retourne a sa position initiale.

Mon mouvement est bloqué une fois le bonne a -60°. Et pas moyen de le faire continuer en inversant de sens.

Si quelqu'un a une petite idée, ce serait bien simpas car là je coince... merci.


Code:

void CLEventReceiver::majPosMesh()// mise à jour de la position
{
    core::vector3df e = m_EnnemiJambeOS1->getRotation();  // Récupération de l'angle de rotation

     if(m_Nperso != 0 && m_isAvance == true){                     // Si j'appui sur Z m_isAvance == true

                if(e.Y<=0 && e.Y>=-60)
                {
                    e.Y -= 0.1;     // Si la rotation du Bone (OS) est entre 0 et -60, le bone tourne jusqu'à -60
       
                }
        }

        m_Nperso->setPosition(c);
        m_Nperso->setRotation(d);

        m_EnnemiJambeOS1->setRotation(e);
}

J'ai préféré enlever mes tentatives de test if() pour la suite du mouvement et je ne vois vraiment pas comment aborder cela ...

Hors ligne


#1 

04-03-2013 09:35:00

johnplayer
Habitué
Date d'inscription: 30-09-2007
Messages: 431

Tu ne peux pas intégrer ce mouvement dans la modélisation? Comme ça, au lieu de bouger le bone lors de l'appui sur le bouton, tu change la frame en cours. Ce serait plus simple à mon avis.

La modification des bones est bien lorsque tu veux corriger un mouvement. Mais pour contrôler un mesh, il faudrait qu'Irrlicht gère la cinématique inversée, ce qui n'est pas le cas (en même temps, c'est compliqué à mettre en place).


core i7 4970K @ 4GHz - 32GB ddr3 19200(2400MHz) - ssd samsung 840 evo 250GB - GTX1080Ti (4K) - Cooler master storm stryker blanc.
"L'alcool, c'est comme Activia, c'est actif à l'intérieur et ça se voit à l'extérieur."

Hors ligne


#2 

04-03-2013 15:59:04

Magun
SleekThink Producer
Lieu: Punakha
Date d'inscription: 18-11-2007
Messages: 910
Corrections: 2
Site web

évite les conditions surtout dans un code qui seras executer plusieur fois par frame sur plusieur entiter

essaye plutot quelque chose dans le genre:

Code c++ :


float factor = 0.1f; // header
factor &= (!(e.Y <= -60 && factor >> 31) | (e.Y >= 30 !(factor << 31))) << 31; // set the bit sign

e.Y += factor;



31 ou 0 ça dépend si t'est en bigendian ou non
ça doit être un truc dans le genre, jsuis pas sur, l'interet c'est de faire des if mathematique et de jouer sur le sign

si tu dépasse 30 et que le sign est +, il deviens -
et si ça dépasse -60 et que le sign est - il deviens +

tant qu'il n'atteint pas 30 il croit
tant qu'il n'atteint pas -60 il decroit
si j'ai bien comprit ta question

ps: '-' = 1 et '+' = 0

Hors ligne


#3 

04-03-2013 21:28:13

jonath313
Abonné
Date d'inscription: 28-12-2009
Messages: 240

oui c'est bien çà Magun, c'est vrai que l'idée du signe est plutot judicieuse.

Cependant quand j'utilise ce code j'ai des erreurs à la compilation :

Code:

C:\Users\Jonath\Documents\Prog C\irrlicht8\CLEventReceiver.cpp||In member function 'void CLEventReceiver::majPosMesh()':|
C:\Users\Jonath\Documents\Prog C\irrlicht8\CLEventReceiver.cpp|208|error: invalid operands of types 'float' and 'int' to binary 'operator>>'|
C:\Users\Jonath\Documents\Prog C\irrlicht8\CLEventReceiver.cpp|208|error: expected ')' before '!' token|
C:\Users\Jonath\Documents\Prog C\irrlicht8\CLEventReceiver.cpp|208|error: expected ')' before ';' token|
||=== Build finished: 3 errors, 0 warnings (0 minutes, 2 seconds) ===|

Hors ligne


#4 

05-03-2013 00:11:48

Magun
SleekThink Producer
Lieu: Punakha
Date d'inscription: 18-11-2007
Messages: 910
Corrections: 2
Site web

tu peut faire un cast vers un int (le bit de sign devrai être preserver)
ou alors passe par une union ..

au pire tu sauvegarde le sign a par ( 1 ou -1 ) que tu calcule en debut de frame et tu multipli temporairement ton facteur par celui-ci
j'avais jamais fait gaffe que c'est operateur n'était pas dispo pour les floatants ... neutral

Hors ligne


#5 

05-03-2013 02:09:02

jonath313
Abonné
Date d'inscription: 28-12-2009
Messages: 240

Je t'avouerai que je n'ai pas trop compris ton dernier message. Un "cast" vers une int ? Une union ?

En fait ce que je veux réaliser c'est çà :


^e.Y (rotation de l'os)
|
|
|------ . (e.Y = -60)
|      .   .
|     .     .
|    .       .
|   .         .
|  .           .
| .             .
|.               .
-----------------------------------------> temps
                   .           .
                    .         .
                     .       .
                      .     .
                       .   .
--------------------. (e.Y = 30)


J'ai dans un premier temps pensé à une petite fonction du genre :

     e.Y = 60*sin(temps/10);

Mais le soucis c'est que dans ma fonction de mise à jour de la position je fais :

Code:

void CLEventReceiver::majPosMesh(){

float temps;
core::vector3df e = m_EnnemiJambeOS1->getRotation();

    if(m_Nperso != 0 && m_isAvance == true){            //la touche est enfoncee
        
          temps+=0.1;
         e.Y = 60*sin(temps/10);


    }
        m_EnnemiJambeOS1->setRotation(e);

}

En théorie si le temps s'incrémente de 0.1 en 0.1, je devrais avoir une belle sinusoïde et ma rotation devrait varier de 60° à - 60°.

Mais j'ai l'impression que ma variable "temps" ne s'incrémente pas...

Dernière modification par jonath313 (05-03-2013 15:16:59)

Hors ligne


#6 

05-03-2013 16:34:11

Magun
SleekThink Producer
Lieu: Punakha
Date d'inscription: 18-11-2007
Messages: 910
Corrections: 2
Site web

c'est normal t'a variable temps est local à la fonction
quand tu apelle t'a fonctions il aloue un "espace de travail" dans le qu'elle est <<storer>> t'a variable
a la fin de l'appele cette espace est detruit, donc au final t'a un varibale temp qui contient quelquechose d'indefinie
et tu rajoute 0.1 ...

utiliser sin c'est un idée qui ce tien mais niveau perf tu va avoir mal !
ps: jolie ton graph en ascii

ps 2:
union:

Code c++ :


union convert
{
    float f;
    int i;
};

convert c;
c.f = 1.0f;
c.i |= 1 << 31; // set bit 32 to 1 ( - ) => c.f = -1.0f



cast:

Code c++ :


*(int*)&factor |= 1 << 31; // set to negative

Hors ligne


#7 

05-03-2013 17:47:22

jonath313
Abonné
Date d'inscription: 28-12-2009
Messages: 240

lol merci pour le graphique !

Bin c'est pas que je suis contre ton procédé mais je n'arrive pas à l'utiliser .
Pourquoi :

le mouvement de la rotation est décomposé en 3.

1) le personnage est au repos donc angle (e.Y) = 0°
2) Le personnage engage sa jambe => angle de rotation décroit jusqu'à -60°
3) L'angle est de -60, alors la jambe repart dans l'autre sens (incrémentation de l'angle jusqu'à 30°)
4) A 30 ° on revient à zéros.

Le problème c'est que géré çà par des condition if() est impossible.

Pourquoi:

1) dans le deuxième point cas l'angle décroit -> on se situe entre 0 et -60
2) dans le troisiéme point l'angle se situe entre -60 et 30
3) Puis enfin l'angle se situe entre 0 et 30°.

Le problème c'est que forcément quand je fais mes tests if et bien l'angle est toujours entre -60° et 30° et donc impossible de faire des incrémentations et décrémentations, tout se bloque.

Je ne vois vraiment pas comment faire autrement si ce n'est que le sinus qui me coutera chére en ressource car je ne vais pas faire que bouger un seul os...

Hors ligne


#8 

05-03-2013 22:02:35

Magun
SleekThink Producer
Lieu: Punakha
Date d'inscription: 18-11-2007
Messages: 910
Corrections: 2
Site web

c'est possible a géré avec des if, mais ça entraine des saut dans le registre ip voire la nécéssiter de recharger un segment mémoire ... c'est pas térrible dans ce cas d'utilisation
mais l'important c'est aussi que t'arrive a ce que tu veut faire, mais par toi même !
je te donne donc juste des pistes, sinon tu ne t'améliorera pas wink

avec des if ça donne quelque chose dans ce style

Code c++ :


if(pMove) // ex: irr::SEvent::SKeyboardEvent::PressedDown == true
{
  if(factor >= 0 && e.Y >= 30)
  {
    factor = -factor; // invert sign
  }
  if(factor < 0 && e.Y <= -60)
  {
    factor = -factor; // invert sign
  }
  e.Y += factor;
}
else if(return_to_origin)
{
  if(e.Y >= -0.01f || e.Y <= 0.01f) // aproximativ equals
    return_to_origin = false;
  e.Y += factor;
}
else
{
  return_to_origin = true;
  // calculate new direction
}



mais tu pourrais très bien resoudre ce problème mathématiquement je pensse que c'est un bonne exercice d'ailleur wink
(pour une simple jambe, sinon faudra faire un systeme d'état si tu veut animer en fonction d'evenement externe)

ex:

Code c++ :


e.Y += ((return_to_origin | pMove)*direction)*speed;



pMove = { 0, 1 }
return_to_origin = { 0, 1 }
direction = { -1, 1 }

Hors ligne


Options Liens officiels Caractéristiques Statistiques Communauté
Corrections
irrlicht
irrklang
irredit
irrxml
xhtml 1.0
css 2.1
Propulsé par FluxBB
Traduit par FluxBB.fr
883 membres
1429 sujets
11121 messages
Dernier membre inscrit: Saidov17
95 invités en ligne
Aucun membre connecté
RSS Feed