Page 1 of 1

[fixed]pingpong bug?(CSceneNodeAnimatorFlyStraight)

Posted: Thu Dec 31, 2009 6:57 am
by gbox
There is a bug in CSceneNodeAnimatorFlyStraight.
It occurs when the pingpong option to apply.
Reverts back to the middle.

I have modified the animateNode as shown below.

Code: Select all

void CSceneNodeAnimatorFlyStraight::animateNode(ISceneNode* node, u32 timeMs)
{
	if (!node)
		return;

	u32 t = (timeMs-StartTime);

	core::vector3df pos = Start;

	if (!Loop && t >= TimeForWay)
	{
		pos = End;
		HasFinished = true;
	}
	else
	{
		if(PingPong) //<< gbox modification begine
		{
			f32 phase = fmodf( (f32) t, (f32) TimeForWay*2 );
			core::vector3df rel = Vector * phase * TimeFactor;

			if ( phase < TimeForWay )
			{
				pos += rel;
			}
			else
			{
				pos = (End - Start) + (End - rel);
			}
		}//gbox modification end >>
		else
		{
			f32 phase = fmodf( (f32) t, (f32) TimeForWay );
			core::vector3df rel = Vector * phase * TimeFactor;

			if ( !PingPong || phase < TimeForWay * 0.5f )
			{
				pos += rel;
			}
			else
			{
				pos = End - rel;
			}
		}
	}

	node->setPosition(pos);
}


Posted: Thu Dec 31, 2009 11:14 am
by CuteAlien
Could you please describe what you fix/what goes wrong? An example would be great.

edit: removed old test code.

Posted: Thu Dec 31, 2009 6:35 pm
by gbox
Could you please describe what you fix/what goes wrong? An example would be great.

Code: Select all

{
				irr::scene::ISceneNode *pNode;
				pNode = pSmgr->addCubeSceneNode();
				pNode->setMaterialFlag(irr::video::EMF_LIGHTING,false);
				pNode->setMaterialFlag(irr::video::EMF_WIREFRAME,true);
				pNode->setName("usr/scene/cube");
				irr::scene::ISceneNodeAnimator *pAnim;
				pAnim = pSmgr->createFlyStraightAnimator(
					irr::core::vector3df(-10,0,0),
					irr::core::vector3df(10,0,0),5000,true,true);
				pNode->addAnimator(pAnim);
				pAnim->drop();
			}
wrong :
cube node does not arrive at 'End Position'.
cube node turn back at (0,0,0)

fix :
cube node turn back at (10,0,0)

Posted: Fri Jan 01, 2010 5:33 pm
by CuteAlien
Oh it's - flystraightanimator ... when I read pingpong I automatically assumed the bug is in followsplineanimator because I had reworked that recently :-) Thanks for reporting, I will take a look at it in the weekend.

Posted: Sun Jan 03, 2010 5:48 pm
by CuteAlien
I fixed it now in svn branch 1.6, so should work in 1.6.1.

My new test-code is:

Code: Select all

#include <irrlicht.h>
#include <iostream>

using namespace irr;

#ifdef _MSC_VER
#pragma comment(lib, "Irrlicht.lib")
#endif

namespace   // empty namespace makes sure all variables in here are only defined local in this file.
{
const wchar_t* const DriverTypeNames[] =
{
	L"NULL",
	L"SOFTWARE",
	L"BURNINGSVIDEO",
	L"DIRECT3D8",
	L"DIRECT3D9",
	L"EDT_OPENGL",
	0,
};

enum
{
	GUI_ID_BUTTON_SET_ANIMATOR = 1,
};
};   // namespace


/*
Application configuration
*/
struct SConfig
{
	SConfig()
			: RenderInBackground(true)
			, DriverType(video::EDT_BURNINGSVIDEO)
			, ScreenSize(640, 480)
	{
	}

