RTS Camera

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
kevin[be]
Posts: 23
Joined: Sun Dec 21, 2008 2:42 pm

RTS Camera

Post by kevin[be] »

Hi,

I have found a great rtc camera, by Cmd Kewin.
Unfortunatly, it doesn't work with irrlicht 1.5
Whatever I change in the code, I keep getting errors like 'cannot initiate abstract class due to the following members' and then a whole list.

I use visual studio 2008

http://www.irrlicht3d.org/wiki/index.ph ... ByCmdKewin

Any ideas?

-- The output from VS

>------ Build started: Project: Trinity, Configuration: Debug Win32 ------
1>Compiling...
1>game.cpp
1>c:\trinity\trinity\game.cpp(29) : error C2259: 'RTSCamera' : cannot instantiate abstract class
1> due to following members:
1> 'void irr::scene::ICameraSceneNode::setRotation(const irr::core::vector3df &)' : is abstract
1> c:\library\irrlicht1.5\include\icamerascenenode.h(77) : see declaration of 'irr::scene::ICameraSceneNode::setRotation'
1> 'void irr::scene::ICameraSceneNode::setProjectionMatrix(const irr::core::matrix4 &,bool)' : is abstract
1> c:\library\irrlicht1.5\include\icamerascenenode.h(45) : see declaration of 'irr::scene::ICameraSceneNode::setProjectionMatrix'
1> 'const irr::core::matrix4 &irr::scene::ICameraSceneNode::getProjectionMatrix(void) const' : is abstract
1> c:\library\irrlicht1.5\include\icamerascenenode.h(49) : see declaration of 'irr::scene::ICameraSceneNode::getProjectionMatrix'
1> 'const irr::core::matrix4 &irr::scene::ICameraSceneNode::getViewMatrix(void) const' : is abstract
1> c:\library\irrlicht1.5\include\icamerascenenode.h(53) : see declaration of 'irr::scene::ICameraSceneNode::getViewMatrix'
1> 'const irr::core::vector3df &irr::scene::ICameraSceneNode::getTarget(void) const' : is abstract
1> c:\library\irrlicht1.5\include\icamerascenenode.h(81) : see declaration of 'irr::scene::ICameraSceneNode::getTarget'
1> 'const irr::core::vector3df &irr::scene::ICameraSceneNode::getUpVector(void) const' : is abstract
1> c:\library\irrlicht1.5\include\icamerascenenode.h(89) : see declaration of 'irr::scene::ICameraSceneNode::getUpVector'
1> 'irr::f32 irr::scene::ICameraSceneNode::getNearValue(void) const' : is abstract
1> c:\library\irrlicht1.5\include\icamerascenenode.h(93) : see declaration of 'irr::scene::ICameraSceneNode::getNearValue'
1> 'irr::f32 irr::scene::ICameraSceneNode::getFarValue(void) const' : is abstract
1> c:\library\irrlicht1.5\include\icamerascenenode.h(97) : see declaration of 'irr::scene::ICameraSceneNode::getFarValue'
1> 'irr::f32 irr::scene::ICameraSceneNode::getAspectRatio(void) const' : is abstract
1> c:\library\irrlicht1.5\include\icamerascenenode.h(101) : see declaration of 'irr::scene::ICameraSceneNode::getAspectRatio'
1> 'irr::f32 irr::scene::ICameraSceneNode::getFOV(void) const' : is abstract
1> c:\library\irrlicht1.5\include\icamerascenenode.h(105) : see declaration of 'irr::scene::ICameraSceneNode::getFOV'
1> 'const irr::scene::SViewFrustum *irr::scene::ICameraSceneNode::getViewFrustum(void) const' : is abstract
1> c:\library\irrlicht1.5\include\icamerascenenode.h(126) : see declaration of 'irr::scene::ICameraSceneNode::getViewFrustum'
1> 'bool irr::scene::ICameraSceneNode::isInputReceiverEnabled(void) const' : is abstract
1> c:\library\irrlicht1.5\include\icamerascenenode.h(134) : see declaration of 'irr::scene::ICameraSceneNode::isInputReceiverEnabled'
1> 'void irr::scene::ICameraSceneNode::bindTargetAndRotation(bool)' : is abstract
1> c:\library\irrlicht1.5\include\icamerascenenode.h(152) : see declaration of 'irr::scene::ICameraSceneNode::bindTargetAndRotation'
1> 'bool irr::scene::ICameraSceneNode::getTargetAndRotationBinding(void) const' : is abstract
1> c:\library\irrlicht1.5\include\icamerascenenode.h(156) : see declaration of 'irr::scene::ICameraSceneNode::getTargetAndRotationBinding'
1> 'bool irr::scene::ICameraSceneNode::OnEvent(const irr::SEvent &)' : is abstract
1> c:\library\irrlicht1.5\include\icamerascenenode.h(62) : see declaration of 'irr::scene::ICameraSceneNode::OnEvent'
1>c:\rellion soft\trinity\trinity\game.cpp(48) : warning C4018: '>=' : signed/unsigned mismatch
1>RTSCamera.cpp
1>c:\rellion soft\trinity\trinity\rtscamera.cpp(146) : error C2039: 'OnPreRender' : is not a member of 'irr::scene::ISceneNode'
1> c:\library\irrlicht1.5\include\iscenenode.h(35) : see declaration of 'irr::scene::ISceneNode'
1>Generating Code...
1>Build Time 0:00
1>Build log was saved at "file://c:\Trinity\Trinity\Debug\BuildLog.htm"
1>Trinity - 2 error(s), 1 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Last edited by kevin[be] on Sun Jun 07, 2009 7:36 pm, edited 2 times in total.
Lonesome Ducky
Competition winner
Posts: 1123
Joined: Sun Jun 10, 2007 11:14 pm

