예제 #1
0
 void toggleCameraFpsMode()
 {
     ICameraSceneNode * cam = irrDevice->getSceneManager()->getActiveCamera();
     if (cam)
     {
         cam->setInputReceiverEnabled( !cam->isInputReceiverEnabled());
     }
 }
		void CSSceneNodeAnimatorFPS::animateNode(ISceneNode* node, u32 timeMs)
		{
			if (!node || node->getType() != ESNT_CAMERA)
				return;

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

			if (firstUpdate)
			{
				camera->updateAbsolutePosition();
				if (CursorControl)
				{
					CursorControl->setPosition(m_CursorOffsetX, m_CursorOffsetY);
					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;
			}

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

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

			// update position
			core::vector3df pos = camera->getPosition();

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

			if (CursorControl)
			{
				if (CursorPos != CenterCursor)
				{
					relativeRotation.Y -= (m_CursorOffsetX - CursorPos.X) * RotateSpeed;
					relativeRotation.X -= (m_CursorOffsetY - 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(m_CursorOffsetX, m_CursorOffsetY);
					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.
				video::IVideoDriver* driver = smgr->getVideoDriver();
				core::vector2d<u32> mousepos(u32(CursorControl->getPosition().X), u32(CursorControl->getPosition().Y));
				core::rect<u32> 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(m_CursorOffsetX, m_CursorOffsetY);
					CenterCursor = CursorControl->getRelativePosition();
					CursorPos = CenterCursor;
				}
			}

			// set target

			target.set(0, 0, core::max_(1.f, pos.getLength()));
			core::vector3df movedir = target;

			core::matrix4 mat;
			mat.setRotationDegrees(core::vector3df(relativeRotation.X, relativeRotation.Y, 0));
			mat.transformVect(target);

			if (NoVerticalMovement)
			{
				mat.setRotationDegrees(core::vector3df(0, relativeRotation.Y, 0));
				mat.transformVect(movedir);
			}
			else
			{
				movedir = target;
			}

			movedir.normalize();

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

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

			// strafing

			core::vector3df strafevect = target;
			strafevect = strafevect.crossProduct(camera->getUpVector());

			if (NoVerticalMovement)
				strafevect.Y = 0.0f;

			strafevect.normalize();

			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::ConstIterator 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);
		}
void CSceneNodeAnimatorCameraFPS::animateNode(IDummyTransformationSceneNode* node, uint32_t 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;
	}

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

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

	// update position
	core::vector3df pos = camera->getPosition();

	// Update rotation
	core::vector3df target = (camera->getTarget() - camera->getAbsolutePosition());
	core::vector3df 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.
		video::IVideoDriver* driver = smgr->getVideoDriver();
		core::vector2d<uint32_t> mousepos(uint32_t(CursorControl->getPosition().X), uint32_t(CursorControl->getPosition().Y));
		core::rect<uint32_t> 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, core::max_(1.f, pos.getLength()));
	core::vector3df movedir = target;

	core::matrix4x3 mat;
	mat.setRotationDegrees(core::vector3df(relativeRotation.X, relativeRotation.Y, 0));
	mat.transformVect(&target.X);

	if (NoVerticalMovement)
	{
		mat.setRotationDegrees(core::vector3df(0, relativeRotation.Y, 0));
		mat.transformVect(&movedir.X);
	}
	else
	{
		movedir = target;
	}

	movedir.normalize();

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

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

	// strafing

	core::vector3df strafevect = target;
	strafevect = strafevect.crossProduct(camera->getUpVector());

	if (NoVerticalMovement)
		strafevect.Y = 0.0f;

	strafevect.normalize();

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

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

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

	// write right target
	target += pos;
	camera->setTarget(target);
}
//! OnAnimate() is called just before rendering the whole scene.
//! nodes may calculate or store animations here, and may do other useful things,
//! dependent on what they are.
void CSceneNodeAnimatorCameraMaya::animateNode(ISceneNode *node, u32 timeMs)
{
	//Alt + LM = Rotate around camera pivot
	//Alt + LM + MM = Dolly forth/back in view direction (speed % distance camera pivot - max distance to pivot)
	//Alt + MM = Move on camera plane (Screen center is about the mouse pointer, depending on move speed)

	if (!node || node->getType() != ESNT_CAMERA)
		return;

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

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

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

	if (OldCamera != camera)
	{
		OldTarget = camera->getTarget();
		OldCamera = camera;
		LastCameraTarget = OldTarget;
	}
	else
	{
		OldTarget += camera->getTarget() - LastCameraTarget;
	}

	core::vector3df target = camera->getTarget();

	f32 nRotX = RotX;
	f32 nRotY = RotY;
	f32 nZoom = CurrentZoom;

	if ( (isMouseKeyDown(0) && isMouseKeyDown(2)) || isMouseKeyDown(1) )
	{
		if (!Zooming)
		{
			ZoomStart = MousePos;
			Zooming = true;
			nZoom = CurrentZoom;
		}
		else
		{
			const f32 targetMinDistance = 0.1f;
			nZoom += (ZoomStart.X - MousePos.X) * ZoomSpeed;

			if (nZoom < targetMinDistance) // jox: fixed bug: bounce back when zooming to close
				nZoom = targetMinDistance;
		}
	}
	else if (Zooming)
	{
		const f32 old = CurrentZoom;
		CurrentZoom = CurrentZoom + (ZoomStart.X - MousePos.X ) * ZoomSpeed;
		nZoom = CurrentZoom;

		if (nZoom < 0)
			nZoom = CurrentZoom = old;
		Zooming = false;
	}

	// Translation ---------------------------------

	core::vector3df translate(OldTarget), upVector(camera->getUpVector());

	core::vector3df tvectX = Pos - target;
	tvectX = tvectX.crossProduct(upVector);
	tvectX.normalize();

	const SViewFrustum* const va = camera->getViewFrustum();
	core::vector3df tvectY = (va->getFarLeftDown() - va->getFarRightDown());
	tvectY = tvectY.crossProduct(upVector.Y > 0 ? Pos - target : target - Pos);
	tvectY.normalize();

	if (isMouseKeyDown(2) && !Zooming)
	{
		if (!Translating)
		{
			TranslateStart = MousePos;
			Translating = true;
		}
		else
		{
			translate +=  tvectX * (TranslateStart.X - MousePos.X)*TranslateSpeed +
			              tvectY * (TranslateStart.Y - MousePos.Y)*TranslateSpeed;
		}
	}
	else if (Translating)
	{
		translate += tvectX * (TranslateStart.X - MousePos.X)*TranslateSpeed +
		             tvectY * (TranslateStart.Y - MousePos.Y)*TranslateSpeed;
		OldTarget = translate;
		Translating = false;
	}

	// Rotation ------------------------------------

	if (isMouseKeyDown(0) && !Zooming)
	{
		if (!Rotating)
		{
			RotateStart = MousePos;
			Rotating = true;
			nRotX = RotX;
			nRotY = RotY;
		}
		else
		{
			nRotX += (RotateStart.X - MousePos.X) * RotateSpeed;
			nRotY += (RotateStart.Y - MousePos.Y) * RotateSpeed;
		}
	}
	else if (Rotating)
	{
		RotX += (RotateStart.X - MousePos.X) * RotateSpeed;
		RotY += (RotateStart.Y - MousePos.Y) * RotateSpeed;
		nRotX = RotX;
		nRotY = RotY;
		Rotating = false;
	}

	// Set Pos ------------------------------------

	target = translate;

	Pos.X = nZoom + target.X;
	Pos.Y = target.Y;
	Pos.Z = target.Z;

	Pos.rotateXYBy(nRotY, target);
	Pos.rotateXZBy(-nRotX, target);

	// Rotation Error ----------------------------

	// jox: fixed bug: jitter when rotating to the top and bottom of y
	upVector.set(0,1,0);
	upVector.rotateXYBy(-nRotY);
	upVector.rotateXZBy(-nRotX+180.f);

	camera->setPosition(Pos);
	camera->setTarget(target);
	camera->setUpVector(upVector);
	LastCameraTarget = camera->getTarget();
}