void DLL_EXPORT physicsInitialized(void) {
  printf("physicsInitialized!\n");
  irr::scene::ISceneManager *pSmgr = g_pDevice->getSceneManager();

  char sName[][0xFF] = { "car%i", "plane%i", "heli%i", "tank%i" };
  bool b = true;
  int i = 1;

  do {
    char s[0xFF];
    b = false;

    for (int j = 0; j < 4; j++) {
      sprintf(s,sName[j],i);
      irr::ode::CIrrOdeBody *p = reinterpret_cast<irr::ode::CIrrOdeBody *>(pSmgr->getSceneNodeFromName(s));
      if (p && p->isVisible()) {
        printf("\t\t\"%s\"\n",s);
        g_lBodies.push_back(p);
        b = true;
      }
    }
    i++;
  }
  while (b);

  g_itBody = g_lBodies.end();
}
    virtual bool onEvent(irr::ode::IIrrOdeEvent *pEvent) {
      if (g_pCamera && g_pCamera->handlesEvent(pEvent)) g_pCamera->onEvent(pEvent);

      if (pEvent->getType()==irr::ode::eIrrOdeEventLoadScene) {
        searchPlaneBodies(m_pDevice->getSceneManager()->getRootSceneNode());
        searchTankBodies (m_pDevice->getSceneManager()->getRootSceneNode());
        searchCarBodies  (m_pDevice->getSceneManager()->getRootSceneNode());
        searchHeliBodies (m_pDevice->getSceneManager()->getRootSceneNode());

        const c8 sForests[][255]={ "RandomForest1", "RandomForest2", "Forest1", "Forest2" };

        for (u32 i=0; i<2; i++) {
          printf("merging \"%s\"...\n",sForests[i]);
          irr::scene::ISceneManager *smgr=m_pDevice->getSceneManager();
          scene::ISceneNode *p=smgr->getSceneNodeFromName(sForests[i]);
          CRandomForest *pForest=(CRandomForest *)p;
          if (pForest!=NULL) {
            CMeshCombiner *pCombine=new CMeshCombiner(0.8f);
            irr::core::array<irr::scene::IMeshSceneNode *> aMeshSceneNodes;
            irr::core::array<irr::scene::ISceneNode *> aTrees=pForest->getGeneratedTrees();

            for (u32 j=0; j<aTrees.size(); j++) {
              irr::scene::IMeshSceneNode *p=(irr::scene::IMeshSceneNode *)aTrees[j];
              aMeshSceneNodes.push_back(p);
            }

            printf("%i trees\n",aMeshSceneNodes.size());

            if (aMeshSceneNodes.size()>0) {
              c8 s[0xFF];
              sprintf(s,"MyCombinedTrees_%i",i);
              irr::scene::IMesh *pCombined=pCombine->combineMeshes(smgr,m_pDevice->getVideoDriver(),aMeshSceneNodes,s);
              if (pCombined!=NULL) {
                irr::scene::ISceneNode *pRoot=smgr->getSceneNodeFromName(sForests[i+2]);
                irr::scene::IMeshSceneNode *pNode=smgr->addMeshSceneNode(pCombined,pRoot==NULL?smgr->getRootSceneNode():pRoot);
                for (u32 i=0; i<pNode->getMaterialCount(); i++) {
                  pNode->getMaterial(i).setFlag(irr::video::EMF_LIGHTING,false);
                  pNode->getMaterial(i).MaterialType=irr::video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
                }
              }
            }
          }
        }
        return true;
      }

      if (pEvent->getType()==irr::ode::eIrrOdeEventStep) {
        irr::core::list<CCockpitPlane *>::Iterator pit;
        for (pit = m_lPlaneCockpits.begin(); pit != m_lPlaneCockpits.end(); pit++) (*pit)->update();

        irr::core::list<CCockpitCar *>::Iterator cit;
        for (cit = m_lCarCockpits.begin(); cit != m_lCarCockpits.end(); cit++) (*cit)->update();

        if (g_pCamera) g_pCamera->update();
      }

      return false;
    }
