Page 1 of 1

teleporter problem (animator) [FIXED]

Posted: Thu Mar 29, 2007 10:16 am
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?

Posted: Thu Mar 29, 2007 4:50 pm
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();

Posted: Thu Mar 29, 2007 11:23 pm
by Catprog
How do I go over a list of the animators (irr:core:list <irr::scene::ISceneNodeAnimator>)

Posted: Thu Mar 29, 2007 11:52 pm
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);
}

Posted: Fri Mar 30, 2007 12:14 am
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();

Posted: Fri Mar 30, 2007 4:29 am
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.

Posted: Fri Mar 30, 2007 5:02 am
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

Posted: Fri Mar 30, 2007 5:19 am
by Catprog
Thanks for your help

Posted: Tue Jun 30, 2009 1:13 pm
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.

Posted: Tue Jun 30, 2009 10:10 pm
by BlindSide
In the second context you mistyped sAnim instead of gAnim, 3rd line from the bottom. Problem might be unrelated though.

Posted: Wed Jul 01, 2009 12:14 am
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.

Posted: Wed Jul 01, 2009 3:57 am
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(); 			
		}

Posted: Mon Apr 11, 2011 3:45 pm
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