Post by Lonesome Ducky »

It would be easier to just show us the errors it gives. Try running it again, and copy and paste some of the errors you get so we can better understand your problem.
kevin[be]
Posts: 23
Joined: Sun Dec 21, 2008 2:42 pm

Post by kevin[be] »

And this is how i load it:

RTSCamera* camera = new RTSCamera(device,smgr->getRootSceneNode(),smgr,-1,1000.0f,10.0f,10.0f);
camera->setPosition(vector3df(0,0,0));
netkoji
Posts: 10
Joined: Sun Feb 01, 2009 1:32 pm

Post by netkoji »

Judging from your error message the interface in irrlicht has changed and the provided implementation does not define certain pure virtual methods. Solving that problem will get your code to compile (I suspect that defining empty functions would help just fine).
Midnight
Posts: 1772
Joined: Fri Jul 02, 2004 2:37 pm
Location: Wonderland

Post by Midnight »

netkoji wrote:(I suspect that defining empty functions would help just fine).
he means this

object() = 0;



also a "const SEvent& event" would probably help.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Midnight wrote:
netkoji wrote:(I suspect that defining empty functions would help just fine).
he means this

object() = 0;
No, an empty function would be

Code: Select all

func() {}
. Otherwise you still need an implementation (except for the compiler generated functions, like default constructors).
kevin[be]
Posts: 23
Joined: Sun Dec 21, 2008 2:42 pm

Post by kevin[be] »

Thank guys, it worked by adding the empty functions
xirtamatrix
Posts: 219
Joined: Fri Feb 19, 2010 4:03 pm
Location: Estonia

Post by xirtamatrix »

Hi,

I'm trying to make the same camera code work with Irrlicht 1.7 and getting same errors for the 5 missing functions. I have defined empty functions for them in the form:

virtual void bindTargetAndRotation( bool bound) {};
virtual void setRotation( const core::vector3df & rotation) {};
virtual void setViewMatrixAffector( const core::matrix4 & affector ) {};

virtual bool getTargetAndRotationBinding(void) const {};
virtual const core::matrix4& getViewMatrixAffector() const {};

The problem is, for the first three which are void it works fine, for the last 2 it gives me error:

1>c:\documents and settings\...\...\visual studio 2008\projects\rtscamera\rtscamera\rtscamera.h(44) : error C4716: 'RTSCamera::getTargetAndRotationBinding' : must return a value

1>c:\documents and settings\...\...\visual studio 2008\projects\rtscamera\rtscamera\rtscamera.h(45) : error C4716: 'RTSCamera::getViewMatrixAffector' : must return a value

Can someone please help me out here?
Many thanks!

/regards
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

You shouldn't derive from ICamera, but use a camera animator instead. That will avoid most of these problems. But it also requires lots of refactoring in this case.
The errors simply tell you that the functions require something to return. Since your function implementations won't do anything useful anyway, just return false in the first case and core::IdtentityMatrix in the second.
Jumach
Posts: 32
Joined: Sun Mar 14, 2010 9:42 pm
Location: Oregon

Post by Jumach »

This sounds good. Any way you could post your code when it is working for 1.7?
xirtamatrix
Posts: 219
Joined: Fri Feb 19, 2010 4:03 pm
Location: Estonia

Post by xirtamatrix »

Thanks hybrid, I got it working to my satisfaction with Irrlicht 1.7 though had to make a few changes here and there.

What I cant figure out is why colllision detection is not working on it?? If I change the camera to FPS the collison works perfectly, hence, the problem lies somewhere within the RTS class. Any ideas??

Here follows the complete code for anyone who may wish to use it with Irrlicht 1.7:

rtscamera.h

Code: Select all

#ifndef __RTSCAMERA__ 
#define __RTSCAMERA__ 

#include <irrlicht.h> 

using namespace irr; 
using namespace core; 
using namespace scene; 
using namespace video; 
using namespace io; 
using namespace gui; 

