// render
// irr scenenode impl
void CGameGrassSceneNode::render()
{
	ISceneManager	*smgr = getSceneManager();
	IVideoDriver	*driver = smgr->getVideoDriver();
	

#ifdef GSEDITOR
	CGameObject::EObjectState state = m_owner->getObjectState();
	
	// draw bbox on select
	if ( 
			state == CGameObject::Move ||
			state == CGameObject::Review		
		)
		setDebugDataVisible( EDS_BBOX );
	else
		setDebugDataVisible( 0 );

	// call object draw
	m_owner->drawObject();
#endif

	// set world transform
	driver->setTransform( video::ETS_WORLD, getAbsoluteTransformation());

	// set current material with config shader
    driver->setMaterial( m_Material);

	// draw mesh with grass shader
	int meshCount = m_mesh->getMeshBufferCount();
	for ( int i = 0; i < meshCount; i++ )
		driver->drawMeshBuffer(m_mesh->getMeshBuffer(i));

	// draw bouding box
	if ( DebugDataVisible & scene::EDS_BBOX )
	{
		driver->setTransform(video::ETS_WORLD, core::IdentityMatrix);
		video::SMaterial deb_m;
		deb_m.Lighting = false;
		driver->setMaterial(deb_m);

		core::aabbox3d<f32> tbox = m_mesh->getBoundingBox();
		getAbsoluteTransformation().transformBoxEx(tbox);

		driver->draw3DBox( tbox, video::SColor(255,255,255,255));
	}

#ifdef GSEDITOR	
	// draw move
	if ( 
			state == CGameObject::Move || 
			state == CGameObject::Rotation ||
			state == CGameObject::Scale
		)
		m_owner->drawFrontUpLeftVector();	
	
	if ( state == CGameObject::Rotation )
		m_owner->drawCircleAroundObject();	
#endif

}
	void CSceneNodeAnimatorCameraFPS::animateNode(ISceneNode* node, UINT32 timeMs)
	{
		if (!node || node->getType() != ESNT_CAMERA)
			return;

		ICameraSceneNode* camera = static_cast<ICameraSceneNode*>(node);

		if (firstUpdate)
		{
			camera->updateAbsolutePosition();
			if (CursorControl)
			{
				CursorControl->setPosition(0.5f, 0.5f);
				CursorPos = CenterCursor = CursorControl->getRelativePosition();
			}

			LastAnimationTime = timeMs;

			firstUpdate = false;
		}

		// If the camera isn't the active camera, and receiving input, then don't process it.
		if (!camera->isInputReceiverEnabled())
		{
			firstInput = true;
			return;
		}

		if (firstInput)
		{
			allKeysUp();
			firstInput = false;
		}

		ISceneManager * smgr = camera->getSceneManager();
		if (smgr && smgr->getActiveCamera() != camera)
			return;

		// get time
		FLOAT32 timeDiff = (FLOAT32)(timeMs - LastAnimationTime);
		LastAnimationTime = timeMs;

		// update position
		Vector3 pos = camera->getPosition();

		// Update rotation
		Vector3 target = (camera->getTarget() - camera->getAbsolutePosition());
		Vector3 relativeRotation = target.getHorizontalAngle();

		if (CursorControl)
		{
			if (CursorPos != CenterCursor)
			{
				relativeRotation.y -= (0.5f - CursorPos.x) * RotateSpeed;
				relativeRotation.x -= (0.5f - CursorPos.y) * RotateSpeed * MouseYDirection;

				// X < MaxVerticalAngle or X > 360-MaxVerticalAngle

				if (relativeRotation.x > MaxVerticalAngle * 2 &&
					relativeRotation.x < 360.0f - MaxVerticalAngle)
				{
					relativeRotation.x = 360.0f - MaxVerticalAngle;
				}
				else
					if (relativeRotation.x > MaxVerticalAngle &&
						relativeRotation.x < 360.0f - MaxVerticalAngle)
					{
						relativeRotation.x = MaxVerticalAngle;
					}

				// Do the fix as normal, special case below
				// reset cursor position to the centre of the window.
				CursorControl->setPosition(0.5f, 0.5f);
				CenterCursor = CursorControl->getRelativePosition();

				// needed to avoid problems when the event receiver is disabled
				CursorPos = CenterCursor;
			}

			// Special case, mouse is whipped outside of window before it can update.
			IVideoDriver* driver = smgr->getVideoDriver();
			Vector2 mousepos(UINT32(CursorControl->getPosition().x), UINT32(CursorControl->getPosition().y));
			rect<UINT32> screenRect(0, 0, driver->getScreenSize().Width, driver->getScreenSize().Height);

			// Only if we are moving outside quickly.
			bool reset = !screenRect.isPointInside(mousepos);

			if (reset)
			{
				// Force a reset.
				CursorControl->setPosition(0.5f, 0.5f);
				CenterCursor = CursorControl->getRelativePosition();
				CursorPos = CenterCursor;
			}
		}

		// set target

		target.set(0, 0, Math::_max<Real>(1.f, pos.length()));
		Vector3 movedir = target;

		Matrix4 mat;
		mat.setRotationDegrees(Vector3(relativeRotation.x, relativeRotation.y, 0));
		//mat.transformVect(target);
		target = mat.transformAffine(target);

		if (NoVerticalMovement)
		{
			mat.setRotationDegrees(Vector3(0, relativeRotation.y, 0));
			//mat.transformVect(movedir);
			target = mat.transformAffine(target);
		}
		else
		{
			movedir = target;
		}

		movedir.normalise();

		if (CursorKeys[EKA_MOVE_FORWARD])
			pos += movedir * timeDiff * MoveSpeed;

		if (CursorKeys[EKA_MOVE_BACKWARD])
			pos -= movedir * timeDiff * MoveSpeed;

		// strafing

		Vector3 strafevect = target;
		strafevect = strafevect.crossProduct(camera->getUpVector());

		if (NoVerticalMovement)
			strafevect.y = 0.0f;

		strafevect.normalise();

		if (CursorKeys[EKA_STRAFE_LEFT])
			pos += strafevect * timeDiff * MoveSpeed;

		if (CursorKeys[EKA_STRAFE_RIGHT])
			pos -= strafevect * timeDiff * MoveSpeed;

		// For jumping, we find the collision response animator attached to our camera
		// and if it's not falling, we tell it to jump.
		if (CursorKeys[EKA_JUMP_UP])
		{
			const ISceneNodeAnimatorList& animators = camera->getAnimators();
			ISceneNodeAnimatorList::const_iterator it = animators.begin();
			while (it != animators.end())
			{
				if (ESNAT_COLLISION_RESPONSE == (*it)->getType())
				{
					ISceneNodeAnimatorCollisionResponse * collisionResponse =
						static_cast<ISceneNodeAnimatorCollisionResponse *>(*it);

					if (!collisionResponse->isFalling())
						collisionResponse->jump(JumpSpeed);
				}

				it++;
			}
		}

		// write translation
		camera->setPosition(pos);

		// write right target
		target += pos;
		camera->setTarget(target);
	}