teleporter problem (animator) [FIXED]

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.
Post Reply
Catprog
Posts: 164
Joined: Wed Jan 31, 2007 9:07 am
Contact:

teleporter problem (animator) [FIXED]

Post by Catprog »

I have a problem with teleporting.

The situation is

...|---|
|-| T |-|
|.........|
|.........|
|.........|
|-------|


...|--|
|_|...|-|
|.........|
|.........|
|.........|
|-------|

. = space

You go in to the T and then you go to the back of the other one. The problem is you only go to the back of the one with the T.


If I remove all the animators it works but then I can't put them back.

Any ideas?
Last edited by Catprog on Fri Mar 30, 2007 5:20 am, edited 1 time in total.
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

Animators don't work well when you move the node that they are animating. The simplest solution is to remove the old animator, move the node, create a new animator that is a clone of the previous one, and add the clone back to the original node. Here is some code that should work with the collision response animator...

Code: Select all

scene::ISceneNodeAnimator*
ISceneNodeAnimatorCollisionResponse_clone(scene::ISceneNodeAnimator* anim, scene::ISceneNode* node, scene::ISceneManager* smgr)
{
  if (! (anim && node && smgr))
    return 0;

  if (anim->getType() != scene::ESNAT_COLLISION_RESPONSE)
    return 0;

  scene::ISceneNodeAnimatorCollisionResponse* src =
    (scene::ISceneNodeAnimatorCollisionResponse*)anim;

  scene::ISceneNodeAnimatorCollisionResponse* dst =
    smgr->createCollisionResponseAnimator(src->getWorld(),
                                          node,
                                          src->getEllipsoidRadius(),
                                          src->getGravity(),
                                          src->getEllipsoidTranslation()
                                          ); // someone forgot to expose methods for accessing sliding speed!

  return dst;
}
You would use it like this...

Code: Select all

  // find/get the collsion response animator
  scene::ISceneNodeAnimator* anim = //...
  anim->grab(); // make sure it won't be deleted until we want it to

  node->removeAnimator(anim);

  // teleport/move node to new location

  scene::ISceneNodeAnimator* clone =
    ISceneNodeAnimatorCollisionResponse_clone(anim, node, smgr);

  // we no longer need the original
  anim->drop();

  node->addAnimator(clone);
  clone->drop();
Catprog
Posts: 164
Joined: Wed Jan 31, 2007 9:07 am
Contact:

Post by Catprog »

How do I go over a list of the animators (irr:core:list <irr::scene::ISceneNodeAnimator>)
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

You use iterators [irr::core::list<T>::Iterator]...

Code: Select all

core::list<ISceneNodeAnimator*>::Iterator beg = node->getAnimators().begin();
core::list<ISceneNodeAnimator*>::Iterator end = node->getAnimators().end();
for (; beg != end; ++beg)
{
  // (*beg) will be a pointer to an animator
}
You have to be very careful if you call a function that modifies the list that you are iterating over. If you are about to call a function that removes the item you are iterating over, you should advance the iterator before you remove, and make sure not to advance the iterator again or you'll skip the next item in the list...

Code: Select all

while (beg != end)
{
  ISceneNodeAnimator* animator = *beg;
  ++beg;

  if (you want to remove the animator)
    node->removeAnimator(animator);
}
Catprog
Posts: 164
Joined: Wed Jan 31, 2007 9:07 am
Contact:

Post by Catprog »

Unhandled exception at 0x00404e54 in TerrainRendering.exe: 0xC0000005: Access violation reading location 0xcccccccc.

The error occurs at

irrlist.h

void clear()

SKListNode* next = node->next;

When called by

Code: Select all

irr::core::list <scene::ISceneNodeAnimator*> animList =
					camera->getAnimators();
Catprog
Posts: 164
Joined: Wed Jan 31, 2007 9:07 am
Contact:

Post by Catprog »

I found a workaround where I only activate the animator for the room that the player is in.

I would still like to know how to fix the list problem though.
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

Use a reference instead of making a copy.

Code: Select all

// notice the 'const' and '&' here
const core::list <scene::ISceneNodeAnimator*>& animList = camera->getAnimators();
The reason it doesn't work is someone didn't test their code before they submitted. The list copy constructor calls the assignment operator without initializing any of the members. The bug was fixed before Irrlicht 1.3. You could go and fix the list copy constructor yourself. It is a pretty easy change to make. You don't need to recompile Irrlicht if you make the change either.

Code: Select all

