Problem with selecting node

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.
Virror
Posts: 191
Joined: Mon May 02, 2011 3:15 pm

Problem with selecting node

Post by Virror »

Hello again : p
I searched alot on the forums on this issue, and found alot of posts about it, but still cant get it to work. Clicking on a node and getting it to move an so on is easy with "getSceneNodeAndCollisionPointFromRay". Problem is i cant access a custom nodes properties : / Maybe im doing it totally wrong..

Edit: Problem is that the references to the Item gets random values only.

The node class. The Item class inherits the 2ISceneNode" class

Code: Select all

#include "Stone.h"
#include <irrlicht.h>
#include "Main.h"

using namespace irr;
using namespace video;
using namespace scene;

Stone::Stone(ISceneNode* parent, ISceneManager* irrScene, s32 id)
	: Item(parent, irrScene, id)
{
	setWeight(1);
	setType(IT_COMPONENT);
	setName(L"Stone");
	setDescription(L"A big stone");
}

Stone::~Stone(void)
{
}

void Stone::Create(ISceneManager* irrScene, IVideoDriver * irrVideo, f32 xPos, f32 yPos, f32 zPos)
{
	ITriangleSelector* meshSelector = 0;
	IMesh * mesh = irrScene->getMesh("T:/Game project/Files/Models/Stone.ms3d");
	ISceneNode* stone = irrScene->addMeshSceneNode(mesh,0, MT_ITEM, vector3df(xPos, yPos, zPos),
													vector3df(0,100,0),vector3df(9.0F,9.0F,9.0F));
	stone->setMaterialFlag(EMF_LIGHTING, false);
	meshSelector = irrScene->createTriangleSelector(mesh,stone);
	stone->setTriangleSelector(meshSelector);
	meshSelector->drop();
}

Code: Select all

Item::Item(ISceneNode* parent, ISceneManager* irrScene, s32 id)

Code: Select all

void EventReceiver::EventLeftUp(void)
{
	leftButtonDown = false;
	vector3df intersection;
	triangle3df hitTriangle;
	line3d<f32> ray;
	ray.start = camera->getPosition();
	ray.end = ray.start + (camera->getTarget() - ray.start).normalize() * 300.0f;
	ISceneNode * selectedSceneNode = collMan->getSceneNodeAndCollisionPointFromRay(
		ray,
		intersection, // This will be the position of the collision
		hitTriangle, // This will be the triangle hit in the collision
		0, // Check all
		0); // Check the entire scene (this is actually the implicit default)
	if(selectedSceneNode)
	{
		if(selectedSceneNode->getID() == MT_TREE)
		{
			//selectedSceneNode->setRotation(vector3df(90,90,0));
			//((Tree*)selectedSceneNode)->setCut(true);
			chatList->addItem(stringw(((Tree*)selectedSceneNode)->getHp()).c_str());
		}
		else if(selectedSceneNode->getID() == MT_ITEM)
		{
			myPlayer->AddItem((Item*)selectedSceneNode);
		}

Code: Select all

bool Player::AddItem(Item * newItem)
{
	if(invCounter < 99)
	{
		char temp[5];
		char temp3[40] = "Total weight: ";
		inventory->Append(newItem);
		invTree->addRow(invCounter);
		invTree->setCellText(invCounter,0,newItem->getName());
		sprintf(temp, "%.1f", newItem->getWeight());
		invTree->setCellText(invCounter,1,temp);
		totalWeight += inventory->Look(invCounter)->getWeight();
		invCounter++;
		sprintf(temp, "%.1f", totalWeight);
		strcat(temp3, temp);
		strcat(temp3, "kg / 100kg");
		weightText->setText(stringw(temp3).c_str());
		return true;
	}
	else
		return false;
}
Last edited by Virror on Sun May 15, 2011 11:23 am, edited 1 time in total.
user-r3
Posts: 70
Joined: Tue Dec 07, 2010 4:09 pm

Post by user-r3 »

Hi, I don't see your problem, but if you want to use your selectedSceneNode as a Stone you write

Code: Select all

Stone* stone = (Stone*)(selectedSceneNode);
But as I can see from

Code: Select all

myPlayer->AddItem((Item*)selectedSceneNode); 
you may already know that...
Radikalizm
Posts: 1215
Joined: Tue Jan 09, 2007 7:03 pm
Location: Leuven, Belgium

Post by Radikalizm »

If you say you can't access custom node properties, you mean that the functions getHp() for example causes an error when called? Or am I seeing this wrong?
Virror
Posts: 191
Joined: Mon May 02, 2011 3:15 pm

Post by Virror »

Yes, but myPlayer has a linked list as a inventory were he saves stuff as pointers to "Item". Thats why i want it as item
Virror
Posts: 191
Joined: Mon May 02, 2011 3:15 pm

Post by Virror »

Radikalizm wrote:If you say you can't access custom node properties, you mean that the functions getHp() for example causes an error when called? Or am I seeing this wrong?
It wont give error, but it gives some random value from memory.
Xaryl
Posts: 90
Joined: Sat Apr 30, 2011 11:54 pm

Post by Xaryl »

I only glanced through your code, so I might be wrong..

are you sure the selected node is the Stone itself, not Stone::stone?

actually there's no Stone::stone.. it is a local variable

Edit: I guess I will be a little bit more specific

Code: Select all

   ISceneNode* stone = irrScene->addMeshSceneNode(mesh,0, MT_ITEM, vector3df(xPos, yPos, zPos),
                                       vector3df(0,100,0),vector3df(9.0F,9.0F,9.0F));


in the create function

Edit again:
either that or it looks like you are trying to cast a regular irrlicht node to something else.

ps. sorry sort of in a hurry, if you still can't figure it out I will take a look at it again later
Virror
Posts: 191
Joined: Mon May 02, 2011 3:15 pm

Post by Virror »

Reply was a bit confusing, but i think i know what you mean : p
Will look into it ; )

Edit: I think i know whats wrong, but not how to fix it. If i make a

Code: Select all

stone = irrScene->addMeshSceneNode(mesh, 0, MT_ITEM, vector3df(xPos, yPos, zPos),
													vector3df(0,100,0),vector3df(9.0F,9.0F,9.0F));
there is no connection what so ever, so when i click the stone i only getting the reference to the stone i created, not the stone class. How can i fix this?
Last edited by Virror on Sun May 15, 2011 10:14 pm, edited 1 time in total.
Xaryl
Posts: 90
Joined: Sat Apr 30, 2011 11:54 pm

Post by Xaryl »

heh sorry, basically

Code: Select all

ISceneNode* stone = irrScene->addMeshSceneNode(mesh,0, MT_ITEM, vector3df(xPos, yPos, zPos),
                                       vector3df(0,100,0),vector3df(9.0F,9.0F,9.0F));

creates the irrlicht scene node (not Stone or Item), but in

Code: Select all

myPlayer->AddItem((Item*)selectedSceneNode);


the pointer of something that is actually from the base class is being used as a pointer of a object from a derived class.
(In another word, the node is not really an Item*, but it is being used as an Item*.)
the behaviour would be undefined.
Virror
Posts: 191
Joined: Mon May 02, 2011 3:15 pm

Post by Virror »

Thats exactly what i found out : )
Problem is how to make this right : p
Xaryl
Posts: 90
Joined: Sat Apr 30, 2011 11:54 pm

