lier une animation au deplacement d'un mesh
Proposé par ramis

le mardi 04 novembre 2008 à 20h 02mn 49s

5750 visualisations



Bonjour tout le monde !

Bon ,je doute que ce soit très utile tellement c'est simple , mais ça pourra peut etre aider les grands débutants comme moi ...
Il s'agit ici , en quelque sorte , de l'adaptation du code de Kevin Leohnart sur les evenements , où il explique comment faire bouger Sydney .
Ici , il s'agit de faire coincider l'animation "courir" de sydney avec le moment où elle (il :-S ? )se déplace . ^^
C'est vraiment , vraiment tout con , et abondamment commenté .

Voilà le code de main.cpp :

Code:

#include "CEventReceiver.h"


int main(void)
{

    irr::IrrlichtDevice* device = irr::createDevice(irr::video::EDT_OPENGL,irr::core::dimension2d<irr::s32>(640,480),32,false,false,false);//On créé notre device ...
    irr::video::IVideoDriver* driver = device->getVideoDriver ();//...notre driver ...
    irr::scene::ISceneManager *sceneManager = device->getSceneManager ();//... et notre scene manager

    device->getCursorControl ()-> setVisible (false);//vala , c'est plus zoli comme ça , sans curseur :)

    irr::scene::IAnimatedMeshMD2* modele;//Ici ...
    modele = (irr::scene::IAnimatedMeshMD2*)sceneManager->getMesh("sydney.md2");//...on charge...
    irr::scene::IAnimatedMeshSceneNode* Nmodele = sceneManager->addAnimatedMeshSceneNode(modele);//...Sydney !







    Nmodele->setMaterialFlag(irr::video::EMF_LIGHTING, false);//On fait en sorte que Sydney ne dépende pas de la lumière (tant mieux , y en a pas)
    Nmodele->setMaterialTexture( 0, driver->getTexture("sydney.bmp") );//On applique la texture à Sydney

    irr::scene::ICameraSceneNode *camera;//Ici ...
    camera = sceneManager->addCameraSceneNodeFPS(0, 100.0f, 300.0f);//...on créé une camera FPS


    CEventReceiver receiver(Nmodele);//On créé un objet instance de la classe CEventReceiver : c'est notre capteur d'évènements
    device->setEventReceiver(&receiver);//on définit cet objet comme le capteur pour notre device


    Nmodele->setAnimationSpeed(40); //On définit la vitesse des animations

    Nmodele->setMD2Animation(EMAT_STAND);//A l'origine , Sydney est immobile : on lance donc l'animation EMAT_STAND (l'animation où Sydney ne bouge pas , donc)

    //La boucle de rendu
    while (device->run())
    {
        driver->beginScene(true, true, irr::video::SColor(0,200,200,200));
        receiver.majPosMesh();//a chaque frame , on appelle la fonction qui met à jour la position du Mesh
        receiver.majAnimMesh();//a chaque frame , on appelle la fonction qui , si besoin est  , modifie l'animation du mesh
        sceneManager->drawAll ();
        driver->endScene ();
    }

    device->drop ();//On libère la memoire
    return 0;//et on retourne 0 pour dire que tout s'est bien passé
}

celui de CEventReceiver.h :

Code:

#include <irrlicht.h>
//Les namespaces nous évitent d'avoir toujours à recopier le parent de la classe qu'on appelle .Je sais , c'est pas bien ...
using namespace irr;
using namespace core;
using namespace gui;
using namespace video;
using namespace scene;



class CEventReceiver : public irr::IEventReceiver//On créé une classe CEventReceiver , fille de la classe IEventReceiver
{

public ://dans la partie publique , on va mettre les prototypes de nos fonctions

    CEventReceiver(irr::scene::IAnimatedMeshSceneNode* Nmodele);//On créé le constructeur , qui prend en parametre le node de notre modele(ici , Sydney , donc)
    virtual bool OnEvent(const irr::SEvent &event);//Cette fonction est lancée en cas d'évenement
    void majPosMesh();//On met à jour la position de notre mesh
    void majAnimMesh();//On met à jour l'animation du mesh , si besoin est

private ://dans la partie privée , on met nos attributs

    irr::scene::IAnimatedMeshSceneNode* m_Nmodele;//Le node que l'on va manipuler
    bool m_animrun;//Un booléen qui indique si l'animation du personnage est "courir"(EMAT_RUN) , ou pas
    bool m_isMoving;//Un booléen qui indique si on bouge , ou pas
};

et CEventReceiver.cpp :

Code:

#include "CEventReceiver.h"