class RTSCamera : public ICameraSceneNode 
{ 
   public: 
      RTSCamera(IrrlichtDevice* devicepointer,ISceneNode* parent,ISceneManager* smgr,s32 id, 
         f32 rotateSpeed = -1000.0f,f32 zoomSpeed = 1000.0f,f32 translationSpeed = 1000.0f); 

      virtual ~RTSCamera(); 

      //Events 
      virtual void render(); 
      virtual bool OnEvent(const SEvent& event); 
      virtual void OnRegisterSceneNode(); 
      virtual void OnAnimate(u32 timeMs); 

      //Setup 
      virtual void setInputReceiverEnabled(bool enabled); 
      virtual bool isInputReceiverEnabled() const; 

      //Gets 
      virtual const aabbox3d<f32>& getBoundingBox() const; 
      virtual const matrix4& getProjectionMatrix() const; 
      virtual const SViewFrustum* getViewFrustum() const; 
      virtual const core::vector3df& getTarget() const; 
      virtual const matrix4& getViewMatrix() const; 
      virtual const core::vector3df& getUpVector() const; 
      virtual f32 getNearValue() const; 
      virtual f32 getFarValue() const; 
      virtual f32 getAspectRatio() const; 
      virtual f32 getFOV() const; 

      //Sets 
      virtual void setNearValue(f32 zn); 
      virtual void setFarValue(f32 zf); 
      virtual void setAspectRatio(f32 aspect); 
      virtual void setFOV(f32 fovy); 
      virtual void setUpVector(const vector3df& pos); 
      virtual void setProjectionMatrix(const matrix4& projection); 
      virtual void setPosition(const vector3df& newpos); 
      virtual void setTarget(const vector3df& newpos); 

     virtual void setRotation(const irr::core::vector3df &) {} 
     virtual void setProjectionMatrix(const irr::core::matrix4 &,bool) {} 
     virtual void setViewMatrixAffector(const irr::core::matrix4 &) {} 
     virtual const core::matrix4& getViewMatrixAffector() const {return irr::core::IdentityMatrix;}; 
     virtual void bindTargetAndRotation(bool) {} 
     virtual bool getTargetAndRotationBinding() const {return 0;} 

      virtual void setZoomSpeed(f32 value); 
      virtual void setTranslateSpeed(f32 value); 
      virtual void setRotationSpeed(f32 value); 


      //Helper Functions 
      //virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0); 
      //virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0); 
      void pointCameraAtNode(ISceneNode* selectednode); 
      void setMinZoom(f32 amount); 
      void setMaxZoom(f32 amount); 

      //Type Return 
      virtual ESCENE_NODE_TYPE getType() const { return ESNT_CAMERA; } 

      //Public Attributes 
      bool atMinDistance; 
      bool atMaxDistance; 
      ISceneNode* selectednode; 
   protected: 
      //Properties 
      vector3df Target; 
      vector3df UpVector; 
      matrix4 Projection; 
      matrix4 View; 
      SViewFrustum ViewArea; 
      aabbox3d<f32> BBox; 
      bool InputReceiverEnabled; 
      dimension2d<f32> screenDim; 
      f32 Fovy;      // Field of view, in radians. 
      f32 Aspect;   // Aspect ratio. 
      f32 ZNear;   // value of the near view-plane. 
      f32 ZFar;   // Z-value of the far view-plane. 

      void recalculateProjectionMatrix(); 
      void recalculateViewArea(); 

   private: 
      IrrlichtDevice* device; 
      vector3df Pos; 
      bool zooming, rotating, moving, translating; 
      f32 zoomSpeed; 
      f32 translateSpeed; 
      f32 rotateSpeed; 
      f32 rotateStartX, rotateStartY; 
      f32 zoomStartX, zoomStartY; 
      f32 translateStartX, translateStartY; 
      f32 currentZoom; 
      f32 rotX, rotY; 
      vector3df oldTarget; 
      vector2df MousePos; 
      bool Keys[KEY_KEY_CODES_COUNT]; 
      bool MouseKeys[3]; 
      f32 targetMinDistance; 
      f32 targetMaxDistance; 

      enum MOUSE_BUTTON 
      { 
         MOUSE_BUTTON_RIGHT, 
         MOUSE_BUTTON_MIDDLE, 
         MOUSE_BUTTON_LEFT 
      }; 

      void allKeysUp(); 
      void allMouseButtonsUp(); 
      bool isKeyDown(s32 key); 
      bool isMouseButtonDown(s32 key); 
      void animate(); 
      void updateAnimationState(); 
}; 

#endif 


rtscamera.cpp

Code: Select all


#include "rtscamera.h" 

