Bonjours à tous, j'ai réalisé une class pour faire une camera a la 3eme personne en me basant sur une trouvé sur le net (http://irrlicht.sourceforge.net/phpBB2/ … php?t=1140).

Je l'ai largement modifieé afin qu'elle corresponde un peu plus a mes critères, en esperant que sa puisse venir en aide a certains.

Je ne suis pas un as de la programmation, ainsi toute les remarques et améliorations sont les bienvenus.

Derniere chose, j'ai utilisé irrlicht 1.2 pour compiler ce code, méfiance donc si vous utilisez une autre version, il me semble qu'il doit y avoir quelque petite modif.


FollowingCamera.hppexemple.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168

#include<irrlicht.h>

using namespace irr;
using namespace core;                 
using namespace scene;                                                   

class FollowingCamera
{
     ISceneNode* pTargetNode;
     ICameraSceneNode* Camera;

     vector3df LastTargetPosition;
     vector3df LastTargetRotation;
     
     vector3df NewCamPosition;
     vector3df FinalCamPosition;
     vector3df Vecteur;

     bool MonInitialPos;            // Mettre true pour utiliser la position initiale de la camera.
     f32 MaDistance;                // Distance entre l'objet et la camera.
     f32 MonAltitudeCamera;         // Hauteur de la camera, par rapport a l'objet.
     f32 MonDeltaCible;             // Permet d'incrementer ou de decrementer la hauteur du point cible (par defaut le centre de l'objet).
     vector3df MonInitialCamPosition;  // vecteur permettant d'initialiser la position de la camera.(facultatif)
                                       // par defaut la camera se place derriere l'objet suivant la distance et la hauteur indiqué.
     f32 EcartObj;
     f32 EcartXObj;
     f32 EcartZObj;
     f32 DistX;
     f32 VittX;
     f32 DistY;
     f32 VittY;
     f32 DistZ;
     f32 VittZ;
     f32 CoeffVittCam;
     f32 ix;
     f32 iy;
     f32 iz;
     
     bool TestNode ;
     bool Verrou ;

     public:
     // constructeur
     FollowingCamera(ISceneNode* TargetNode, ISceneManager*smgr,
                     bool InitialPos = false, ITriangleSelector* selectorCam,
                     f32 Distance = 200.0f, f32 AltitudeCamera = 100.0f, f32 DeltaCible = 0.0f,
                     vector3df InitialCamPosition = vector3df(-100.0f, 100.0f, 0.0f),
                     s32 id = -1);

     // destructeur
     ~FollowingCamera();

     ICameraSceneNode* getCam() { return Camera; }

     void Update();
};

// constructeur
FollowingCamera::FollowingCamera(ISceneNode* TargetNode, ISceneManager*smgr,
                                 bool InitialPos,
                                 ITriangleSelector* selectorCam = 0,
                                 f32 Distance, f32 AltitudeCamera, f32 DeltaCible,
                                 vector3df InitialCamPosition,
                                 s32 id )
{
     MonInitialPos = InitialPos;
     MaDistance = Distance;
     MonAltitudeCamera = AltitudeCamera;
     MonDeltaCible = DeltaCible;
     MonInitialCamPosition = InitialCamPosition;
     
     LastTargetPosition = TargetNode->getPosition();
     
     Vecteur = vector3df(LastTargetPosition.X,LastTargetPosition.Y+DeltaCible,LastTargetPosition.Z);

     TestNode = true;
     Verrou = false;
     
     CoeffVittCam = 200;       // coefficient de vitesse de replacement de camera (au plus il est petit, au plus elle va vite)
       
     if(InitialPos == true)
     {
          Camera = smgr->addCameraSceneNode(0,
                                            vector3df(InitialCamPosition.X,InitialCamPosition.Y + LastTargetPosition.Y,InitialCamPosition.Z),
                                            vector3df(LastTargetPosition.X,(LastTargetPosition.Y + DeltaCible),LastTargetPosition.Z),
                                            id );
     }
     else
     {
          EcartXObj = Distance * cos(TargetNode->getRotation().Y * PI/180.0f);
          EcartZObj = Distance * sin(TargetNode->getRotation().Y * PI/180.0f);

          Camera = smgr->addCameraSceneNode(0,
                                            vector3df(LastTargetPosition.X - EcartXObj,AltitudeCamera + LastTargetPosition.Y,LastTargetPosition.Z + EcartZObj),
                                            vector3df(LastTargetPosition.X,(LastTargetPosition.Y + DeltaCible),LastTargetPosition.Z),
                                            id );     
     }
     
     //collision
     ISceneNodeAnimator* CollisionCamera = smgr->createCollisionResponseAnimator(
     selectorCam, Camera, core::vector3df(10,10,10),
     vector3df(0,0,0),
     vector3df(0,0,0));
     Camera->addAnimator(CollisionCamera);
     CollisionCamera->drop();
         
     pTargetNode = TargetNode;
     pTargetNode->grab();
}