//! copy constructor
list(const list<T>& other)
  : root(0), last(0), size(0) // add this line
{
   *this = other;
}
Travis
Catprog
Posts: 164
Joined: Wed Jan 31, 2007 9:07 am
Contact:

Post by Catprog »

Thanks for your help
crosel
Posts: 11
Joined: Fri May 29, 2009 6:53 am

Post by crosel »

I know this is an old thread but im struggling here and need some help.

Im pretty much trying to do the same thing, but i need multiple "teleports"

I have three rooms, red room, green room, and blue room. I need to be able to go from red to green, from green to blue, from blue to red.

I can create a one way teleport no problem using this code, however i encounter error's when dealing the animator. For some reason, it doesnt like the grab function.

Here is the code ive implemented.

Code: Select all

if(selectedSceneNode == sphere) //First room teleport
{
	sAnim = anim; //sAnim is the animator for the first room
	sAnim->grab(); 

	camera->removeAnimator(sAnim);

	camera->setPosition(vector3df(-270,60,230)); //Move to Blue Room
			
	ISceneNodeAnimator* clone =
				ISceneNodeAnimatorCollisionResponse_clone(sAnim, camera, smgr);

	sAnim->drop();
	camera->addAnimator(clone);
	clone->drop(); 
}

else if(selectedSceneNode == gSphere) //Second Room

{
		gAnim = anim; //2nd room animator
		gAnim->grab(); 

		camera->removeAnimator(gAnim);

		camera->setPosition(vector3df(-100,60,230)); // Move to green room
			
		ISceneNodeAnimator* clone =
				ISceneNodeAnimatorCollisionResponse_clone(gAnim, camera, smgr);

		sAnim->drop();
		camera->addAnimator(clone);
		clone->drop(); 
}
This is the actual error message i get:

Unhandled exception at 0x00f64276 in ProjectFPS.exe: 0xC0000005: Access violation reading location 0x0cd2afe8.
BlindSide
Admin
Posts: 2821
Joined: Thu Dec 08, 2005 9:09 am
Location: NZ!

Post by BlindSide »

In the second context you mistyped sAnim instead of gAnim, 3rd line from the bottom. Problem might be unrelated though.
ShadowMapping for Irrlicht!: Get it here
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
crosel
Posts: 11
Joined: Fri May 29, 2009 6:53 am

Post by crosel »

yea changing it didnt do anything :P

So essentially i have three rooms, a sphere in each room, and by "shooting" at each sphere, i wanna teleport the camera from one room to the next.
crosel
Posts: 11
Joined: Fri May 29, 2009 6:53 am

Post by crosel »

Ive figured it out :> lol

I only had to add a single line,

anim = clone;

Where anim is the original animator applied to the camera. The issue was, the 2nd time i ran the "teleport" function, it would try to remove the original animator, but that had already been removed. Therefore, by making the original animator a copy of the new animator, i can continue to remove it. So simple lol

Code is like so:

Code: Select all

if(selectedSceneNode == sphere || selectedSceneNode == bSphere || selectedSceneNode == gSphere  )
		{
			ISceneNodeAnimator* newAnim = anim;

			newAnim->grab(); 
			camera->removeAnimator(newAnim);

			if(selectedSceneNode == sphere)
			{
				camera->setPosition(vector3df(-270,60,230)); //Move to Blue Room
			}
			else if(selectedSceneNode == bSphere)
			{
				camera->setPosition(vector3df(0,60,0)); //Move to Original Room
			}
			else if(selectedSceneNode == gSphere)
			{
				camera->setPosition(vector3df(5000,60,0)); //Move to RedRoom
			}
			
			ISceneNodeAnimator* clone =
				ISceneNodeAnimatorCollisionResponse_clone(newAnim, camera, smgr);

			newAnim->drop();
			camera->addAnimator(clone);
			anim = clone;
			clone->drop(); 			
		}
lpb313
Posts: 4
Joined: Mon Jul 19, 2010 2:29 pm
Location: IRIT - Toulouse France

Post by lpb313 »

Hi,

I found another simpler solution for beginners who have the same problems.
This solution works with version 1.7.x

Most needed now to clone the annimator. You have to use ISceneNodeAnimatorCollisionResponse and setTargetNode() method.

Code: Select all

//add the animator to the respective node
irr::scene::ISceneNodeAnimatorCollisionResponse* anim = smgr->createCollisionResponseAnimator(
		selector, node);

//...
//teleport/move node to new location 
node->setPosition(core::vector3df(x,y,z));

//force the animator to update its last target position for the node
anim->setTargetNode(node);

Bye
Post Reply