RTSCamera::RTSCamera(IrrlichtDevice* devicepointer,ISceneNode* parent,ISceneManager* smgr,s32 id, 
    f32 rs,f32 zs,f32 ts) 
   : ICameraSceneNode(parent,smgr,id,vector3df(1.0f,1.0f,1.0f),vector3df(0.0f,0.0f,0.0f), 
               vector3df(1.0f,1.0f,1.0f)),InputReceiverEnabled(true) 
{ 
   device = devicepointer; 
   BBox.reset(0,0,0); 

   UpVector.set(0.0f, 1.0f, 0.0f); 

   // set default projection 
   Fovy = core::PI / 2.5f;   // Field of view, in radians. 
   Aspect = 4.0f / 3.0f;   // Aspect ratio. 
   ZNear = 1.0f;      // value of the near view-plane. 
   ZFar = 100000.0f;      // Z-value of the far view-plane. 

   IVideoDriver* d = smgr->getVideoDriver(); 
   if (d) 
      Aspect = (f32)d->getCurrentRenderTargetSize().Width / (f32)d->getCurrentRenderTargetSize().Height; 

   zooming = false; 
   rotating = false; 
   moving = false; 
   translating = false; 
   zoomSpeed = zs; 
   rotateSpeed = rs; 
   translateSpeed = ts; 
   targetMinDistance = 1.0f; 
   targetMaxDistance = 2000.0f; 
   Target.set(0.0f,0.0f,0.0f); 
   rotX = 0; 
   rotY = 0; 
   oldTarget = Target; 

   atMinDistance = false; 
   atMaxDistance = false; 

   allKeysUp(); 
   allMouseButtonsUp(); 

   recalculateProjectionMatrix(); 
   recalculateViewArea(); 

   smgr->setActiveCamera(this); 
} 

RTSCamera::~RTSCamera() 
{ 
} 

bool RTSCamera::OnEvent(const SEvent& event) 
{ 
   if (!InputReceiverEnabled) 
      return false; 

   dimension2d<u32> ssize = SceneManager->getVideoDriver()->getScreenSize(); 
   if(event.EventType == EET_MOUSE_INPUT_EVENT) 
   { 
      //printf("a\n"); 
      switch(event.MouseInput.Event) 
      { 
         case EMIE_LMOUSE_PRESSED_DOWN: 
            selectednode = SceneManager->getSceneCollisionManager()->getSceneNodeFromScreenCoordinatesBB(device->getCursorControl()->getPosition()); 
            if(selectednode && selectednode->getType() == ESNT_BILLBOARD) 
            { 
               pointCameraAtNode(selectednode); 
            } 
            else 
            { 
               selectednode = NULL; 
               MouseKeys[0] = true; 
            } 
            break; 
         case EMIE_RMOUSE_PRESSED_DOWN: 
            MouseKeys[2] = true; 
            break; 
         case EMIE_MMOUSE_PRESSED_DOWN: 
            MouseKeys[1] = true; 
            break; 
         case EMIE_LMOUSE_LEFT_UP: 
            MouseKeys[0] = false; 
            break; 
         case EMIE_RMOUSE_LEFT_UP: 
            MouseKeys[2] = false; 
            break; 
         case EMIE_MMOUSE_LEFT_UP: 
            MouseKeys[1] = false; 
            break; 
         case EMIE_MOUSE_MOVED: 
            { 
               IVideoDriver* driver = SceneManager->getVideoDriver(); 
               if (driver) 
               { 
                  MousePos.X = event.MouseInput.X / (f32)ssize.Width; 
                  MousePos.Y = event.MouseInput.Y / (f32)ssize.Height; 
               } 
            } 
            break; 
         case EMIE_MOUSE_WHEEL: 
            currentZoom -= event.MouseInput.Wheel * zoomSpeed; 
            break; 
         default: 
            break; 
      } 

      return true; 
   } 

   if(event.EventType == EET_KEY_INPUT_EVENT) 
   { 
      Keys[event.KeyInput.Key] = event.KeyInput.PressedDown; 
      return true; 
   } 

   return false; 
} 

void RTSCamera::OnRegisterSceneNode() 
{ 
    
   vector3df pos = getAbsolutePosition(); 
   vector3df tgtv = Target - pos; 
   tgtv.normalize(); 

   vector3df up = UpVector; 
   up.normalize(); 

   f32 dp = tgtv.dotProduct(up); 

   if ( core::equals ( fabs ( dp ), 1.f ) ) 
   { 
      up.X += 0.5f; 
   } 

   //ViewArea.Matrices [ ETS_VIEW ].buildCameraLookAtMatrixLH(pos, Target, up); 
   ViewArea.getTransform(ETS_VIEW).buildCameraLookAtMatrixLH(pos, Target, up); 
   //ViewArea.setTransformState ( ETS_VIEW ); 
   recalculateViewArea(); 

   if( SceneManager->getActiveCamera () == this ) 
      SceneManager->registerNodeForRendering(this, ESNRP_CAMERA); 

   if(IsVisible) 
      ISceneNode::OnRegisterSceneNode(); 
    
} 