CEventReceiver::CEventReceiver(irr::scene::IAnimatedMeshSceneNode* Nmodele)//revoilà notre constructeur :)
{
    m_Nmodele = Nmodele;//On pointe le mesh passe en parametre.
    m_isMoving = false;//Par défaut , le modele est immobile .Donc le booléen qui indique si l'on bouge est à false
    m_animrun=false;//et comme l'animation n'est du coup pas "courir" , on met notre booléen à false aussi
}


bool CEventReceiver::OnEvent(const irr::SEvent &event)//En cas d'évenement :
{
    //On verifie que le pointeur est ok
    if(m_Nmodele != 0
    //Qu'il s'agit d'un event concernant un appui/relachement de touche
    && event.EventType == irr::EET_KEY_INPUT_EVENT
    //Qu'il s'agit bien de la touche z
    && event.KeyInput.Key == irr::KEY_KEY_Z)
    {
        //Si il s'agit d'un appui
        if(event.KeyInput.PressedDown == true)
            m_isMoving = true;//On passe notre booléen "est en train de bouger" à true


        //Sinon c'est un relachement
        else
            m_isMoving = false;//Donc , comme on doit s'arrêter , on met ce même booléen à false
        //L'event est traite, on retourne true
        return true;
    }
    //Si on arrive la, c'est qu'on a pas traite l'event , donc on retourne false
    return false;
}


void CEventReceiver::majPosMesh()//revoilà notre chère fonction de mise à jour de la position
{
    //On verifie que le pointeur vers le mesh est
    //ok et que la touche est enfoncee
    if(m_Nmodele != 0 && m_isMoving == true)
    {
       //On commence par recuperer la position actuelle
        irr::core::vector3df v = m_Nmodele->getPosition();

        //On y ajoute la valeur de deplacement
        v.X += 0.5f;
        //On renvoie la nouvelle position .Sydney va avancer !!!
        m_Nmodele->setPosition(v);
    }
}
void CEventReceiver::majAnimMesh()//Ici , on met à jour l'animation
{
    if(m_Nmodele != 0 && m_isMoving == true && m_animrun ==false)    //Si le pointeur vers le mesh est ok , si l'on bouge et si l'on n'a pas encore mis à jour l'animation ...
    {
        m_Nmodele->setMD2Animation(EMAT_RUN);//on passe à l'animation "courir"
        m_animrun=true;//on declare que l'animation courir est bien en trainde se derouler
    }
        if(m_Nmodele != 0 && m_isMoving == false && m_animrun ==true)    //Si le pointeur vers le mesh est ok , si l'on ne bouge plus et si l'on n'a pas encore mis à jour l'animation ...
    {
        m_Nmodele->setMD2Animation(EMAT_STAND);//on passe à l'animation "rester en place"
        m_animrun=false;//et on declare que l'animation courir ne se deroule plus , du coup
    }
}

Voilà .J'imagine (non , je suis sûr ^^) qu'on peut beaucoup optimiser .Mais ça m'a fait un peu pratiquer , au moins ^^, et il y a peut etre une chance pour que ça serve à un autre débutant smile .

bonne soirée wink


#1 

04-11-2008 20:31:10

tmyke
Administrateur
Date d'inscription: 24-03-2008
Messages: 1025

Merci Ramis, même un tuto simple est un tuto utile. Donc cool d'avoir ajouté cela.
wink

Hors ligne


#2 

04-11-2008 20:46:02

ramis
Membre
Date d'inscription: 27-10-2008
Messages: 92

merci , c'est sympa ^^
vais essayer de l'adapter pour faire un système de déplacement complet (encore un truc inutile ^^ décidément , j'en ai plein la tête )

Hors ligne


#3 

08-11-2008 22:06:37

achoura
Membre
Date d'inscription: 30-10-2008
Messages: 41

bonjour (ou bonsoir lol ) ,
voila, votre code me semble trés utiles pour un noob comme moi qui veut faire bouger son personnage qui est encore dans 3dmax sad . ... je parle trop,,je suis entrain de modéliser dans 3ds max et je connais absolument pas qu'est ce que je doit faire pour le faire bouger avec les touches clavier dans irrLicht,,, je suis déja le tutorial de Kevin Leonhart  sur siteduzero mais en parallèle veuillez m'aider un peu et merci d'avance ... big_smile


Le vrai savoir c'est ce qu'il reste dans le cerveau après tous oubliés.

Hors ligne


#4 

09-11-2008 10:32:34

ramis
Membre
Date d'inscription: 27-10-2008
Messages: 92

