Modified third person camera troubles
Modified third person camera troubles
Hey everyone,
I recently wanted a third person camera and attempted an update version of keless' camera based on ICameraSceneNode and IEventReceiver. However for the life of me I cannot get this thing to link. I keep getting undefined reference to ICameraSceneNode::setTarget() errors. Any ideas?
Source code: http://pastebin.com/f4351bca3
Thanks!
- Alec
I recently wanted a third person camera and attempted an update version of keless' camera based on ICameraSceneNode and IEventReceiver. However for the life of me I cannot get this thing to link. I keep getting undefined reference to ICameraSceneNode::setTarget() errors. Any ideas?
Source code: http://pastebin.com/f4351bca3
Thanks!
- Alec
Modified third person camera troubles
Hi,
The problem is that setTarget method is "pure virtual method" one, declared in the ICameraSceneNode class. Thus you can not call it from your's derived class.
Also my compiler issued such a warning :
warning C4584: 'ThirdPersonCamera' : base-class 'irr::IEventReceiver' is already a base-class of 'irr::scene::ICameraSceneNode'.
The problem is that setTarget method is "pure virtual method" one, declared in the ICameraSceneNode class. Thus you can not call it from your's derived class.
Also my compiler issued such a warning :
warning C4584: 'ThirdPersonCamera' : base-class 'irr::IEventReceiver' is already a base-class of 'irr::scene::ICameraSceneNode'.
So I suppose I should have to reimplement that function; and I didnt realize ICameraSceneNode was already doing multiple-inheritance with IEventReceiver, so it should be safe to just overload OnEvent.
[Edit]
I have no idea how I would ago about rewriting that function and frustrated by the fact that I cant use it from a derived class. Looking through CCameraSceneNode.cpp/h in the irrlicht source code didnt give me much insight.
[Edit]
I have no idea how I would ago about rewriting that function and frustrated by the fact that I cant use it from a derived class. Looking through CCameraSceneNode.cpp/h in the irrlicht source code didnt give me much insight.
I'm still not quite clear on what your suggesting. I attempt this:
But that didnt solve the problem.
Code: Select all
void ThirdPersonCamera::setTarget(const vector3df &pos)
{
ICameraSceneNode::setTarget(pos);
}
-
- Admin
- Posts: 3590
- Joined: Mon Oct 09, 2006 9:36 am
- Location: Scotland - gonnae no slag aff mah Engleesh
- Contact:
Uh...
It appears to assume that ICameraSceneNode provides a full camera implementation. That's no longer correct (was it ever?). If you want to do that now, you'll either have to base your camera on CCameraSceneNode, or encapsulate one.
I don't know what vintage that code it, but it's certainly not valid with Irrlicht 1.4+.koto wrote:The problem is that setTarget method is "pure virtual method" one, declared in the ICameraSceneNode class. Thus you can not call it from your's derived class.
It appears to assume that ICameraSceneNode provides a full camera implementation. That's no longer correct (was it ever?). If you want to do that now, you'll either have to base your camera on CCameraSceneNode, or encapsulate one.
Please upload candidate patches to the tracker.
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
-
- Admin
- Posts: 3590
- Joined: Mon Oct 09, 2006 9:36 am
- Location: Scotland - gonnae no slag aff mah Engleesh
- Contact:
But you'd still have to implement all the other pure virtual methods of ICameraSceneNode. Easier to just encapsulate a CCameraSceneNode.
Actually, I wouldn't bother doing it as a scene node at all: I'd just call the body of ThirdPersonCamera::OnRegisterSceneNode() from my main loop, but since we're 'fixing' ThirdPersonCamera...
Actually, I wouldn't bother doing it as a scene node at all: I'd just call the body of ThirdPersonCamera::OnRegisterSceneNode() from my main loop, but since we're 'fixing' ThirdPersonCamera...
Code: Select all
#include <irrlicht.h>
#ifdef _IRR_WINDOWS_
#pragma comment(lib, "Irrlicht.lib")
#endif
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
// Note: This is based on ISceneNode, NOT ICameraSceneNode, since we don't want to have to
// implement all the methods in ICameraSceneNode
class ThirdPersonCamera : public ISceneNode
{
public:
ThirdPersonCamera(
ISceneNode* child,
ISceneManager* scene,
s32 id = -1,
vector3df position = vector3df(0, 0, 0),
f32 camHeight = 80.0f,
f32 camLeash = 100.0f,
f32 camSpeed = 1.0f
) : ISceneNode(scene->getRootSceneNode(), scene, id)
{
realCamera = scene->addCameraSceneNode(this);
speed = camSpeed;
height = camHeight;
leash = camLeash;
target = child;
// Setup camera
lastTargetPos = target->getAbsolutePosition();
setPosition(lastTargetPos + vector3df(0, 20, 20));
realCamera->setTarget(lastTargetPos);
target->grab();
}
~ThirdPersonCamera()
{
target->drop();
}
void OnRegisterSceneNode()
{
vector3df myPosition = getAbsolutePosition();
const vector3df currTargetPos = target->getAbsolutePosition();
vector3df camToTarg = currTargetPos - myPosition;
// Leash is only in the X-Z plane, so only count distance using X and Z
vector2df xzDist(camToTarg.X, camToTarg.Z);
// If too far away, move camera closer
if (xzDist.getLength() > leash)
{
// Set X-Z position, move closer
vector3df camToTargOrig = vector3df( xzDist.X, 0, xzDist.Y);
camToTarg = camToTargOrig.normalize() * (camToTargOrig.getLength() - leash);
myPosition += camToTarg;
}
// Set Y position
myPosition.Y = currTargetPos.Y + height;
setPosition(myPosition);
// Look at target position
realCamera->setTarget(currTargetPos);
lastTargetPos = currTargetPos;
// Register scene node for rendering
if (IsVisible)
SceneManager->registerNodeForRendering(this);
ISceneNode::OnRegisterSceneNode();
}
void render(void) { /* noop */ }
const core::aabbox3d<f32>& ThirdPersonCamera::getBoundingBox() const
{
return realCamera->getBoundingBox();
}
ICameraSceneNode * getRealCamera(void)
{
return realCamera;
}
private:
ICameraSceneNode * realCamera;
ISceneNode* target;
vector3df lastTargetPos;
f32 height;
f32 leash;
f32 speed;
};
// I'm going to use a separate event receiver, since there's little logical reason to
// put the functionality into a camera.
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()
{
IrrlichtDevice *device =
createDevice( video::EDT_OPENGL, dimension2d<s32>(640, 480), 16,
false, false, false, 0);
IVideoDriver* driver = device->getVideoDriver();
ISceneManager* smgr = device->getSceneManager();
IAnimatedMesh* mesh = smgr->getMesh("../../media/sydney.md2");
IAnimatedMeshSceneNode* node = smgr->addAnimatedMeshSceneNode( mesh );
if (node)
{
node->setMaterialFlag(EMF_LIGHTING, false);
node->setMD2Animation ( scene::EMAT_STAND );
node->setMaterialTexture( 0, driver->getTexture("../../media/sydney.bmp") );
}
const f32 heightOffset = node->getBoundingBox().getExtent().Y - node->getBoundingBox().getCenter().Y;
node->setPosition(vector3df(1000, 0, 1000));
ThirdPersonCamera * camera = new ThirdPersonCamera(node, smgr);
MyEventReceiver eventReceiver;
device->setEventReceiver(&eventReceiver);
scene::ITerrainSceneNode* terrain = smgr->addTerrainSceneNode(
"../../media/terrain-heightmap.bmp",
0, // parent node
-1, // node id
core::vector3df(0.f, 0.f, 0.f), // position
core::vector3df(0.f, 0.f, 0.f), // rotation
core::vector3df(40.f, 4.4f, 40.f), // scale
video::SColor ( 255, 255, 255, 255 ), // vertexColor,
5, // maxLOD
scene::ETPS_17, // patchSize
4 // smoothFactor
);
terrain->setMaterialFlag(video::EMF_LIGHTING, false);
terrain->setMaterialTexture(0, driver->getTexture("../../media/terrain-texture.jpg"));
terrain->setMaterialTexture(1, driver->getTexture("../../media/detailmap3.jpg"));
terrain->setMaterialType(video::EMT_DETAIL_MAP);
terrain->scaleTexture(1.0f, 20.0f);
u32 then = device->getTimer()->getTime();
while(device->run())
{
u32 now = device->getTimer()->getTime();
f32 delta = (f32)(now - then) / 1000.f;
then = now;
if(eventReceiver.IsKeyDown(KEY_KEY_A))
node->setRotation(node->getRotation() + (vector3df(0, -180, 0) * delta));
if(eventReceiver.IsKeyDown(KEY_KEY_D))
node->setRotation(node->getRotation() + (vector3df(0, 180, 0) * delta));
if(eventReceiver.IsKeyDown(KEY_KEY_W))
{
// vector3df direction = node->getRotation().rotationToDirection(vector3df(1, 0, 0)); // Will be available in 1.5
vector3df direction(1, 0, 0); // Sydney faces +X
direction.rotateXZBy(-node->getRotation().Y); // rotateXZBy() seems bass ackwards
node->setPosition(node->getAbsolutePosition() + (direction * 100.f * delta));
}
if(eventReceiver.IsKeyDown(KEY_KEY_S))
{
// vector3df direction = node->getRotation().rotationToDirection(vector3df(1, 0, 0)); // Will be available in 1.5
vector3df direction(1, 0, 0); // Sydney faces +X
direction.rotateXZBy(-node->getRotation().Y); // rotateXZBy() seems bass ackwards
node->setPosition(node->getAbsolutePosition() + (direction * -100.f * delta));
}
node->updateAbsolutePosition();
vector3df position = node->getAbsolutePosition();
position.Y = terrain->getHeight(position.X, position.Z) + heightOffset;
node->setPosition(position);
driver->beginScene(true, true, SColor(255,100,101,140));
smgr->drawAll();
driver->endScene();
}
camera->drop();
device->drop();
return 0;
}
Last edited by rogerborg on Wed Aug 27, 2008 9:20 am, edited 1 time in total.
Please upload candidate patches to the tracker.
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
Yes I was assuming when I tried to write my implementation that it was a full implementation. Although it seems that it was intended to be more of an abstract class, am I right? But if thats the case then why would we be instantiating it for example with addCameraSceneNode()? I dont know, just a thought.rogerborg wrote: It appears to assume that ICameraSceneNode provides a full camera implementation. That's no longer correct (was it ever?). If you want to do that now, you'll either have to base your camera on CCameraSceneNode, or encapsulate one.
Yea, the original code for this class actually did it that way. Although people were suggesting that it might make more sense to make it a scene node so it could automatically update itself. Thanks a lot for your help and your code, I will be trying this out later. Perhaps it does make more sense to simply have an update() function or something and call it from the mainloop.rogerborg wrote: Actually, I wouldn't bother doing it as a scene node at all: I'd just call the body of ThirdPersonCamera::OnRegisterSceneNode() from my main loop, but since we're 'fixing' ThirdPersonCamera...
rogerborg, I tried compiling your example today and quickly discovered that it wasnt compiling. Apparently because vector3df does not have a function rotationToDirection() and I even checked the docs to confirm this.
I figured it might have been because I was running an older version of Irrlicht but that doesnt seem to be the case.
[Edit]
Well I found an SVN log entry on July 17 for revision 1416 where it's noted that your rotationToDirection() function was added. So I am assuming run this with an SVN build, and I would assume it will be availible in 1.5?
Code: Select all
[maddog39@desktop ThirdPersonCamera]$ make
g++ main.cpp -O3 -march=core2 -I/usr/include/irrlicht -lIrrlicht -lX11 -lXxf86vm -lXext -lXrandr -lGL -lGLU -o tpc
main.cpp:83: error: extra qualification ‘ThirdPersonCamera::’ on member ‘getBoundingBox’
main.cpp: In function ‘int main()’:
main.cpp:199: error: ‘const class irr::core::vector3d<float>’ has no member named ‘rotationToDirection’
main.cpp:205: error: ‘const class irr::core::vector3d<float>’ has no member named ‘rotationToDirection’
make: *** [all] Error 1
Code: Select all
[maddog39@desktop ThirdPersonCamera]$ pacman -Qi irrlicht
Name : irrlicht
Version : 1.4.1-0
URL : http://irrlicht.sourceforge.net/index.html
Licenses : zlib/libpng
Groups : None
Provides : None
Depends On : x-server zlib libpng libjpeg
Optional Deps : None
Required By : None
Conflicts With : None
Replaces : None
Installed Size : 38359.13 K
Packager : Unknown Packager
Architecture : i686
Build Date : Thu 24 Jul 2008 11:10:00 AM EDT
Install Date : Thu 24 Jul 2008 11:11:26 AM EDT
Install Reason : Explicitly installed
Install Script : No
Description : The Irrlicht Engine is an open source high performance realtime 3D engine.
Well I found an SVN log entry on July 17 for revision 1416 where it's noted that your rotationToDirection() function was added. So I am assuming run this with an SVN build, and I would assume it will be availible in 1.5?
-
- Admin
- Posts: 3590
- Joined: Mon Oct 09, 2006 9:36 am
- Location: Scotland - gonnae no slag aff mah Engleesh
- Contact:
All of the Irrlicht "I" classes are interfaces. They all contain at least one pure virtual method that needs to be implemented in a concrete class. None of them should be directly instantiatable.maddog39 wrote:Yes I was assuming when I tried to write my implementation that [ICameraSceneNode] was a full implementation. Although it seems that it was intended to be more of an abstract class, am I right? But if thats the case then why would we be instantiating it for example with addCameraSceneNode()? I dont know, just a thought.
So when you do ISceneManager::addCameraSceneNode(), it returns an ICameraSceneNode *, but it's actually a CCameraSceneNode object that's created.
Ah, I'm sorry, you're quite right. I always use the SVN trunk, and forget that most users are still on 1.4 / 1.4.1. I've corrected the sample to use rotateXZBy() instead.maddog39 wrote:rogerborg, I tried compiling your example today and quickly discovered that it wasnt compiling. Apparently because vector3df does not have a function rotationToDirection() and I even checked the docs to confirm this.
Please upload candidate patches to the tracker.
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way