	bool RenderInBackground;
	video::E_DRIVER_TYPE DriverType;
	core::dimension2d<u32> ScreenSize;
};

/*
Main application class
*/
class CApp : public IEventReceiver
{
	friend int main(int argc, char *argv[]);

public:
	CApp()
			: IsRunning(false)
			, Device(0)
			, Camera(0)
			, MeshSceneNode(0)
			, MeshSceneNodePingPong(0)
			, MeshSceneNodeLoop(0)
			, MeshSceneNodePingPongLoop(0)
	{
	}

	~CApp()
	{
	}

	// stop running - will quit at end of mainloop
	void stopApp()
	{
		IsRunning = false;
	}
	
	void AddAnimator(scene::IMeshSceneNode* node, bool loop, bool pingpong)
	{
		core::vector3df start( core::vector3df(-10,0,0) + node->getPosition() );
		core::vector3df end( core::vector3df(10,0,0) + node->getPosition() );
		scene::ISceneNodeAnimator * animator = Device->getSceneManager()->createFlyStraightAnimator(
				start, end, 2000, loop, pingpong);
		node->addAnimator(animator);
		animator->drop();		
	}

	virtual bool OnEvent(const SEvent &event)
	{
		if ( event.EventType == EET_GUI_EVENT )
		{
			if ( event.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED )
			{
				if ( event.GUIEvent.Caller->getID() == GUI_ID_BUTTON_SET_ANIMATOR )
				{
					event.GUIEvent.Caller->setEnabled(false);
					if ( MeshSceneNode )
					{
						irr::core::vector3df start( irr::core::vector3df(-10,0,0) + MeshSceneNode->getPosition() );
						irr::core::vector3df end( irr::core::vector3df(10,0,0) + MeshSceneNode->getPosition() );
						Device->getSceneManager()->addCubeSceneNode (5.0f, 0, -1, start+core::vector3df(0, -5, 0), core::vector3df(0, 0, 0), core::vector3df(1.0f, 1.0f, 1.0f));
						Device->getSceneManager()->addCubeSceneNode (5.0f, 0, -1, end+core::vector3df(0, -5, 0), core::vector3df(0, 0, 0), core::vector3df(1.0f, 1.0f, 1.0f));
						
						AddAnimator(MeshSceneNode, false, false);
						AddAnimator(MeshSceneNodePingPong, false, true);
						AddAnimator(MeshSceneNodeLoop, true, false);
						AddAnimator(MeshSceneNodePingPongLoop, true, true);
					}
				}
			}
		}
		return false;
	}

protected:

	bool init(int argc, char *argv[])
	{
		//      Config.DriverType = getDriverTypeFromConsole();
		if ( (int)Config.DriverType < 0 )
			return false;

		Device = createDevice(Config.DriverType, Config.ScreenSize);
		if (!Device)
			return false;

		Device->setWindowCaption( DriverTypeNames[Config.DriverType] );
		Device->setEventReceiver(this);
		scene::ISceneManager* smgr = Device->getSceneManager();
		//video::IVideoDriver * driver = Device->getVideoDriver ();
		gui::IGUIEnvironment* guiEnv = Device->getGUIEnvironment();

		// set a nicer font
		gui::IGUISkin* skin = guiEnv->getSkin();
		gui::IGUIFont* font = guiEnv->getFont("../../media/fonthaettenschweiler.bmp");
		if (font)
			skin->setFont(font);

		guiEnv->addButton(core::rect<s32>(20, 30, 120, 50), 0, GUI_ID_BUTTON_SET_ANIMATOR, L"Set animator");


		Camera = smgr->addCameraSceneNode (0, core::vector3df(0, 0, 0),
		                                   core::vector3df(0, 0, 100),
		                                   -1);

		MeshSceneNode = smgr->addCubeSceneNode (5.0f, 0, -1,
		                                        core::vector3df(-35, 0, 100),
		                                        core::vector3df(0, 0, 0),
		                                        core::vector3df(1.0f, 1.0f, 1.0f));
		MeshSceneNodePingPong = smgr->addCubeSceneNode (5.0f, 0, -1,
		                                        core::vector3df(-35, 5, 100),
		                                        core::vector3df(0, 0, 0),
		                                        core::vector3df(1.0f, 1.0f, 1.0f));
		MeshSceneNodeLoop = smgr->addCubeSceneNode (5.0f, 0, -1,
		                                        core::vector3df(-35, 10, 100),
		                                        core::vector3df(0, 0, 0),
		                                        core::vector3df(1.0f, 1.0f, 1.0f));
		MeshSceneNodePingPongLoop = smgr->addCubeSceneNode (5.0f, 0, -1,
		                                        core::vector3df(-35, 15, 100),
		                                        core::vector3df(0, 0, 0),
		                                        core::vector3df(1.0f, 1.0f, 1.0f));
	

		/*scene::ILightSceneNode* nodeLight = */
		smgr->addLightSceneNode(0, core::vector3df(0, 0, 0),
		                        video::SColorf(1.0f, 1.0f, 1.0f),
		                        100.0f);

		return true;
	}

