Help on 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.
Post Reply
JFT
Posts: 11
Joined: Mon Feb 02, 2009 5:32 pm

Help on RTS Camera

Post by JFT »

Hi,
I tried to use some code from cmd Kevins RTS Camera and put it together with some own code, to get it working again with Version 1.5.
It compiles, but the Camera is not doing what it is supposed to do.
Maybe someone can see the mistake(s):

Camera.h:

Code: Select all

#ifndef __RTSCAMERA_H__
#define __RTSCAMERA_H__

#include <irrlicht.h>
#include <ICameraSceneNode.h>
#include "MasterEventReceiver.cpp"

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






virtual ~RTSCamera();



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

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

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

  //Sets
  virtual void setRotation(const irr::core::vector3df& rotation);
  virtual void setProjectionMatrix(const irr::core::matrix4& projection, bool isOrthogonal = false);
  virtual void bindTargetAndRotation(bool bound);
  virtual bool getTargetAndRotationBinding(void) const;
  virtual void setNearValue(irr::f32 zn);
  virtual void setFarValue(irr::f32 zf);
  virtual void setAspectRatio(irr::f32 aspect);
  virtual void setFOV(irr::f32 fovy);
  virtual void setUpVector(const irr::core::vector3df& pos);
  virtual void setProjectionMatrix(const irr::core::matrix4& projection);
  //virtual void setPosition(const irr::core::vector3df& newpos);
  virtual void setTarget(const irr::core::vector3df& newpos);

  //Helper Functions
  void pointCameraAtNode(ISceneNode* selectednode);
  void setMinZoom(irr::f32 amount);
  void setMaxZoom(irr::f32 amount);

  //Type Return
  virtual irr::scene::ESCENE_NODE_TYPE getType() { return irr::scene::ESNT_CAMERA; }

protected:
  //Properties
  irr::core::vector3df Target;
  irr::core::vector3df UpVector;
  irr::core::matrix4 Projection;
  irr::core::matrix4 View;
  irr::scene::SViewFrustum ViewArea;
  irr::core::aabbox3d<irr::f32> BBox;
  bool InputReceiverEnabled;
  irr::core::dimension2d<irr::f32> screenDim;
  irr::f32 Fovy;      //Field of view, in radians.
  irr::f32 Aspect;      //Aspect ratio.
  irr::f32 ZNear;      //Value of the near view-plane.
  irr::f32 ZFar;      //Z-value of the far view-plane.

  void recalculateProjectionMatrix();
  void recalculateViewArea();

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

  enum MOUSE_BUTTON
    {
    MOUSE_BUTTON_LEFT,
    MOUSE_BUTTON_MIDDLE,
    MOUSE_BUTTON_RIGHT
    };


 void Movement();


};

#endif

Camera.cpp:

Code: Select all

#include "Camera.h"



using namespace irr;

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

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

  Fovy = core::PI / 2.5f;
  Aspect = 4.0f / 3.0f;
  ZNear = 1.0f;
  ZFar = 3000.0f;

  video::IVideoDriver* d = smgr->getVideoDriver();
  if (d)
    {
    screenDim.Width = (f32)d->getCurrentRenderTargetSize().Width;
    screenDim.Height = (f32)d->getCurrentRenderTargetSize().Height;
    Aspect = screenDim.Width / screenDim.Height;
    }

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

  //allKeysUp();
  //allMouseKeysUp();

  recalculateProjectionMatrix();
  recalculateViewArea();

  smgr->setActiveCamera(this);
}


RTSCamera::~RTSCamera()
{
}
bool TargetAndRotationAreBound = false;

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

  ISceneNode* selectednode;
  core::dimension2d<s32> ssize = SceneManager->getVideoDriver()->getScreenSize();

  if(event.EventType == EET_MOUSE_INPUT_EVENT)
    {
    switch(event.MouseInput.Event)
      {
      case EMIE_LMOUSE_PRESSED_DOWN:
        selectednode = SceneManager->
          getSceneCollisionManager()->
          getSceneNodeFromScreenCoordinatesBB(
                                              device->getCursorControl()->getPosition(),0xFF,false);

        if(selectednode)
          pointCameraAtNode(selectednode);
        else
          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:
        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;
      }
    return true;
    }

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

  return false;
}