salut achoura ,
merci de t'interesser à ce code smile
Le principe est tout simple en fait :
-Tu met en place ta scène , normalement
-En paralléle ,tu écris une classe CEventReceiver , qui hérite de la classe irr::IEventReceiver .
{Cette classe doit contenir :
-Une méthode constructeur , qui va servir tout simplement à initialiser les attributs de ta classe pour que ton personnage n'avance pas et ne marche pas.
-Une méthode OnEvent , ici en fait , on surcharge la méthode OnEvent de IEventReceiver .Cela va servir , en cas d'évènement(en l'occurence , appui sur Z) , à indiquer que ton personnage marche , à présent .Tout simplement   ;o) .Si il n'y a pas d'évenement , on indique que ton personnage ne marche plus .
-Une méthode majPosMesh , qui va servir à mettre à jour la position du mesh .En gros , si on a déclaré que le personnage est en train de marcher dans la méthode OnEvent , on va maintenant le faire avancer régulièrement , en modifiant sa position (pour le faire avancer , il va donc falloir ajouter 1 sur l'axe X , par exemple ).Si le personnage ne marche pas , on ne fait rien .
-Enfin , une méthode majAnimMesh , qui met à jour l'animation du mesh .Celle ci fait deux tests : si le personnage a été déclaré en train de courir dans OnEvent et que son animation n'est pas à "courir" : alors on met son animation à "courir" et on le déclare , grâce à un attribut booléen .Si le personnage n'est pas en train de courir mais que son animation est à "courir" , alors on met son animation à "ne courre pas" et on déclare que l'animation du personnage n'est plus "courir" , dans le même booléen .}

Après cela ,dans la boucle de rendu , il te suffit d'appeller à chaque fois les méthodes majPosMesh et majAnimMesh pour faire les tests à chaque frames et réagir correctement .La méthode OnEvent , étant une surcharge d'une éthode de IEventReceiver , est automatiquement appellée .

Voilà ! J'espère que c'est assez clair .Avec le code , tu devrais y arriver assez bien wink .Bon courage pour ton projet big_smile

Hors ligne


#5 

11-11-2008 10:39:12

achoura
Membre
Date d'inscription: 30-10-2008
Messages: 41

Bonjour, merci à vous pour m'interesser à moi big_smile ,,, c moi qui devra remercier .....ok bref j'ai utiliser le code et il est "absolutly good". reste une chose à réviser : les constantes d'animation du modele sydney.md2 (pour tous les modeles md2) comme EMAT_RUN, EMAT_WALK, EMAT_STAND ....... voila comment faire ça dans ma propre personnage .3ds ,, par logique je pense qu'il y a un editeur md2 qui doit importer les modeles 3ds pour ajouter des modifications, j'accepte tous vos propositions et conseilles avec des bras ouvert et merci encore . Fidelement Achoura big_smile


Le vrai savoir c'est ce qu'il reste dans le cerveau après tous oubliés.

Hors ligne


#6 

11-11-2008 12:15:44

ramis
Membre
Date d'inscription: 27-10-2008
Messages: 92

SAlut achoura ,
bah suis content que ça te serve ^^
Pour remplacer les Nmodele->setMD2Animation(EMAT_MACHIN); , tu peux essayer avec     Nmodele->setFrameLoop(framededebut, framedefin); .
Ce sera peut etre plus simple à mettre en oeuvre big_smile .
Pour l'animation , (je parle toujours en blender wink  ) tu peux , je pense , la faire directement dans le logiciel de modelisation .
Mais c'est pas toujours évident (et moi j'aime pas tongue) > le principe (je pense que tu le sais déjà ^^) c'est d'armaturer ton modèle (lui mettre un squelette , quoi) pour pouvoir le manipuler simplement , puis de créer ton animation frame par frame , en modifiant la position d'une partie de ton personnage (les jambes par ex , pour un mouvement de marche) .Puis tu exporte ton personnage et tu indique de quelle frame à quelle frame il marche , de quelle frame à quelle frame il saute, etc .

Hors ligne


#7 

11-11-2008 14:31:25

achoura
Membre
Date d'inscription: 30-10-2008
Messages: 41

merci Ramis ,, j'ai mnt une vision plus clair et le flou dans mes yeux commence a devenir plus nette. justement en 3ds max j'utilise une Biped(squelette) pour animer mon caractére et le mettre en vie big_smile . je vais travailler un peu mnt sur le projet et je vous metterez à jour dés que possible,,,, @bientôt


Le vrai savoir c'est ce qu'il reste dans le cerveau après tous oubliés.

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
Analysé par
872 membres
1423 sujets
11109 messages
Dernier membre inscrit: Glider
8 invités en ligne
Aucun membre connecté
RSS Feed

[ Générée en 0.017 sec., 10 requêtes exécutées ]