// destructeur
FollowingCamera::~FollowingCamera()
{
     pTargetNode->drop();
}

void FollowingCamera::Update()
{
     if(!Camera || !pTargetNode) return;
     
     vector3df CurrTargetPosition = pTargetNode->getPosition();
     
     if(Verrou == false)  // pour tester le premier deplacement de l'objet, avant de replacer la camera.
     {
           vector3df CurrTargetRotation = pTargetNode->getRotation();
           if((CurrTargetPosition.X != LastTargetPosition.X || CurrTargetPosition.Z != LastTargetPosition.Z || CurrTargetRotation.Y != LastTargetRotation.Y))
           {
                TestNode = false;
                Verrou = true;
           }
           LastTargetRotation = CurrTargetRotation;     
     } 
       
     if(TestNode == false)
     {           
          NewCamPosition = Camera->getPosition();

          EcartXObj = MaDistance * cos(pTargetNode->getRotation().Y * PI/180.0f);
          EcartZObj = MaDistance * sin(pTargetNode->getRotation().Y * PI/180.0f);
          FinalCamPosition = vector3df(CurrTargetPosition.X - EcartXObj,MonAltitudeCamera+CurrTargetPosition.Y,CurrTargetPosition.Z + EcartZObj);
         
          DistX = NewCamPosition.X - FinalCamPosition.X;
          DistY = NewCamPosition.Y - FinalCamPosition.Y;
          DistZ = NewCamPosition.Z - FinalCamPosition.Z;
          if( DistX > 0 ) {ix = -1;} else {ix = 1; DistX=(-1)*DistX;}
          if( DistY > 0 ) {iy = -1;} else {iy = 1; DistY=(-1)*DistY;}
          if( DistZ > 0 ) {iz = -1;} else {iz = 1; DistZ=(-1)*DistZ;}       
          VittX = DistX / CoeffVittCam;
          VittY = DistY / CoeffVittCam;
          VittZ = DistZ / CoeffVittCam;
          Camera->setPosition(vector3df(NewCamPosition.X +(ix*VittX),NewCamPosition.Y +(iy*VittY),NewCamPosition.Z +(iz*VittZ)));

          DistX = Vecteur.X - CurrTargetPosition.X;
          DistY = Vecteur.Y - (CurrTargetPosition.Y + MonDeltaCible);
          DistZ = Vecteur.Z - CurrTargetPosition.Z;
          if( DistX > 0 ) {ix = -1;} else {ix = 1; DistX=(-1)*DistX;}
          if( DistY > 0 ) {iy = -1;} else {iy = 1; DistY=(-1)*DistY;}
          if( DistZ > 0 ) {iz = -1;} else {iz = 1; DistZ=(-1)*DistZ;}       
          VittX = DistX / CoeffVittCam;
          VittY = DistY / CoeffVittCam;
          VittZ = DistZ / CoeffVittCam;
         
          Vecteur = vector3df(Vecteur.X+(ix*VittX),Vecteur.Y+(iy*VittY),Vecteur.Z+(iz*VittZ));
          Camera->setTarget(Vecteur);   
     }
     
     LastTargetPosition = CurrTargetPosition;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138

]#include<irrlicht.h>
#include<iostream>

#include"FollowingCamera.hpp"
 
using namespace irr;           
using namespace core;                               
using namespace scene;                                                           
using namespace video;                                                 
using namespace gui;                                         
using namespace io;                                         
         
#pragma comment(lib, "Irrlicht.lib")     

ISceneNode* player = 0;     
IrrlichtDevice* device = 0;   
   