void RTSCamera::OnRegisterSceneNode()
{
  video::IVideoDriver* driver = SceneManager->getVideoDriver();
  if (!driver)
    return;

  if (SceneManager->getActiveCamera() == this)
    {
    screenDim.Width = (f32)driver->getCurrentRenderTargetSize().Width;
    screenDim.Height = (f32)driver->getCurrentRenderTargetSize().Height;

    driver->setTransform(video::ETS_PROJECTION,Projection);

    //If UpVector and Vector to Target are the same, we have a problem.
    //Correct it.
    core::vector3df pos = getAbsolutePosition();
    core::vector3df tgtv = Target - pos;
    tgtv.normalize();

    core::vector3df up = UpVector;
    up.normalize();

    f32 dp = tgtv.dotProduct(up);
    if ((dp > -1.0001f && dp < -0.9999f) || (dp < 1.0001f && dp > 0.9999f))
      up.X += 1.0f;

    View.buildCameraLookAtMatrixLH(pos,Target,up);
    recalculateViewArea();

    SceneManager->registerNodeForRendering(this,scene::ESNRP_CAMERA);
    }

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

void RTSCamera::render()
{
  video::IVideoDriver* driver = SceneManager->getVideoDriver();
  if (!driver)
    return;

  driver->setTransform(video::ETS_VIEW,View);
}

void RTSCamera::OnPostRender(u32 timeMs)
{
//  animate();

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

  //TODO Add Animators
}

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

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

const core::aabbox3d<f32>& RTSCamera::getBoundingBox() const
{
  return BBox;
}

const core::matrix4& RTSCamera::getProjectionMatrix() const
{
  return Projection;
}

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

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

const core::matrix4& RTSCamera::getViewMatrix() const
{
  return 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::setRotation(const core::vector3df& rotation)
{
	if(TargetAndRotationAreBound)
		Target = getAbsolutePosition() + rotation.rotationToDirection();

	ISceneNode::setRotation(rotation);
}

void RTSCamera::setProjectionMatrix(const irr::core::matrix4& projection, bool isOrthogonal)
{
	IsOrthogonal = isOrthogonal;
	ViewArea.Matrices [ video::ETS_PROJECTION ] = projection;
	ViewArea.setTransformState ( video::ETS_PROJECTION );
}

void RTSCamera::bindTargetAndRotation(bool bound)
{
	TargetAndRotationAreBound = bound;
}

bool RTSCamera::getTargetAndRotationBinding(void) const
{
	return TargetAndRotationAreBound;
}

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 core::vector3df& pos)
{
  UpVector = pos;
}

void RTSCamera::setProjectionMatrix(const core::matrix4& projection)
{
  Projection = 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::pointCameraAtNode(ISceneNode* selectednode)
{
  core::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()
{
  Projection.buildProjectionMatrixPerspectiveFovLH(Fovy,Aspect,ZNear,ZFar);
}

void RTSCamera::recalculateViewArea()
{
  core::matrix4 mat = Projection * View;
  ViewArea = scene::SViewFrustum(mat);

  ViewArea.cameraPosition = getAbsolutePosition();
  ViewArea.recalculateBoundingBox();
}



void RTSCamera::Movement(){
    const f32 MOVEMENT_SPEED = 500.f;

    const f32 frameDeltaTime = 0.05 ;
    core::vector3df pos = getUpVector();
    core::vector3df target = getTarget();
   if (MousePos.X < 0.1){



        pos.X -= MOVEMENT_SPEED*frameDeltaTime;
        target.X -= MOVEMENT_SPEED*frameDeltaTime;
        }
    else if (MousePos.X > 0.90){
          pos.X += MOVEMENT_SPEED*frameDeltaTime;
          target.X += MOVEMENT_SPEED*frameDeltaTime;
        }

    if (MousePos.Y < 0.10) {
        pos.Y -= MOVEMENT_SPEED*frameDeltaTime;
        target.Y -= MOVEMENT_SPEED*frameDeltaTime;
        }
    else if (MousePos.Y > 0.90) {
            pos.Y += MOVEMENT_SPEED*frameDeltaTime;
            target.Y += MOVEMENT_SPEED*frameDeltaTime;
        }



    setUpVector(vector3df(pos.X,pos.Y,pos.Z));
    setTarget(vector3df(pos.X,pos.Y,pos.Z));
}


Thanks for helping!!

Sorry for bad english.

MfG

JFT

Edit:
I use it like this:
in main.cpp:

Code: Select all

RTSCamera*camera = new RTSCamera(device,node,smgr,-1);
    camera->setPosition(vector3df(600,600,600));
rogerborg
Admin
Posts: 3590
Joined: Mon Oct 09, 2006 9:36 am
Location: Scotland - gonnae no slag aff mah Engleesh
Contact:

Re: Help on RTS Camera

Post by rogerborg »

JFT wrote:It compiles, but the Camera is not doing what it is supposed to do.
Help us to help you. What is it doing? What is it supposed to do?
Please upload candidate patches to the tracker.
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
JFT
Posts: 11
Joined: Mon Feb 02, 2009 5:32 pm

Post by JFT »

Sorry, I want to use the camera as a Real Time Strategy camera.

For Example: If the mouse courser is on the right side the camera should move to the right.

But when i use it is doing nothing....
And if i click on a mesh or the cameras target and position changes right at the side of the mesh. But only the first time i click afterwards it does nothing...

Hope that helped.

Sorry for bad english
Post Reply