I would like to animate an object from the top of the screen to the bottom of the screen. How can I get the coordinates of a 3d point in the top of the screen and the coordinates of a 3d point in the bottom?
Thanks in advance
[]s
screen coordinates, from the camera point of view
-
- Admin
- Posts: 3590
- Joined: Mon Oct 09, 2006 9:36 am
- Location: Scotland - gonnae no slag aff mah Engleesh
- Contact:
You'll also need to decide a depth / distance at which to place your 3d point, since there's no direct mapping between a 2d point and a 3d point.
I'd suggest something like:
You'll need to initialise topScreenPosition and bottomScreenPosition with appropriate 2d positions. Apologies if it doesn't doesn't compile cleanly; I'm in lazy Sunday morning mode.
I'd suggest something like:
Code: Select all
enum { DRAW_DISTANCE = 100.f /* adjust empirically based on the desired model size on screen */ };
core::position2di topScreenPosition(/* set the desired top screen position */);
core::position2di bottomScreenPosition(/* set the desired bottom screen position */);
core::line3df topRay = smgr->getSceneCollisionManager()->getRayFromScreenCoordinates(
topScreenPosition, smgr->getActiveCamera());
core::line3df bottomRay = smgr->getSceneCollisionManager()->getRayFromScreenCoordinates(
bottomScreenPosition, smgr->getActiveCamera());
core::vector3df top3DPosition = topRay.start + (topRay.getVector().normalize() * DRAW_DISTANCE);
core::vector3df bottom3DPosition = bottomRay.start + (bottomRay.getVector().normalize() * DRAW_DISTANCE);
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 a lot for replying my message. I tried what you suggested, but it didn't work... Could I have done something wrong?
I have a screen resolution of 720 x 480. I have used the following piece of code:
{
smgr->setActiveCamera(camera);
enum { DRAW_DISTANCE = 100 /* adjust empirically based on the desired model size on screen */ };
core::position2di topScreenPosition(0, 0/* set the desired top screen position */);
core::position2di bottomScreenPosition(700,400/* set the desired bottom screen position */);
core::line3df topRay = smgr->getSceneCollisionManager()->getRayFromScreenCoordinates(
topScreenPosition, smgr->getActiveCamera());
core::line3df bottomRay = smgr->getSceneCollisionManager()->getRayFromScreenCoordinates(
bottomScreenPosition, smgr->getActiveCamera());
core::vector3df top3DPosition = topRay.start + (topRay.getVector().normalize() * DRAW_DISTANCE);
core::vector3df bottom3DPosition = bottomRay.start + (bottomRay.getVector().normalize() * DRAW_DISTANCE);
printf("%.2f %.2f %.2f <-> %.2f %.2f %.2f \n",
top3DPosition.X, top3DPosition.Y, top3DPosition.Z,
bottom3DPosition.X, bottom3DPosition.Y, bottom3DPosition.Z);
fflush(stdout);
myNode->anim2 = smgr->createFlyStraightAnimator(
core::vector3df(0, 100, 50), core::vector3df(0, -100, 50),
//top3DPosition, bottom3DPosition,
4000, true);
myNode->addAnimator(myNode->anim2);
myNode->anim2->drop();
}
My camera is at (0,0,-300) pointing to (0,0,0):
camera = smgr->addCameraSceneNode(0, core::vector3df(0, 0, -300), core::vector3df(0, 0, 0));
I was expecting my node to animate from (0,0) to (700,400), in screen coordinates, but take a look at the values of top and bottom position, after code is executed:
bottom: -0.33 0.33 -200.00
top: 0.31 -0.22 -200.00
The Z coordinate seems correct, but X and Y are too small... The object just stay stopped at screen center.
It seems it lacks the multiplication for some factor, but I am a bit confused, because Z coordinate is right... Any idea?
Thanks a lot for replying my message. I tried what you suggested, but it didn't work... Could I have done something wrong?
I have a screen resolution of 720 x 480. I have used the following piece of code:
{
smgr->setActiveCamera(camera);
enum { DRAW_DISTANCE = 100 /* adjust empirically based on the desired model size on screen */ };
core::position2di topScreenPosition(0, 0/* set the desired top screen position */);
core::position2di bottomScreenPosition(700,400/* set the desired bottom screen position */);
core::line3df topRay = smgr->getSceneCollisionManager()->getRayFromScreenCoordinates(
topScreenPosition, smgr->getActiveCamera());
core::line3df bottomRay = smgr->getSceneCollisionManager()->getRayFromScreenCoordinates(
bottomScreenPosition, smgr->getActiveCamera());
core::vector3df top3DPosition = topRay.start + (topRay.getVector().normalize() * DRAW_DISTANCE);
core::vector3df bottom3DPosition = bottomRay.start + (bottomRay.getVector().normalize() * DRAW_DISTANCE);
printf("%.2f %.2f %.2f <-> %.2f %.2f %.2f \n",
top3DPosition.X, top3DPosition.Y, top3DPosition.Z,
bottom3DPosition.X, bottom3DPosition.Y, bottom3DPosition.Z);
fflush(stdout);
myNode->anim2 = smgr->createFlyStraightAnimator(
core::vector3df(0, 100, 50), core::vector3df(0, -100, 50),
//top3DPosition, bottom3DPosition,
4000, true);
myNode->addAnimator(myNode->anim2);
myNode->anim2->drop();
}
My camera is at (0,0,-300) pointing to (0,0,0):
camera = smgr->addCameraSceneNode(0, core::vector3df(0, 0, -300), core::vector3df(0, 0, 0));
I was expecting my node to animate from (0,0) to (700,400), in screen coordinates, but take a look at the values of top and bottom position, after code is executed:
bottom: -0.33 0.33 -200.00
top: 0.31 -0.22 -200.00
The Z coordinate seems correct, but X and Y are too small... The object just stay stopped at screen center.
It seems it lacks the multiplication for some factor, but I am a bit confused, because Z coordinate is right... Any idea?
-
- Admin
- Posts: 3590
- Joined: Mon Oct 09, 2006 9:36 am
- Location: Scotland - gonnae no slag aff mah Engleesh
- Contact:
Ah, excuse me, I forgot that the camera won't have the correct matrices until after it's been updated. This is a gotcha that catches a lot of people out.
The trick is to force an update before you use it to calculate the ray. It's a but esoteric, but I know that all the necessary calculations are called in OnRegisterSceneNode(), so we can just call that:
Complete sample app:
The trick is to force an update before you use it to calculate the ray. It's a but esoteric, but I know that all the necessary calculations are called in OnRegisterSceneNode(), so we can just call that:
Code: Select all
ICameraSceneNode * camera = smgr->addCameraSceneNode(0, core::vector3df(0,-40,0), core::vector3df(0,0,0));
camera->OnRegisterSceneNode();
Code: Select all
#include <irrlicht.h>
using namespace irr;
#pragma comment(lib, "Irrlicht.lib")
int main()
{
IrrlichtDevice *device =
createDevice(video::EDT_OPENGL, core::dimension2d<s32>(640, 480), 32, false);
video::IVideoDriver* driver = device->getVideoDriver();
scene::ISceneManager* smgr = device->getSceneManager();
scene::ICameraSceneNode * camera = smgr->addCameraSceneNode(0, core::vector3df(0,-40,0), core::vector3df(0,0,0));
camera->OnRegisterSceneNode();
scene::IBillboardSceneNode * node = smgr->addBillboardSceneNode();
node->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR );
node->setMaterialTexture(0, driver->getTexture("../../media/particle.bmp"));
node->setMaterialFlag(video::EMF_LIGHTING, false);
enum { DRAW_DISTANCE = 100 };
core::position2di topScreenPosition(driver->getScreenSize().Width / 2, 0);
core::position2di bottomScreenPosition(driver->getScreenSize().Width / 2,
driver->getScreenSize().Height);
core::line3df topRay = smgr->getSceneCollisionManager()->getRayFromScreenCoordinates(
topScreenPosition, smgr->getActiveCamera());
core::line3df bottomRay = smgr->getSceneCollisionManager()->getRayFromScreenCoordinates(
bottomScreenPosition, smgr->getActiveCamera());
core::vector3df top3DPosition = topRay.start + (topRay.getVector().normalize() * DRAW_DISTANCE);
core::vector3df bottom3DPosition = bottomRay.start + (bottomRay.getVector().normalize() * DRAW_DISTANCE);
scene::ISceneNodeAnimator * anim = smgr->createFlyStraightAnimator(top3DPosition,
bottom3DPosition,
4000, true);
node->addAnimator(anim);
anim->drop();
while(device->run())
{
driver->beginScene(true, true, video::SColor(0,100,100,100));
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
Now it worked fine! Thanks a lot!!
Just to understand a little better what I am doing, may you tell me what exactly this line means?
core::line3df topRay = smgr->getSceneCollisionManager()->getRayFromScreenCoordinates(
topScreenPosition, smgr->getActiveCamera());
Is it getting an horizontal line that passes by screen coordinate topScreenPosition? Or is it a ray trace, from camera's position to screen coordinates?
Would I be able to use the same trick to perform an animation from the left of the screen to the right?
Just to understand a little better what I am doing, may you tell me what exactly this line means?
core::line3df topRay = smgr->getSceneCollisionManager()->getRayFromScreenCoordinates(
topScreenPosition, smgr->getActiveCamera());
Is it getting an horizontal line that passes by screen coordinate topScreenPosition? Or is it a ray trace, from camera's position to screen coordinates?
Would I be able to use the same trick to perform an animation from the left of the screen to the right?
-
- Admin
- Posts: 3590
- Joined: Mon Oct 09, 2006 9:36 am
- Location: Scotland - gonnae no slag aff mah Engleesh
- Contact:
Are you familiar with view frustums?mvalle wrote: core::line3df topRay = smgr->getSceneCollisionManager()->getRayFromScreenCoordinates(
topScreenPosition, smgr->getActiveCamera());
Is it getting an horizontal line that passes by screen coordinate topScreenPosition? Or is it a ray trace, from camera's position to screen coordinates?
That (particular) calculation creates a ray that goes from the camera position, out along the centre of the top plane of the view frustum. Any point along that ray will appear to be at the top of the screen.
Similarly, the ray from bottomScreenPosition goes out along the bottom plane of the view frustum.
Sure, just change the co-ordinates of the two points. Notice that rather than hardwiring them, I've used driver->getScreenSize(), so to go from the centre of the left side to the centre of the right side, your two points would be:mvalle wrote:Would I be able to use the same trick to perform an animation from the left of the screen to the right?
Code: Select all
core::position2di startPosition(0, driver->getScreenSize().Height / 2);
core::position2di endPosition(driver->getScreenSize().Width, driver->getScreenSize().Height / 2);
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