Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //h
- #pragma once
- #include "CDrawable.h"
- class CameraAnimator : public ISceneNodeAnimator, CDrawable
- {
- public:
- using CDrawable::CDrawable;
- CameraAnimator(ICameraSceneNode* cam);
- ~CameraAnimator(void);
- virtual void animateNode(ISceneNode* node, u32 timeMs);
- virtual ISceneNodeAnimator* createClone(ISceneNode* node, ISceneManager* newManager = 0);
- virtual bool OnEvent(const SEvent& event);
- virtual bool isEventReceiverEnabled() const { return true; }
- virtual ESCENE_NODE_ANIMATOR_TYPE getType() const { return ESNAT_UNKNOWN; }
- virtual bool hasFinished() const { return false; }
- static void ApplyForceAndTorqueCallback(const NewtonBody* body, dFloat timestep, int threadIndex);
- static void SetTransformCallback(const NewtonBody* body, const dFloat* matrix, int threadIndex);
- void OnDraw();
- protected:
- core::map<EKEY_ACTION, bool> _pressed;
- core::map<EKEY_CODE, EKEY_ACTION> _actions;
- u32 LastAnimationTime;
- ICursorControl* _cursor;
- ICameraSceneNode* _cam;
- vector2df _cursorPos, _centerCursor;
- f32 _rotateSpeed, _mouseYDirection, _maxVerticalAngle, _moveSpeed, _jumpSpeed;
- NewtonBody* _body;
- NewtonCollision* _collision;
- };
- //cpp
- #include "StdAfx.h"
- #include "CameraAnimator.h"
- CameraAnimator::CameraAnimator(ICameraSceneNode* cam) : LastAnimationTime(0), _maxVerticalAngle(88.0f),
- _moveSpeed(0.01f), _rotateSpeed(50.0f), _jumpSpeed(1.0f),
- _mouseYDirection(1.0f), _cam(cam)
- {
- _cursor = device->getCursorControl();
- _cursor->setVisible(false);
- _actions[KEY_KEY_W] = EKA_MOVE_FORWARD;
- _actions[KEY_KEY_A] = EKA_STRAFE_LEFT;
- _actions[KEY_KEY_S] = EKA_MOVE_BACKWARD;
- _actions[KEY_KEY_D] = EKA_STRAFE_RIGHT;
- _pressed[EKA_MOVE_FORWARD] = false;
- _pressed[EKA_MOVE_BACKWARD] = false;
- _pressed[EKA_STRAFE_RIGHT] = false;
- _pressed[EKA_STRAFE_LEFT] = false;
- _cursor->setPosition(0.5f, 0.5f);
- _cursorPos = _centerCursor = _cursor->getRelativePosition();
- f32 bodyOffset[16] = {
- 1.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, 1.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 1.0f, 0.0f,
- 0.0f, 0.0f, 0.0f, 1.0f
- };
- _collision = NewtonCreateCapsule(world->phys, 1.0f, 2.0f, 0, bodyOffset);
- _body = NewtonCreateBody(world->phys, _collision);
- NewtonBodySetUserData(_body, this->_cam);
- vector3df rot = cam->getRotation();
- vector3df pos = cam->getPosition() * IRRTONEWTON;
- matrix4 mx;
- mx.setTranslation(pos);
- NewtonBodySetMatrix(_body, mx.pointer());
- NewtonBodySetMassMatrix(_body, 1.0f, 1.0f, 1.0f, 1.0f);
- NewtonBodySetForceAndTorqueCallback(_body, CameraAnimator::ApplyForceAndTorqueCallback);
- NewtonBodySetTransformCallback(_body, CameraAnimator::SetTransformCallback);
- }
- CameraAnimator::~CameraAnimator(void)
- {
- NewtonReleaseCollision(world->phys, _collision);
- NewtonDestroyBody(world->phys, _body);
- _cursor->drop();
- }
- void CameraAnimator::animateNode( ISceneNode* node, u32 timeMs )
- {
- if (!node || node->getType() != ESNT_CAMERA)
- return;
- ICameraSceneNode* camera = static_cast<ICameraSceneNode*>(node);
- if (!LastAnimationTime && LastAnimationTime != timeMs)
- {
- camera->updateAbsolutePosition();
- LastAnimationTime = timeMs;
- }
- // If the camera isn't the active camera, and receiving input, then don't process it.
- if(!camera->isInputReceiverEnabled())
- return;
- try
- {
- if(camera->getSceneManager()->getActiveCamera() != camera)
- return;
- }
- catch (SeException* e)
- {
- 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 (_cursor)
- {
- _cursorPos = _cursor->getRelativePosition();
- 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.
- _cursor->setPosition(0.5f, 0.5f);
- _centerCursor = _cursor->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.
- core::vector2d<u32> mousepos(u32(_cursor->getPosition().X), u32(_cursor->getPosition().Y));
- core::rect<u32> screenRect(0, 0, driver->getScreenSize().Width, driver->getScreenSize().Height);
- // Only if we are moving outside quickly.
- if(!screenRect.isPointInside(mousepos))
- {
- // Force a reset.
- _cursor->setPosition(0.5f, 0.5f);
- _centerCursor = _cursor->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 (_pressed[EKA_MOVE_FORWARD])
- pos += movedir * timeDiff * _moveSpeed;
- if (_pressed[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 (_pressed[EKA_STRAFE_LEFT])
- pos += strafevect * timeDiff * _moveSpeed;
- if (_pressed[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);
- }
- ISceneNodeAnimator* CameraAnimator::createClone( ISceneNode* node, ISceneManager* newManager /*= 0*/ )
- {
- ISceneNodeAnimator* clone = new CameraAnimator(_cam);
- return clone;
- }
- bool CameraAnimator::OnEvent( const SEvent& event )
- {
- switch(event.EventType)
- {
- case EET_MOUSE_INPUT_EVENT:
- break;
- case EET_KEY_INPUT_EVENT:
- map<EKEY_CODE, EKEY_ACTION>::Node* action = _actions.find(event.KeyInput.Key);
- if(action)
- _pressed[action->getValue()] = event.KeyInput.PressedDown;
- break;
- }
- return true;
- }
- void CameraAnimator::ApplyForceAndTorqueCallback( const NewtonBody* body, dFloat timestep, int threadIndex )
- {
- dFloat Ixx, Iyy, Izz;
- dFloat mass;
- NewtonBodyGetMassMatrix(body, &mass, &Ixx, &Iyy, &Izz);
- dVector gravityForce(0.0f, mass * -0.5f, 0.0f, 1.0f);
- NewtonBodySetForce(body, &gravityForce[0]);
- }
- void CameraAnimator::SetTransformCallback( const NewtonBody* body, const dFloat* matrix, int threadIndex )
- {
- ISceneNode* node = (ISceneNode*) NewtonBodyGetUserData(body);
- if (node)
- {
- matrix4 transform;
- transform.setM(matrix);
- node->setPosition(transform.getTranslation() * NEWTONTOIRR);
- node->setRotation(transform.getRotationDegrees());
- }
- }
- void _cdecl NewtonDebugCollision(void* body, int vertexCount, const float* faceVertec, int faceId)
- {
- s32 i = vertexCount - 1;
- core::vector3df p0 (faceVertec[i * 3 + 0] * NEWTONTOIRR, faceVertec[i * 3 + 1] * NEWTONTOIRR, faceVertec[i * 3 + 2] * NEWTONTOIRR);
- SColor color(255, 55, 255, 0);
- for (i = 0; i < vertexCount; i++)
- {
- core::vector3df p1 (faceVertec[i * 3 + 0] * NEWTONTOIRR, faceVertec[i * 3 + 1] * NEWTONTOIRR, faceVertec[i * 3 + 2] * NEWTONTOIRR);
- driver->draw3DLine (p0, p1, color);
- p0 = p1;
- }
- }
- void CameraAnimator::OnDraw()
- {
- // phys debug
- matrix4 matx;
- NewtonBodyGetMatrix(_body, &matx[0]);
- NewtonCollisionForEachPolygonDo(_collision, &matx[0], NewtonDebugCollision, 0);
- /////////////
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement