As I am just a beginner of this engine, I am just studying the code in the second tutorial, Quake3Map.
I notice that a camera should be set after the node is established, so that the user can see the scene.
However, if I want to do something within this scene, what should I do?
Can a user modify objects in the camera?
-
- Posts: 126
- Joined: Sun Apr 02, 2006 1:21 am
- Location: Canada
First, I have a question for you. What exactly do you mean by "However, if I want to do something within this scene, what should I do?"
I think you mean, for example, how can you make a cube move during the scene?
Well, first let me address your point about the camera. Unless I am horribly mistaken at this very late hour, there should be no reason why you must create a camera after the node.
Your code probably looks something like:
I excluded a large portion, of course, but if I remember correctly, this is basically how the tutorials are structured.
Now, first, there is no reason why I couldn't create my camera before I created the cube, and the reason is pretty simple.
The while-loop is the render loop. Every frame, this loop is executed. So, the actual drawing is occurring at the function call smgr->drawAll();
Look back at how we created the camera and the cube scene node. They are created by the ISceneManager, thus they are also managed by the ISceneManager.
The scene manager keeps track of all your 3D data, and perceives the world from the active camera. So, as long as you set a camera before the render loop, there should be no problem.
About the second part of your question. Again, I'm not very clear on what you meant, but I'm guessing you might want something to move around. For this, remember that the render loop is called every frame. In order to move something around, it's position should be updated every frame.
So, let's just make the cube that I created move in a straight line:
(The only thing changed is in the render loop)
So the idea is to set the position of the cube to the previous position plus the amount that you want to offset it by (in this case 2).
If this didn't answer your question, then feel free to ask!
I think you mean, for example, how can you make a cube move during the scene?
Well, first let me address your point about the camera. Unless I am horribly mistaken at this very late hour, there should be no reason why you must create a camera after the node.
Your code probably looks something like:
Code: Select all
...
ISceneNode* cube = smgr->addCubeSceneNode(10.0f);
cube->setMaterialFlag(EMF_LIGHTING, false);
smgr->addCameraSceneNodeFPS();
while (device->run())
{
driver->beginScene(true, true, SColor(255, 255, 255, 255);
smgr->drawAll();
driver->endScene();
}
device->drop();
Now, first, there is no reason why I couldn't create my camera before I created the cube, and the reason is pretty simple.
The while-loop is the render loop. Every frame, this loop is executed. So, the actual drawing is occurring at the function call smgr->drawAll();
Look back at how we created the camera and the cube scene node. They are created by the ISceneManager, thus they are also managed by the ISceneManager.
The scene manager keeps track of all your 3D data, and perceives the world from the active camera. So, as long as you set a camera before the render loop, there should be no problem.
About the second part of your question. Again, I'm not very clear on what you meant, but I'm guessing you might want something to move around. For this, remember that the render loop is called every frame. In order to move something around, it's position should be updated every frame.
So, let's just make the cube that I created move in a straight line:
(The only thing changed is in the render loop)
Code: Select all
...
ISceneNode* cube = smgr->addCubeSceneNode(10.0f);
cube->setMaterialFlag(EMF_LIGHTING, false);
smgr->addCameraSceneNodeFPS();
while (device->run())
{
cube->setPosition(vector3df(cube->getAbsolutePosition().X + 2, 0, 0));
driver->beginScene(true, true, SColor(255, 255, 255, 255);
smgr->drawAll();
driver->endScene();
}
device->drop();
If this didn't answer your question, then feel free to ask!
Thanks for your reply.
I think you have corrected my concept. Now I know that the order of statements before the while loop are not very important as they are just to setup the things to be displayed.
For the "if I want to do something within this scene, what should I do?", I mean if I create a button for users to click, then after it is clicked, a new objected will be created somewhere in the scene and users are allowed to move that newly created object by drag&drop. Can Irrlicht support this kind of action? or should I use game engine instead?
I think you have corrected my concept. Now I know that the order of statements before the while loop are not very important as they are just to setup the things to be displayed.
For the "if I want to do something within this scene, what should I do?", I mean if I create a button for users to click, then after it is clicked, a new objected will be created somewhere in the scene and users are allowed to move that newly created object by drag&drop. Can Irrlicht support this kind of action? or should I use game engine instead?
-
- Posts: 126
- Joined: Sun Apr 02, 2006 1:21 am
- Location: Canada
Sure, there should be no problem doing this.
I assume you've got a button set up and working. The function I am about to present, you would call when the button is pressed.
Of course, you need to have access to your ISceneManager, so you could declare it outside the scope of the main function, or you could pass it in as an argument:
Remember, the node instance is only available in it's scope. So after you leave the function, you cannot refer to it as node. Instead, you would have to retrieve it from the SceneManager. ISceneManager has functions for retrieving SceneNodes by name or id. If, every time you create a new scene node you also give that node a unique name, you can then access it later simply by using the methods in the SceneManager.
Alternatively, you could also keep track of them yourself (which is probably what i would do). Irrlicht has it's own array class that functions very similarly to an stl vector and is quite easy to use!
Again, of course, the array needs to be accessible to the function. I also haven't actually used it in awhile, but I'm pretty sure you can use the standard array access method, i.e. you could access the 3rd element in the collection by doing sceneNodes[2].
Gah, I hope that's legible It keeps on getting later, and I have no idea why I'm still awake!
I assume you've got a button set up and working. The function I am about to present, you would call when the button is pressed.
Code: Select all
void createCube()
{
ISceneNode* node = smgr->addCubeSceneNode(10.0f);
// Do other things... apply textures, set it to a new position etc.
}
Code: Select all
void createCube(ISceneManager* sceneManager)
{
ISceneNode* node = sceneManager->addCubeSceneNode(10.0f);
node->changeSomeSettings(:P);
}
Alternatively, you could also keep track of them yourself (which is probably what i would do). Irrlicht has it's own array class that functions very similarly to an stl vector and is quite easy to use!
Code: Select all
array<ISceneNode*> sceneNodes;
void createCube(ISceneManager* sceneManager)
{
ISceneNode* node = sceneManager->addCubeSceneNode(10.0f);
node->changeSomeSettings(:P);
sceneNodes.push_back(node);
}
Gah, I hope that's legible It keeps on getting later, and I have no idea why I'm still awake!
Thanks.
I think I know how to add a new object (i.e. node) after clicking a button.
However, how can I drag and drop a node?
p.s. I notice that I must use Maya camera since the FPS camera will have the cursor stuck in the middle of the window, so the button cannot be clicked.
This leads to a new problem. Assume I have created a new node after clicking a button and I want to drag and drop it to somewhere else. As I am using Maya camera, when I click and hold the left mouse on the node and move the mouse, the camera view will change. So, how to fix the background/camera view when doing drag and drop?
I think I know how to add a new object (i.e. node) after clicking a button.
However, how can I drag and drop a node?
p.s. I notice that I must use Maya camera since the FPS camera will have the cursor stuck in the middle of the window, so the button cannot be clicked.
This leads to a new problem. Assume I have created a new node after clicking a button and I want to drag and drop it to somewhere else. As I am using Maya camera, when I click and hold the left mouse on the node and move the mouse, the camera view will change. So, how to fix the background/camera view when doing drag and drop?
the following is a fully functional program. just paste into a new project, compile and run.
select a mode button and then use left mouse to pick node to manipulate
hold left mouse down and move mouse to manipulate node.
right mouse toggle camera able to move
addbox button will add additional boxes to move around, scale etc...
select a mode button and then use left mouse to pick node to manipulate
hold left mouse down and move mouse to manipulate node.
right mouse toggle camera able to move
addbox button will add additional boxes to move around, scale etc...
Code: Select all
// IrrEditor.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#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")
IrrlichtDevice *device = 0;
IVideoDriver *driver = 0;
ISceneManager *smgr = 0;
IGUIEnvironment *guienv = 0;
ICameraSceneNode *camera = 0;
ISceneCollisionManager *CollMan = 0;
enum EditorMode
{
MODE_NONE,
MODE_QUIT,
MODE_TRANSLATE,
MODE_ROTATE,
MODE_SCALE,
};
position2di initialCursorPosition; // where mouse cursor started
position2di initialObjectPosition; // where ray from camera to object intersected screen
ISceneNode* SelectedNode = 0; // the selected node
bool ShiftIsPressed = 0; // is the shift key pressed?
bool LMouseButtonDown = 0; // is the left mouse button down?
EditorMode Mode = MODE_NONE;
float RotateSpeed = 0.01f;
float ScaleSpeed = 0.01f;
#define ID_QUIT 101
#define ID_TRANSLATE 102
#define ID_ROTATE 103
#define ID_SCALE 104
#define ID_ADDBOX 105
class MyEventReceiver : public IEventReceiver
{
public:
virtual bool OnEvent(const SEvent& anevent)
{
switch(anevent.EventType)
{
case EET_GUI_EVENT :
{
switch (anevent.GUIEvent.EventType)
{
case EGET_BUTTON_CLICKED:
{
switch (anevent.GUIEvent.Caller->getID())
{
case ID_QUIT : { Mode = MODE_QUIT; } break;
case ID_TRANSLATE : { Mode = MODE_TRANSLATE; } break;
case ID_ROTATE : { Mode = MODE_ROTATE; } break;
case ID_SCALE : { Mode = MODE_SCALE; } break;
case ID_ADDBOX :
{
ISceneNode* box = smgr->addCubeSceneNode();
box->setMaterialTexture(0, driver->getTexture("media/fire.bmp"));
box->setMaterialFlag(video::EMF_LIGHTING, false);
box->setMaterialFlag(video::EMF_FOG_ENABLE,false);
} break;
} break;
} break;
}
} break;
case EET_KEY_INPUT_EVENT :
{
if (anevent.KeyInput.Shift) ShiftIsPressed = true;
else ShiftIsPressed = false;
} break;
// if it is a mouse event
case EET_MOUSE_INPUT_EVENT :
{
// based upon the mouse event type
switch (anevent.MouseInput.Event)
{
case EMIE_LMOUSE_PRESSED_DOWN :
{
if (Mode == MODE_NONE) return false;
// what a freakin hack
LMouseButtonDown = true;
// check for a node being selected
SelectedNode = CollMan->getSceneNodeFromScreenCoordinatesBB(device->getCursorControl()->getPosition(),0,true);
// If we selected a node
if(SelectedNode)
{
// Remember where the node and cursor were when it was clicked on
initialCursorPosition = device->getCursorControl()->getPosition();
initialObjectPosition = CollMan->getScreenCoordinatesFrom3DPosition(SelectedNode->getAbsolutePosition(), camera);
SelectedNode->setDebugDataVisible(scene::EDS_BBOX);
}
// we used this message?
return (SelectedNode != 0);
} break;
case EMIE_LMOUSE_LEFT_UP :
{
LMouseButtonDown = false;
if (SelectedNode) SelectedNode->setDebugDataVisible(scene::EDS_OFF);
SelectedNode = 0;
return false;
} break;
case EMIE_RMOUSE_LEFT_UP :
{
if (camera)
{
camera->setInputReceiverEnabled(!camera->isInputReceiverEnabled());
device->getCursorControl()->setVisible(!camera->isInputReceiverEnabled());
if (camera->isInputReceiverEnabled()) Mode = MODE_NONE;
}
} break;
case EMIE_MOUSE_MOVED :
{
if (!LMouseButtonDown) return false;
if (Mode == MODE_TRANSLATE)
{
if (SelectedNode)
{
vector3df p = SelectedNode->getPosition();
if (ShiftIsPressed)
{
plane3df const planeXY(SelectedNode->getAbsolutePosition(), vector3df(1.f, 0.f, 0.f));
position2di currentCursorPosition(device->getCursorControl()->getPosition());
position2di effectiveObjectPosition = initialObjectPosition + currentCursorPosition - initialCursorPosition;
line3df ray(CollMan->getRayFromScreenCoordinates(effectiveObjectPosition, camera));
vector3df intersectWithPlane;
vector3df oldPos = SelectedNode->getAbsolutePosition();
if(planeXY.getIntersectionWithLine(ray.start, ray.getVector(), intersectWithPlane))
{
intersectWithPlane.X = oldPos.X;
intersectWithPlane.Z = oldPos.Z;
SelectedNode->setPosition(intersectWithPlane);
}
}
else
{
plane3df const planeXZ(SelectedNode->getAbsolutePosition(), vector3df(0.f, 1.f, 0.f));
position2di currentCursorPosition(device->getCursorControl()->getPosition());
position2di effectiveObjectPosition = initialObjectPosition + currentCursorPosition - initialCursorPosition;
line3df ray(CollMan->getRayFromScreenCoordinates(effectiveObjectPosition, camera));
vector3df intersectWithPlane;
if(planeXZ.getIntersectionWithLine(ray.start, ray.getVector(), intersectWithPlane))
{
SelectedNode->setPosition(intersectWithPlane);
}
}
}
} // end mode translate
else
if (Mode == MODE_ROTATE)
{
if (SelectedNode)
{
vector3df rot = SelectedNode->getRotation();
position2di currentCursorPosition(device->getCursorControl()->getPosition());
if (ShiftIsPressed)
{
if (initialObjectPosition.X < currentCursorPosition.X) rot.X -= RotateSpeed;
if (initialObjectPosition.X > currentCursorPosition.X) rot.X += RotateSpeed;
}
else
{
if (initialObjectPosition.X < currentCursorPosition.X) rot.Y -= RotateSpeed;
if (initialObjectPosition.X > currentCursorPosition.X) rot.Y += RotateSpeed;
if (initialObjectPosition.Y < currentCursorPosition.Y) rot.Z -= 1;
if (initialObjectPosition.Y > currentCursorPosition.Y) rot.Z += 1;
}
initialObjectPosition = currentCursorPosition;
SelectedNode->setRotation(rot);
}
}
else
if (Mode == MODE_SCALE)
{
if (SelectedNode)
{
vector3df scale = SelectedNode->getScale();
position2di currentCursorPosition(device->getCursorControl()->getPosition());
if (initialObjectPosition.X > currentCursorPosition.X)
{
scale.X -= ScaleSpeed;
scale.Y -= ScaleSpeed;
scale.Z -= ScaleSpeed;
}
if (initialObjectPosition.X < currentCursorPosition.X)
{
scale.X += ScaleSpeed;
scale.Y += ScaleSpeed;
scale.Z += ScaleSpeed;
}
initialObjectPosition = currentCursorPosition;
SelectedNode->setScale(scale);
}
}
} break;
}
}
}
return 0;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
// create the device
device = createDevice( video::EDT_OPENGL, dimension2d<u32>(640, 480), 16, false, false, false, 0);
if (!device) return 1;
MyEventReceiver receiver;
device->setEventReceiver(&receiver);
// get a pointer to all of the irr items
driver = device->getVideoDriver();
smgr = device->getSceneManager();
guienv = device->getGUIEnvironment();
CollMan = smgr->getSceneCollisionManager();
// add my little plug
int x = 10;
int y = 10;
int width = 100;
int height = 20;
int space = 5;
guienv->addButton(core::rect<s32>(x,y,x+width,y+height),0,ID_QUIT,L"QUIT");
y += height + space;
guienv->addButton(core::rect<s32>(x,y,x+width,y+height),0,ID_TRANSLATE,L"Translate");
y += height + space;
guienv->addButton(core::rect<s32>(x,y,x+width,y+height),0,ID_ROTATE,L"Rotate");
y += height + space;
guienv->addButton(core::rect<s32>(x,y,x+width,y+height),0,ID_SCALE,L"Scale");
y += height + space;
guienv->addButton(core::rect<s32>(x,y,x+width,y+height),0,ID_ADDBOX,L"Add A Box");
// load a mesh
IAnimatedMesh* mesh = smgr->getMesh("media/sydney.md2");
if (!mesh) return 1;
// create a node
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") );
}
// add a camera
camera = smgr->addCameraSceneNodeFPS();
camera->setPosition(vector3df(0,40,-40));
camera->setTarget(vector3df(0,0,0));
camera->setIsDebugObject(true);
camera->setInputReceiverEnabled(false);
// run the scne
while(Mode != MODE_QUIT)
{
device->run();
driver->beginScene(true, true, SColor(255,100,101,140));
smgr->drawAll();
guienv->drawAll();
driver->endScene();
}
// kill the device
device->drop();
return 0;
}
Thanks for the code
I will study it deeply later.
I have just compiled and run it.
Actually, if there is a map loaded e.g. Quake3 map like tutorial 2, can I move the object to a place where it will not overlap the map? (i.e. the object cannot be moved through the wall of the map, there should be some constraints)
Apart from the above, my university FYP requires using OpenCV to detect hand gestures to control the camera. I think this is the most difficult part.....because I dont know how OpenCV can interact with Irrlicht engine...
I will study it deeply later.
I have just compiled and run it.
Actually, if there is a map loaded e.g. Quake3 map like tutorial 2, can I move the object to a place where it will not overlap the map? (i.e. the object cannot be moved through the wall of the map, there should be some constraints)
Apart from the above, my university FYP requires using OpenCV to detect hand gestures to control the camera. I think this is the most difficult part.....because I dont know how OpenCV can interact with Irrlicht engine...
I am trying to help as much as possible, but the topics you ask about are not trivial. The code I provided will function as a small editor and you can pretty easily modify it to add whatever nodes you like. As for the nodes not intersecting, you are talking about adding a physics engine to the mix. There are many good libraries available, all of which do the same basic things. You could get a good 'which is better' discussion going if you like. I wont participate in it though
Check out the tutorials. I think there are a few code snippets in that section for adding physics.
if you choose one, feel free to share your successes with the rest of the forum,
Check out the tutorials. I think there are a few code snippets in that section for adding physics.
if you choose one, feel free to share your successes with the rest of the forum,