irr::CIrrDeviceWinCE* getDeviceFromHWnd(HWND hWnd)
{
	irr::core::list<SEnvMapper>::Iterator it = EnvMap.begin();
	for (; it!= EnvMap.end(); ++it)
		if ((*it).hWnd == hWnd)
			return (*it).irrDev;

	return 0;
}
SEnvMapper* getEnvMapperFromHWnd(HWND hWnd)
{
	irr::core::list<SEnvMapper>::Iterator it = EnvMap.begin();
	for (; it!= EnvMap.end(); ++it)
		if ((*it).hWnd == hWnd)
			return &(*it);

	return 0;
}
//! destructor
CIrrDeviceWinCE::~CIrrDeviceWinCE()
{
	// unregister environment

	if (ChangedToFullScreen)
		SHFullScreen(HWnd, SHFS_SHOWTASKBAR | SHFS_SHOWSTARTICON | SHFS_SHOWSIPBUTTON);

	irr::core::list<SEnvMapper>::Iterator it = EnvMap.begin();
	for (; it!= EnvMap.end(); ++it)
		if ((*it).hWnd == HWnd)
		{
			EnvMap.erase(it);
			break;
		}
}
bool DLL_EXPORT handleEvent(const irr::SEvent &event) {
  bool bRet = false;
  if (g_pCtrl) g_pCtrl->OnEvent(event);
  if (g_pCamera) bRet = g_pCamera->OnEvent(event);

  if (!bRet) {
    if (event.EventType == irr::EET_KEY_INPUT_EVENT) {
      if (event.KeyInput.PressedDown && event.KeyInput.Key == irr::KEY_TAB) {
        if (g_itBody == g_lBodies.end()) {
          g_pCamera->setTarget(NULL);
          g_itBody = g_lBodies.begin();
        }
        else {
          g_pCamera->setTarget(*g_itBody);
          g_itBody++;
        }
      }
    }
  }

  return bRet;
}
void TeleporterSceneNode::teleport(ISceneNode* const node, const irr::core::vector3df& target)
{
	this->dontTeleport = true;
	this->dontTeleportTimer = 3.0f;

	node->setPosition(target);

	//update animators if any
	const irr::core::list<irr::scene::ISceneNodeAnimator*> anims = node->getAnimators();
	irr::core::list<irr::scene::ISceneNodeAnimator*>::ConstIterator it = anims.begin();
	const irr::core::list<irr::scene::ISceneNodeAnimator*>::ConstIterator end = anims.end();
    for(; it != end; ++it)
    {
    	irr::scene::ISceneNodeAnimator* const anim = (*it);
    	const irr::scene::ESCENE_NODE_ANIMATOR_TYPE& type = anim->getType();

    	switch (type)
    	{
    	case ESNAT_FLY_CIRCLE: break;
    	case ESNAT_FLY_STRAIGHT: break;
    	case ESNAT_FOLLOW_SPLINE: break;
    	case ESNAT_ROTATION: break;
    	case ESNAT_TEXTURE: break;
    	case ESNAT_DELETION: break;
    	case ESNAT_COLLISION_RESPONSE:
    	{
    		ISceneNodeAnimatorCollisionResponse* const col = (ISceneNodeAnimatorCollisionResponse*)anim;
//    		col->setTargetNode(node);
    	}
		break;
    	case ESNAT_CAMERA_FPS:
    	{
    		//ISceneNodeAnimatorCameraFPS* col = (ISceneNodeAnimatorCameraFPS*)anim;
    	}
    	break;

    	case ESNAT_CAMERA_MAYA: break;
    	case ESNAT_UNKNOWN: break;
    	default: break;
    	}

    }

    node->updateAbsolutePosition();

	this->whirl[0]->setVisible(false);
	this->whirl[1]->setVisible(false);

#ifdef _SOUND
	//play teleport sound
	if (demo->getSoundEngine() && demo->getConfiguration()->isSoundEnabled())
	{
		irrklang::ISound* snd = 0;
		snd = demo->getSoundEngine()->play3D("media/sounds/teleport.wav", this->placeA.getCenter(), false, true);
		if (snd)
		{
			snd->setMinDistance(500.0f);
			snd->setIsPaused(false);
			snd->drop();
			snd = 0;
		}

		snd = demo->getSoundEngine()->play3D("media/sounds/teleport.wav", this->placeB.getCenter(), false, true);
		if (snd)
		{
			snd->setMinDistance(500.0f);
			snd->setIsPaused(false);
			snd->drop();
			snd = 0;
		}
	}
#endif
}