void RTSCamera::render() 
{ 
   IVideoDriver* driver = SceneManager->getVideoDriver(); 
   if ( driver) 
   { 
      //driver->setTransform(ETS_PROJECTION, ViewArea.Matrices [ ETS_PROJECTION ] ); 
      driver->setTransform(ETS_PROJECTION, ViewArea.getTransform(ETS_PROJECTION) ); 
      //driver->setTransform(ETS_VIEW, ViewArea.Matrices [ ETS_VIEW ] ); 
      driver->setTransform(ETS_VIEW, ViewArea.getTransform(ETS_VIEW) ); 
   } 
} 

void RTSCamera::OnAnimate(u32 timeMs) 
{ 
   animate(); 

   ISceneNode::setPosition(Pos); 
   updateAbsolutePosition(); 
} 

void RTSCamera::setInputReceiverEnabled(bool enabled) 
{ 
   InputReceiverEnabled = enabled; 
} 

bool RTSCamera::isInputReceiverEnabled() const 
{ 
   _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; 
   return InputReceiverEnabled; 
} 

const aabbox3d<f32>& RTSCamera::getBoundingBox() const 
{ 
   return ViewArea.getBoundingBox(); 
} 

const matrix4& RTSCamera::getProjectionMatrix() const 
{ 
   //return ViewArea.Matrices [ ETS_PROJECTION ]; 
   return ViewArea.getTransform(ETS_PROJECTION); 
} 

const SViewFrustum* RTSCamera::getViewFrustum() const 
{ 
   return &ViewArea; 
} 

const core::vector3df& RTSCamera::getTarget() const 
{ 
   return Target; 
} 

const matrix4& RTSCamera::getViewMatrix() const 
{ 
   //return ViewArea.Matrices [ video::ETS_VIEW ]; 
   return ViewArea.getTransform(ETS_VIEW); 
} 

const core::vector3df& RTSCamera::getUpVector() const 
{ 
   return UpVector; 
} 

f32 RTSCamera::getNearValue() const 
{ 
   return ZNear; 
} 

f32 RTSCamera::getFarValue() const 
{ 
   return ZFar; 
} 

f32 RTSCamera::getAspectRatio() const 
{ 
   return Aspect; 
} 

f32 RTSCamera::getFOV() const 
{ 
   return Fovy; 
} 

void RTSCamera::setNearValue(f32 f) 
{ 
   ZNear = f; 
   recalculateProjectionMatrix(); 
} 

void RTSCamera::setFarValue(f32 f) 
{ 
   ZFar = f; 
   recalculateProjectionMatrix(); 
} 

void RTSCamera::setAspectRatio(f32 f) 
{ 
   Aspect = f; 
   recalculateProjectionMatrix(); 
} 

void RTSCamera::setFOV(f32 f) 
{ 
   Fovy = f; 
   recalculateProjectionMatrix(); 
} 

void RTSCamera::setUpVector(const vector3df& pos) 
{ 
   UpVector = pos; 
} 

void RTSCamera::setProjectionMatrix(const matrix4& projection) 
{ 
   //ViewArea.Matrices [ ETS_PROJECTION ] = projection; 
   ViewArea.getTransform(ETS_PROJECTION) = projection; 
   //ViewArea.setTransformState ( ETS_PROJECTION ); 
} 

void RTSCamera::setPosition(const core::vector3df& pos) 
{ 
   Pos = pos; 
   updateAnimationState(); 

   ISceneNode::setPosition(pos); 
} 

void RTSCamera::setTarget(const core::vector3df& pos) 
{ 
   Target = oldTarget = pos; 
   updateAnimationState(); 
} 

void RTSCamera::setZoomSpeed(f32 value) 
{ 
   zoomSpeed = value; 
} 

void RTSCamera::setTranslateSpeed(f32 value) 
{ 
   translateSpeed = value; 
} 

void RTSCamera::setRotationSpeed(f32 value) 
{ 
   rotateSpeed = value; 
} 

void RTSCamera::pointCameraAtNode(ISceneNode* selectednode) 
{ 
   vector3df totarget = getPosition() - getTarget(); 
   setPosition(selectednode->getPosition() + (totarget.normalize() * 100)); 
   setTarget(selectednode->getPosition()); 
   updateAnimationState(); 
} 

void RTSCamera::setMinZoom(f32 amount) 
{ 
   targetMinDistance = amount; 
} 

void RTSCamera::setMaxZoom(f32 amount) 
{ 
   targetMaxDistance = amount; 
} 

void RTSCamera::recalculateProjectionMatrix() 
{ 
   //ViewArea.Matrices [ ETS_PROJECTION ].buildProjectionMatrixPerspectiveFovLH(Fovy, Aspect, ZNear, ZFar); 
   ViewArea.getTransform(ETS_PROJECTION).buildProjectionMatrixPerspectiveFovLH(Fovy, Aspect, ZNear, ZFar); 
   //ViewArea.setTransformState ( ETS_PROJECTION ); 
} 


