That video is a very good example except i do want it with the keyboard
So what is happening is the camera's look at is being controlled by the mouse and that is all fine and done, all working good and don't need to touch it.
The problem is moving the position of the camera.
What i would like to happen is for the camera to free roam around the whole area of the sphere like you were walking on it.
at the moment what will happen is that if you press one way (say a and d), it will circle the centre all fine but then when you want to go up and down it will depend on there it is.
if it is right in front of the objects then it's all good and will rotate properly over and create a full circle.
But if you move 90 degrees to that then the camera's position just rotates around itself and not over the objects. because it is locked to the axises.
it's really hard to explain in text and i don't really know anything else that uses something like it, my friend pointed out that it would be simillar to the start of populus when you are looking at the globe.
SO what is happening at the moment, if you are looking at a sphere, in an essence if you are on the equator you do a full circle of the radius but if you move a bit further down, say to the antartic, then if you hit left and right again then it will still go around in that direction only it is a much smaller circle. as it is still thinking it is using the axis for the equator as it's rotation.
What i want is that if you hit right then you would move right, then when it stopped it would in a sence, reset the axises so then if we hit up it would roll over the top of the globe, and then if i hit left anywhere it would still perform a full circle the size of the radius rather then just looking around the centre axis and doing little circle.
i don't know if this helps you to understand my problem or just makes it more confusing
anyway enjoy
Rotating around an arbitrary axis
-
- Admin
- Posts: 3590
- Joined: Mon Oct 09, 2006 9:36 am
- Location: Scotland - gonnae no slag aff mah Engleesh
- Contact:
I am absolutely baffled as to how the behaviour that you are describing is different from that in the compilable, runnable sample app that I have already posted.
Can you please do yourself a favour and actually compile and run the following code. You can just replace one of the SDK examples with this source and it should build and run.
Can you please do yourself a favour and actually compile and run the following code. You can just replace one of the SDK examples with this source and it should build and run.
Code: Select all
#include <irrlicht.h>
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
#pragma comment(lib, "Irrlicht.lib")
// Standard event receiver
class MyEventReceiver : public IEventReceiver
{
public:
virtual bool OnEvent(const SEvent& event)
{
if (event.EventType == irr::EET_KEY_INPUT_EVENT)
KeyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown;
return false;
}
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:
bool KeyIsDown[KEY_KEY_CODES_COUNT];
};
void rotateVectorAroundAxis(vector3df & vector, const vector3df & axis, f32 radians)
{
quaternion MrQuaternion;
matrix4 MrMatrix;
(void)MrQuaternion.fromAngleAxis(radians, axis);
MrQuaternion.getMatrix(MrMatrix);
MrMatrix.rotateVect(vector);
}
int main()
{
MyEventReceiver receiver;
IrrlichtDevice *device =
createDevice( video::EDT_OPENGL, dimension2d<s32>(640, 480), 32,
false, false, false, &receiver);
IVideoDriver* driver = device->getVideoDriver();
ISceneManager* smgr = device->getSceneManager();
// Place some random billboards to give us something to look at.
for(int i = 0; i < 100; ++i)
{
IBillboardSceneNode * bill = smgr->addBillboardSceneNode();
bill->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR );
bill->setMaterialTexture(0, driver->getTexture("../../media/particle.bmp"));
bill->setMaterialFlag(video::EMF_LIGHTING, false);
bill->setPosition(vector3df((f32)(rand()%500) - 250.f, (f32)(rand()%500) - 250.f, (f32)(rand()%500) - 250.f));
}
ISceneNode * targetNode = smgr->addAnimatedMeshSceneNode(smgr->getMesh("../../media/dwarf.x"));
targetNode->setMaterialFlag(video::EMF_LIGHTING, false);
ICameraSceneNode * camera = smgr->addCameraSceneNode();
f32 orbitDistance = 100.f;
u32 then = device->getTimer()->getTime();
while(device->run())
{
u32 const now = device->getTimer()->getTime();
const f32 moveSpeed = (f32)(now - then) / 500.f; // Let's rotate at a framerate independent speed
then = now;
// Work out the 3 axes for the camera.
vector3df forward = (camera->getTarget() - camera->getAbsolutePosition()).normalize();
vector3df up = camera->getUpVector();
vector3df right = forward.crossProduct(up);
// yaw around the up axis
if(receiver.IsKeyDown(KEY_KEY_D))
rotateVectorAroundAxis(forward, up, -moveSpeed);
else if(receiver.IsKeyDown(KEY_KEY_A))
rotateVectorAroundAxis(forward, up, +moveSpeed);
// pitch around the right axis (we need to change both forward AND up)
if(receiver.IsKeyDown(KEY_KEY_W))
{
rotateVectorAroundAxis(forward, right, -moveSpeed);
rotateVectorAroundAxis(up, right, -moveSpeed);
}
else if(receiver.IsKeyDown(KEY_KEY_S))
{
rotateVectorAroundAxis(forward, right, +moveSpeed);
rotateVectorAroundAxis(up, right, +moveSpeed);
}
// roll around the forward axis
if(receiver.IsKeyDown(KEY_KEY_Q))
rotateVectorAroundAxis(up, forward, +moveSpeed);
else if(receiver.IsKeyDown(KEY_KEY_E))
rotateVectorAroundAxis(up, forward, -moveSpeed);
if(receiver.IsKeyDown(KEY_KEY_Z))
orbitDistance = max_(10.f, orbitDistance - moveSpeed * 100.f);
else if(receiver.IsKeyDown(KEY_KEY_X))
orbitDistance = min_(200.f, orbitDistance + moveSpeed * 100.f);
// Move BACK up the forward axis of the camera to place it in its orbit.
camera->setPosition(targetNode->getAbsolutePosition() - (forward * orbitDistance));
// Point the camera at the target node, and align its up axis correctly.
camera->setTarget(targetNode->getAbsolutePosition());
camera->setUpVector(up);
driver->beginScene(true, true, SColor(255,100,101,140));
smgr->drawAll();
driver->endScene();
}
device->drop();
return 0;
}
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
Rogerborg, thanks very much for posting this code. I had just finished my first example skydome program using irrlicht, and was looking for exactly this type of 360 all axis rotation camera about the origin. It works perfectly.
One thing I have not investigated yet is using mouse/joystick control in addition to keyboard control for rotation. Is that a straightforward change to the code or do I need to check for the mouse/joystick for each axis and direction?
Thx!
One thing I have not investigated yet is using mouse/joystick control in addition to keyboard control for rotation. Is that a straightforward change to the code or do I need to check for the mouse/joystick for each axis and direction?
Thx!
I guess there's probably a thousand examples showing this behaviour for mouseinput aswell, but why not stick to this example... and that is essentially what I'm trying to do...
I made a FPS camera, orienting my code on the irrlicht FPS camera, but soon I had to realize that it gives me the gimbal lock behaviour, so I remembered this thread and thought I give it a try with quaternions... to be honest, I heard the term a lot, but I haven't even checked a wiki for its meaning, thus I have no understanding of what I'm doing... (<-The usual case)... ok... unacceptable actually... I do some reading now... WhoOo... Question N°2 Can anyone try to explain what an extension to real numbers is supposed to mean ?
What I have so far is the cursor delta for each frame:
pseudo code:
one of the obvious problems is, that I dont have a keyInput to wait for, instead I have a mouse delta... I compiled rogerborgs example and tested what happens if I hold up + right same time, and it did what it's supposed to do, so I thought since I have no event seperating each axis I'll have to do it all at the same time... as you can see, I uncommented a few to see what's going on with each of them seperatly... anyway it's not really working, best I got was rotation on X and Y as expected but strange & undesired banking...
Well basically ... help !!! and a big thank you...
I'd need a few more years or a lot more patience...
I made a FPS camera, orienting my code on the irrlicht FPS camera, but soon I had to realize that it gives me the gimbal lock behaviour, so I remembered this thread and thought I give it a try with quaternions... to be honest, I heard the term a lot, but I haven't even checked a wiki for its meaning, thus I have no understanding of what I'm doing... (<-The usual case)... ok... unacceptable actually... I do some reading now... WhoOo... Question N°2 Can anyone try to explain what an extension to real numbers is supposed to mean ?
What I have so far is the cursor delta for each frame:
pseudo code:
Code: Select all
gui::ICursorControl* cursor;
...
cursor = device->getCursorControl();
...
event Receiver:
...
if (event.MouseInput.Event == EMIE_MOUSE_MOVED)
{
CursorPos = cursor->getRelativePosition();
}
...
...
core::vector2df delta = CursorPos - core::vector2df(0.5,0.5);
cursor->setPosition(core::vector2df(0.5,0.5));
...
core::vector3df forwardD = cam->getTarget() - camPos;
forwardD.normalize();
core::vector3df upD = cam->getUpVector();
core::vector3df rightD = forwardD.crossProduct(upD);
...
...
//here it starts getting really confusing for me
...
...
rotateVectorAroundAxis(forwardD, upD, delta.X);
//rotateVectorAroundAxis(forwardD, rightD, delta.Y*-1);
//rotateVectorAroundAxis(upD, rightD, delta.Y*-1);
//rotateVectorAroundAxis(upD, forwardD, 0.0);
// And re-orient the camera to face along the foward and up axes.
camera->setTarget(camPos + forwardD);
camera->setUpVector(upD);
Well basically ... help !!! and a big thank you...
I'd need a few more years or a lot more patience...
strange... when I'm doing it in rogerborgs example it works just fine... couldn't say aynthing else... It feels like those puzzles with 2 pictures that look exactly the same on the first look and you have to find the 5 detail differences...
anyway, the following seems to work perfect and does the described with mouse input...
...und sie wussten nicht was sie taten...
anyway, the following seems to work perfect and does the described with mouse input...
Code: Select all
#include <irrlicht.h>
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
#pragma comment(lib, "Irrlicht.lib")
gui::ICursorControl* cursor;
core::position2d<f32> CursorPos;
// Standard event receiver
class MyEventReceiver : public IEventReceiver
{
public:
virtual bool OnEvent(const SEvent& event)
{
if (event.EventType == irr::EET_KEY_INPUT_EVENT)
{
KeyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown;
}
if (event.EventType == EET_MOUSE_INPUT_EVENT)
{
if (event.MouseInput.Event == EMIE_MOUSE_MOVED)
{
CursorPos = cursor->getRelativePosition();
}
}
return false;
}
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:
bool KeyIsDown[KEY_KEY_CODES_COUNT];
};
void rotateVectorAroundAxis(vector3df & vector, const vector3df & axis, f32 radians)
{
quaternion MrQuaternion;
matrix4 MrMatrix;
(void)MrQuaternion.fromAngleAxis(radians, axis);
MrQuaternion.getMatrix(MrMatrix,core::vector3df(0,0,0));
MrMatrix.rotateVect(vector);
}
int main()
{
MyEventReceiver receiver;
IrrlichtDevice *device =
createDevice( video::EDT_OPENGL, dimension2d<u32>(640, 480), 32,
false, false, false, &receiver);
IVideoDriver* driver = device->getVideoDriver();
ISceneManager* smgr = device->getSceneManager();
cursor = device->getCursorControl();
// Place some random billboards to give us something to look at.
for(int i = 0; i < 100; ++i)
{
scene::IBillboardSceneNode * bill = smgr->addBillboardSceneNode();
bill->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR );
bill->setMaterialTexture(0, driver->getTexture("../../media/particle.bmp"));
bill->setMaterialFlag(video::EMF_LIGHTING, false);
bill->setMaterialFlag(video::EMF_ZBUFFER, false);
bill->setPosition(vector3df((f32)(rand()%500) - 250.f, (f32)(rand()%500) - 250.f, (f32)(rand()%500) - 250.f));
}
ICameraSceneNode * camera = smgr->addCameraSceneNode();
camera->setPosition(core::vector3df(5,0,1));
u32 then = device->getTimer()->getTime();
while(device->run())
{
u32 const now = device->getTimer()->getTime();
const f32 moveSpeed = (f32)(now - then) / 500.f; // Let's rotate at a framerate independent speed
then = now;
// Work out the 3 axes for the camera.
vector3df forward = (camera->getTarget() - camera->getAbsolutePosition()).normalize();
vector3df up = camera->getUpVector();
vector3df right = forward.crossProduct(up);
core::vector2df delta = CursorPos - core::vector2df(0.5,0.5);
cursor->setPosition(core::vector2df(0.5,0.5));
rotateVectorAroundAxis(forward, up, delta.X);
rotateVectorAroundAxis(forward, right, delta.Y*-1);
rotateVectorAroundAxis(up, right, delta.Y*-1);
// And re-orient the camera to face along the foward and up axes.
camera->setTarget(camera->getAbsolutePosition() + forward);
camera->setUpVector(up);
driver->beginScene(true, true, SColor(255,100,101,140));
smgr->drawAll();
driver->endScene();
}
device->drop();
return 0;
}
well, I still havent't solved the puzzle... I'm already googling "Quaternions for dummies"...
I animated the camera in the above example with a fly circle animator and the result was a pole flipping camera again... Do I have to move the target in a flycircle aswell ?
Seems unlogical because the forward axis and up axis is worked out on each frame and the target is set to camera position + forward before being alligned to forward and up, so it should work in a flycircle aswell, shouldn't it ?
well, to phrase it, it works fine as long as the camera isn't moving, and to make myself more clear I am not trying to get an orbiting camera but a camera that rotates around itself...
thanks again
EDIT:
I think I got it right & the example actually covers it all...
well, at least I added mouseinput...
http://irrlicht.sourceforge.net/phpBB2/ ... highlight=
I animated the camera in the above example with a fly circle animator and the result was a pole flipping camera again... Do I have to move the target in a flycircle aswell ?
Seems unlogical because the forward axis and up axis is worked out on each frame and the target is set to camera position + forward before being alligned to forward and up, so it should work in a flycircle aswell, shouldn't it ?
well, to phrase it, it works fine as long as the camera isn't moving, and to make myself more clear I am not trying to get an orbiting camera but a camera that rotates around itself...
thanks again
EDIT:
I think I got it right & the example actually covers it all...
well, at least I added mouseinput...
is actually perfectly right and just my inability to think 3 dimensional at times. Remembering my days with the flightsim I figured it's the way it's supposed to be... This thread has it covered aswell btw:zillion42 wrote:...undesired banking...
http://irrlicht.sourceforge.net/phpBB2/ ... highlight=