	video::E_DRIVER_TYPE getDriverTypeFromConsole()
	{
		printf("Please select the driver you want for this example:\n"\
		       " (a) Direct3D 9.0c\n (b) Direct3D 8.1\n (c) OpenGL 1.5\n"\
		       " (d) Software Renderer\n (e) Burning's Software Renderer\n"\
		       " (f) NullDevice\n (otherKey) exit\n\n");

		char i;
		std::cin >> i;

		switch (i)
		{

			case 'a':
				return video::EDT_DIRECT3D9;
			case 'b':
				return video::EDT_DIRECT3D8;
			case 'c':
				return video::EDT_OPENGL;
			case 'd':
				return video::EDT_SOFTWARE;
			case 'e':
				return video::EDT_BURNINGSVIDEO;
			case 'f':
				return video::EDT_NULL;
			default:
				return video::E_DRIVER_TYPE(-1);
		}
	}

	bool update()
	{
		using namespace irr;

		video::IVideoDriver* videoDriver =  Device->getVideoDriver();
		if ( !Device->run() )
			return false;

		if ( Device->isWindowActive() || Config.RenderInBackground )
		{
			gui::IGUIEnvironment* guiEnv = Device->getGUIEnvironment();
			scene::ISceneManager* smgr = Device->getSceneManager();
			gui::IGUISkin * skin = guiEnv->getSkin();

			video::SColor bkColor( skin->getColor(gui::EGDC_APP_WORKSPACE) );
			videoDriver->beginScene(true, true, bkColor);

			smgr->drawAll();
			guiEnv->drawAll();

			videoDriver->endScene();
		}

		return true;
	}

	void run()
	{
		IsRunning = true;

		if ( !Device )
			return;

		// main application loop
		while (IsRunning)
		{
			if ( !update() )
				break;

			Device->sleep( 5 );
		}
	}

	void quit()
	{
		IsRunning = false;
		if ( Device )
		{
			Device->closeDevice();
			Device->drop();
			Device = NULL;
		}
	}

private:
	SConfig                  	Config;
	volatile bool            	IsRunning;
	IrrlichtDevice *          	Device;
	scene::ICameraSceneNode *   Camera;
	scene::IMeshSceneNode* 		MeshSceneNode;
	scene::IMeshSceneNode* 		MeshSceneNodePingPong;
	scene::IMeshSceneNode* 		MeshSceneNodeLoop;
	scene::IMeshSceneNode* 		MeshSceneNodePingPongLoop;
};

int main(int argc, char *argv[])
{
	CApp APP;

	if ( !APP.init(argc, argv) )
	{
		printf("init failed\n");
		return 1;
	}

	APP.run();
	APP.quit();

	return 0;
}