void RTSCamera::recalculateViewArea() 
{ 
   ViewArea.cameraPosition = getAbsolutePosition(); 
   //ViewArea.setFrom ( ViewArea.Matrices [ SViewFrustum::ETS_VIEW_PROJECTION_3 ] ); 
   ViewArea.setFrom ( ViewArea.getTransform(ETS_PROJECTION)*ViewArea.getTransform(ETS_VIEW) ); 
} 

void RTSCamera::allKeysUp() 
{ 
   for(int i = 0;i < KEY_KEY_CODES_COUNT;i++) 
      Keys[i] = false; 
} 

void RTSCamera::allMouseButtonsUp() 
{ 
   for (s32 i=0; i<3; ++i) 
      MouseKeys[i] = false; 
} 

bool RTSCamera::isKeyDown(s32 key) 
{ 
   return Keys[key]; 
} 

bool RTSCamera::isMouseButtonDown(s32 key) 
{ 
   return MouseKeys[key]; 
} 

void RTSCamera::animate() 
{ 
   f32 nRotX = rotX; 
   f32 nRotY = rotY; 
   f32 nZoom = currentZoom; 

   vector3df translate(oldTarget); 
   vector3df tvectX = Pos - Target; 
   tvectX = tvectX.crossProduct(UpVector); 
   tvectX.normalize(); 

   //Zoom 
   if (isMouseButtonDown(MOUSE_BUTTON_RIGHT) && isMouseButtonDown(MOUSE_BUTTON_LEFT)) 
   { 
      if (!zooming) 
      { 
         zoomStartX = MousePos.X; 
         zoomStartY = MousePos.Y; 
         zooming = true; 
         nZoom = currentZoom; 
      } 
      else 
      { 
         f32 old = nZoom; 
         nZoom += (zoomStartX - MousePos.X) * zoomSpeed * 100; 

//         f32 targetMinDistance = 0.1f; 
//         if (nZoom < targetMinDistance) 
//            nZoom = targetMinDistance; 

         if (nZoom < targetMinDistance) 
            nZoom = targetMinDistance; 
         else if (nZoom > targetMaxDistance) 
            nZoom = targetMaxDistance; 


         if (nZoom < 0) 
            nZoom = old; 
      } 
   } 
   else 
   { 
      if (zooming) 
      { 
         f32 old = currentZoom; 
         currentZoom = currentZoom + (zoomStartX - MousePos.X ) * zoomSpeed; 
         nZoom = currentZoom; 

         if (nZoom < 0) 
            nZoom = currentZoom = old; 
      } 
      zooming = false; 
   } 

   //Rotate 
   if(isMouseButtonDown(MOUSE_BUTTON_LEFT) && !zooming) 
   { 
      if (!rotating) 
      { 
         rotateStartX = MousePos.X; 
         rotateStartY = MousePos.Y; 
         rotating = true; 
         nRotX = rotX; 
         nRotY = rotY; 
      } 
      else 
      { 
         nRotX += (rotateStartX - MousePos.X) * rotateSpeed; 
         nRotY += (rotateStartY - MousePos.Y) * rotateSpeed; 
      } 
   } 
   else 
   { 
      if (rotating) 
      { 
         rotX = rotX + (rotateStartX - MousePos.X) * rotateSpeed; 
         rotY = rotY + (rotateStartY - MousePos.Y) * rotateSpeed; 
         nRotX = rotX; 
         nRotY = rotY; 
      } 

      rotating = false; 
   } 

   //Translate 
   if(isMouseButtonDown(MOUSE_BUTTON_RIGHT) && !zooming) 
   { 
      if (!translating) 
      { 
         translateStartX = MousePos.X; 
         translateStartY = MousePos.Y; 
         translating = true; 
      } 
      else 
      { 
         translate += tvectX * (translateStartX - MousePos.X) * translateSpeed; 
         translate.X += tvectX.Z * (translateStartY - MousePos.Y) * translateSpeed; 
         translate.Z -= tvectX.X * (translateStartY - MousePos.Y) * translateSpeed; 

         oldTarget = translate; 
      } 
   } 
   else if (isKeyDown(KEY_KEY_W) || isKeyDown(KEY_UP) && !zooming) 
   { 
      if (!translating) 
         translating = true; 
      else 
      { 
         vector3df movevector = getPosition() - getTarget(); 
         movevector.Y = 0; 
         movevector.normalize(); 

         setPosition(getPosition() - movevector * translateSpeed); 
         setTarget(getTarget() - movevector * translateSpeed); 
         updateAbsolutePosition(); 
      } 
   } 
   else if (isKeyDown(KEY_KEY_S) || isKeyDown(KEY_DOWN) && !zooming) 
   { 
      if (!translating) 
         translating = true; 
      else 
      { 
         vector3df movevector = getPosition() - getTarget(); 
         movevector.Y = 0; 
         movevector.normalize(); 

         setPosition(getPosition() + movevector * translateSpeed); 
         setTarget(getTarget() + movevector * translateSpeed); 
         updateAbsolutePosition(); 
      } 
   } 
   else if (isKeyDown(KEY_KEY_A) || isKeyDown(KEY_LEFT) && !zooming) 
   { 
      if (!translating) 
         translating = true; 
      else 
      { 
         vector3df totargetvector = getPosition() - getTarget(); 
         totargetvector.normalize(); 
         vector3df crossvector = totargetvector.crossProduct(getUpVector()); 
         vector3df strafevector = crossvector.normalize(); 

         setPosition(getPosition() - strafevector * translateSpeed); 
         setTarget(getTarget() - strafevector * translateSpeed); 
         updateAbsolutePosition(); 
      } 
   } 
   else if (isKeyDown(KEY_KEY_D) || isKeyDown(KEY_RIGHT) && !zooming) 
   { 
      if (!translating) 
         translating = true; 
      else 
      { 
         vector3df totargetvector = getPosition() - getTarget(); 
         totargetvector.normalize(); 
         vector3df crossvector = totargetvector.crossProduct(getUpVector()); 
         vector3df strafevector = crossvector.normalize(); 

         setPosition(getPosition() + strafevector * translateSpeed); 
         setTarget(getTarget() + strafevector * translateSpeed); 
         updateAbsolutePosition(); 
      } 
   } 
   else 
   { 
      translating = false; 

      if (!translating && !zooming && !rotating) 
      { 
         //Mouse Coordinates go from 0 to 1 on both axes 
         if (MousePos.X < 0.05)   //Up 
         { 
            vector3df totargetvector = getPosition() - getTarget(); 
            totargetvector.normalize(); 
            vector3df crossvector = totargetvector.crossProduct(getUpVector()); 
            vector3df strafevector = crossvector.normalize(); 

            setPosition(getPosition() - strafevector * translateSpeed); 
            setTarget(getTarget() - strafevector * translateSpeed); 
            updateAbsolutePosition(); 
         } 
         else if (MousePos.X > 0.95) //Down 
         { 
            vector3df totargetvector = getPosition() - getTarget(); 
            totargetvector.normalize(); 
            vector3df crossvector = totargetvector.crossProduct(getUpVector()); 
            vector3df strafevector = crossvector.normalize(); 

            setPosition(getPosition() + strafevector * translateSpeed); 
            setTarget(getTarget() + strafevector * translateSpeed); 
            updateAbsolutePosition(); 
         } 
         else if (MousePos.Y < 0.05)   //Up 
         { 
            vector3df movevector = getPosition() - getTarget(); 
            movevector.Y = 0; 
            movevector.normalize(); 

            setPosition(getPosition() - movevector * translateSpeed); 
            setTarget(getTarget() - movevector * translateSpeed); 
            updateAbsolutePosition(); 
         } 
         else if (MousePos.Y > 0.95) //Down 
         { 
            vector3df movevector = getPosition() - getTarget(); 
            movevector.Y = 0; 
            movevector.normalize(); 

            setPosition(getPosition() + movevector * translateSpeed); 
            setTarget(getTarget() + movevector * translateSpeed); 
            updateAbsolutePosition(); 
         } 
      } 
   } 

   //Set Position 
   Target = translate; 

   Pos.X = nZoom + Target.X; 
   Pos.Y = Target.Y; 
   Pos.Z = Target.Z; 

   Pos.rotateXYBy(nRotY, Target); 
   Pos.rotateXZBy(-nRotX, Target); 

   //Correct Rotation Error 
   UpVector.set(0,1,0); 
   UpVector.rotateXYBy(-nRotY, core::vector3df(0,0,0)); 
   UpVector.rotateXZBy(-nRotX+180.f, core::vector3df(0,0,0)); 
} 