Post by Xaryl »

you can always try to use some of the codes from the .cpp in irrlicht source code (either by inheritance or direct copy) and create a proper scene node with mesh, but I do not think that is the way to go.

There's a lazy way out if the structure allows...
Create a wrapping class that contains the node.
The down side is that the picked node is not the object directly, so you will have to have something like

Code: Select all

map<ISceneNode*,Item*>node_to_item;
to keep track of them, which would make creating and deleting less flexible.

I can think of yet another lazy way...
You can make your Item really simple IScenenode similar to empty scene node, and the created mesh as a child of it, and so you get your object by getting the parent of the selected scene node.
This though, doubles the node amount, it might double the work when calculating their position and make the program less efficient.

If anyone has a simple solution, I would like to know too.
serengeor
Posts: 1712
Joined: Tue Jan 13, 2009 7:34 pm
Location: Lithuania

Post by serengeor »

simple solution would be to use bullets collision library, create a separate class like GameObject which holds the node and the physics body. Attach the game object to your body like:

Code: Select all

body->setUserPointer((void*)MyGameObjectPtr);
then when you get your ray cast body result you can:

Code: Select all

if(rayCastResultBody)
{
GameObject * obj = (GameObject*)rayCastResultBody->getUserPointer();
}
Or if you feel like modifying irrlicht's sources you could make irrlicht support user pointers :)
Working on game: Marrbles (Currently stopped).
Virror
Posts: 191
Joined: Mon May 02, 2011 3:15 pm

Post by Virror »

Never thought it would be this complicated to do one of the most basic things in a game, selecting a node and accessing some properties : p

Will look in to your suggestions : )
serengeor
Posts: 1712
Joined: Tue Jan 13, 2009 7:34 pm
Location: Lithuania

Post by serengeor »

Virror wrote:Never thought it would be this complicated to do one of the most basic things in a game, selecting a node and accessing some properties : p
Well selecting node is one thing, and getting object related to the node is quite other thing. You have to think of some way to connect them together. Using a std::map could be a solution, but not as good as storing pointers, because the more objects you have the more lag it will produce while searching trough the std::map for selected object.
Working on game: Marrbles (Currently stopped).
Virror
Posts: 191
Joined: Mon May 02, 2011 3:15 pm

Post by Virror »

Its to bad i cant set the class as a parent, that would have been a great way of solving it, or a special class pointer would have been even better. I guess the parent of a scene node has to be attached to the scene? You have given me some good thoughts : )
serengeor
Posts: 1712
Joined: Tue Jan 13, 2009 7:34 pm
Location: Lithuania

Post by serengeor »

Virror wrote:Its to bad i cant set the class as a parent, that would have been a great way of solving it, or a special class pointer would have been even better. I guess the parent of a scene node has to be attached to the scene? You have given me some good thoughts : )
You can only parent classes that are inherithed from base abstract class that is ISceneNode in this case. Thats why you can't parent your classes.
The pointer method should be fairly easy to implement. Because you would only add its functionality to ISceneNode, and it could be used by all node types.

basically you would add:

Code: Select all

ISceneNode
{
public:
void setUserPointer(void * userPtr){m_userPointer=userPtr;}
void * getUserPointer(){return m_userPointer;}
protected:
void * m_userPointer;
}
And also it would be good to initialize it to NULL in the constructor of ISceneNode so you could check whether its been set or not.

To use it with cube scene node for example you would do:

Code: Select all

BoxItem * boxItem= ...;
ISceneNode * node = smgr->addCubeSceneNode();
node->setUserPointer((void*) boxItem);
Where box item would be derived from item, and you could access item type from Item class.
So when you get your box from ray collision test you would access your item like so:

Code: Select all

if(rayCollisionNode->getUserPointer()) ///checking if item is set or not, because we want to avoid segfaults.
{
Item * item = (Item*)rayCollisionNode->getUserPointer();
if(Item->getType()==EIT_BOX_ITEM)
{
BoxItem * box=(BoxItem*)item;
///You can call now any specific box item methods etc.
}
}
Working on game: Marrbles (Currently stopped).
Post Reply