//==============================================================================

class MonEcouteur : public IEventReceiver
{
public:   
   virtual bool OnEvent(SEvent event)   
   {     
      if (event.KeyInput.Key == KEY_KEY_A && event.KeyInput.PressedDown)
      { 
           player->setRotation( vector3df(0, player->getRotation().Y - 5.0f, 0) );
           return true;   
      }               
 
      if (event.KeyInput.Key == KEY_KEY_E && event.KeyInput.PressedDown)
      {
           player->setRotation( vector3df(0, player->getRotation().Y + 5.0f, 0) ); 
           return true;   
      } 

      if (event.KeyInput.Key == KEY_KEY_Z && event.KeyInput.PressedDown)
      {                       
           vector3df facing( cos( player->getRotation().Y * PI/180.0f ), 0, -sin( player->getRotation().Y * PI/180.0f ) );
           facing.normalize();
           vector3df newPos = player->getPosition() + (facing*5.0f); 
           player->setPosition( newPos );
           return true;
      }
     
      if (event.KeyInput.Key == KEY_KEY_S && event.KeyInput.PressedDown)       
      {
           vector3df facing( cos( player->getRotation().Y * PI/180.0f ), 0, -sin( player->getRotation().Y * PI/180.0f ) );
           facing.normalize();
           vector3df newPos = player->getPosition() - (facing*5.0f)  ;
           player->setPosition( newPos );
           return true;
      }     
      return false;
   }

};

//==============================================================================

int main()
{
    MonEcouteur receiver;
    IrrlichtDevice *device =
        createDevice( video::EDT_OPENGL, dimension2d<s32>(640, 480), 16,
            false, false, false, &receiver);
              
    device->setWindowCaption(L"Following Camera"); 
   
    IVideoDriver* driver = device->getVideoDriver();
    ISceneManager* smgr = device->getSceneManager();
    IGUIEnvironment* guienv = device->getGUIEnvironment();
    
//=================================== objet ====================================

    device->getFileSystem()->addZipFileArchive("media/terrain/map-20kdm2.pk3");
   
    IAnimatedMesh* q3levelmesh = smgr->getMesh("20kdm2.bsp");
    ISceneNode* q3node = 0;
   
    if (q3levelmesh)
        q3node = smgr->addOctTreeSceneNode(q3levelmesh->getMesh(0));

    ITriangleSelector* selector = 0;
   
    if (q3node)
    {       
        q3node->setPosition(vector3df(-1370,-130,-1400));
        selector = smgr->createOctTreeTriangleSelector(q3levelmesh->getMesh(0), q3node, 128);
        q3node->setTriangleSelector(selector);
        selector->drop();       
    }   

    player = smgr->addAnimatedMeshSceneNode(smgr->               
    getMesh("media/objet/faerie.md2"));     
    player->setRotation(irr::core::vector3df(0,0,0) );
    player->setMaterialTexture(0, driver->getTexture("media/texture/faerie5.bmp"));
    player->setMaterialFlag(video::EMF_LIGHTING , false);
    player->setPosition(vector3df(76,-25,-61));   
    player->setScale(core::vector3df(1.5,1.5,1.5));
       
    ISceneNodeAnimator* anim = smgr->createCollisionResponseAnimator(
        selector, player, vector3df(15,40,20),
        vector3df(0,-3,0),     
        vector3df(0,0,0)); 
    player->addAnimator(anim);     
    anim->drop();           
      
//==================================Camera======================================
                                         
    FollowingCamera* MaCamera = new FollowingCamera(player, smgr,
                                                  true,           // Pour utiliser une position initiale.
                                                  selector,       // Pour les collisions.
                                                  100,            // Distance.
                                                  50,             // Hauteur.
                                                  30,             // Delta cible.
                                                  vector3df(-50,200,-120));   // Position initiale.                   
    smgr->setActiveCamera( MaCamera->getCam() );         
     
//==============================================================================
       
    while(device->run())         
    {   
         
        driver->beginScene(true, true, SColor(255,100,101,140));
       
        smgr->drawAll(); 
        guienv->drawAll();
        if(MaCamera) {MaCamera->Update();}       
       
        driver->endScene();
            
    }           
    if(MaCamera) {delete MaCamera;}
    device->drop();

    return 0;
}