void RTSCamera::updateAnimationState() 
{ 
   vector3df pos(Pos - Target); 

   // X rotation 
   vector2df vec2d(pos.X, pos.Z); 
   rotX = (f32)vec2d.getAngle(); 

   // Y rotation 
   pos.rotateXZBy(rotX, vector3df()); 
   vec2d.set(pos.X, pos.Y); 
   rotY = -(f32)vec2d.getAngle(); 

   // Zoom 
   currentZoom = (f32)Pos.getDistanceFrom(Target); 
}





and here is how I'm using it:

main.cpp

Code: Select all

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

#include "rtscamera.h"

using namespace irr; 
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;


#ifdef _IRR_WINDOWS_
#pragma comment(lib, "Irrlicht.lib")
#pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup")
#endif





// event reciever 
class MyEventReceiver : public IEventReceiver 
{ 
public: 
   // This is the one method that we have to implement 
   virtual bool OnEvent(const SEvent& event) 
   { 
      // Remember whether each key is down or up 
      if (event.EventType == irr::EET_KEY_INPUT_EVENT) 
         KeyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown; 

      return false; 
   } 

   // This is used to check whether a key is being held down 
   virtual bool IsKeyDown(EKEY_CODE keyCode) const 
   { 
      return KeyIsDown[keyCode]; 
   } 
    
   MyEventReceiver() 
   { 
      for (u32 i=0; i<KEY_KEY_CODES_COUNT; ++i) 
         KeyIsDown[i] = false; 
   } 

private: 
   // We use this array to store the current state of each key 
   bool KeyIsDown[KEY_KEY_CODES_COUNT]; 
}; 



int main() 
{    

    // create device 
	
	MyEventReceiver receiver; 
	
	IrrlichtDevice* device = createDevice(EDT_OPENGL, 
         dimension2d<u32>(1024, 768), 16, false, false, false, &receiver); 

	if (device == 0) 
      return 1; // could not create selected driver. 


   IVideoDriver* driver = device->getVideoDriver(); 
   ISceneManager* smgr = device->getSceneManager(); 
 
	
	//Make the background
	
	device->getFileSystem()->addZipFileArchive("map-20kdm2.pk3");
	scene::IAnimatedMesh* mesh = smgr->getMesh("20kdm2.bsp");
	scene::ISceneNode* bg = smgr->addOctreeSceneNode(mesh->getMesh(0));
	bg->setPosition(core::vector3df(-1300,-144,-1249));

	
	//Triangle Selecty-ness on the background
	
	scene::ITriangleSelector* selector = 0;
	selector = smgr->createOctreeTriangleSelector(mesh->getMesh(0), bg, 128);
	bg->setTriangleSelector(selector);
	selector->drop();



	//add RTS Camera
	RTSCamera* camera = new RTSCamera(device,smgr->getRootSceneNode(),smgr,-1,100.0f,10.0f,10.0f);
	//ICameraSceneNode *camera= smgr->addCameraSceneNodeFPS(0, 50.0f,0.2f,-1,0,0,true,0.0f,false,true); 
	camera->setPosition(vector3df(0,9,-14)); 
	camera->setTranslateSpeed(5);//speed of cam movement
	camera->setRotationSpeed(50);//speed of cam rotation

	
	//Set collision for camera
	
	scene::ISceneNodeAnimator *collision = smgr->createCollisionResponseAnimator(
		selector,camera,core::vector3df(20,40,20),
		core::vector3df(0,-2,0),
		core::vector3df(0,0,0), 
		0.0f);
	camera->addAnimator(collision);

	collision->drop();	



	int lastFPS = -1;

	while(device->run())
	{
		if (device->isWindowActive())
		{
			//eventReceiver.endEventProcess(); 
			driver->beginScene(true, true, video::SColor(255,200,200,200));
			smgr->drawAll();
			driver->endScene();

			int fps = driver->getFPS();

			if (lastFPS != fps)
			{
				core::stringw str = L"Irrlicht Engine - Quake 3 Map example [";
				str += driver->getName();
				str += "] FPS:";
				str += fps;

				device->setWindowCaption(str.c_str());
				lastFPS = fps;
			}
			//eventReceiver.startEventProcess();    
		}
		else
			device->yield();
	}

	/*
	In the end, delete the Irrlicht device.
	*/
	device->drop();
	return 0;
}

cheers!
to live, is natural; to die, is not!
xirtamatrix
Posts: 219
Joined: Fri Feb 19, 2010 4:03 pm
Location: Estonia

Post by xirtamatrix »

hybrid wrote:You shouldn't derive from ICamera, but use a camera animator instead.

ok, if all I want is to have a simple camera which moves forwards/backwards with up/down keys and rotates with left/right keys, what would be the best and easiest way of doing it? Do I still need a camera animator for achieving this?


/regards
to live, is natural; to die, is not!
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Yes, using the animator way is much easier than providing your own camera solution, because you don't need to implement all those ICamera methods. Instead, you just have to implement the special movement you want, and that's all.
Jumach
Posts: 32
Joined: Sun Mar 14, 2010 9:42 pm
Location: Oregon

Post by Jumach »

I added the rtscamera.cpp to my project but when I compile my main.cpp I get an error on line 134:

if ( core::equals ( fabs ( dp ), 1.f ) )

No idea why I can't get this to work...
Last edited by Jumach on Thu Mar 18, 2010 7:50 am, edited 1 time in total.
xirtamatrix
Posts: 219
Joined: Fri Feb 19, 2010 4:03 pm
Location: Estonia

Post by xirtamatrix »

Jumach wrote:I get an error on line 93 :RTSCamera* camera = new RTSCamera(device,smgr->getRootSceneNode(),smgr,-1,100.0f,10.0f,10.0f);

The error says it is an undefined reference...Did I put the rtscamera.h file in the wrong place? Why am I getting this error?

Yes, this could mean it's not finding the rtscamera.h file. Which OS you're using? which IDE? would be easier to tell if you post the actual error (just copy/paste)
to live, is natural; to die, is not!
Post Reply